001 /**
002 * <copyright>
003 *
004 * Copyright (c) 2002-2009 IBM Corporation and others.
005 * All rights reserved. This program and the accompanying materials
006 * are made available under the terms of the Eclipse Public License v1.0
007 * which accompanies this distribution, and is available at
008 * http://www.eclipse.org/legal/epl-v10.html
009 *
010 * Contributors:
011 * IBM - Initial API and implementation
012 *
013 * </copyright>
014 *
015 * $Id: BasicEList.java,v 1.18 2009/01/16 12:55:02 emerks Exp $
016 */
017 package org.eclipse.emf.common.util;
018
019
020 import java.io.IOException;
021 import java.io.ObjectInputStream;
022 import java.io.ObjectOutputStream;
023 import java.io.Serializable;
024 import java.lang.reflect.Array;
025 import java.util.Collection;
026 import java.util.Iterator;
027 import java.util.List;
028 import java.util.ListIterator;
029 import java.util.RandomAccess;
030
031
032 /**
033 * A highly extensible list implementation.
034 */
035 public class BasicEList<E> extends AbstractEList<E> implements RandomAccess, Cloneable, Serializable
036 {
037 private static final long serialVersionUID = 1L;
038
039 /**
040 * The size of the list.
041 */
042 protected int size;
043
044 /**
045 * The underlying data storage of the list.
046 */
047 protected transient Object [] data;
048
049 /**
050 * Creates an empty instance with no initial capacity.
051 * The data storage will be null.
052 */
053 public BasicEList()
054 {
055 super();
056 }
057
058 /**
059 * Creates an empty instance with the given capacity.
060 * @param initialCapacity the initial capacity of the list before it must grow.
061 * @exception IllegalArgumentException if the <code>initialCapacity</code> is negative.
062 */
063 public BasicEList(int initialCapacity)
064 {
065 if (initialCapacity < 0)
066 {
067 throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
068 }
069
070 data = newData(initialCapacity);
071 }
072
073 /**
074 * Creates an instance that is a copy of the collection.
075 * @param collection the initial contents of the list.
076 */
077 public BasicEList(Collection<? extends E> collection)
078 {
079 size = collection.size();
080
081 // Conditionally create the data.
082 //
083 if (size > 0)
084 {
085 // Allow for a bit-shift of growth.
086 //
087 data = newData(size + size / 8 + 1);
088 collection.toArray(data);
089 }
090 }
091
092 /**
093 * Creates an initialized instance that directly uses the given arguments.
094 * @param size the size of the list.
095 * @param data the underlying storage of the list.
096 */
097 protected BasicEList(int size, Object [] data)
098 {
099 this.size = size;
100 this.data = data;
101 }
102
103 /**
104 * Returns new allocated data storage.
105 * Clients may override this to create typed storage.
106 * The cost of type checking via a typed array is negligible.
107 * @return new data storage.
108 */
109 protected Object [] newData(int capacity)
110 {
111 return new Object [capacity];
112 }
113
114 /**
115 * Assigns the object into the data storage at the given index and returns the object that's been stored.
116 * Clients can monitor access to the storage via this method.
117 * @param index the position of the new content.
118 * @param object the new content.
119 * @return the object that's been stored.
120 *
121 */
122 protected E assign(int index, E object)
123 {
124 data[index] = object;
125 return object;
126 }
127
128 /**
129 * Returns the number of objects in the list.
130 * @return the number of objects in the list.
131 */
132 @Override
133 public int size()
134 {
135 return size;
136 }
137
138 /**
139 * Returns whether the list has zero size.
140 * @return whether the list has zero size.
141 */
142 @Override
143 public boolean isEmpty()
144 {
145 return size == 0;
146 }
147
148 /**
149 * Returns whether the list contains the object.
150 * This implementation uses either <code>equals</code> or <code>"=="</code> depending on {@link #useEquals useEquals}.
151 * @param object the object in question.
152 * @return whether the list contains the object.
153 * @see #useEquals
154 */
155 @Override
156 public boolean contains(Object object)
157 {
158 if (useEquals() && object != null)
159 {
160 for (int i = 0; i < size; ++i)
161 {
162 if (object.equals(data[i]))
163 {
164 return true;
165 }
166 }
167 }
168 else
169 {
170 for (int i = 0; i < size; ++i)
171 {
172 if (data[i] == object)
173 {
174 return true;
175 }
176 }
177 }
178
179 return false;
180 }
181
182 /**
183 * Returns the position of the first occurrence of the object in the list.
184 * This implementation uses either <code>equals</code> or <code>"=="</code> depending on {@link #useEquals useEquals}.
185 * @param object the object in question.
186 * @return the position of the first occurrence of the object in the list.
187 */
188 @Override
189 public int indexOf(Object object)
190 {
191 if (useEquals() && object != null)
192 {
193 for (int i = 0; i < size; ++i)
194 {
195 if (object.equals(data[i]))
196 {
197 return i;
198 }
199 }
200 }
201 else
202 {
203 for (int i = 0; i < size; ++i)
204 {
205 if (data[i] == object)
206 {
207 return i;
208 }
209 }
210 }
211 return -1;
212 }
213
214 /**
215 * Returns the position of the last occurrence of the object in the list.
216 * This implementation uses either <code>equals</code> or <code>"=="</code> depending on {@link #useEquals useEquals}.
217 * @param object the object in question.
218 * @return the position of the last occurrence of the object in the list.
219 */
220 @Override
221 public int lastIndexOf(Object object)
222 {
223 if (useEquals() && object != null)
224 {
225 for (int i = size - 1; i >= 0; --i)
226 {
227 if (object.equals(data[i]))
228 {
229 return i;
230 }
231 }
232 }
233 else
234 {
235 for (int i = size - 1; i >= 0; --i)
236 {
237 if (data[i] == object)
238 {
239 return i;
240 }
241 }
242 }
243 return -1;
244 }
245
246 /**
247 * Returns an array containing all the objects in sequence.
248 * Clients may override {@link #newData newData} to create typed storage in this case.
249 * @return an array containing all the objects in sequence.
250 * @see #newData
251 */
252 @Override
253 public Object[] toArray()
254 {
255 Object[] result = newData(size);
256
257 // Guard for no data.
258 //
259 if (size > 0)
260 {
261 System.arraycopy(data, 0, result, 0, size);
262 }
263 return result;
264 }
265
266 /**
267 * Returns an array containing all the objects in sequence.
268 * @param array the array that will be filled and returned, if it's big enough;
269 * otherwise, a suitably large array of the same type will be allocated and used instead.
270 * @return an array containing all the objects in sequence.
271 * @see #newData
272 */
273 @Override
274 public <T> T[] toArray(T[] array)
275 {
276 // Guard for no data.
277 //
278 if (size > 0)
279 {
280 if (array.length < size)
281 {
282 @SuppressWarnings("unchecked") T [] newArray = (T[])Array.newInstance(array.getClass().getComponentType(), size);
283 array = newArray;
284 }
285
286 System.arraycopy(data, 0, array, 0, size);
287 }
288
289 if (array.length > size)
290 {
291 array[size] = null;
292 }
293
294 return array;
295 }
296
297 /**
298 * Returns direct <b>unsafe</b> access to the underlying data storage.
299 * Clients may <b>not</b> modify this
300 * and may <b>not</b> assume that the array remains valid as the list is modified.
301 * @return direct <b>unsafe</b> access to the underlying data storage.
302 */
303 public Object [] data()
304 {
305 return data;
306 }
307
308 /**
309 * Updates directly and <b>unsafely</b> the underlying data storage.
310 * Clients <b>must</b> be aware that this subverts all callbacks
311 * and hence possibly the integrity of the list.
312 */
313 public void setData(int size, Object [] data)
314 {
315 this.size = size;
316 this.data = data;
317 ++modCount;
318 }
319
320 /**
321 * An IndexOutOfBoundsException that constructs a message from the argument data.
322 * Having this avoids having the byte code that computes the message repeated/inlined at the creation site.
323 */
324 protected static class BasicIndexOutOfBoundsException extends AbstractEList.BasicIndexOutOfBoundsException
325 {
326 private static final long serialVersionUID = 1L;
327
328 /**
329 * Constructs an instance with a message based on the arguments.
330 */
331 public BasicIndexOutOfBoundsException(int index, int size)
332 {
333 super(index, size);
334 }
335 }
336
337 /**
338 * Returns the object at the index.
339 * This implementation delegates to {@link #resolve resolve}
340 * so that clients may transform the fetched object.
341 * @param index the position in question.
342 * @return the object at the index.
343 * @exception IndexOutOfBoundsException if the index isn't within the size range.
344 * @see #resolve
345 * @see #basicGet
346 */
347 @SuppressWarnings("unchecked")
348 @Override
349 public E get(int index)
350 {
351 if (index >= size)
352 throw new BasicIndexOutOfBoundsException(index, size);
353
354 return resolve(index, (E)data[index]);
355 }
356
357 /**
358 * Returns the object at the index without {@link #resolve resolving} it.
359 * @param index the position in question.
360 * @return the object at the index.
361 * @exception IndexOutOfBoundsException if the index isn't within the size range.
362 * @see #resolve
363 * @see #get
364 */
365 @Override
366 public E basicGet(int index)
367 {
368 if (index >= size)
369 throw new BasicIndexOutOfBoundsException(index, size);
370
371 return primitiveGet(index);
372 }
373
374 /**
375 * Returns the object at the index without {@link #resolve resolving} it and without range checking the index.
376 * @param index the position in question.
377 * @return the object at the index.
378 * @see #resolve
379 * @see #get
380 * @see #basicGet(int)
381 */
382 @SuppressWarnings("unchecked")
383 @Override
384 protected E primitiveGet(int index)
385 {
386 return (E)data[index];
387 }
388
389 /**
390 * Sets the object at the index
391 * and returns the old object at the index;
392 * it does no ranging checking or uniqueness checking.
393 * This implementation delegates to {@link #assign assign}, {@link #didSet didSet}, and {@link #didChange didChange}.
394 * @param index the position in question.
395 * @param object the object to set.
396 * @return the old object at the index.
397 * @see #set
398 */
399 @Override
400 public E setUnique(int index, E object)
401 {
402 @SuppressWarnings("unchecked") E oldObject = (E)data[index];
403 assign(index, validate(index, object));
404 didSet(index, object, oldObject);
405 didChange();
406 return oldObject;
407 }
408
409 /**
410 * Adds the object at the end of the list;
411 * it does no uniqueness checking.
412 * This implementation delegates to {@link #assign assign}, {@link #didAdd didAdd}, and {@link #didChange didChange}.
413 * after uniqueness checking.
414 * @param object the object to be added.
415 * @see #add(Object)
416 */
417 @Override
418 public void addUnique(E object)
419 {
420 // ++modCount
421 //
422 grow(size + 1);
423
424 assign(size, validate(size, object));
425 didAdd(size++, object);
426 didChange();
427 }
428
429 /**
430 * Adds the object at the given index in the list;
431 * it does no ranging checking or uniqueness checking.
432 * This implementation delegates to {@link #assign assign}, {@link #didAdd didAdd}, and {@link #didChange didChange}.
433 * @param object the object to be added.
434 * @see #add(int, Object)
435 */
436 @Override
437 public void addUnique(int index, E object)
438 {
439 // ++modCount
440 //
441 grow(size + 1);
442
443 E validatedObject = validate(index, object);
444 if (index != size)
445 {
446 System.arraycopy(data, index, data, index + 1, size - index);
447 }
448 assign(index, validatedObject);
449 ++size;
450 didAdd(index, object);
451 didChange();
452 }
453
454 /**
455 * Adds each object of the collection to the end of the list;
456 * it does no uniqueness checking.
457 * This implementation delegates to {@link #assign assign}, {@link #didAdd didAdd}, and {@link #didChange didChange}.
458 * @param collection the collection of objects to be added.
459 * @see #addAll(Collection)
460 */
461 @Override
462 public boolean addAllUnique(Collection<? extends E> collection)
463 {
464 int growth = collection.size();
465
466 // ++modCount
467 //
468 grow(size + growth);
469
470 Iterator<? extends E> objects = collection.iterator();
471 int oldSize = size;
472 size += growth;
473 for (int i = oldSize; i < size; ++i)
474 {
475 E object = objects.next();
476 assign(i, validate(i, object));
477 didAdd(i, object);
478 didChange();
479 }
480
481 return growth != 0;
482 }
483
484 /**
485 * Adds each object of the collection at each successive index in the list
486 * and returns whether any objects were added;
487 * it does no ranging checking or uniqueness checking.
488 * This implementation delegates to {@link #assign assign}, {@link #didAdd didAdd}, and {@link #didChange didChange}.
489 * @param index the index at which to add.
490 * @param collection the collection of objects to be added.
491 * @return whether any objects were added.
492 * @see #addAll(int, Collection)
493 */
494 @Override
495 public boolean addAllUnique(int index, Collection<? extends E> collection)
496 {
497 int growth = collection.size();
498
499 // ++modCount
500 //
501 grow(size + growth);
502
503 int shifted = size - index;
504 if (shifted > 0)
505 {
506 System.arraycopy(data, index, data, index + growth, shifted);
507 }
508
509 Iterator<? extends E> objects = collection.iterator();
510 size += growth;
511 for (int i = 0; i < growth; ++i)
512 {
513 E object = objects.next();
514 assign(index, validate(index, object));
515 didAdd(index, object);
516 didChange();
517 ++index;
518 }
519
520 return growth != 0;
521 }
522
523 /**
524 * Adds each object from start to end of the array at the index of list
525 * and returns whether any objects were added;
526 * it does no ranging checking or uniqueness checking.
527 * This implementation delegates to {@link #assign assign}, {@link #didAdd didAdd}, and {@link #didChange didChange}.
528 * @param objects the objects to be added.
529 * @param start the index of first object to be added.
530 * @param end the index past the last object to be added.
531 * @return whether any objects were added.
532 * @see #addAllUnique(Object[], int, int)
533 */
534 @Override
535 public boolean addAllUnique(Object [] objects, int start, int end)
536 {
537 int growth = end - start;
538
539 // ++modCount
540 //
541 grow(size + growth);
542
543 size += growth;
544 int index = size;
545 for (int i = start; i < end; ++i)
546 {
547 @SuppressWarnings("unchecked") E object = (E)objects[i];
548 assign(index, validate(index, object));
549 didAdd(index, object);
550 didChange();
551 ++index;
552 }
553
554 return growth != 0;
555 }
556
557 /**
558 * Adds each object from start to end of the array at each successive index in the list
559 * and returns whether any objects were added;
560 * it does no ranging checking or uniqueness checking.
561 * This implementation delegates to {@link #assign assign}, {@link #didAdd didAdd}, and {@link #didChange didChange}.
562 * @param index the index at which to add.
563 * @param objects the objects to be added.
564 * @param start the index of first object to be added.
565 * @param end the index past the last object to be added.
566 * @return whether any objects were added.
567 * @see #addAllUnique(Object[], int, int)
568 */
569 @Override
570 public boolean addAllUnique(int index, Object [] objects, int start, int end)
571 {
572 int growth = end - start;
573
574 // ++modCount
575 //
576 grow(size + growth);
577
578 int shifted = size - index;
579 if (shifted > 0)
580 {
581 System.arraycopy(data, index, data, index + growth, shifted);
582 }
583
584 size += growth;
585 for (int i = start; i < end; ++i)
586 {
587 @SuppressWarnings("unchecked") E object = (E)objects[i];
588 assign(index, validate(index, object));
589 didAdd(index, object);
590 didChange();
591 ++index;
592 }
593
594 return growth != 0;
595 }
596
597 /**
598 * Removes the object at the index from the list and returns it.
599 * This implementation delegates to {@link #didRemove didRemove} and {@link #didChange didChange}.
600 * @param index the position of the object to remove.
601 * @return the removed object.
602 * @exception IndexOutOfBoundsException if the index isn't within the size range.
603 */
604 @Override
605 public E remove(int index)
606 {
607 if (index >= size)
608 throw new BasicIndexOutOfBoundsException(index, size);
609
610 ++modCount;
611 @SuppressWarnings("unchecked") E oldObject = (E)data[index];
612
613 int shifted = size - index - 1;
614 if (shifted > 0)
615 {
616 System.arraycopy(data, index+1, data, index, shifted);
617 }
618
619 // Don't hold onto a duplicate reference to the last object.
620 //
621 data[--size] = null;
622 didRemove(index, oldObject);
623 didChange();
624
625 return oldObject;
626 }
627
628 /**
629 * Clears the list of all objects.
630 * This implementation discards the data storage without modifying it
631 * and delegates to {@link #didClear didClear} and {@link #didChange didChange}.
632 */
633 @Override
634 public void clear()
635 {
636 ++modCount;
637
638 Object [] oldData = data;
639 int oldSize = size;
640
641 // Give it all back to the garbage collector.
642 //
643 data = null;
644 size = 0;
645
646 didClear(oldSize, oldData);
647 didChange();
648 }
649
650 /**
651 * Moves the object at the source index of the list to the target index of the list
652 * and returns the moved object.
653 * This implementation delegates to {@link #assign assign}, {@link #didMove didMove}, and {@link #didChange didChange}.
654 * @param targetIndex the new position for the object in the list.
655 * @param sourceIndex the old position of the object in the list.
656 * @return the moved object.
657 * @exception IndexOutOfBoundsException if either index isn't within the size range.
658 */
659 @Override
660 public E move(int targetIndex, int sourceIndex)
661 {
662 ++modCount;
663 if (targetIndex >= size)
664 throw new IndexOutOfBoundsException("targetIndex=" + targetIndex + ", size=" + size);
665
666 if (sourceIndex >= size)
667 throw new IndexOutOfBoundsException("sourceIndex=" + sourceIndex + ", size=" + size);
668
669 @SuppressWarnings("unchecked") E object = (E)data[sourceIndex];
670 if (targetIndex != sourceIndex)
671 {
672 if (targetIndex < sourceIndex)
673 {
674 System.arraycopy(data, targetIndex, data, targetIndex + 1, sourceIndex - targetIndex);
675 }
676 else
677 {
678 System.arraycopy(data, sourceIndex + 1, data, sourceIndex, targetIndex - sourceIndex);
679 }
680 assign(targetIndex, object);
681 didMove(targetIndex, object, sourceIndex);
682 didChange();
683 }
684 return object;
685 }
686
687 /**
688 * Shrinks the capacity of the list to the minimal requirements.
689 * @see #grow
690 */
691 public void shrink()
692 {
693 ++modCount;
694
695 // Conditionally create the data.
696 //
697 if (size == 0)
698 {
699 // Give it all back to the garbage collector.
700 //
701 data = null;
702 }
703 else if (size < data.length)
704 {
705 Object [] oldData = data;
706 data = newData(size);
707 System.arraycopy(oldData, 0, data, 0, size);
708 }
709 }
710
711 /**
712 * Grows the capacity of the list
713 * to ensure that no additional growth is needed until the size exceeds the specified minimum capacity.
714 * @see #shrink
715 */
716 public void grow(int minimumCapacity)
717 {
718 ++modCount;
719 int oldCapacity = data == null ? 0 : data.length;
720 if (minimumCapacity > oldCapacity)
721 {
722 Object oldData[] = data;
723
724 // This seems to be a pretty sweet formula that supports good growth.
725 // Adding an object to a list will create a list of capacity 4,
726 // which is just about the average list size.
727 //
728 int newCapacity = oldCapacity + oldCapacity / 2 + 4;
729 if (newCapacity < minimumCapacity)
730 {
731 newCapacity = minimumCapacity;
732 }
733 data = newData(newCapacity);
734 if (oldData != null)
735 {
736 System.arraycopy(oldData, 0, data, 0, size);
737 }
738 }
739 }
740
741 private synchronized void writeObject(ObjectOutputStream objectOutputStream) throws IOException
742 {
743 objectOutputStream.defaultWriteObject();
744 if (data == null)
745 {
746 objectOutputStream.writeInt(0);
747 }
748 else
749 {
750 objectOutputStream.writeInt(data.length);
751 for (int i = 0; i < size; ++i)
752 {
753 objectOutputStream.writeObject(data[i]);
754 }
755 }
756 }
757
758 private synchronized void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException
759 {
760 objectInputStream.defaultReadObject();
761 int arrayLength = objectInputStream.readInt();
762 if (arrayLength > 0)
763 {
764 try
765 {
766 data = newData(arrayLength);
767 }
768 catch (Throwable exception)
769 {
770 data = new Object[arrayLength];
771 }
772
773 for (int i = 0; i < size; ++i)
774 {
775 @SuppressWarnings("unchecked") E object = (E)objectInputStream.readObject();
776 didAdd(i, assign(i, object));
777 }
778 }
779 }
780
781 /**
782 * Returns a shallow copy of this list.
783 * @return a shallow copy of this list.
784 */
785 @Override
786 public Object clone()
787 {
788 try
789 {
790 @SuppressWarnings("unchecked") BasicEList<E> clone = (BasicEList<E>)super.clone();
791 if (size > 0)
792 {
793 clone.size = size;
794 clone.data = newData(size);
795 System.arraycopy(data, 0, clone.data, 0, size);
796 }
797 return clone;
798 }
799 catch (CloneNotSupportedException exception)
800 {
801 throw new InternalError();
802 }
803 }
804
805 /**
806 * An extensible iterator implementation.
807 * @deprecated
808 * @see AbstractEList.EIterator
809 */
810 @Deprecated
811 protected class EIterator<E1> extends AbstractEList<E>.EIterator<E1>
812 {
813 // Pointless extension
814 }
815
816 /**
817 * An extended read-only iterator that does not {@link BasicEList#resolve resolve} objects.
818 * @deprecated
819 * @see AbstractEList.NonResolvingEIterator
820 */
821 @Deprecated
822 protected class NonResolvingEIterator<E1> extends AbstractEList<E>.NonResolvingEIterator<E1>
823 {
824 // Pointless extension
825 }
826
827 /**
828 * An extensible list iterator implementation.
829 * @deprecated
830 * @see AbstractEList.EListIterator
831 */
832 @Deprecated
833 protected class EListIterator<E1> extends AbstractEList<E>.EListIterator<E1>
834 {
835 /**
836 * Creates an instance.
837 */
838 public EListIterator()
839 {
840 super();
841 }
842
843 /**
844 * Creates an instance advanced to the index.
845 * @param index the starting index.
846 */
847 public EListIterator(int index)
848 {
849 super(index);
850 cursor = index;
851 }
852 }
853
854 /**
855 * An extended read-only list iterator that does not {@link BasicEList#resolve resolve} objects.
856 * @deprecated
857 * @see AbstractEList.NonResolvingEListIterator
858 */
859 @Deprecated
860 protected class NonResolvingEListIterator<E1> extends AbstractEList<E>.NonResolvingEListIterator<E1>
861 {
862 /**
863 * Creates an instance.
864 */
865 public NonResolvingEListIterator()
866 {
867 super();
868 }
869
870 /**
871 * Creates an instance advanced to the index.
872 * @param index the starting index.
873 */
874 public NonResolvingEListIterator(int index)
875 {
876 super(index);
877 }
878 }
879
880 /**
881 * An unmodifiable version of {@link BasicEList}.
882 */
883 public static class UnmodifiableEList<E> extends BasicEList<E>
884 {
885 private static final long serialVersionUID = 1L;
886
887 /**
888 * Creates an initialized instance.
889 * @param size the size of the list.
890 * @param data the underlying storage of the list.
891 */
892 public UnmodifiableEList(int size, Object [] data)
893 {
894 this.size = size;
895 this.data = data;
896 }
897
898 /**
899 * Throws an exception.
900 * @exception UnsupportedOperationException always because it's not supported.
901 */
902 @Override
903 public E set(int index, E object)
904 {
905 throw new UnsupportedOperationException();
906 }
907
908 /**
909 * Throws an exception.
910 * @exception UnsupportedOperationException always because it's not supported.
911 */
912 @Override
913 public boolean add(E object)
914 {
915 throw new UnsupportedOperationException();
916 }
917
918 /**
919 * Throws an exception.
920 * @exception UnsupportedOperationException always because it's not supported.
921 */
922 @Override
923 public void add(int index, E object)
924 {
925 throw new UnsupportedOperationException();
926 }
927
928 /**
929 * Throws an exception.
930 * @exception UnsupportedOperationException always because it's not supported.
931 */
932 @Override
933 public boolean addAll(Collection<? extends E> collection)
934 {
935 throw new UnsupportedOperationException();
936 }
937
938 /**
939 * Throws an exception.
940 * @exception UnsupportedOperationException always because it's not supported.
941 */
942 @Override
943 public boolean addAll(int index, Collection<? extends E> collection)
944 {
945 throw new UnsupportedOperationException();
946 }
947
948 /**
949 * Throws an exception.
950 * @exception UnsupportedOperationException always because it's not supported.
951 */
952 @Override
953 public boolean remove(Object object)
954 {
955 throw new UnsupportedOperationException();
956 }
957
958 /**
959 * Throws an exception.
960 * @exception UnsupportedOperationException always because it's not supported.
961 */
962 @Override
963 public E remove(int index)
964 {
965 throw new UnsupportedOperationException();
966 }
967
968 /**
969 * Throws an exception.
970 * @exception UnsupportedOperationException always because it's not supported.
971 */
972 @Override
973 public boolean removeAll(Collection<?> collection)
974 {
975 throw new UnsupportedOperationException();
976 }
977
978 /**
979 * Throws an exception.
980 * @exception UnsupportedOperationException always because it's not supported.
981 */
982 @Override
983 public boolean retainAll(Collection<?> collection)
984 {
985 throw new UnsupportedOperationException();
986 }
987
988 /**
989 * Throws an exception.
990 * @exception UnsupportedOperationException always because it's not supported.
991 */
992 @Override
993 public void clear()
994 {
995 throw new UnsupportedOperationException();
996 }
997
998 /**
999 * Throws an exception.
1000 * @exception UnsupportedOperationException always because it's not supported.
1001 */
1002 @Override
1003 public void move(int index, E object)
1004 {
1005 throw new UnsupportedOperationException();
1006 }
1007
1008 /**
1009 * Throws an exception.
1010 * @exception UnsupportedOperationException always because it's not supported.
1011 */
1012 @Override
1013 public E move(int targetIndex, int sourceIndex)
1014 {
1015 throw new UnsupportedOperationException();
1016 }
1017
1018 /**
1019 * Throws an exception.
1020 * @exception UnsupportedOperationException always because it's not supported.
1021 */
1022 @Override
1023 public void shrink()
1024 {
1025 throw new UnsupportedOperationException();
1026 }
1027
1028 /**
1029 * Throws an exception.
1030 * @exception UnsupportedOperationException always because it's not supported.
1031 */
1032 @Override
1033 public void grow(int minimumCapacity)
1034 {
1035 throw new UnsupportedOperationException();
1036 }
1037
1038 /**
1039 * Returns the {@link BasicEList#basicIterator basic iterator}.
1040 * @return the basic iterator.
1041 */
1042 @Override
1043 public Iterator<E> iterator()
1044 {
1045 return basicIterator();
1046 }
1047
1048 /**
1049 * Returns the {@link #basicListIterator() basic list iterator}.
1050 * @return the basic list iterator.
1051 */
1052 @Override
1053 public ListIterator<E> listIterator()
1054 {
1055 return basicListIterator();
1056 }
1057
1058 /**
1059 * Returns the {@link #basicListIterator(int) basic list iterator} advanced to the index.
1060 * @param index the starting index.
1061 * @return the basic list iterator.
1062 */
1063 @Override
1064 public ListIterator<E> listIterator(int index)
1065 {
1066 return basicListIterator(index);
1067 }
1068 }
1069
1070 /**
1071 * Returns an <b>unsafe</b> list that provides a {@link #resolve non-resolving} view of the underlying data storage.
1072 * @return an <b>unsafe</b> list that provides a non-resolving view of the underlying data storage.
1073 */
1074 @Override
1075 protected List<E> basicList()
1076 {
1077 if (size == 0)
1078 {
1079 return ECollections.emptyEList();
1080 }
1081 else
1082 {
1083 return new UnmodifiableEList<E>(size, data);
1084 }
1085 }
1086
1087 /**
1088 * A <code>BasicEList</code> that {@link #useEquals uses} <code>==</code> instead of <code>equals</code> to compare members.
1089 */
1090 public static class FastCompare<E> extends BasicEList<E>
1091 {
1092 private static final long serialVersionUID = 1L;
1093
1094 /**
1095 * Creates an empty instance with no initial capacity.
1096 */
1097 public FastCompare()
1098 {
1099 super();
1100 }
1101
1102 /**
1103 * Creates an empty instance with the given capacity.
1104 * @param initialCapacity the initial capacity of the list before it must grow.
1105 * @exception IllegalArgumentException if the <code>initialCapacity</code> is negative.
1106 */
1107 public FastCompare(int initialCapacity)
1108 {
1109 super(initialCapacity);
1110 }
1111
1112 /**
1113 * Creates an instance that is a copy of the collection.
1114 * @param collection the initial contents of the list.
1115 */
1116 public FastCompare(Collection<? extends E> collection)
1117 {
1118 super(collection.size());
1119 addAll(collection);
1120 }
1121
1122 /**
1123 * Returns <code>false</code> because this list uses <code>==</code>.
1124 * @return <code>false</code>.
1125 */
1126 @Override
1127 protected boolean useEquals()
1128 {
1129 return false;
1130 }
1131 }
1132 }