KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > collection > AbstractPersistentCollection


1 //$Id: AbstractPersistentCollection.java,v 1.22 2005/06/17 19:36:08 oneovthafew Exp $
2
package org.hibernate.collection;
3
4 import java.io.Serializable JavaDoc;
5 import java.util.ArrayList JavaDoc;
6 import java.util.Collection JavaDoc;
7 import java.util.HashSet JavaDoc;
8 import java.util.Iterator JavaDoc;
9 import java.util.List JavaDoc;
10 import java.util.ListIterator JavaDoc;
11
12 import org.hibernate.AssertionFailure;
13 import org.hibernate.HibernateException;
14 import org.hibernate.LazyInitializationException;
15 import org.hibernate.engine.ForeignKeys;
16 import org.hibernate.engine.SessionImplementor;
17 import org.hibernate.engine.TypedValue;
18 import org.hibernate.persister.collection.CollectionPersister;
19 import org.hibernate.type.Type;
20 import org.hibernate.util.EmptyIterator;
21
22 /**
23  * Base class implementing <tt>PersistentCollection</tt>
24  * @see PersistentCollection
25  * @author Gavin King
26  */

27 public abstract class AbstractPersistentCollection
28     implements Serializable JavaDoc, PersistentCollection {
29
30     private transient SessionImplementor session;
31     private boolean initialized;
32     private transient List JavaDoc additions;
33     private transient boolean directlyAccessible;
34     private transient boolean initializing;
35     private Object JavaDoc owner;
36     
37     private String JavaDoc role;
38     private Serializable JavaDoc key;
39     // collections detect changes made via their public interface and mark
40
// themselves as dirty as a performance optimization
41
private boolean dirty;
42     private Serializable JavaDoc storedSnapshot;
43
44     public final String JavaDoc getRole() {
45         return role;
46     }
47     
48     public final Serializable JavaDoc getKey() {
49         return key;
50     }
51     
52     public final boolean isUnreferenced() {
53         return role==null;
54     }
55     
56     public final boolean isDirty() {
57         return dirty;
58     }
59     
60     public final void clearDirty() {
61         dirty = false;
62     }
63     
64     public final void dirty() {
65         dirty = true;
66     }
67     
68     public final Serializable JavaDoc getStoredSnapshot() {
69         return storedSnapshot;
70     }
71     
72     //Careful: these methods do not initialize the collection.
73
/**
74      * Is the initialized collection empty?
75      */

76     public abstract boolean empty();
77     /**
78      * Called by any read-only method of the collection interface
79      */

80     protected final void read() {
81         initialize(false);
82     }
83     /**
84      * Is the collection currently connected to an open session?
85      */

86     private final boolean isConnectedToSession() {
87         return session!=null && session.isOpen();
88     }
89
90     /**
91      * Called by any writer method of the collection interface
92      */

93     protected final void write() {
94         initialize(true);
95         dirty();
96     }
97     /**
98      * Is this collection in a state that would allow us to
99      * "queue" additions?
100      */

101     private boolean isQueueAdditionEnabled() {
102         return !initialized &&
103             isConnectedToSession() &&
104             session.getPersistenceContext().isInverseCollection(this);
105     }
106     /**
107      * Queue an addition
108      */

109     protected final boolean queueAdd(Object JavaDoc element) {
110         if ( isQueueAdditionEnabled() ) {
111             if (additions==null) additions = new ArrayList JavaDoc(10);
112             additions.add(element);
113             dirty = true; //needed so that we remove this collection from the second-level cache
114
return true;
115         }
116         else {
117             return false;
118         }
119     }
120     /**
121      * Queue additions
122      */

123     protected final boolean queueAddAll(Collection JavaDoc coll) {
124         if ( isQueueAdditionEnabled() ) {
125             if (additions==null) additions = new ArrayList JavaDoc(20);
126             additions.addAll(coll);
127             return true;
128         }
129         else {
130             return false;
131         }
132     }
133
134     /**
135      * After reading all existing elements from the database,
136      * add the queued elements to the underlying collection.
137      */

138     public void delayedAddAll(Collection JavaDoc coll) {
139         throw new AssertionFailure("Collection does not support delayed initialization");
140     }
141
142     /**
143      * After flushing, re-init snapshot state.
144      */

145     public void setSnapshot(Serializable JavaDoc key, String JavaDoc role, Serializable JavaDoc snapshot) {
146         this.key = key;
147         this.role = role;
148         this.storedSnapshot = snapshot;
149     }
150
151     /**
152      * After flushing, clear any "queued" additions, since the
153      * database state is now synchronized with the memory state.
154      */

155     public void postAction() {
156         if (additions!=null) additions=null;
157         clearDirty();
158     }
159     
160     /**
161      * Not called by Hibernate, but used by non-JDK serialization,
162      * eg. SOAP libraries.
163      */

164     public AbstractPersistentCollection() {}
165
166     protected AbstractPersistentCollection(SessionImplementor session) {
167         this.session = session;
168     }
169
170     /**
171      * return the user-visible collection (or array) instance
172      */

173     public Object JavaDoc getValue() {
174         return this;
175     }
176
177     /**
178      * Called just before reading any rows from the JDBC result set
179      */

180     public void beginRead() {
181         // override on some subclasses
182
initializing = true;
183     }
184
185     /**
186      * Called after reading all rows from the JDBC result set
187      */

188     public boolean endRead() {
189         //override on some subclasses
190
return afterInitialize();
191     }
192     
193     public boolean afterInitialize() {
194         setInitialized();
195         //do this bit after setting initialized to true or it will recurse
196
if (additions!=null) {
197             delayedAddAll(additions);
198             additions=null;
199             return false;
200         }
201         else {
202             return true;
203         }
204     }
205
206     /**
207      * Initialize the collection, if possible, wrapping any exceptions
208      * in a runtime exception
209      * @param writing currently obsolete
210      * @throws LazyInitializationException if we cannot initialize
211      */

212     protected final void initialize(boolean writing) {
213         if (!initialized) {
214             if (initializing) {
215                 throw new LazyInitializationException("illegal access to loading collection");
216             }
217             if ( isConnectedToSession() ) {
218                 if ( session.isConnected() ) {
219                     session.initializeCollection(this, writing);
220                 }
221                 else {
222                     throwLazyInitializationException("session is disconnected");
223                 }
224             }
225             else {
226                 throwLazyInitializationException("no session or session was closed");
227             }
228         }
229     }
230     
231     private void throwLazyInitializationException(String JavaDoc msg) {
232         throw new LazyInitializationException(
233                 "failed to lazily initialize a collection" +
234                 (role==null ? "" : " of role: " + role) +
235                 ", " + msg
236             );
237     }
238
239     protected final void setInitialized() {
240         this.initializing = false;
241         this.initialized = true;
242     }
243
244     protected final void setDirectlyAccessible(boolean directlyAccessible) {
245         this.directlyAccessible = directlyAccessible;
246     }
247
248     /**
249      * Could the application possibly have a direct reference to
250      * the underlying collection implementation?
251      */

252     public boolean isDirectlyAccessible() {
253         return directlyAccessible;
254     }
255
256     /**
257      * Disassociate this collection from the given session.
258      * @return true if this was currently associated with the given session
259      */

260     public final boolean unsetSession(SessionImplementor currentSession) {
261         if (currentSession==this.session) {
262             this.session=null;
263             return true;
264         }
265         else {
266             return false;
267         }
268     }
269
270     /**
271      * Associate the collection with the given session.
272      * @return false if the collection was already associated with the session
273      * @throws HibernateException if the collection was already associated
274      * with another open session
275      */

276     public final boolean setCurrentSession(SessionImplementor session) throws HibernateException {
277         if (session==this.session) {
278             return false;
279         }
280         else {
281             if ( isConnectedToSession() ) {
282                 throw new HibernateException("Illegal attempt to associate a collection with two open sessions");
283             }
284             else {
285                 this.session = session;
286                 return true;
287             }
288         }
289     }
290
291     /**
292      * Do we need to completely recreate this collection when it changes?
293      */

294     public boolean needsRecreate(CollectionPersister persister) {
295         return false;
296     }
297     
298     /**
299      * To be called internally by the session, forcing
300      * immediate initialization.
301      */

302     public final void forceInitialization() throws HibernateException {
303         if (!initialized) {
304             if (initializing) {
305                 throw new AssertionFailure("force initialize loading collection");
306             }
307             if (session==null) {
308                 throw new HibernateException("collection is not associated with any session");
309             }
310             if ( !session.isConnected() ) {
311                 throw new HibernateException("disconnected session");
312             }
313             session.initializeCollection(this, false);
314         }
315     }
316
317
318     /**
319      * Get the current snapshot from the session
320      */

321     protected final Serializable JavaDoc getSnapshot() {
322         return session.getPersistenceContext().getSnapshot(this);
323     }
324
325     /**
326      * Is this instance initialized?
327      */

328     public final boolean wasInitialized() {
329         return initialized;
330     }
331     
332     public boolean isRowUpdatePossible() {
333         return true;
334     }
335
336     /**
337      * Does this instance have any "queued" additions?
338      */

339     public final boolean hasQueuedAdditions() {
340         return additions!=null;
341     }
342     /**
343      * Iterate the "queued" additions
344      */

345     public final Iterator JavaDoc queuedAdditionIterator() {
346         return hasQueuedAdditions() ?
347             additions.iterator() :
348             EmptyIterator.INSTANCE;
349     }
350
351     /**
352      * Called before inserting rows, to ensure that any surrogate keys
353      * are fully generated
354      */

355     public void preInsert(CollectionPersister persister) throws HibernateException {}
356     /**
357      * Called after inserting a row, to fetch the natively generated id
358      */

359     public void afterRowInsert(CollectionPersister persister, Object JavaDoc entry, int i) throws HibernateException {}
360     /**
361      * get all "orphaned" elements
362      */

363     public abstract Collection JavaDoc getOrphans(Serializable JavaDoc snapshot, String JavaDoc entityName) throws HibernateException;
364
365     /**
366      * Get the current session
367      */

368     protected final SessionImplementor getSession() {
369         return session;
370     }
371
372     final class IteratorProxy implements Iterator JavaDoc {
373         private final Iterator JavaDoc iter;
374         IteratorProxy(Iterator JavaDoc iter) {
375             this.iter=iter;
376         }
377         public boolean hasNext() {
378             return iter.hasNext();
379         }
380
381         public Object JavaDoc next() {
382             return iter.next();
383         }
384
385         public void remove() {
386             write();
387             iter.remove();
388         }
389
390     }
391
392     final class ListIteratorProxy implements ListIterator JavaDoc {
393         private final ListIterator JavaDoc iter;
394         ListIteratorProxy(ListIterator JavaDoc iter) {
395             this.iter = iter;
396         }
397         public void add(Object JavaDoc o) {
398             write();
399             iter.add(o);
400         }
401
402         public boolean hasNext() {
403             return iter.hasNext();
404         }
405
406         public boolean hasPrevious() {
407             return iter.hasPrevious();
408         }
409
410         public Object JavaDoc next() {
411             return iter.next();
412         }
413
414         public int nextIndex() {
415             return iter.nextIndex();
416         }
417
418         public Object JavaDoc previous() {
419             return iter.previous();
420         }
421
422         public int previousIndex() {
423             return iter.previousIndex();
424         }
425
426         public void remove() {
427             write();
428             iter.remove();
429         }
430
431         public void set(Object JavaDoc o) {
432             write();
433             iter.set(o);
434         }
435
436     }
437
438     class SetProxy implements java.util.Set JavaDoc {
439
440         final Collection JavaDoc set;
441
442         SetProxy(Collection JavaDoc set) {
443             this.set=set;
444         }
445         public boolean add(Object JavaDoc o) {
446             write();
447             return set.add(o);
448         }
449
450         public boolean addAll(Collection JavaDoc c) {
451             write();
452             return set.addAll(c);
453         }
454
455         public void clear() {
456             write();
457             set.clear();
458         }
459
460         public boolean contains(Object JavaDoc o) {
461             return set.contains(o);
462         }
463
464         public boolean containsAll(Collection JavaDoc c) {
465             return set.containsAll(c);
466         }
467
468         public boolean isEmpty() {
469             return set.isEmpty();
470         }
471
472         public Iterator JavaDoc iterator() {
473             return new IteratorProxy( set.iterator() );
474         }
475
476         public boolean remove(Object JavaDoc o) {
477             write();
478             return set.remove(o);
479         }
480
481         public boolean removeAll(Collection JavaDoc c) {
482             write();
483             return set.removeAll(c);
484         }
485
486         public boolean retainAll(Collection JavaDoc c) {
487             write();
488             return set.retainAll(c);
489         }
490
491         public int size() {
492             return set.size();
493         }
494
495         public Object JavaDoc[] toArray() {
496             return set.toArray();
497         }
498
499         public Object JavaDoc[] toArray(Object JavaDoc[] array) {
500             return set.toArray(array);
501         }
502
503     }
504
505     final class ListProxy implements java.util.List JavaDoc {
506
507         private final java.util.List JavaDoc list;
508
509         ListProxy(java.util.List JavaDoc list) {
510             this.list = list;
511         }
512
513         public void add(int index, Object JavaDoc value) {
514             write();
515             list.add(index, value);
516         }
517
518         /**
519          * @see java.util.Collection#add(Object)
520          */

521         public boolean add(Object JavaDoc o) {
522             write();
523             return list.add(o);
524         }
525
526         /**
527          * @see java.util.Collection#addAll(Collection)
528          */

529         public boolean addAll(Collection JavaDoc c) {
530             write();
531             return list.addAll(c);
532         }
533
534         /**
535          * @see java.util.List#addAll(int, Collection)
536          */

537         public boolean addAll(int i, Collection JavaDoc c) {
538             write();
539             return list.addAll(i, c);
540         }
541
542         /**
543          * @see java.util.Collection#clear()
544          */

545         public void clear() {
546             write();
547             list.clear();
548         }
549
550         /**
551          * @see java.util.Collection#contains(Object)
552          */

553         public boolean contains(Object JavaDoc o) {
554             return list.contains(o);
555         }
556
557         /**
558          * @see java.util.Collection#containsAll(Collection)
559          */

560         public boolean containsAll(Collection JavaDoc c) {
561             return list.containsAll(c);
562         }
563
564         /**
565          * @see java.util.List#get(int)
566          */

567         public Object JavaDoc get(int i) {
568             return list.get(i);
569         }
570
571         /**
572          * @see java.util.List#indexOf(Object)
573          */

574         public int indexOf(Object JavaDoc o) {
575             return list.indexOf(o);
576         }
577
578         /**
579          * @see java.util.Collection#isEmpty()
580          */

581         public boolean isEmpty() {
582             return list.isEmpty();
583         }
584
585         /**
586          * @see java.util.Collection#iterator()
587          */

588         public Iterator JavaDoc iterator() {
589             return new IteratorProxy( list.iterator() );
590         }
591
592         /**
593          * @see java.util.List#lastIndexOf(Object)
594          */

595         public int lastIndexOf(Object JavaDoc o) {
596             return list.lastIndexOf(o);
597         }
598
599         /**
600          * @see java.util.List#listIterator()
601          */

602         public ListIterator JavaDoc listIterator() {
603             return new ListIteratorProxy( list.listIterator() );
604         }
605
606         /**
607          * @see java.util.List#listIterator(int)
608          */

609         public ListIterator JavaDoc listIterator(int i) {
610             return new ListIteratorProxy( list.listIterator(i) );
611         }
612
613         /**
614          * @see java.util.List#remove(int)
615          */

616         public Object JavaDoc remove(int i) {
617             write();
618             return list.remove(i);
619         }
620
621         /**
622          * @see java.util.Collection#remove(Object)
623          */

624         public boolean remove(Object JavaDoc o) {
625             write();
626             return list.remove(o);
627         }
628
629         /**
630          * @see java.util.Collection#removeAll(Collection)
631          */

632         public boolean removeAll(Collection JavaDoc c) {
633             write();
634             return list.removeAll(c);
635         }
636
637         /**
638          * @see java.util.Collection#retainAll(Collection)
639          */

640         public boolean retainAll(Collection JavaDoc c) {
641             write();
642             return list.retainAll(c);
643         }
644
645         /**
646          * @see java.util.List#set(int, Object)
647          */

648         public Object JavaDoc set(int i, Object JavaDoc o) {
649             write();
650             return list.set(i, o);
651         }
652
653         /**
654          * @see java.util.Collection#size()
655          */

656         public int size() {
657             return list.size();
658         }
659
660         /**
661          * @see java.util.List#subList(int, int)
662          */

663         public List JavaDoc subList(int i, int j) {
664             return list.subList(i, j);
665         }
666
667         /**
668          * @see java.util.Collection#toArray()
669          */

670         public Object JavaDoc[] toArray() {
671             return list.toArray();
672         }
673
674         /**
675          * @see java.util.Collection#toArray(Object[])
676          */

677         public Object JavaDoc[] toArray(Object JavaDoc[] array) {
678             return list.toArray(array);
679         }
680
681     }
682
683
684     protected static Collection JavaDoc getOrphans(
685             Collection JavaDoc oldElements,
686             Collection JavaDoc currentElements,
687             String JavaDoc entityName,
688             SessionImplementor session)
689     throws HibernateException {
690
691         // short-circuit(s)
692
if ( currentElements.size()==0 ) return oldElements; // no new elements, the old list contains only Orphans
693
if ( oldElements.size()==0) return oldElements; // no old elements, so no Orphans neither
694

695         Type idType = session.getFactory().getEntityPersister(entityName).getIdentifierType();
696
697         // create the collection holding the Orphans
698
Collection JavaDoc res = new ArrayList JavaDoc();
699
700         // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
701
java.util.Set JavaDoc currentIds = new HashSet JavaDoc();
702         for ( Iterator JavaDoc it=currentElements.iterator(); it.hasNext(); ) {
703             Object JavaDoc current = it.next();
704             if ( current!=null && ForeignKeys.isNotTransient(entityName, current, null, session) ) {
705                 Serializable JavaDoc currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, current, session);
706                 currentIds.add( new TypedValue( idType, currentId, session.getEntityMode() ) );
707             }
708         }
709
710         // iterate over the *old* list
711
for ( Iterator JavaDoc it=oldElements.iterator(); it.hasNext(); ) {
712             Object JavaDoc old = it.next();
713             Serializable JavaDoc oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, old, session);
714             if ( !currentIds.contains( new TypedValue( idType, oldId, session.getEntityMode() ) ) ) res.add(old);
715         }
716
717         return res;
718     }
719
720     static void identityRemove(
721             Collection JavaDoc list,
722             Object JavaDoc object,
723             String JavaDoc entityName,
724             SessionImplementor session)
725     throws HibernateException {
726
727         if ( object!=null && ForeignKeys.isNotTransient(entityName, object, null, session) ) {
728             
729             Type idType = session.getFactory().getEntityPersister(entityName).getIdentifierType();
730
731             Serializable JavaDoc idOfCurrent = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, object, session);
732             Iterator JavaDoc iter = list.iterator();
733             while ( iter.hasNext() ) {
734                 Serializable JavaDoc idOfOld = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, iter.next(), session);
735                 if ( idType.isEqual( idOfCurrent, idOfOld, session.getEntityMode(), session.getFactory() ) ) {
736                     iter.remove();
737                     break;
738                 }
739             }
740
741         }
742     }
743     
744     public Object JavaDoc getIdentifier(Object JavaDoc entry, int i) {
745         throw new UnsupportedOperationException JavaDoc();
746     }
747     
748     public Object JavaDoc getOwner() {
749         return owner;
750     }
751     
752     public void setOwner(Object JavaDoc owner) {
753         this.owner = owner;
754     }
755     
756 }
757
Popular Tags