KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > indirection > IndirectList


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2005, Oracle. All rights reserved.
22
package oracle.toplink.essentials.indirection;
23
24 import java.util.*;
25 import oracle.toplink.essentials.internal.indirection.*;
26
27 /**
28  * IndirectList allows a domain class to take advantage of TopLink indirection
29  * without having to declare its instance variable as a ValueHolderInterface.
30  * <p>To use an IndirectList:<ul>
31  * <li> Declare the appropriate instance variable with type IndirectList (jdk1.1)
32  * or Collection/List/Vector (jdk1.2).
33  * <li> Send the message #useTransparentCollection() to the appropriate
34  * CollectionMapping.
35  * </ul>
36  * TopLink will place an
37  * IndirectList in the instance variable when the containing domain object is read from
38  * the datatabase. With the first message sent to the IndirectList, the contents
39  * are fetched from the database and normal Collection/List/Vector behavior is resumed.
40  *
41  * @see oracle.toplink.essentials.mappings.CollectionMapping
42  * @see oracle.toplink.essentials.indirection.IndirectMap
43  * @author Big Country
44  * @since TOPLink/Java 2.5
45  */

46 public class IndirectList extends Vector implements IndirectContainer {
47
48     /** Reduce type casting. */
49     protected Vector delegate;
50
51     /** Delegate indirection behavior to a value holder. */
52     protected ValueHolderInterface valueHolder;
53     
54     /** The mapping attribute name, used to raise change events. */
55     private transient String JavaDoc attributeName;
56
57     /** Store initial size for lazy init. */
58     protected int initialCapacity = 10;
59
60     /**
61      * PUBLIC:
62      * Construct an empty IndirectList so that its internal data array
63      * has size <tt>10</tt> and its standard capacity increment is zero.
64      */

65     public IndirectList() {
66         this(10);
67     }
68
69     /**
70      * PUBLIC:
71      * Construct an empty IndirectList with the specified initial capacity and
72      * with its capacity increment equal to zero.
73      *
74      * @param initialCapacity the initial capacity of the vector
75      * @exception IllegalArgumentException if the specified initial capacity
76      * is negative
77      */

78     public IndirectList(int initialCapacity) {
79         this(initialCapacity, 0);
80     }
81
82     /**
83      * PUBLIC:
84      * Construct an empty IndirectList with the specified initial capacity and
85      * capacity increment.
86      *
87      * @param initialCapacity the initial capacity of the vector
88      * @param capacityIncrement the amount by which the capacity is
89      * increased when the vector overflows
90      * @exception IllegalArgumentException if the specified initial capacity
91      * is negative
92      */

93     public IndirectList(int initialCapacity, int capacityIncrement) {
94         super(0);
95         this.initialize(initialCapacity, capacityIncrement);
96     }
97
98     /**
99      * PUBLIC:
100      * Construct an IndirectList containing the elements of the specified
101      * collection, in the order they are returned by the collection's
102      * iterator.
103      * @param c a collection containing the elements to construct this IndirectList with.
104      */

105     public IndirectList(Collection c) {
106         super(0);
107         this.initialize(c);
108     }
109
110     /**
111      * @see java.util.Vector#add(int, java.lang.Object)
112      */

113     public void add(int index, Object JavaDoc element) {
114         this.getDelegate().add(index, element);
115         raiseAddChangeEvent(element);
116     }
117     
118     /**
119      * Raise the add change event and relationship maintainence.
120      */

121     protected void raiseAddChangeEvent(Object JavaDoc element) {
122         if (hasBeenRegistered()) {
123             ((UnitOfWorkQueryValueHolder)getValueHolder()).updateForeignReferenceSet(element, null);
124         }
125     }
126     
127     /**
128      * Raise the remove change event.
129      */

130     protected void raiseRemoveChangeEvent(Object JavaDoc element) {
131         if (hasBeenRegistered()) {
132             ((UnitOfWorkQueryValueHolder)getValueHolder()).updateForeignReferenceRemove(element);
133         }
134     }
135
136     /**
137      * @see java.util.Vector#add(java.lang.Object)
138      */

139     public synchronized boolean add(Object JavaDoc o) {
140         this.getDelegate().add(o);
141         raiseAddChangeEvent(o);
142         return true;
143     }
144
145     /**
146      * @see java.util.Vector#addAll(int, java.util.Collection)
147      */

148     public synchronized boolean addAll(int index, Collection c) {
149         Iterator objects = c.iterator();
150         // Must trigger add events if tracked or uow.
151
if (hasBeenRegistered()) {
152             while (objects.hasNext()) {
153                 this.add(index, objects.next());
154                 index++;
155             }
156             return true;
157         }
158
159         return this.getDelegate().addAll(index, c);
160
161     }
162
163     /**
164      * @see java.util.Vector#addAll(java.util.Collection)
165      */

166     public synchronized boolean addAll(Collection c) {
167         // Must trigger add events if tracked or uow.
168
if (hasBeenRegistered()) {
169             Iterator objects = c.iterator();
170             while (objects.hasNext()) {
171                 this.add(objects.next());
172             }
173             return true;
174         }
175
176         return getDelegate().addAll(c);
177     }
178
179     /**
180      * @see java.util.Vector#addElement(java.lang.Object)
181      */

182     public synchronized void addElement(Object JavaDoc obj) {
183         this.add(obj);
184     }
185
186     /**
187      * PUBLIC:
188      * Return the freshly-built delegate.
189      * <br>In jdk1.1, the delegate may not be a Vector (in which case, it better be another IndirectList).
190      * <br>In jdk1.2, IndirectList is a subclass of Vector, so there is no need to check.
191      */

192     protected Vector buildDelegate() {
193         return (Vector)getValueHolder().getValue();
194     }
195
196     /**
197      * @see java.util.Vector#capacity()
198      */

199     public int capacity() {
200         return this.getDelegate().capacity();
201     }
202
203     /**
204      * @see java.util.Vector#clear()
205      */

206     public void clear() {
207         if (hasBeenRegistered()) {
208             Iterator objects = this.iterator();
209             while (objects.hasNext()) {
210                 Object JavaDoc o = objects.next();
211                 objects.remove();
212                 this.raiseRemoveChangeEvent(o);
213             }
214         } else {
215             this.getDelegate().clear();
216         }
217     }
218
219     /**
220      * PUBLIC:
221      * @see java.util.Vector#clone()
222      * This will result in a database query if necessary.
223      */

224
225     /*
226         There are 3 situations when clone() is called:
227         1. The developer actually wants to clone the collection (typically to modify one
228             of the 2 resulting collections). In which case the contents must be read from
229             the database.
230         2. A UnitOfWork needs a clone (or backup clone) of the collection. But the
231             UnitOfWork checks "instantiation" before cloning collections ("un-instantiated"
232             collections are not cloned).
233         3. A MergeManager needs an extra copy of the collection (because the "backup"
234             and "target" are the same object?). But the MergeManager checks "instantiation"
235             before merging collections (again, "un-instantiated" collections are not merged).
236     */

237     public synchronized Object JavaDoc clone() {
238         IndirectList result = (IndirectList)super.clone();
239         result.delegate = (Vector)this.getDelegate().clone();
240         result.attributeName = null;
241         return result;
242     }
243
244     /**
245      * PUBLIC:
246      * @see java.util.Vector#contains(java.lang.Object)
247      */

248     public boolean contains(Object JavaDoc elem) {
249         return this.getDelegate().contains(elem);
250     }
251
252     /**
253      * @see java.util.Vector#containsAll(java.util.Collection)
254      */

255     public synchronized boolean containsAll(Collection c) {
256         return this.getDelegate().containsAll(c);
257     }
258
259     /**
260      * @see java.util.Vector#copyInto(java.lang.Object[])
261      */

262     public synchronized void copyInto(Object JavaDoc[] anArray) {
263         this.getDelegate().copyInto(anArray);
264     }
265
266     /**
267      * @see java.util.Vector#elementAt(int)
268      */

269     public synchronized Object JavaDoc elementAt(int index) {
270         return this.getDelegate().elementAt(index);
271     }
272
273     /**
274      * @see java.util.Vector#elements()
275      */

276     public Enumeration elements() {
277         return this.getDelegate().elements();
278     }
279
280     /**
281      * @see java.util.Vector#ensureCapacity(int)
282      */

283     public synchronized void ensureCapacity(int minCapacity) {
284         this.getDelegate().ensureCapacity(minCapacity);
285     }
286
287     /**
288      * @see java.util.Vector#equals(java.lang.Object)
289      */

290     public synchronized boolean equals(Object JavaDoc o) {
291         return this.getDelegate().equals(o);
292     }
293
294     /**
295      * @see java.util.Vector#firstElement()
296      */

297     public synchronized Object JavaDoc firstElement() {
298         return this.getDelegate().firstElement();
299     }
300
301     /**
302      * @see java.util.Vector#get(int)
303      */

304     public synchronized Object JavaDoc get(int index) {
305         return this.getDelegate().get(index);
306     }
307
308     /**
309      * PUBLIC:
310      * Check whether the contents have been read from the database.
311      * If they have not, read them and set the delegate.
312      */

313     protected synchronized Vector getDelegate() {
314         if (delegate == null) {
315             delegate = this.buildDelegate();
316         }
317         return delegate;
318     }
319
320     /**
321      * PUBLIC:
322      * Return the valueHolder.
323      */

324     public synchronized ValueHolderInterface getValueHolder() {
325         // PERF: lazy initialize value holder and vector as are normally set after creation.
326
if (valueHolder == null) {
327             valueHolder = new ValueHolder(new Vector(this.initialCapacity, this.capacityIncrement));
328         }
329         return valueHolder;
330     }
331
332     /**
333      * INTERNAL:
334      * return whether this IndirectList has been registered with the UnitOfWork
335      */

336     public boolean hasBeenRegistered() {
337         return getValueHolder() instanceof oracle.toplink.essentials.internal.indirection.UnitOfWorkQueryValueHolder;
338     }
339
340     /**
341      * INTERNAL:
342      * @see java.util.Vector#hashCode()
343      */

344     public synchronized int hashCode() {
345         return this.getDelegate().hashCode();
346     }
347
348     /**
349      * @see java.util.Vector#indexOf(java.lang.Object)
350      */

351     public int indexOf(Object JavaDoc elem) {
352         return this.getDelegate().indexOf(elem);
353     }
354
355     /**
356      * @see java.util.Vector#indexOf(java.lang.Object, int)
357      */

358     public synchronized int indexOf(Object JavaDoc elem, int index) {
359         return this.getDelegate().indexOf(elem, index);
360     }
361
362     /**
363      * Initialize the instance.
364      */

365     protected void initialize(int initialCapacity, int capacityIncrement) {
366         this.initialCapacity = initialCapacity;
367         this.capacityIncrement = capacityIncrement;
368         this.delegate = null;
369         this.valueHolder = null;
370     }
371
372     /**
373      * Initialize the instance.
374      */

375     protected void initialize(Collection c) {
376         this.delegate = null;
377         Vector temp = new Vector(c);
378         this.valueHolder = new ValueHolder(temp);
379     }
380
381     /**
382      * @see java.util.Vector#insertElementAt(java.lang.Object, int)
383      */

384     public synchronized void insertElementAt(Object JavaDoc obj, int index) {
385         this.getDelegate().insertElementAt(obj, index);
386         this.raiseAddChangeEvent(obj);
387     }
388
389     /**
390      * @see java.util.Vector#isEmpty()
391      */

392     public boolean isEmpty() {
393         return this.getDelegate().isEmpty();
394     }
395
396     /**
397      * PUBLIC:
398      * Return whether the contents have been read from the database.
399      */

400     public boolean isInstantiated() {
401         return this.getValueHolder().isInstantiated();
402     }
403
404     /**
405      * @see java.util.AbstractList#iterator()
406      */

407     public Iterator iterator() {
408         // Must wrap the interator to raise the remove event.
409
return new Iterator() {
410             Iterator delegateIterator = IndirectList.this.getDelegate().iterator();
411             Object JavaDoc currentObject;
412             
413             public boolean hasNext() {
414                 return this.delegateIterator.hasNext();
415             }
416             
417             public Object JavaDoc next() {
418                 this.currentObject = this.delegateIterator.next();
419                 return this.currentObject;
420             }
421             
422             public void remove() {
423                 this.delegateIterator.remove();
424                 IndirectList.this.raiseRemoveChangeEvent(this.currentObject);
425             }
426         };
427     }
428
429     /**
430      * @see java.util.Vector#lastElement()
431      */

432     public synchronized Object JavaDoc lastElement() {
433         return this.getDelegate().lastElement();
434     }
435
436     /**
437      * @see java.util.Vector#lastIndexOf(java.lang.Object)
438      */

439     public int lastIndexOf(Object JavaDoc elem) {
440         return this.getDelegate().lastIndexOf(elem);
441     }
442
443     /**
444      * @see java.util.Vector#lastIndexOf(java.lang.Object, int)
445      */

446     public synchronized int lastIndexOf(Object JavaDoc elem, int index) {
447         return this.getDelegate().lastIndexOf(elem, index);
448     }
449
450     /**
451      * @see java.util.AbstractList#listIterator()
452      */

453     public ListIterator listIterator() {
454         return this.listIterator(0);
455     }
456
457     /**
458      * @see java.util.AbstractList#listIterator(int)
459      */

460     public ListIterator listIterator(final int index) {
461         // Must wrap the interator to raise the remove event.
462
return new ListIterator() {
463             ListIterator delegateIterator = IndirectList.this.getDelegate().listIterator(index);
464             Object JavaDoc currentObject;
465             
466             public boolean hasNext() {
467                 return this.delegateIterator.hasNext();
468             }
469             
470             public boolean hasPrevious() {
471                 return this.delegateIterator.hasPrevious();
472             }
473             
474             public int previousIndex() {
475                 return this.delegateIterator.previousIndex();
476             }
477             
478             public int nextIndex() {
479                 return this.delegateIterator.nextIndex();
480             }
481             
482             public Object JavaDoc next() {
483                 this.currentObject = this.delegateIterator.next();
484                 return this.currentObject;
485             }
486             
487             public Object JavaDoc previous() {
488                 this.currentObject = this.delegateIterator.previous();
489                 return this.currentObject;
490             }
491             
492             public void remove() {
493                 this.delegateIterator.remove();
494                 IndirectList.this.raiseRemoveChangeEvent(this.currentObject);
495             }
496             
497             public void set(Object JavaDoc object) {
498                 this.delegateIterator.set(object);
499                 IndirectList.this.raiseRemoveChangeEvent(this.currentObject);
500                 IndirectList.this.raiseAddChangeEvent(object);
501             }
502             
503             public void add(Object JavaDoc object) {
504                 this.delegateIterator.add(object);
505                 IndirectList.this.raiseAddChangeEvent(object);
506             }
507         };
508     }
509
510     /**
511      * @see java.util.Vector#remove(int)
512      */

513     public synchronized Object JavaDoc remove(int index) {
514         Object JavaDoc value = this.getDelegate().remove(index);
515         this.raiseRemoveChangeEvent(value);
516         return value;
517     }
518
519     /**
520      * @see java.util.Vector#remove(java.lang.Object)
521      */

522     public boolean remove(Object JavaDoc o) {
523         if (this.getDelegate().remove(o)) {
524             this.raiseRemoveChangeEvent(o);
525             return true;
526         }
527         return false;
528     }
529
530     /**
531      * @see java.util.Vector#removeAll(java.util.Collection)
532      */

533     public synchronized boolean removeAll(Collection c) {
534         // Must trigger remove events if tracked or uow.
535
if (hasBeenRegistered()) {
536             Iterator objects = c.iterator();
537             while (objects.hasNext()) {
538                 this.remove(objects.next());
539             }
540             return true;
541         }
542         return this.getDelegate().removeAll(c);
543     }
544
545     /**
546      * @see java.util.Vector#removeAllElements()
547      */

548     public synchronized void removeAllElements() {
549         // Must trigger remove events if tracked or uow.
550
if (hasBeenRegistered()) {
551             Iterator objects = this.iterator();
552             while (objects.hasNext()) {
553                 Object JavaDoc object = objects.next();
554                 objects.remove();
555                 this.raiseRemoveChangeEvent(object);
556             }
557             return;
558         }
559         this.getDelegate().removeAllElements();
560     }
561
562     /**
563      * @see java.util.Vector#removeElement(java.lang.Object)
564      */

565     public synchronized boolean removeElement(Object JavaDoc obj) {
566         return this.remove(obj);
567     }
568
569     /**
570      * @see java.util.Vector#removeElementAt(int)
571      */

572     public synchronized void removeElementAt(int index) {
573         this.remove(index);
574     }
575
576     /**
577      * @see java.util.Vector#retainAll(java.util.Collection)
578      */

579     public synchronized boolean retainAll(Collection c) {
580         // Must trigger remove events if tracked or uow.
581
if (hasBeenRegistered()) {
582             Iterator objects = getDelegate().iterator();
583             while (objects.hasNext()) {
584                 Object JavaDoc object = objects.next();
585                 if (!c.contains(object)) {
586                     objects.remove();
587                     this.raiseRemoveChangeEvent(object);
588                 }
589             }
590             return true;
591         }
592         return this.getDelegate().retainAll(c);
593     }
594
595     /**
596      * @see java.util.Vector#set(int, java.lang.Object)
597      */

598     public synchronized Object JavaDoc set(int index, Object JavaDoc element) {
599         Object JavaDoc oldValue = this.getDelegate().set(index, element);
600         this.raiseRemoveChangeEvent(oldValue);
601         this.raiseAddChangeEvent(element);
602         return oldValue;
603     }
604
605     /**
606      * @see java.util.Vector#setElementAt(java.lang.Object, int)
607      */

608     public synchronized void setElementAt(Object JavaDoc obj, int index) {
609         this.set(index, obj);
610     }
611
612     /**
613      * @see java.util.Vector#setSize(int)
614      */

615     public synchronized void setSize(int newSize) {
616         // Must trigger remove events if tracked or uow.
617
if (hasBeenRegistered()) {
618             if (newSize > this.size()) {
619                 for (int index = size(); index > newSize; index--) {
620                     this.remove(index - 1);
621                 }
622             }
623         }
624         this.getDelegate().setSize(newSize);
625     }
626
627     /**
628      * PUBLIC:
629      * Set the value holder.
630      */

631     public void setValueHolder(ValueHolderInterface valueHolder) {
632         this.delegate = null;
633         this.valueHolder = valueHolder;
634     }
635
636     /**
637      * @see java.util.Vector#size()
638      */

639     public int size() {
640         return this.getDelegate().size();
641     }
642
643     /**
644      * @see java.util.Vector#subList(int, int)
645      */

646     public List subList(int fromIndex, int toIndex) {
647         return this.getDelegate().subList(fromIndex, toIndex);
648     }
649
650     /**
651      * @see java.util.Vector#toArray()
652      */

653     public synchronized Object JavaDoc[] toArray() {
654         return this.getDelegate().toArray();
655     }
656
657     /**
658      * @see java.util.Vector#toArray(java.lang.Object[])
659      */

660     public synchronized Object JavaDoc[] toArray(Object JavaDoc[] a) {
661         return this.getDelegate().toArray(a);
662     }
663
664     /**
665      * PUBLIC:
666      * Use the java.util.Vector#toString(); but wrap it with braces to indicate
667      * there is a bit of indirection.
668      * Don't allow this method to trigger a database read.
669      * @see java.util.Vector#toString()
670      */

671     public String JavaDoc toString() {
672         if (ValueHolderInterface.shouldToStringInstantiate) {
673             return this.getDelegate().toString();
674         }
675         if (this.isInstantiated()) {
676             return "{" + this.getDelegate().toString() + "}";
677         } else {
678             return "{" + oracle.toplink.essentials.internal.helper.Helper.getShortClassName(this.getClass()) + ": not instantiated}";
679         }
680     }
681
682     /**
683      * @see java.util.Vector#trimToSize()
684      */

685     public synchronized void trimToSize() {
686         this.getDelegate().trimToSize();
687     }
688      
689     /**
690      * Return the mapping attribute name, used to raise change events.
691      */

692      public String JavaDoc getTopLinkAttributeName() {
693          return attributeName;
694      }
695      
696     /**
697      * Set the mapping attribute name, used to raise change events.
698      * This is required if the change listener is set.
699      */

700      public void setTopLinkAttributeName(String JavaDoc attributeName) {
701          this.attributeName = attributeName;
702      }
703 }
704
Popular Tags