| 1 17 package org.eclipse.emf.common.util; 18 19 20 import java.io.IOException ; 21 import java.io.ObjectInputStream ; 22 import java.io.ObjectOutputStream ; 23 import java.io.Serializable ; 24 import java.lang.reflect.Array ; 25 import java.util.AbstractList ; 26 import java.util.Collection ; 27 import java.util.ConcurrentModificationException ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.ListIterator ; 31 import java.util.NoSuchElementException ; 32 33 34 37 public class BasicEList extends AbstractList implements EList, Cloneable , Serializable 38 { 39 42 protected int size; 43 44 47 protected transient Object data[]; 48 49 53 public BasicEList() 54 { 55 } 56 57 62 public BasicEList(int initialCapacity) 63 { 64 if (initialCapacity < 0) 65 { 66 throw new IllegalArgumentException ("Illegal Capacity: " + initialCapacity); 67 } 68 69 data = newData(initialCapacity); 70 } 71 72 76 public BasicEList(Collection collection) 77 { 78 size = collection.size(); 79 80 if (size > 0) 83 { 84 data = newData(size + size / 8 + 1); 87 collection.toArray(data); 88 } 89 } 90 91 96 protected BasicEList(int size, Object [] data) 97 { 98 this.size = size; 99 this.data = data; 100 } 101 102 108 protected Object [] newData(int capacity) 109 { 110 return new Object [capacity]; 111 } 112 113 119 protected boolean useEquals() 120 { 121 return true; 122 } 123 124 128 protected boolean equalObjects(Object firstObject, Object secondObject) 129 { 130 return 131 useEquals() && firstObject != null ? 132 firstObject.equals(secondObject) : 133 firstObject == secondObject; 134 } 135 136 141 protected boolean canContainNull() 142 { 143 return true; 144 } 145 146 152 protected boolean isUnique() 153 { 154 return false; 155 } 156 157 167 protected Object validate(int index, Object object) 168 { 169 if (!canContainNull() && object == null) 170 { 171 throw new IllegalArgumentException ("The 'no null' constraint is violated"); 172 } 173 174 return object; 175 } 176 177 185 protected Object assign(int index, Object object) 186 { 187 return data[index] = object; 188 } 189 190 198 protected Object resolve(int index, Object object) 199 { 200 return object; 201 } 202 203 211 protected void didSet(int index, Object newObject, Object oldObject) 212 { 213 } 214 215 222 protected void didAdd(int index, Object newObject) 223 { 224 } 225 226 233 protected void didRemove(int index, Object oldObject) 234 { 235 } 236 237 245 protected void didClear(int size, Object [] oldObjects) 246 { 247 if (oldObjects != null) 248 { 249 for (int i = 0; i < size; ++i) 250 { 251 didRemove(i, oldObjects[i]); 252 } 253 } 254 } 255 256 264 protected void didMove(int index, Object movedObject, int oldIndex) 265 { 266 } 267 268 273 protected void didChange() 274 { 275 } 276 277 281 public int size() 282 { 283 return size; 284 } 285 286 290 public boolean isEmpty() 291 { 292 return size == 0; 293 } 294 295 302 public boolean contains(Object object) 303 { 304 if (useEquals() && object != null) 305 { 306 for (int i = 0; i < size; ++i) 307 { 308 if (object.equals(data[i])) 309 { 310 return true; 311 } 312 } 313 } 314 else 315 { 316 for (int i = 0; i < size; ++i) 317 { 318 if (data[i] == object) 319 { 320 return true; 321 } 322 } 323 } 324 325 return false; 326 } 327 328 337 public boolean containsAll(Collection collection) 338 { 339 for (Iterator i = collection.iterator(); i.hasNext(); ) 340 { 341 if (!contains(i.next())) 342 { 343 return false; 344 } 345 } 346 347 return true; 348 } 349 350 356 public int indexOf(Object object) 357 { 358 if (useEquals() && object != null) 359 { 360 for (int i = 0; i < size; ++i) 361 { 362 if (object.equals(data[i])) 363 { 364 return i; 365 } 366 } 367 } 368 else 369 { 370 for (int i = 0; i < size; ++i) 371 { 372 if (data[i] == object) 373 { 374 return i; 375 } 376 } 377 } 378 return -1; 379 } 380 381 387 public int lastIndexOf(Object object) 388 { 389 if (useEquals() && object != null) 390 { 391 for (int i = size - 1; i >= 0; --i) 392 { 393 if (object.equals(data[i])) 394 { 395 return i; 396 } 397 } 398 } 399 else 400 { 401 for (int i = size - 1; i >= 0; --i) 402 { 403 if (data[i] == object) 404 { 405 return i; 406 } 407 } 408 } 409 return -1; 410 } 411 412 418 public Object [] toArray() 419 { 420 Object [] result = newData(size); 421 422 if (size > 0) 425 { 426 System.arraycopy(data, 0, result, 0, size); 427 } 428 return result; 429 } 430 431 438 public Object [] toArray(Object array[]) 439 { 440 if (size > 0) 443 { 444 if (array.length < size) 445 { 446 array = (Object [])Array.newInstance(array.getClass().getComponentType(), size); 447 } 448 449 System.arraycopy(data, 0, array, 0, size); 450 } 451 452 if (array.length > size) 453 { 454 array[size] = null; 455 } 456 457 return array; 458 } 459 460 466 public Object [] data() 467 { 468 return data; 469 } 470 471 476 public void setData(int size, Object [] data) 477 { 478 this.size = size; 479 this.data = data; 480 ++modCount; 481 } 482 483 487 protected static class BasicIndexOutOfBoundsException extends IndexOutOfBoundsException  488 { 489 492 public BasicIndexOutOfBoundsException(int index, int size) 493 { 494 super("index=" + index + ", size=" + size); 495 } 496 } 497 498 508 public Object get(int index) 509 { 510 if (index >= size) 511 throw new BasicIndexOutOfBoundsException(index, size); 512 513 return resolve(index, data[index]); 514 } 515 516 524 public Object basicGet(int index) 525 { 526 if (index >= size) 527 throw new BasicIndexOutOfBoundsException(index, size); 528 529 return data[index]; 530 } 531 532 544 public Object set(int index, Object object) 545 { 546 if (index >= size) 547 throw new BasicIndexOutOfBoundsException(index, size); 548 549 if (isUnique()) 550 { 551 int currentIndex = indexOf(object); 552 if (currentIndex >=0 && currentIndex != index) 553 { 554 throw new IllegalArgumentException ("The 'no duplicates' constraint is violated"); 555 } 556 } 557 558 return setUnique(index, object); 559 } 560 561 571 public Object setUnique(int index, Object object) 572 { 573 Object oldObject = data[index]; 574 assign(index, validate(index, object)); 575 didSet(index, object, oldObject); 576 didChange(); 577 return oldObject; 578 } 579 580 591 public boolean add(Object object) 592 { 593 if (isUnique() && contains(object)) 594 { 595 return false; 596 } 597 else 598 { 599 addUnique(object); 600 return true; 601 } 602 } 603 604 612 public void addUnique(Object object) 613 { 614 grow(size + 1); 617 618 assign(size, validate(size, object)); 619 didAdd(size++, object); 620 didChange(); 621 } 622 623 634 public void add(int index, Object object) 635 { 636 if (index > size) 637 throw new BasicIndexOutOfBoundsException(index, size); 638 639 if (isUnique() && contains(object)) 640 { 641 throw new IllegalArgumentException ("The 'no duplicates' constraint is violated"); 642 } 643 644 addUnique(index, object); 645 } 646 647 654 public void addUnique(int index, Object object) 655 { 656 grow(size + 1); 659 660 if (index != size) 661 { 662 System.arraycopy(data, index, data, index + 1, size - index); 663 } 664 assign(index, validate(index, object)); 665 ++size; 666 didAdd(index, object); 667 didChange(); 668 } 669 670 680 public boolean addAll(Collection collection) 681 { 682 if (isUnique()) 683 { 684 collection = getNonDuplicates(collection); 685 } 686 return addAllUnique(collection); 687 } 688 689 696 public boolean addAllUnique(Collection collection) 697 { 698 int growth = collection.size(); 699 700 grow(size + growth); 703 704 Iterator objects = collection.iterator(); 705 int oldSize = size; 706 size += growth; 707 for (int i = oldSize; i < size; ++i) 708 { 709 Object object = objects.next(); 710 assign(i, validate(i, object)); 711 didAdd(i, object); 712 didChange(); 713 } 714 715 return growth != 0; 716 } 717 718 731 public boolean addAll(int index, Collection collection) 732 { 733 if (index > size) 734 throw new BasicIndexOutOfBoundsException(index, size); 735 736 if (isUnique()) 737 { 738 collection = getNonDuplicates(collection); 739 } 740 return addAllUnique(index, collection); 741 } 742 743 753 public boolean addAllUnique(int index, Collection collection) 754 { 755 int growth = collection.size(); 756 757 grow(size + growth); 760 761 int shifted = size - index; 762 if (shifted > 0) 763 { 764 System.arraycopy(data, index, data, index + growth, shifted); 765 } 766 767 Iterator objects = collection.iterator(); 768 size += growth; 769 for (int i = 0; i < growth; ++i) 770 { 771 Object object = objects.next(); 772 assign(index, validate(index, object)); 773 didAdd(index, object); 774 didChange(); 775 ++index; 776 } 777 778 return growth != 0; 779 } 780 781 789 public boolean remove(Object object) 790 { 791 int index = indexOf(object); 792 if (index >= 0) 793 { 794 remove(index); 795 return true; 796 } 797 else 798 { 799 return false; 800 } 801 } 802 803 808 public boolean removeAll(Collection collection) 809 { 810 boolean modified = false; 811 for (int i = size; --i >= 0; ) 812 { 813 if (collection.contains(data[i])) 814 { 815 remove(i); 816 modified = true; 817 } 818 } 819 820 return modified; 821 } 822 823 830 public Object remove(int index) 831 { 832 if (index >= size) 833 throw new BasicIndexOutOfBoundsException(index, size); 834 835 ++modCount; 836 Object oldObject = data[index]; 837 838 int shifted = size - index - 1; 839 if (shifted > 0) 840 { 841 System.arraycopy(data, index+1, data, index, shifted); 842 } 843 844 data[--size] = null; 847 didRemove(index, oldObject); 848 didChange(); 849 850 return oldObject; 851 } 852 853 861 public boolean retainAll(Collection collection) 862 { 863 boolean modified = false; 864 for (int i = size; --i >= 0; ) 865 { 866 if (!collection.contains(data[i])) 867 { 868 remove(i); 869 modified = true; 870 } 871 } 872 return modified; 873 } 874 875 880 public void clear() 881 { 882 ++modCount; 883 884 Object [] oldData = data; 885 int oldSize = size; 886 887 data = null; 890 size = 0; 891 892 didClear(oldSize, oldData); 893 didChange(); 894 } 895 896 904 public void move(int index, Object object) 905 { 906 move(index, indexOf(object)); 907 } 908 909 918 public Object move(int targetIndex, int sourceIndex) 919 { 920 ++modCount; 921 if (targetIndex >= size) 922 throw new IndexOutOfBoundsException ("targetIndex=" + targetIndex + ", size=" + size); 923 924 if (sourceIndex >= size) 925 throw new IndexOutOfBoundsException ("sourceIndex=" + sourceIndex + ", size=" + size); 926 927 Object object = data[sourceIndex]; 928 if (targetIndex != sourceIndex) 929 { 930 if (targetIndex < sourceIndex) 931 { 932 System.arraycopy(data, targetIndex, data, targetIndex + 1, sourceIndex - targetIndex); 933 } 934 else 935 { 936 System.arraycopy(data, sourceIndex + 1, data, sourceIndex, targetIndex - sourceIndex); 937 } 938 assign(targetIndex, object); 939 didMove(targetIndex, object, sourceIndex); 940 didChange(); 941 } 942 return object; 943 } 944 945 949 public void shrink() 950 { 951 ++modCount; 952 953 if (size == 0) 956 { 957 data = null; 960 } 961 else if (size < data.length) 962 { 963 Object [] oldData = data; 964 data = newData(size); 965 System.arraycopy(oldData, 0, data, 0, size); 966 } 967 } 968 969 974 public void grow(int minimumCapacity) 975 { 976 ++modCount; 977 int oldCapacity = data == null ? 0 : data.length; 978 if (minimumCapacity > oldCapacity) 979 { 980 Object oldData[] = data; 981 982 int newCapacity = oldCapacity + oldCapacity / 2 + 4; 987 if (newCapacity < minimumCapacity) 988 { 989 newCapacity = minimumCapacity; 990 } 991 data = newData(newCapacity); 992 if (oldData != null) 993 { 994 System.arraycopy(oldData, 0, data, 0, size); 995 } 996 } 997 } 998 999 private synchronized void writeObject(ObjectOutputStream objectOutputStream) throws IOException  1000 { 1001 objectOutputStream.defaultWriteObject(); 1002 if (data == null) 1003 { 1004 objectOutputStream.writeInt(0); 1005 } 1006 else 1007 { 1008 objectOutputStream.writeInt(data.length); 1009 for (int i = 0; i < size; ++i) 1010 { 1011 objectOutputStream.writeObject(data[i]); 1012 } 1013 } 1014 } 1015 1016 private synchronized void readObject(ObjectInputStream objectInputStream) throws IOException , ClassNotFoundException  1017 { 1018 objectInputStream.defaultReadObject(); 1019 int arrayLength = objectInputStream.readInt(); 1020 if (arrayLength > 0) 1021 { 1022 try 1023 { 1024 data = newData(arrayLength); 1025 } 1026 catch (Throwable exception) 1027 { 1028 data = new Object [arrayLength]; 1029 } 1030 1031 for (int i = 0; i < size; ++i) 1032 { 1033 didAdd(i, assign(i, objectInputStream.readObject())); 1034 } 1035 } 1036 } 1037 1038 1042 public Object clone() 1043 { 1044 try 1045 { 1046 BasicEList clone = (BasicEList)super.clone(); 1047 if (size > 0) 1048 { 1049 clone.size = size; 1050 clone.data = newData(size); 1051 System.arraycopy(data, 0, clone.data, 0, size); 1052 } 1053 return clone; 1054 } 1055 catch (CloneNotSupportedException exception) 1056 { 1057 throw new InternalError (); 1058 } 1059 } 1060 1061 1067 public boolean equals(Object object) 1068 { 1069 if (object == this) 1070 { 1071 return true; 1072 } 1073 1074 if (!(object instanceof List )) 1075 { 1076 return false; 1077 } 1078 1079 List list = (List )object; 1080 if (list
|