KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > emf > common > util > BasicEList


1 /**
2  * <copyright>
3  *
4  * Copyright (c) 2002-2004 IBM Corporation and others.
5  * All rights reserved. This program and the accompanying materials
6  * are made available under the terms of the Eclipse Public License v1.0
7  * which accompanies this distribution, and is available at
8  * http://www.eclipse.org/legal/epl-v10.html
9  *
10  * Contributors:
11  * IBM - Initial API and implementation
12  *
13  * </copyright>
14  *
15  * $Id: BasicEList.java,v 1.10 2005/06/12 13:24:00 emerks Exp $
16  */

17 package org.eclipse.emf.common.util;
18
19
20 import java.io.IOException JavaDoc;
21 import java.io.ObjectInputStream JavaDoc;
22 import java.io.ObjectOutputStream JavaDoc;
23 import java.io.Serializable JavaDoc;
24 import java.lang.reflect.Array JavaDoc;
25 import java.util.AbstractList JavaDoc;
26 import java.util.Collection JavaDoc;
27 import java.util.ConcurrentModificationException JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.ListIterator JavaDoc;
31 import java.util.NoSuchElementException JavaDoc;
32
33
34 /**
35  * A highly extensible list implementation.
36  */

37 public class BasicEList extends AbstractList JavaDoc implements EList, Cloneable JavaDoc, Serializable JavaDoc
38 {
39   /**
40    * The size of the list.
41    */

42   protected int size;
43
44   /**
45    * The underlying data storage of the list.
46    */

47   protected transient Object JavaDoc data[];
48
49   /**
50    * Creates an empty instance with no initial capacity.
51    * The data storage will be null.
52    */

53   public BasicEList()
54   {
55   }
56
57   /**
58    * Creates an empty instance with the given capacity.
59    * @param initialCapacity the initial capacity of the list before it must grow.
60    * @exception IllegalArgumentException if the <code>initialCapacity</code> is negative.
61    */

62   public BasicEList(int initialCapacity)
63   {
64     if (initialCapacity < 0)
65     {
66       throw new IllegalArgumentException JavaDoc("Illegal Capacity: " + initialCapacity);
67     }
68
69     data = newData(initialCapacity);
70   }
71
72   /**
73    * Creates an instance that is a copy of the collection.
74    * @param collection the initial contents of the list.
75    */

76   public BasicEList(Collection JavaDoc collection)
77   {
78     size = collection.size();
79
80     // Conditionally create the data.
81
//
82
if (size > 0)
83     {
84       // Allow for a bit-shift of growth.
85
//
86
data = newData(size + size / 8 + 1);
87       collection.toArray(data);
88     }
89   }
90
91   /**
92    * Creates an initialized instance that directly uses the given arguments.
93    * @param size the size of the list.
94    * @param data the underlying storage of the list.
95    */

96   protected BasicEList(int size, Object JavaDoc [] data)
97   {
98     this.size = size;
99     this.data = data;
100   }
101
102   /**
103    * Returns new allocated data storage.
104    * Clients may override this to create typed storage.
105    * The cost of type checking via a typed array is negligable.
106    * @return new data storage.
107    */

108   protected Object JavaDoc [] newData(int capacity)
109   {
110     return new Object JavaDoc [capacity];
111   }
112
113   /**
114    * Returns whether <code>equals</code> rather than <code>==</code> should be used to compare members.
115    * The default is to return <code>true</code> but clients can optimize performance by returning <code>false</code>.
116    * The performance difference is highly significant.
117    * @return whether <code>equals</code> rather than <code>==</code> should be used.
118    */

119   protected boolean useEquals()
120   {
121     return true;
122   }
123
124   /**
125    * Returns whether two objects are equal using the {@link #useEquals appropriate} comparison mechanism.
126    * @return whether two objects are equal.
127    */

128   protected boolean equalObjects(Object JavaDoc firstObject, Object JavaDoc secondObject)
129   {
130     return
131       useEquals() && firstObject != null ?
132         firstObject.equals(secondObject) :
133         firstObject == secondObject;
134   }
135
136   /**
137    * Returns whether <code>null</code> is a valid object for the list.
138    * The default is to return <code>true</code>, but clients can override this to exclude <code>null</code>.
139    * @return whether <code>null</code> is a valid object for the list.
140    */

141   protected boolean canContainNull()
142   {
143     return true;
144   }
145
146   /**
147    * Returns whether objects are constrained to appear at most once in the list.
148    * The default is to return <code>false</code>, but clients can override this to ensure uniqueness of contents.
149    * The performance impact is signifcant: operations such as <code>add</code> are O(n) as a result requiring uniqueness.
150    * @return whether objects are constrained to appear at most once in the list.
151    */

152   protected boolean isUnique()
153   {
154     return false;
155   }
156
157   /**
158    * Validates a new content object and returns the validated object.
159    * This implementation checks for null, if {@link #canContainNull necessary} and returns the argument object.
160    * Clients may throw additional types of runtime exceptions
161    * in order to handle constraint violations.
162    * @param index the position of the new content.
163    * @param object the new content.
164    * @return the validated content.
165    * @exception IllegalArgumentException if a constraint prevents the object from being added.
166    */

167   protected Object JavaDoc validate(int index, Object JavaDoc object)
168   {
169     if (!canContainNull() && object == null)
170     {
171       throw new IllegalArgumentException JavaDoc("The 'no null' constraint is violated");
172     }
173
174     return object;
175   }
176
177   /**
178    * Assigns the object into the data storage at the given index and returns the object that's been stored.
179    * Clients can monitor access to the storage via this method.
180    * @param index the position of the new content.
181    * @param object the new content.
182    * @return the object that's been stored.
183    *
184    */

185   protected Object JavaDoc assign(int index, Object JavaDoc object)
186   {
187     return data[index] = object;
188   }
189
190   /**
191    * Resolves the object at the index and returns the result.
192    * This implementation simply returns the <code>object</code>;
193    * clients can use this to transform objects as they are fetched.
194    * @param index the position of the content.
195    * @param object the content.
196    * @return the resolved object.
197    */

198   protected Object JavaDoc resolve(int index, Object JavaDoc object)
199   {
200     return object;
201   }
202
203   /**
204    * Called to indicate that the data storage has been set.
205    * This implementation does nothing;
206    * clients can use this to monitor settings to the data storage.
207    * @param index the position that was set.
208    * @param newObject the new object at the position.
209    * @param oldObject the old object at the position.
210    */

211   protected void didSet(int index, Object JavaDoc newObject, Object JavaDoc oldObject)
212   {
213   }
214
215   /**
216    * Called to indicate that an object has been added to the data storage.
217    * This implementation does nothing;
218    * clients can use this to monitor additions to the data storage.
219    * @param index the position object the new object.
220    * @param newObject the new object at the position.
221    */

222   protected void didAdd(int index, Object JavaDoc newObject)
223   {
224   }
225
226   /**
227    * Called to indicate that an object has been removed from the data storage.
228    * This implementation does nothing;
229    * clients can use this to monitor removals from the data storage.
230    * @param index the position of the old object.
231    * @param oldObject the old object at the position.
232    */

233   protected void didRemove(int index, Object JavaDoc oldObject)
234   {
235   }
236
237   /**
238    * Called to indicate that the data storage has been cleared.
239    * This implementation calls {@link #didRemove didRemove} for each object;
240    * clients can use this to monitor clearing of the data storage.
241    * @param size the original size of the list.
242    * @param oldObjects the old data storage being discarded.
243    * @see #didRemove
244    */

245   protected void didClear(int size, Object JavaDoc [] 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   /**
257    * Called to indicate that an object has been moved in the data storage.
258    * This implementation does nothing;
259    * clients can use this to monitor movement in the data storage.
260    * @param index the position of the moved object.
261    * @param movedObject the moved object at the position.
262    * @param oldIndex the position the object was at before the move.
263    */

264   protected void didMove(int index, Object JavaDoc movedObject, int oldIndex)
265   {
266   }
267
268   /**
269    * Called to indicate that the data storage has been changed.
270    * This implementation does nothing;
271    * clients can use this to monitor change in the data storage.
272    */

273   protected void didChange()
274   {
275   }
276
277   /**
278    * Returns the number of objects in the list.
279    * @return the number of objects in the list.
280    */

281   public int size()
282   {
283     return size;
284   }
285
286   /**
287    * Returns whether the list has zero size.
288    * @return whether the list has zero size.
289    */

290   public boolean isEmpty()
291   {
292     return size == 0;
293   }
294
295   /**
296    * Returns whether the list contains the object.
297    * This implementation uses either <code>equals</code> or <code>"=="</code> depending on {@link #useEquals useEquals}.
298    * @param object the object in question.
299    * @return whether the list contains the object.
300    * @see #useEquals
301    */

302   public boolean contains(Object JavaDoc 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   /**
329    * Returns whether the list contains each object in the collection.
330    * This implementation delegates to {@link #contains contains},
331    * which may use either <code>equals</code> or <code>"=="</code> depending on {@link #useEquals useEquals}.
332    * @param collection the collection of objects in question.
333    * @return whether the list contains each object in the collection.
334    * @see #contains
335    * @see #useEquals
336    */

337   public boolean containsAll(Collection JavaDoc collection)
338   {
339     for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
340     {
341       if (!contains(i.next()))
342       {
343         return false;
344       }
345     }
346
347     return true;
348   }
349
350   /**
351    * Returns the position of the first occurrence of the object in the list.
352    * This implementation uses either <code>equals</code> or <code>"=="</code> depending on {@link #useEquals useEquals}.
353    * @param object the object in question.
354    * @return the position of the first occurrence of the object in the list.
355    */

356   public int indexOf(Object JavaDoc 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   /**
382    * Returns the position of the last occurrence of the object in the list.
383    * This implementation uses either <code>equals</code> or <code>"=="</code> depending on {@link #useEquals useEquals}.
384    * @param object the object in question.
385    * @return the position of the last occurrence of the object in the list.
386    */

387   public int lastIndexOf(Object JavaDoc 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   /**
413    * Returns an array containing all the objects in sequence.
414    * Clients may override {@link #newData newData} to create typed storage in this case.
415    * @return an array containing all the objects in sequence.
416    * @see #newData
417    */

418   public Object JavaDoc[] toArray()
419   {
420     Object JavaDoc[] result = newData(size);
421
422     // Guard for no data.
423
//
424
if (size > 0)
425     {
426       System.arraycopy(data, 0, result, 0, size);
427     }
428     return result;
429   }
430
431   /**
432    * Returns an array containing all the objects in sequence.
433    * @param array the array that will be filled and returned, if it's big enough;
434    * otherwise, a suitably large array of the same type will be allocated and used instead.
435    * @return an array containing all the objects in sequence.
436    * @see #newData
437    */

438   public Object JavaDoc[] toArray(Object JavaDoc array[])
439   {
440     // Guard for no data.
441
//
442
if (size > 0)
443     {
444       if (array.length < size)
445       {
446         array = (Object JavaDoc[])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   /**
461    * Returns direct <b>unsafe</b> access to the underlying data storage.
462    * Clients may <b>not</b> modify this
463    * and may <b>not</b> assume that the array remains valid as the list is modified.
464    * @return direct <b>unsafe</b> access to the underlying data storage.
465    */

466   public Object JavaDoc [] data()
467   {
468     return data;
469   }
470
471   /**
472    * Updates directly and <b>unsafely</b> the underlying data storage.
473    * Clients <b>must</b> be aware that this subverts all callbacks
474    * and hence possibly the integrity of the list.
475    */

476   public void setData(int size, Object JavaDoc [] data)
477   {
478     this.size = size;
479     this.data = data;
480     ++modCount;
481   }
482
483   /**
484    * An IndexOutOfBoundsException that constructs a message from the argument data.
485    * Having this avoids having the byte code that computes the message repeated/inlined at the creation site.
486    */

487   protected static class BasicIndexOutOfBoundsException extends IndexOutOfBoundsException JavaDoc
488   {
489     /**
490      * Constructs an instance with a message based on the arguments.
491      */

492     public BasicIndexOutOfBoundsException(int index, int size)
493     {
494       super("index=" + index + ", size=" + size);
495     }
496   }
497   
498   /**
499    * Returns the object at the index.
500    * This implementation delegates to {@link #resolve resolve}
501    * so that clients may transform the fetched object.
502    * @param index the position in question.
503    * @return the object at the index.
504    * @exception IndexOutOfBoundsException if the index isn't within the size range.
505    * @see #resolve
506    * @see #basicGet
507    */

508   public Object JavaDoc get(int index)
509   {
510     if (index >= size)
511       throw new BasicIndexOutOfBoundsException(index, size);
512
513     return resolve(index, data[index]);
514   }
515
516   /**
517    * Returns the object at the index without {@link #resolve resolving} it.
518    * @param index the position in question.
519    * @return the object at the index.
520    * @exception IndexOutOfBoundsException if the index isn't within the size range.
521    * @see #resolve
522    * @see #get
523    */

524   public Object JavaDoc basicGet(int index)
525   {
526     if (index >= size)
527       throw new BasicIndexOutOfBoundsException(index, size);
528
529     return data[index];
530   }
531
532   /**
533    * Sets the object at the index
534    * and returns the old object at the index.
535    * This implementation delegates to {@link #setUnique setUnique}
536    * after range checking and after {@link #isUnique uniqueness} checking.
537    * @param index the position in question.
538    * @param object the object to set.
539    * @return the old object at the index.
540    * @exception IndexOutOfBoundsException if the index isn't within the size range.
541    * @exception IllegalArgumentException if there is a constraint violation, e.g., non-uniqueness.
542    * @see #setUnique
543    */

544   public Object JavaDoc set(int index, Object JavaDoc 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 JavaDoc("The 'no duplicates' constraint is violated");
555       }
556     }
557
558     return setUnique(index, object);
559   }
560
561   /**
562    * Sets the object at the index
563    * and returns the old object at the index;
564    * it does no ranging checking or uniqueness checking.
565    * This implementation delegates to {@link #assign assign}, {@link #didSet didSet}, and {@link #didChange didChange}.
566    * @param index the position in question.
567    * @param object the object to set.
568    * @return the old object at the index.
569    * @see #set
570    */

571   public Object JavaDoc setUnique(int index, Object JavaDoc object)
572   {
573     Object JavaDoc oldObject = data[index];
574     assign(index, validate(index, object));
575     didSet(index, object, oldObject);
576     didChange();
577     return oldObject;
578   }
579
580   /**
581    * Adds the object at the end of the list
582    * and returns whether the object was added;
583    * if {@link #isUnique uniqueness} is required,
584    * duplicates will be ignored and <code>false</code> will be returned.
585    * This implementation delegates to {@link #addUnique(Object) addUnique(Object)}
586    * after uniqueness checking.
587    * @param object the object to be added.
588    * @return whether the object was added.
589    * @see #addUnique(Object)
590    */

591   public boolean add(Object JavaDoc 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   /**
605    * Adds the object at the end of the list;
606    * it does no uniqueness checking.
607    * This implementation delegates to {@link #assign assign}, {@link #didAdd didAdd}, and {@link #didChange didChange}.
608    * after uniqueness checking.
609    * @param object the object to be added.
610    * @see #add(Object)
611    */

612   public void addUnique(Object JavaDoc object)
613   {
614     // ++modCount
615
//
616
grow(size + 1);
617
618     assign(size, validate(size, object));
619     didAdd(size++, object);
620     didChange();
621   }
622
623   /**
624    * Adds the object at the given index in the list.
625    * If {@link #isUnique uniqueness} is required,
626    * duplicates will be ignored.
627    * This implementation delegates to {@link #addUnique(int, Object) addUnique(int, Object)}
628    * after uniqueness checking.
629    * @param object the object to be added.
630    * @exception IllegalArgumentException if {@link #isUnique uniqueness} is required,
631    * and the object is a duplicate.
632    * @see #addUnique(int, Object)
633    */

634   public void add(int index, Object JavaDoc object)
635   {
636     if (index > size)
637       throw new BasicIndexOutOfBoundsException(index, size);
638
639     if (isUnique() && contains(object))
640     {
641       throw new IllegalArgumentException JavaDoc("The 'no duplicates' constraint is violated");
642     }
643
644     addUnique(index, object);
645   }
646
647   /**
648    * Adds the object at the given index in the list;
649    * it does no ranging checking or uniqueness checking.
650    * This implementation delegates to {@link #assign assign}, {@link #didAdd didAdd}, and {@link #didChange didChange}.
651    * @param object the object to be added.
652    * @see #add(int, Object)
653    */

654   public void addUnique(int index, Object JavaDoc object)
655   {
656     // ++modCount
657
//
658
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   /**
671    * Adds each object of the collection to the end of the list.
672    * If {@link #isUnique uniqueness} is required,
673    * duplicates will be {@link #getNonDuplicates removed} from the collection,
674    * which could even result in an empty collection.
675    * This implementation delegates to {@link #addAllUnique(Collection) addAllUnique(Collection)}
676    * after uniqueness checking.
677    * @param collection the collection of objects to be added.
678    * @see #addAllUnique(Collection)
679    */

680   public boolean addAll(Collection JavaDoc collection)
681   {
682     if (isUnique())
683     {
684        collection = getNonDuplicates(collection);
685     }
686     return addAllUnique(collection);
687   }
688
689   /**
690    * Adds each object of the collection to the end of the list;
691    * it does no uniqueness checking.
692    * This implementation delegates to {@link #assign assign}, {@link #didAdd didAdd}, and {@link #didChange didChange}.
693    * @param collection the collection of objects to be added.
694    * @see #addAll(Collection)
695    */

696   public boolean addAllUnique(Collection JavaDoc collection)
697   {
698     int growth = collection.size();
699
700     // ++modCount
701
//
702
grow(size + growth);
703
704     Iterator JavaDoc objects = collection.iterator();
705     int oldSize = size;
706     size += growth;
707     for (int i = oldSize; i < size; ++i)
708     {
709       Object JavaDoc object = objects.next();
710       assign(i, validate(i, object));
711       didAdd(i, object);
712       didChange();
713     }
714
715     return growth != 0;
716   }
717
718   /**
719    * Adds each object of the collection at each successive index in the list
720    * and returns whether any objects were added.
721    * If {@link #isUnique uniqueness} is required,
722    * duplicates will be {@link #getNonDuplicates removed} from the collection,
723    * which could even result in an empty collection.
724    * This implementation delegates to {@link #addAllUnique(int, Collection) addAllUnique(int, Collection)}
725    * after uniqueness checking.
726    * @param index the index at which to add.
727    * @param collection the collection of objects to be added.
728    * @return whether any objects were added.
729    * @see #addAllUnique(int, Collection)
730    */

731   public boolean addAll(int index, Collection JavaDoc 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   /**
744    * Adds each object of the collection at each successive index in the list
745    * and returns whether any objects were added;
746    * it does no ranging checking or uniqueness checking.
747    * This implementation delegates to {@link #assign assign}, {@link #didAdd didAdd}, and {@link #didChange didChange}.
748    * @param index the index at which to add.
749    * @param collection the collection of objects to be added.
750    * @return whether any objects were added.
751    * @see #addAll(int, Collection)
752    */

753   public boolean addAllUnique(int index, Collection JavaDoc collection)
754   {
755     int growth = collection.size();
756
757     // ++modCount
758
//
759
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 JavaDoc objects = collection.iterator();
768     size += growth;
769     for (int i = 0; i < growth; ++i)
770     {
771       Object JavaDoc 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   /**
782    * Removes the object from the list and returns whether the object was actually contained by the list.
783    * This implementation uses {@link #indexOf indexOf} to find the object
784    * and delegates to {@link #remove(int) remove(int)}
785    * in the case that it finds the object.
786    * @param object the object to be removed.
787    * @return whether the object was actually contained by the list.
788    */

789   public boolean remove(Object JavaDoc 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   /**
804    * Removes each object of the collection from the list and returns whether any object was actually contained by the list.
805    * @param collection the collection of objects to be removed.
806    * @return whether any object was actually contained by the list.
807    */

808   public boolean removeAll(Collection JavaDoc 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   /**
824    * Removes the object at the index from the list and returns it.
825    * This implementation delegates to {@link #didRemove didRemove} and {@link #didChange didChange}.
826    * @param index the position of the object to remove.
827    * @return the removed object.
828    * @exception IndexOutOfBoundsException if the index isn't within the size range.
829    */

830   public Object JavaDoc remove(int index)
831   {
832     if (index >= size)
833       throw new BasicIndexOutOfBoundsException(index, size);
834
835     ++modCount;
836     Object JavaDoc 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     // Don't hold onto a duplicate reference to the last object.
845
//
846
data[--size] = null;
847     didRemove(index, oldObject);
848     didChange();
849
850     return oldObject;
851   }
852
853   /**
854    * Removes from the list each object not contained by the collection
855    * and returns whether any object was actually removed.
856    * This delegates to {@link #remove(int) remove(int)}
857    * in the case that it finds an object that isn't retained.
858    * @param collection the collection of objects to be retained.
859    * @return whether any object was actually removed.
860    */

861   public boolean retainAll(Collection JavaDoc 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   /**
876    * Clears the list of all objects.
877    * This implementation discards the data storage without modifying it
878    * and delegates to {@link #didClear didClear} and {@link #didChange didChange}.
879    */

880   public void clear()
881   {
882     ++modCount;
883
884     Object JavaDoc [] oldData = data;
885     int oldSize = size;
886
887     // Give it all back to the garbage collector.
888
//
889
data = null;
890     size = 0;
891
892     didClear(oldSize, oldData);
893     didChange();
894   }
895
896   /**
897    * Moves the object to the index of the list.
898    * This implementation uses {@link #indexOf} of find the object
899    * and delegates to {@link #move(int, int) move(int, int)}.
900    * @param index the new position for the object in the list.
901    * @param object the object to be moved.
902    * @exception IndexOutOfBoundsException if the index isn't within the size range or the object isn't contained by the list.
903    */

904   public void move(int index, Object JavaDoc object)
905   {
906     move(index, indexOf(object));
907   }
908
909   /**
910    * Moves the object at the source index of the list to the target index of the list
911    * and returns the moved object.
912    * This implementation delegates to {@link #assign assign}, {@link #didMove didMove}, and {@link #didChange didChange}.
913    * @param targetIndex the new position for the object in the list.
914    * @param sourceIndex the old position of the object in the list.
915    * @return the moved object.
916    * @exception IndexOutOfBoundsException if either index isn't within the size range.
917    */

918   public Object JavaDoc move(int targetIndex, int sourceIndex)
919   {
920     ++modCount;
921     if (targetIndex >= size)
922       throw new IndexOutOfBoundsException JavaDoc("targetIndex=" + targetIndex + ", size=" + size);
923
924     if (sourceIndex >= size)
925       throw new IndexOutOfBoundsException JavaDoc("sourceIndex=" + sourceIndex + ", size=" + size);
926
927     Object JavaDoc 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   /**
946    * Shrinks the capacity of the list to the minimal requirements.
947    * @see #grow
948    */

949   public void shrink()
950   {
951     ++modCount;
952
953     // Conditionally create the data.
954
//
955
if (size == 0)
956     {
957       // Give it all back to the garbage collector.
958
//
959
data = null;
960     }
961     else if (size < data.length)
962     {
963       Object JavaDoc [] oldData = data;
964       data = newData(size);
965       System.arraycopy(oldData, 0, data, 0, size);
966     }
967   }
968
969   /**
970    * Grows the capacity of the list
971    * to ensure that no additional growth is needed until the size exceeds the specified minimun capacity.
972    * @see #shrink
973    */

974   public void grow(int minimumCapacity)
975   {
976     ++modCount;
977     int oldCapacity = data == null ? 0 : data.length;
978     if (minimumCapacity > oldCapacity)
979     {
980       Object JavaDoc oldData[] = data;
981
982       // This seems to be a pretty sweet formula that supports good growth.
983
// Adding an object to a list will create a list of capacity 4,
984
// which is just about the average list size.
985
//
986
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 JavaDoc objectOutputStream) throws IOException JavaDoc
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 JavaDoc objectInputStream) throws IOException JavaDoc, ClassNotFoundException JavaDoc
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 JavaDoc exception)
1027      {
1028        data = new Object JavaDoc[arrayLength];
1029      }
1030
1031      for (int i = 0; i < size; ++i)
1032      {
1033        didAdd(i, assign(i, objectInputStream.readObject()));
1034      }
1035    }
1036  }
1037
1038  /**
1039   * Returns a shallow copy of this list.
1040   * @return a shallow copy of this list.
1041   */

1042  public Object JavaDoc 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 JavaDoc exception)
1056    {
1057      throw new InternalError JavaDoc();
1058    }
1059  }
1060
1061  /**
1062   * Returns whether the object is a list with corresponding equal objects.
1063   * This implementation uses either <code>equals</code> or <code>"=="</code> depending on {@link #useEquals useEquals}.
1064   * @return whether the object is a list with corresponding equal objects.
1065   * @see #useEquals
1066   */

1067  public boolean equals(Object JavaDoc object)
1068  {
1069    if (object == this)
1070    {
1071      return true;
1072    }
1073
1074    if (!(object instanceof List JavaDoc))
1075    {
1076      return false;
1077    }
1078
1079    List JavaDoc list = (List JavaDoc)object;
1080    if (list.size() != size)
1081    {
1082      return false;
1083    }
1084
1085    Iterator JavaDoc objects = ((List JavaDoc)object).iterator();
1086    if (useEquals())
1087    {
1088      for (int i = 0; i < size; ++i)
1089      {
1090        Object JavaDoc o1 = data[i];
1091        Object JavaDoc o2 = objects.next();
1092        if (o1 == null ? o2 != null : !o1.equals(o2))
1093        {
1094          return false;
1095        }
1096      }
1097    }
1098    else
1099    {
1100      for (int i = 0; i < size; ++i)
1101      {
1102        Object JavaDoc o1 = data[i];
1103        Object JavaDoc o2 = objects.next();
1104        if (o1 != o2)
1105        {
1106          return false;
1107        }
1108      }
1109    }
1110
1111    return true;
1112  }
1113
1114  /**
1115   * Returns a hash code computed from each object's hash code.
1116   * @return a hash code.
1117   */

1118  public int hashCode()
1119  {
1120    int hashCode = 1;
1121    for (int i = 0; i < size; ++i)
1122    {
1123      Object JavaDoc object = data[i];
1124      hashCode = 31 * hashCode + (object == null ? 0 : object.hashCode());
1125    }
1126    return hashCode;
1127  }
1128
1129  /**
1130   * Returns a string of the form <code>"[object1, object2]"</code>.
1131   * @return a string of the form <code>"[object1, object2]"</code>.
1132   */

1133  public String JavaDoc toString()
1134  {
1135    StringBuffer JavaDoc stringBuffer = new StringBuffer JavaDoc();
1136    stringBuffer.append("[");
1137    for (int i = 0; i < size; )
1138    {
1139      stringBuffer.append(String.valueOf(data[i]));
1140      if (++i < size)
1141      {
1142        stringBuffer.append(", ");
1143      }
1144    }
1145    stringBuffer.append("]");
1146    return stringBuffer.toString();
1147  }
1148
1149  /**
1150   * Returns an iterator.
1151   * This implementation allocates a {@link BasicEList.EIterator}.
1152   * @return an iterator.
1153   * @see BasicEList.EIterator
1154   */

1155  public Iterator JavaDoc iterator()
1156  {
1157    return new EIterator();
1158  }
1159
1160  /**
1161   * An extensible iterator implementation.
1162   */

1163  protected class EIterator implements Iterator JavaDoc
1164  {
1165    /**
1166     * The current position of the iterator.
1167     */

1168    protected int cursor = 0;
1169
1170    /**
1171     * The previous position of the iterator.
1172     */

1173    protected int lastCursor = -1;
1174
1175    /**
1176     * The modification count of the containing list.
1177     */

1178    protected int expectedModCount = modCount;
1179
1180    /**
1181     * Returns whether there are more objects.
1182     * @return whether there are more objects.
1183     */

1184    public boolean hasNext()
1185    {
1186      return cursor != size();
1187    }
1188
1189    /**
1190     * Returns the next object and advances the iterator.
1191     * This implementation delegates to {@link BasicEList#get get}.
1192     * @return the next object.
1193     * @exception NoSuchElementException if the iterator is done.
1194     */

1195    public Object JavaDoc next()
1196    {
1197      try
1198      {
1199        Object JavaDoc next = BasicEList.this.get(cursor);
1200        checkModCount();
1201        lastCursor = cursor++;
1202        return next;
1203      }
1204      catch (IndexOutOfBoundsException JavaDoc exception)
1205      {
1206        checkModCount();
1207        throw new NoSuchElementException JavaDoc();
1208      }
1209    }
1210
1211    /**
1212     * Removes the last object returned by {@link #next()} from the list,
1213     * it's an optional operation.
1214     * This implementation can also function in a list iterator
1215     * to act upon on the object returned by calling <code>previous</code>.
1216     * @exception IllegalStateException
1217     * if <code>next</code> has not yet been called,
1218     * or <code>remove</code> has already been called after the last call to <code>next</code>.
1219     */

1220    public void remove()
1221    {
1222      if (lastCursor == -1)
1223      {
1224        throw new IllegalStateException JavaDoc();
1225      }
1226      checkModCount();
1227
1228      try
1229      {
1230        BasicEList.this.remove(lastCursor);
1231        expectedModCount = modCount;
1232        if (lastCursor < cursor)
1233        {
1234          --cursor;
1235        }
1236        lastCursor = -1;
1237      }
1238      catch (IndexOutOfBoundsException JavaDoc exception)
1239      {
1240        throw new ConcurrentModificationException JavaDoc();
1241      }
1242    }
1243
1244    /**
1245     * Checks that the modification count is as expected.
1246     * @exception ConcurrentModificationException if the modification count is not as expected.
1247     */

1248    protected void checkModCount()
1249    {
1250      if (modCount != expectedModCount)
1251      {
1252        throw new ConcurrentModificationException JavaDoc();
1253      }
1254    }
1255  }
1256
1257  /**
1258   * Returns a read-only iterator that does not {@link #resolve resolve} objects.
1259   * This implementation allocates a {@link NonResolvingEIterator}.
1260   * @return a read-only iterator that does not resolve objects.
1261   */

1262  protected Iterator JavaDoc basicIterator()
1263  {
1264    return new NonResolvingEIterator();
1265  }
1266
1267  /**
1268   * An extended read-only iterator that does not {@link #resolve resolve} objects.
1269   */

1270  protected class NonResolvingEIterator extends EIterator
1271  {
1272    /**
1273     * Returns the next object and advances the iterator.
1274     * This implementation accesses the data storage directly.
1275     * @return the next object.
1276     * @exception NoSuchElementException if the iterator is done.
1277     */

1278    public Object JavaDoc next()
1279    {
1280      try
1281      {
1282        Object JavaDoc next = BasicEList.this.data[cursor];
1283        checkModCount();
1284        lastCursor = cursor++;
1285        return next;
1286      }
1287      catch (IndexOutOfBoundsException JavaDoc exception)
1288      {
1289        checkModCount();
1290        throw new NoSuchElementException JavaDoc();
1291      }
1292    }
1293
1294    /**
1295     * Throws and exception.
1296     * @exception UnsupportedOperationException always because it's not supported.
1297     */

1298    public void remove()
1299    {
1300      throw new UnsupportedOperationException JavaDoc();
1301    }
1302  }
1303
1304  /**
1305   * Returns a list iterator.
1306   * This implementation allocates a {@link BasicEList.EListIterator}.
1307   * @return a list iterator.
1308   * @see BasicEList.EListIterator
1309   */

1310  public ListIterator JavaDoc listIterator()
1311  {
1312    return new EListIterator();
1313  }
1314
1315  /**
1316   * Returns a list iterator advanced to the given index.
1317   * This implementation allocates a {@link BasicEList.EListIterator}.
1318   * @param index the starting index.
1319   * @return a list iterator advanced to the index.
1320   * @see BasicEList.EListIterator
1321   * @exception IndexOutOfBoundsException if the index isn't within the size range.
1322   */

1323  public ListIterator JavaDoc listIterator(int index)
1324  {
1325    if (index < 0 || index > size())
1326      throw new BasicIndexOutOfBoundsException(index, size);
1327
1328    return new EListIterator(index);
1329  }
1330
1331  /**
1332   * An extensible list iterator implementation.
1333   */

1334  protected class EListIterator extends EIterator implements ListIterator JavaDoc
1335  {
1336    /**
1337     * Creates an instance.
1338     */

1339    public EListIterator()
1340    {
1341    }
1342
1343    /**
1344     * Creates an instance advanced to the index.
1345     * @param index the starting index.
1346     */

1347    public EListIterator(int index)
1348    {
1349      cursor = index;
1350    }
1351
1352    /**
1353     * Returns whether there are more objects for {@link #previous}.
1354     * Returns whether there are more objects.
1355     */

1356    public boolean hasPrevious()
1357    {
1358      return cursor != 0;
1359    }
1360
1361    /**
1362     * Returns the previous object and advances the iterator.
1363     * This implementation delegates to {@link BasicEList#get get}.
1364     * @return the previous object.
1365     * @exception NoSuchElementException if the iterator is done.
1366     */

1367    public Object JavaDoc previous()
1368    {
1369      try
1370      {
1371        Object JavaDoc previous = BasicEList.this.get(--cursor);
1372        checkModCount();
1373        lastCursor = cursor;
1374        return previous;
1375      }
1376      catch (IndexOutOfBoundsException JavaDoc exception)
1377      {
1378        checkModCount();
1379        throw new NoSuchElementException JavaDoc();
1380      }
1381    }
1382
1383    /**
1384     * Returns the index of the object that would be returned by calling {@link #next next}.
1385     * @return the index of the object that would be returned by calling <code>next</code>.
1386     */

1387    public int nextIndex()
1388    {
1389      return cursor;
1390    }
1391
1392    /**
1393     * Returns the index of the object that would be returned by calling {@link #previous previous}.
1394     * @return the index of the object that would be returned by calling <code>previous</code>.
1395     */

1396    public int previousIndex()
1397    {
1398      return cursor - 1;
1399    }
1400
1401    /**
1402     * Sets the object at the index of the last call to {@link #next next} or {@link #previous previous}.
1403     * This implementation delegates to {@link BasicEList#set set}.
1404     * @param object the object to set.
1405     * @exception IllegalStateException
1406     * if <code>next</code> or <code>previous</code> have not yet been called,
1407     * or {@link #remove remove} or {@link #add add} have already been called
1408     * after the last call to <code>next</code> or <code>previous</code>.
1409     */

1410    public void set(Object JavaDoc object)
1411    {
1412      if (lastCursor == -1)
1413      {
1414        throw new IllegalStateException JavaDoc();
1415      }
1416      checkModCount();
1417
1418      try
1419      {
1420        BasicEList.this.set(lastCursor, object);
1421      }
1422      catch (IndexOutOfBoundsException JavaDoc exception)
1423      {
1424        throw new ConcurrentModificationException JavaDoc();
1425      }
1426    }
1427
1428    /**
1429     * Adds the object at the {@link #next next} index and advances the iterator past it.
1430     * This implementation delegates to {@link BasicEList#add(int, Object) add(int, Object)}.
1431     * @param object the object to add.
1432     */

1433    public void add(Object JavaDoc object)
1434    {
1435      checkModCount();
1436
1437      try
1438      {
1439        BasicEList.this.add(cursor++, object);
1440        expectedModCount = modCount;
1441        lastCursor = -1;
1442      }
1443      catch (IndexOutOfBoundsException JavaDoc exception)
1444      {
1445        throw new ConcurrentModificationException JavaDoc();
1446      }
1447    }
1448  }
1449
1450  /**
1451   * Returns a read-only list iterator that does not {@link #resolve resolve} objects.
1452   * This implementation allocates a {@link NonResolvingEListIterator}.
1453   * @return a read-only list iterator that does not resolve objects.
1454   */

1455  protected ListIterator JavaDoc basicListIterator()
1456  {
1457    return new NonResolvingEListIterator();
1458  }
1459
1460  /**
1461   * Returns a read-only list iterator advanced to the given index that does not {@link #resolve resolve} objects.
1462   * This implementation allocates a {@link NonResolvingEListIterator}.
1463   * @param index the starting index.
1464   * @return a read-only list iterator advanced to the index.
1465   * @exception IndexOutOfBoundsException if the index isn't within the size range.
1466   */

1467  protected ListIterator JavaDoc basicListIterator(int index)
1468  {
1469    if (index < 0 || index > size())
1470      throw new BasicIndexOutOfBoundsException(index, size);
1471
1472    return new NonResolvingEListIterator(index);
1473  }
1474
1475  /**
1476   * An extended read-only list iterator that does not {@link #resolve resolve} objects.
1477   */

1478  protected class NonResolvingEListIterator extends EListIterator
1479  {
1480    /**
1481     * Creates an instance.
1482     */

1483    public NonResolvingEListIterator()
1484    {
1485    }
1486
1487    /**
1488     * Creates an instance advanced to the index.
1489     * @param index the starting index.
1490     */

1491    public NonResolvingEListIterator(int index)
1492    {
1493      super(index);
1494    }
1495
1496    /**
1497     * Returns the next object and advances the iterator.
1498     * This implementation accesses the data storage directly.
1499     * @return the next object.
1500     * @exception NoSuchElementException if the iterator is done.
1501     */

1502    public Object JavaDoc next()
1503    {
1504      try
1505      {
1506        Object JavaDoc next = BasicEList.this.data[cursor];
1507        checkModCount();
1508        lastCursor = cursor++;
1509        return next;
1510      }
1511      catch (IndexOutOfBoundsException JavaDoc exception)
1512      {
1513        checkModCount();
1514        throw new NoSuchElementException JavaDoc();
1515      }
1516    }
1517
1518    /**
1519     * Returns the previous object and advances the iterator.
1520     * This implementation acesses the data storage directly.
1521     * @return the previous object.
1522     * @exception NoSuchElementException if the iterator is done.
1523     */

1524    public Object JavaDoc previous()
1525    {
1526      try
1527      {
1528        Object JavaDoc previous = BasicEList.this.data[--cursor];
1529        checkModCount();
1530        lastCursor = cursor;
1531        return previous;
1532      }
1533      catch (IndexOutOfBoundsException JavaDoc exception)
1534      {
1535        checkModCount();
1536        throw new NoSuchElementException JavaDoc();
1537      }
1538    }
1539
1540    /**
1541     * Throws an exception.
1542     * @exception UnsupportedOperationException always because it's not supported.
1543     */

1544    public void remove()
1545    {
1546      throw new UnsupportedOperationException JavaDoc();
1547    }
1548
1549    /**
1550     * Throws an exception.
1551     * @exception UnsupportedOperationException always because it's not supported.
1552     */

1553    public void set(Object JavaDoc object)
1554    {
1555      throw new UnsupportedOperationException JavaDoc();
1556    }
1557
1558    /**
1559     * Throws an exception.
1560     * @exception UnsupportedOperationException always because it's not supported.
1561     */

1562    public void add(Object JavaDoc object)
1563    {
1564      throw new UnsupportedOperationException JavaDoc();
1565    }
1566  }
1567
1568  /**
1569   * An unmodifiable version of {@link BasicEList}.
1570   */

1571  public static class UnmodifiableEList extends BasicEList
1572  {
1573    /**
1574     * Creates an initialized instance.
1575     * @param size the size of the list.
1576     * @param data the underlying storage of the list.
1577     */

1578    public UnmodifiableEList(int size, Object JavaDoc [] data)
1579    {
1580      this.size = size;
1581      this.data = data;
1582    }
1583
1584    /**
1585     * Throws an exception.
1586     * @exception UnsupportedOperationException always because it's not supported.
1587     */

1588    public Object JavaDoc set(int index, Object JavaDoc object)
1589    {
1590      throw new UnsupportedOperationException JavaDoc();
1591    }
1592
1593    /**
1594     * Throws an exception.
1595     * @exception UnsupportedOperationException always because it's not supported.
1596     */

1597    public boolean add(Object JavaDoc object)
1598    {
1599      throw new UnsupportedOperationException JavaDoc();
1600    }
1601
1602    /**
1603     * Throws an exception.
1604     * @exception UnsupportedOperationException always because it's not supported.
1605     */

1606    public void add(int index, Object JavaDoc object)
1607    {
1608      throw new UnsupportedOperationException JavaDoc();
1609    }
1610
1611    /**
1612     * Throws an exception.
1613     * @exception UnsupportedOperationException always because it's not supported.
1614     */

1615    public boolean addAll(Collection JavaDoc collection)
1616    {
1617      throw new UnsupportedOperationException JavaDoc();
1618    }
1619
1620    /**
1621     * Throws an exception.
1622     * @exception UnsupportedOperationException always because it's not supported.
1623     */

1624    public boolean addAll(int index, Collection JavaDoc collection)
1625    {
1626      throw new UnsupportedOperationException JavaDoc();
1627    }
1628
1629    /**
1630     * Throws an exception.
1631     * @exception UnsupportedOperationException always because it's not supported.
1632     */

1633    public boolean remove(Object JavaDoc object)
1634    {
1635      throw new UnsupportedOperationException JavaDoc();
1636    }
1637
1638    /**
1639     * Throws an exception.
1640     * @exception UnsupportedOperationException always because it's not supported.
1641     */

1642    public Object JavaDoc remove(int index)
1643    {
1644      throw new UnsupportedOperationException JavaDoc();
1645    }
1646
1647    /**
1648     * Throws an exception.
1649     * @exception UnsupportedOperationException always because it's not supported.
1650     */

1651    public boolean removeAll(Collection JavaDoc collection)
1652    {
1653      throw new UnsupportedOperationException JavaDoc();
1654    }
1655
1656    /**
1657     * Throws an exception.
1658     * @exception UnsupportedOperationException always because it's not supported.
1659     */

1660    public boolean retainAll(Collection JavaDoc collection)
1661    {
1662      throw new UnsupportedOperationException JavaDoc();
1663    }
1664
1665    /**
1666     * Throws an exception.
1667     * @exception UnsupportedOperationException always because it's not supported.
1668     */

1669    public void clear()
1670    {
1671      throw new UnsupportedOperationException JavaDoc();
1672    }
1673
1674    /**
1675     * Throws an exception.
1676     * @exception UnsupportedOperationException always because it's not supported.
1677     */

1678    public void move(int index, Object JavaDoc object)
1679    {
1680      throw new UnsupportedOperationException JavaDoc();
1681    }
1682
1683    /**
1684     * Throws an exception.
1685     * @exception UnsupportedOperationException always because it's not supported.
1686     */

1687    public Object JavaDoc move(int targetIndex, int sourceIndex)
1688    {
1689      throw new UnsupportedOperationException JavaDoc();
1690    }
1691
1692    /**
1693     * Throws an exception.
1694     * @exception UnsupportedOperationException always because it's not supported.
1695     */

1696    public void shrink()
1697    {
1698      throw new UnsupportedOperationException JavaDoc();
1699    }
1700
1701    /**
1702     * Throws an exception.
1703     * @exception UnsupportedOperationException always because it's not supported.
1704     */

1705    public void grow(int minimumCapacity)
1706    {
1707      throw new UnsupportedOperationException JavaDoc();
1708    }
1709
1710    /**
1711     * Returns the {@link BasicEList#basicIterator basic iterator}.
1712     * @return the basic iterator.
1713     */

1714    public Iterator JavaDoc iterator()
1715    {
1716      return basicIterator();
1717    }
1718
1719    /**
1720     * Returns the {@link #basicListIterator() basic list iterator}.
1721     * @return the basic list iterator.
1722     */

1723    public ListIterator JavaDoc listIterator()
1724    {
1725      return basicListIterator();
1726    }
1727  
1728    /**
1729     * Returns the {@link #basicListIterator(int) basic list iterator} advanced to the index.
1730     * @param index the starting index.
1731     * @return the basic list iterator.
1732     */

1733    public ListIterator JavaDoc listIterator(int index)
1734    {
1735      return basicListIterator(index);
1736    }
1737  }
1738
1739  /**
1740   * Returns an <b>unsafe</b> list that provides a {@link #resolve non-resolving} view of the underlying data storage.
1741   * @return an <b>unsafe</b> list that provides a non-resolving view of the underlying data storage.
1742   */

1743  protected List JavaDoc basicList()
1744  {
1745    if (size == 0)
1746    {
1747      return ECollections.EMPTY_ELIST;
1748    }
1749    else
1750    {
1751      return new UnmodifiableEList(size, data);
1752    }
1753  }
1754
1755  /**
1756   * A <code>BasicEList</code> that {@link #useEquals uses} <code>==</code> instead of <code>equals</code> to compare members.
1757   */

1758  public static class FastCompare extends BasicEList
1759  {
1760    /**
1761     * Creates an empty instance with no initial capacity.
1762     */

1763    public FastCompare()
1764    {
1765      super();
1766    }
1767
1768    /**
1769     * Creates an empty instance with the given capacity.
1770     * @param initialCapacity the initial capacity of the list before it must grow.
1771     * @exception IllegalArgumentException if the <code>initialCapacity</code> is negative.
1772     */

1773    public FastCompare(int initialCapacity)
1774    {
1775      super(initialCapacity);
1776    }
1777
1778    /**
1779     * Creates an instance that is a copy of the collection.
1780     * @param collection the initial contents of the list.
1781     */

1782    public FastCompare(Collection JavaDoc collection)
1783    {
1784      super(collection.size());
1785      addAll(collection);
1786    }
1787
1788    /**
1789     * Returns <code>false</code> because this list uses <code>==</code>.
1790     * @return <code>false</code>.
1791     */

1792    protected boolean useEquals()
1793    {
1794      return false;
1795    }
1796  }
1797
1798  /**
1799   * Returns the collection of objects in the given collection that are also contained by this list.
1800   * @param collection the other collection.
1801   * @return the collection of objects in the given collection that are also contained by this list.
1802   */

1803  protected Collection JavaDoc getDuplicates(Collection JavaDoc collection)
1804  {
1805    Collection JavaDoc result = collection;
1806    Collection JavaDoc filteredResult = null;
1807    for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
1808    {
1809      Object JavaDoc object = i.next();
1810      if (!contains(object))
1811      {
1812        if (filteredResult == null)
1813        {
1814          result = filteredResult = useEquals() ? new BasicEList(collection) : new FastCompare(collection);
1815        }
1816        filteredResult.remove(object);
1817      }
1818    }
1819    return result;
1820  }
1821
1822  /**
1823   * Returns the collection of objects in the given collection that are not also contained by this list.
1824   * @param collection the other collection.
1825   * @return the collection of objects in the given collection that are not also contained by this list.
1826   */

1827  protected Collection JavaDoc getNonDuplicates(Collection JavaDoc collection)
1828  {
1829    Collection JavaDoc result = useEquals() ? new UniqueEList(collection.size()) : new UniqueEList.FastCompare(collection.size());
1830    for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
1831    {
1832      Object JavaDoc object = i.next();
1833      if (!contains(object))
1834      {
1835        result.add(object);
1836      }
1837    }
1838    return result;
1839  }
1840}
1841
Popular Tags