KickJava   Java API By Example, From Geeks To Geeks.

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


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
26 /**
27  * IndirectMap allows a domain class to take advantage of TopLink indirection
28  * without having to declare its instance variable as a ValueHolderInterface.
29  * <p>To use an IndirectMap:<ul>
30  * <li> Declare the appropriate instance variable with type Hashtable (jdk1.1)
31  * or Map (jdk1.2).
32  * <li> Send the message #useTransparentMap(String) to the appropriate
33  * CollectionMapping.
34  * </ul>
35  * TopLink will place an
36  * IndirectMap in the instance variable when the containing domain object is read from
37  * the datatabase. With the first message sent to the IndirectMap, the contents
38  * are fetched from the database and normal Hashtable/Map behavior is resumed.
39  *
40  * @see oracle.toplink.essentials.mappings.CollectionMapping
41  * @see oracle.toplink.essentials.indirection.IndirectList
42  * @author Big Country
43  * @since TOPLink/Java 2.5
44  */

45 public class IndirectMap extends Hashtable implements IndirectContainer {
46
47     /** Reduce type casting */
48     protected Hashtable delegate;
49
50     /** Delegate indirection behavior to a value holder */
51     protected ValueHolderInterface valueHolder;
52     
53     /** The mapping attribute name, used to raise change events. */
54     private transient String JavaDoc attributeName;
55
56     /** Store initial size for lazy init. */
57     protected int initialCapacity = 11;
58
59     /** Store load factor for lazy init. */
60     protected float loadFactor = 0.75f;
61
62     /**
63      * PUBLIC:
64      * Construct a new, empty IndirectMap with a default
65      * capacity and load factor.
66      */

67     public IndirectMap() {
68         this(11);
69     }
70
71     /**
72      * PUBLIC:
73      * Construct a new, empty IndirectMap with the specified initial capacity
74      * and default load factor.
75      *
76      * @param initialCapacity the initial capacity of the hashtable
77      */

78     public IndirectMap(int initialCapacity) {
79         this(initialCapacity, 0.75f);
80     }
81
82     /**
83      * PUBLIC:
84      * Construct a new, empty IndirectMap with the specified initial
85      * capacity and load factor.
86      *
87      * @param initialCapacity the initial capacity of the hashtable
88      * @param loadFactor a number between 0.0 and 1.0
89      * @exception IllegalArgumentException if the initial capacity is less
90      * than or equal to zero, or if the load factor is less than
91      * or equal to zero
92      */

93     public IndirectMap(int initialCapacity, float loadFactor) {
94         super(0);
95         this.initialize(initialCapacity, loadFactor);
96     }
97
98     /**
99      * PUBLIC:
100      * Construct a new IndirectMap with the same mappings as the given Map.
101      * The IndirectMap is created with a capacity of twice the number of entries
102      * in the given Map or 11 (whichever is greater), and a default load factor, which is 0.75.
103      * @param m a map containing the mappings to use
104      */

105     public IndirectMap(Map m) {
106         super(0);
107         this.initialize(m);
108     }
109
110     /**
111      * Return the freshly-built delegate.
112      */

113     protected Hashtable buildDelegate() {
114         return (Hashtable)getValueHolder().getValue();
115     }
116
117     /**
118      * @see java.util.Hashtable#clear()
119      */

120     public synchronized void clear() {
121         this.getDelegate().clear();
122     }
123
124     /**
125      * @see java.util.Hashtable#clone()
126      * This will result in a database query if necessary.
127      */

128
129     /*
130         There are 3 situations when clone() is called:
131         1. The developer actually wants to clone the collection (typically to modify one
132             of the 2 resulting collections). In which case the contents must be read from
133             the database.
134         2. A UnitOfWork needs a clone (or backup clone) of the collection. But the
135             UnitOfWork checks "instantiation" before cloning collections ("un-instantiated"
136             collections are not cloned).
137         3. A MergeManager needs an extra copy of the collection (because the "backup"
138             and "target" are the same object?). But the MergeManager checks "instantiation"
139             before merging collections (again, "un-instantiated" collections are not merged).
140     */

141     public synchronized Object JavaDoc clone() {
142         IndirectMap result = (IndirectMap)super.clone();
143         result.delegate = (Hashtable)this.getDelegate().clone();
144         return result;
145     }
146
147     /**
148      * @see java.util.Hashtable#contains(java.lang.Object)
149      */

150     public synchronized boolean contains(Object JavaDoc value) {
151         return this.getDelegate().contains(value);
152     }
153
154     /**
155      * @see java.util.Hashtable#containsKey(java.lang.Object)
156      */

157     public synchronized boolean containsKey(Object JavaDoc key) {
158         return this.getDelegate().containsKey(key);
159     }
160
161     /**
162      * @see java.util.Hashtable#containsValue(java.lang.Object)
163      */

164     public boolean containsValue(Object JavaDoc value) {
165         return this.getDelegate().containsValue(value);
166     }
167
168     /**
169      * @see java.util.Hashtable#elements()
170      */

171     public synchronized Enumeration elements() {
172         return this.getDelegate().elements();
173     }
174
175     /**
176      * @see java.util.Hashtable#entrySet()
177      */

178     public Set entrySet() {
179         return new Set (){
180             Set delegateSet = IndirectMap.this.getDelegate().entrySet();
181             
182             public int size(){
183                 return this.delegateSet.size();
184             }
185         
186             public boolean isEmpty(){
187                 return this.delegateSet.isEmpty();
188             }
189         
190             public boolean contains(Object JavaDoc o){
191                 return this.delegateSet.contains(o);
192             }
193         
194             public Iterator iterator(){
195                 return new Iterator() {
196                     Iterator delegateIterator = delegateSet.iterator();
197                     Object JavaDoc currentObject;
198                     
199                     public boolean hasNext() {
200                         return this.delegateIterator.hasNext();
201                     }
202                     
203                     public Object JavaDoc next() {
204                         this.currentObject = this.delegateIterator.next();
205                         return this.currentObject;
206                     }
207                     
208                     public void remove() {
209                         raiseRemoveChangeEvent(((Map.Entry)currentObject).getKey(), ((Map.Entry)currentObject).getValue());
210                         this.delegateIterator.remove();
211                     }
212                 };
213             }
214         
215             public Object JavaDoc[] toArray(){
216                 return this.delegateSet.toArray();
217             }
218     
219             public Object JavaDoc[] toArray(Object JavaDoc a[]){
220                 return this.delegateSet.toArray(a);
221             }
222     
223             public boolean add(Object JavaDoc o){
224                 return this.delegateSet.add(o);
225             }
226         
227             public boolean remove(Object JavaDoc o){
228                 if (!(o instanceof Map.Entry)) {
229                     return false;
230                 }
231                 return (IndirectMap.this.remove(((Map.Entry)o).getKey()) != null);
232             }
233         
234             public boolean containsAll(Collection c){
235                 return this.delegateSet.containsAll(c);
236             }
237         
238             public boolean addAll(Collection c){
239                 return this.delegateSet.addAll(c);
240             }
241         
242             public boolean retainAll(Collection c){
243                 boolean result = false;
244                 Iterator objects = delegateSet.iterator();
245                 while (objects.hasNext()) {
246                     Map.Entry object = (Map.Entry)objects.next();
247                     if (!c.contains(object)) {
248                         objects.remove();
249                         raiseRemoveChangeEvent(object.getKey(), object.getValue());
250                         result = true;
251                     }
252                 }
253                 return result;
254             }
255             
256             public boolean removeAll(Collection c){
257                 boolean result = false;
258                 for (Iterator cs = c.iterator(); cs.hasNext(); ){
259                     Object JavaDoc object = cs.next();
260                     if ( ! (object instanceof Map.Entry)){
261                         continue;
262                     }
263                     Object JavaDoc removed = IndirectMap.this.remove(((Map.Entry)object).getKey());
264                     if (removed != null){
265                         result = true;
266                     }
267                 }
268                 return result;
269             }
270         
271             public void clear(){
272                 IndirectMap.this.clear();
273             }
274         
275             public boolean equals(Object JavaDoc o){
276                 return this.delegateSet.equals(o);
277             }
278             
279             public int hashCode(){
280                 return this.delegateSet.hashCode();
281             }
282         };
283     }
284
285     /**
286      * @see java.util.Hashtable#equals(java.lang.Object)
287      */

288     public synchronized boolean equals(Object JavaDoc o) {
289         return this.getDelegate().equals(o);
290     }
291
292     /**
293      * @see java.util.Hashtable#get(java.lang.Object)
294      */

295     public synchronized Object JavaDoc get(Object JavaDoc key) {
296         return this.getDelegate().get(key);
297     }
298
299     /**
300      * Check whether the contents have been read from the database.
301      * If they have not, read them and set the delegate.
302      */

303     protected synchronized Hashtable getDelegate() {
304         if (delegate == null) {
305             delegate = this.buildDelegate();
306         }
307         return delegate;
308     }
309
310     /**
311      * Return the mapping attribute name, used to raise change events.
312      */

313      public String JavaDoc getTopLinkAttributeName() {
314          return attributeName;
315      }
316     
317     /**
318      * PUBLIC:
319      * Return the valueHolder.
320      */

321     public synchronized ValueHolderInterface getValueHolder() {
322         // PERF: lazy initialize value holder and vector as are normally set after creation.
323
if (valueHolder == null) {
324             valueHolder = new ValueHolder(new Hashtable(initialCapacity, loadFactor));
325         }
326         return valueHolder;
327     }
328
329     /**
330      * @see java.util.Hashtable#hashCode()
331      */

332     public synchronized int hashCode() {
333         return this.getDelegate().hashCode();
334     }
335      
336     /**
337      * Initialize the instance.
338      */

339     protected void initialize(int initialCapacity, float loadFactor) {
340         this.delegate = null;
341         this.loadFactor = loadFactor;
342         this.initialCapacity = initialCapacity;
343         this.valueHolder = null;
344     }
345
346     /**
347      * Initialize the instance.
348      */

349     protected void initialize(Map m) {
350         this.delegate = null;
351         Hashtable temp = new Hashtable(m);
352
353         this.valueHolder = new ValueHolder(temp);
354     }
355
356     /**
357      * @see java.util.Hashtable#isEmpty()
358      */

359     public boolean isEmpty() {
360         return this.getDelegate().isEmpty();
361     }
362
363     /**
364      * PUBLIC:
365      * Return whether the contents have been read from the database.
366      */

367     public boolean isInstantiated() {
368         return this.getValueHolder().isInstantiated();
369     }
370
371     /**
372      * @see java.util.Hashtable#keys()
373      */

374     public synchronized Enumeration keys() {
375         return this.getDelegate().keys();
376     }
377
378     /**
379      * @see java.util.Hashtable#keySet()
380      */

381     public Set keySet() {
382         
383         return new Set (){
384             Set delegateSet = IndirectMap.this.getDelegate().keySet();
385             
386             public int size(){
387                 return this.delegateSet.size();
388             }
389         
390             public boolean isEmpty(){
391                 return this.delegateSet.isEmpty();
392             }
393         
394             public boolean contains(Object JavaDoc o){
395                 return this.delegateSet.contains(o);
396             }
397         
398             public Iterator iterator(){
399                 return new Iterator() {
400                     Iterator delegateIterator = delegateSet.iterator();
401                     Object JavaDoc currentObject;
402                     
403                     public boolean hasNext() {
404                         return this.delegateIterator.hasNext();
405                     }
406                     
407                     public Object JavaDoc next() {
408                         this.currentObject = this.delegateIterator.next();
409                         return this.currentObject;
410                     }
411                     
412                     public void remove() {
413                         IndirectMap.this.raiseRemoveChangeEvent(currentObject, IndirectMap.this.getDelegate().get(currentObject));
414                         this.delegateIterator.remove();
415                     }
416                 };
417             }
418         
419             public Object JavaDoc[] toArray(){
420                 return this.delegateSet.toArray();
421             }
422     
423             public Object JavaDoc[] toArray(Object JavaDoc a[]){
424                 return this.delegateSet.toArray(a);
425             }
426     
427             public boolean add(Object JavaDoc o){
428                 return this.delegateSet.add(o);
429             }
430         
431             public boolean remove(Object JavaDoc o){
432                 return (IndirectMap.this.remove(o) != null);
433             }
434         
435             public boolean containsAll(Collection c){
436                 return this.delegateSet.containsAll(c);
437             }
438         
439             public boolean addAll(Collection c){
440                 return this.delegateSet.addAll(c);
441             }
442         
443             public boolean retainAll(Collection c){
444                 boolean result = false;
445                 Iterator objects = delegateSet.iterator();
446                 while (objects.hasNext()) {
447                     Object JavaDoc object = objects.next();
448                     if (!c.contains(object)) {
449                         objects.remove();
450                         IndirectMap.this.raiseRemoveChangeEvent(object, IndirectMap.this.getDelegate().get(object));
451                         result = true;
452                     }
453                 }
454                 return result;
455             }
456             
457             public boolean removeAll(Collection c){
458                 boolean result = false;
459                 for (Iterator cs = c.iterator(); cs.hasNext(); ){
460                     if (IndirectMap.this.remove(cs.next()) != null ) {
461                         result = true;
462                     }
463                 }
464                 return result;
465             }
466         
467             public void clear(){
468                 IndirectMap.this.clear();
469             }
470         
471             public boolean equals(Object JavaDoc o){
472                 return this.delegateSet.equals(o);
473             }
474             
475             public int hashCode(){
476                 return this.delegateSet.hashCode();
477             }
478         };
479             
480             
481     }
482
483     /**
484      * @see java.util.Hashtable#put(java.lang.Object, java.lang.Object)
485      */

486     public synchronized Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
487         Object JavaDoc oldValue = this.getDelegate().put(key, value);
488         if (oldValue != null){
489             raiseRemoveChangeEvent(key, oldValue);
490         }
491         raiseAddChangeEvent(key, value);
492         return oldValue;
493     }
494     
495
496     /**
497      * @see java.util.Hashtable#putAll(java.util.Map)
498      */

499     public synchronized void putAll(Map t) {
500         this.getDelegate().putAll(t);
501     }
502
503     /**
504      * @see java.util.Hashtable#rehash()
505      */

506     protected void rehash() {
507         throw new InternalError JavaDoc("unsupported");
508     }
509
510     /**
511      * Raise the add change event and relationship maintainence.
512      */

513     protected void raiseAddChangeEvent(Object JavaDoc key, Object JavaDoc value) {
514         // this is where relationship maintenance would go
515
}
516
517     /**
518      * Raise the remove change event.
519      */

520     protected void raiseRemoveChangeEvent(Object JavaDoc key, Object JavaDoc value) {
521         // this is where relationship maintenance would go
522
}
523
524     /**
525      * @see java.util.Hashtable#remove(java.lang.Object)
526      */

527     public synchronized Object JavaDoc remove(Object JavaDoc key) {
528         Object JavaDoc value = this.getDelegate().remove(key);
529         if (value != null){
530             raiseRemoveChangeEvent(key, value);
531         }
532         return value;
533     }
534
535     /**
536      * Set the mapping attribute name, used to raise change events.
537      * This is required if the change listener is set.
538      */

539      public void setTopLinkAttributeName(String JavaDoc attributeName) {
540          this.attributeName = attributeName;
541      }
542      
543     /**
544      * PUBLIC:
545      * Set the value holder.
546      */

547     public void setValueHolder(ValueHolderInterface valueHolder) {
548         this.delegate = null;
549         this.valueHolder = valueHolder;
550     }
551
552     /**
553      * @see java.util.Hashtable#size()
554      */

555     public int size() {
556         return this.getDelegate().size();
557     }
558
559     /**
560      * PUBLIC:
561      * Use the Hashtable.toString(); but wrap it with braces to indicate
562      * there is a bit of indirection.
563      * Don't allow this method to trigger a database read.
564      * @see java.util.Hashtable#toString()
565      */

566     public String JavaDoc toString() {
567         if (ValueHolderInterface.shouldToStringInstantiate) {
568             return this.getDelegate().toString();
569         }
570         if (this.isInstantiated()) {
571             return "{" + this.getDelegate().toString() + "}";
572         } else {
573             return "{" + oracle.toplink.essentials.internal.helper.Helper.getShortClassName(this.getClass()) + ": not instantiated}";
574         }
575     }
576
577     /**
578      * @see java.util.Hashtable#values()
579      */

580     public Collection values() {
581         return new Collection() {
582             protected Collection delegateCollection = IndirectMap.this.getDelegate().values();
583
584             public int size(){
585                 return delegateCollection.size();
586             }
587             
588             public boolean isEmpty(){
589                 return delegateCollection.isEmpty();
590             }
591             
592             public boolean contains(Object JavaDoc o){
593                 return delegateCollection.contains(o);
594             }
595             
596             public Iterator iterator() {
597                 return new Iterator() {
598                     Iterator delegateIterator = delegateCollection.iterator();
599                     Object JavaDoc currentObject;
600                     
601                     public boolean hasNext() {
602                         return this.delegateIterator.hasNext();
603                     }
604                     
605                     public Object JavaDoc next() {
606                         this.currentObject = this.delegateIterator.next();
607                         return this.currentObject;
608                     }
609                     
610                     public void remove() {
611                         Iterator iterator = IndirectMap.this.getDelegate().entrySet().iterator();
612                         while (iterator.hasNext()){
613                             Map.Entry entry = (Map.Entry)iterator.next();
614                             if (entry.getValue().equals(currentObject)){
615                                 IndirectMap.this.raiseRemoveChangeEvent(entry.getKey(), entry.getValue());
616                             }
617                             
618                         }
619                         this.delegateIterator.remove();
620                     }
621                 };
622             }
623         
624             public Object JavaDoc[] toArray(){
625                 return this.delegateCollection.toArray();
626             }
627             
628             public Object JavaDoc[] toArray(Object JavaDoc a[]){
629                 return this.delegateCollection.toArray(a);
630             }
631             
632             public boolean add(Object JavaDoc o){
633                 return this.delegateCollection.add(o);
634             }
635             
636             public boolean remove(Object JavaDoc o){
637                 Iterator iterator = IndirectMap.this.getDelegate().entrySet().iterator();
638                 while (iterator.hasNext()){
639                     Map.Entry entry = (Map.Entry)iterator.next();
640                     if (entry.getValue().equals(o)){
641                         IndirectMap.this.raiseRemoveChangeEvent(entry.getKey(), entry.getValue());
642                     }
643                     return true;
644                 }
645                 return false;
646             }
647             
648             public boolean containsAll(Collection c){
649                 return this.delegateCollection.containsAll(c);
650             }
651             
652             public boolean addAll(Collection c){
653                 return this.delegateCollection.addAll(c);
654             }
655             
656             public boolean removeAll(Collection c){
657                 boolean result = false;
658                 for (Iterator iterator = c.iterator(); iterator.hasNext();){
659                     if (remove(iterator.next()) ){
660                         result = true;
661                     }
662                 }
663                 return result;
664             }
665             
666             public boolean retainAll(Collection c){
667                 boolean result = false;
668                 for (Iterator iterator = IndirectMap.this.entrySet().iterator(); iterator.hasNext();){
669                     Map.Entry entry = (Map.Entry)iterator.next();
670                     if (! c.contains(entry.getValue()) ) {
671                         iterator.remove();
672                         result = true;
673                     }
674                 }
675                 return result;
676             }
677             
678             public void clear(){
679                 IndirectMap.this.clear();
680             }
681             
682             
683             public boolean equals(Object JavaDoc o){
684                 return this.delegateCollection.equals(o);
685             }
686             
687             public int hashCode(){
688                 return this.delegateCollection.hashCode();
689             }
690             
691         };
692     }
693 }
694
Popular Tags