KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > engine > CollectionEntry


1 //$Id: CollectionEntry.java,v 1.18 2005/06/19 16:39:53 oneovthafew Exp $
2
package org.hibernate.engine;
3
4 import java.io.Serializable JavaDoc;
5 import java.util.Collection JavaDoc;
6
7 import org.apache.commons.logging.Log;
8 import org.apache.commons.logging.LogFactory;
9 import org.hibernate.AssertionFailure;
10 import org.hibernate.HibernateException;
11 import org.hibernate.MappingException;
12 import org.hibernate.collection.PersistentCollection;
13 import org.hibernate.persister.collection.CollectionPersister;
14 import org.hibernate.pretty.MessageHelper;
15
16 /**
17  * We need an entry to tell us all about the current state
18  * of a collection with respect to its persistent state
19  *
20  * @author Gavin King
21  */

22 public final class CollectionEntry implements Serializable JavaDoc {
23
24     private static final Log log = LogFactory.getLog(CollectionEntry.class);
25     
26     //ATTRIBUTES MAINTAINED BETWEEN FLUSH CYCLES
27

28     // session-start/post-flush persistent state
29
private Serializable JavaDoc snapshot;
30     // allow the CollectionSnapshot to be serialized
31
private String JavaDoc role;
32     
33     // "loaded" means the reference that is consistent
34
// with the current database state
35
private transient CollectionPersister loadedPersister;
36     private Serializable JavaDoc loadedKey;
37
38     // ATTRIBUTES USED ONLY DURING FLUSH CYCLE
39

40     // during flush, we navigate the object graph to
41
// collections and decide what to do with them
42
private transient boolean reached;
43     private transient boolean processed;
44     private transient boolean doupdate;
45     private transient boolean doremove;
46     private transient boolean dorecreate;
47     // if we instantiate a collection during the flush() process,
48
// we must ignore it for the rest of the flush()
49
private transient boolean ignore;
50     
51     // "current" means the reference that was found during flush()
52
private transient CollectionPersister currentPersister;
53     private transient Serializable JavaDoc currentKey;
54
55     /**
56      * For newly wrapped collections, or dereferenced collection wrappers
57      */

58     public CollectionEntry(CollectionPersister persister, PersistentCollection collection) {
59         // new collections that get found + wrapped
60
// during flush shouldn't be ignored
61
ignore = false;
62
63         collection.clearDirty(); //a newly wrapped collection is NOT dirty (or we get unnecessary version updates)
64

65         snapshot = persister.isMutable() ?
66                 collection.getSnapshot(persister) :
67                 null;
68         collection.setSnapshot(loadedKey, role, snapshot);
69     }
70
71     /**
72      * For collections just loaded from the database
73      */

74     public CollectionEntry(
75             final PersistentCollection collection,
76             final CollectionPersister loadedPersister,
77             final Serializable JavaDoc loadedKey,
78             final boolean ignore
79     ) {
80         this.ignore=ignore;
81
82         //collection.clearDirty()
83

84         this.loadedKey = loadedKey;
85         setLoadedPersister(loadedPersister);
86
87         collection.setSnapshot(loadedKey, role, null);
88
89         //postInitialize() will be called after initialization
90
}
91
92     /**
93      * For uninitialized detached collections
94      */

95     public CollectionEntry(CollectionPersister loadedPersister, Serializable JavaDoc loadedKey) {
96         // detached collection wrappers that get found + reattached
97
// during flush shouldn't be ignored
98
ignore = false;
99
100         //collection.clearDirty()
101

102         this.loadedKey = loadedKey;
103         setLoadedPersister(loadedPersister);
104     }
105     
106     /**
107      * For initialized detached collections
108      */

109     CollectionEntry(PersistentCollection collection, SessionFactoryImplementor factory)
110     throws MappingException {
111         // detached collections that get found + reattached
112
// during flush shouldn't be ignored
113
ignore = false;
114
115         loadedKey = collection.getKey();
116         setLoadedPersister( factory.getCollectionPersister( collection.getRole() ) );
117
118         snapshot = collection.getStoredSnapshot();
119     }
120
121     /**
122      * Determine if the collection is "really" dirty, by checking dirtiness
123      * of the collection elements, if necessary
124      */

125     private void dirty(PersistentCollection collection) throws HibernateException {
126         
127         boolean forceDirty = collection.wasInitialized() &&
128                 !collection.isDirty() && //optimization
129
getLoadedPersister() != null &&
130                 getLoadedPersister().isMutable() && //optimization
131
( collection.isDirectlyAccessible() || getLoadedPersister().getElementType().isMutable() ) && //optimization
132
!collection.equalsSnapshot( getLoadedPersister() );
133         
134         if ( forceDirty ) {
135             collection.dirty();
136         }
137         
138     }
139
140     public void preFlush(PersistentCollection collection) throws HibernateException {
141         
142         boolean nonMutableChange = collection.isDirty() &&
143                 getLoadedPersister()!=null &&
144                 !getLoadedPersister().isMutable();
145         if (nonMutableChange) {
146             throw new HibernateException(
147                     "changed an immutable collection instance: " +
148                     MessageHelper.collectionInfoString( getLoadedPersister().getRole(), getLoadedKey() )
149                 );
150         }
151         
152         dirty(collection);
153         
154         if ( log.isDebugEnabled() && collection.isDirty() && getLoadedPersister() != null ) {
155             log.debug(
156                     "Collection dirty: " +
157                     MessageHelper.collectionInfoString( getLoadedPersister().getRole(), getLoadedKey() )
158                 );
159         }
160
161         setDoupdate(false);
162         setDoremove(false);
163         setDorecreate(false);
164         setReached(false);
165         setProcessed(false);
166     }
167
168     public void postInitialize(PersistentCollection collection) throws HibernateException {
169         snapshot = getLoadedPersister().isMutable() ?
170                 collection.getSnapshot( getLoadedPersister() ) :
171                 null;
172         collection.setSnapshot(loadedKey, role, snapshot);
173     }
174
175     /**
176      * Called after a successful flush
177      */

178     public void postFlush(PersistentCollection collection) throws HibernateException {
179         if ( isIgnore() ) {
180             ignore = false;
181         }
182         else if ( !isProcessed() ) {
183             throw new AssertionFailure( "collection was not processed by flush()" );
184         }
185         collection.setSnapshot(loadedKey, role, snapshot);
186     }
187     
188     /**
189      * Called after execution of an action
190      */

191     public void afterAction(PersistentCollection collection) {
192         loadedKey = getCurrentKey();
193         setLoadedPersister( getCurrentPersister() );
194         
195         boolean resnapshot = collection.wasInitialized() &&
196                 ( isDoremove() || isDorecreate() || isDoupdate() );
197         if ( resnapshot ) {
198             snapshot = loadedPersister==null || !loadedPersister.isMutable() ?
199                     null :
200                     collection.getSnapshot(loadedPersister); //re-snapshot
201
}
202         
203         collection.postAction();
204     }
205
206     public Serializable JavaDoc getKey() {
207         return getLoadedKey();
208     }
209
210     public String JavaDoc getRole() {
211         return role;
212     }
213
214     public Serializable JavaDoc getSnapshot() {
215         return snapshot;
216     }
217
218     private void setLoadedPersister(CollectionPersister persister) {
219         loadedPersister = persister;
220         setRole( persister == null ? null : persister.getRole() );
221     }
222     
223     void afterDeserialize(SessionFactoryImplementor factory) {
224         loadedPersister = factory.getCollectionPersister(role);
225     }
226
227     public boolean wasDereferenced() {
228         return getLoadedKey() == null;
229     }
230
231     public boolean isReached() {
232         return reached;
233     }
234
235     public void setReached(boolean reached) {
236         this.reached = reached;
237     }
238
239     public boolean isProcessed() {
240         return processed;
241     }
242
243     public void setProcessed(boolean processed) {
244         this.processed = processed;
245     }
246
247     public boolean isDoupdate() {
248         return doupdate;
249     }
250
251     public void setDoupdate(boolean doupdate) {
252         this.doupdate = doupdate;
253     }
254
255     public boolean isDoremove() {
256         return doremove;
257     }
258
259     public void setDoremove(boolean doremove) {
260         this.doremove = doremove;
261     }
262
263     public boolean isDorecreate() {
264         return dorecreate;
265     }
266
267     public void setDorecreate(boolean dorecreate) {
268         this.dorecreate = dorecreate;
269     }
270
271     public boolean isIgnore() {
272         return ignore;
273     }
274
275     public CollectionPersister getCurrentPersister() {
276         return currentPersister;
277     }
278
279     public void setCurrentPersister(CollectionPersister currentPersister) {
280         this.currentPersister = currentPersister;
281     }
282
283     /**
284      * This is only available late during the flush
285      * cycle
286      */

287     public Serializable JavaDoc getCurrentKey() {
288         return currentKey;
289     }
290
291     public void setCurrentKey(Serializable JavaDoc currentKey) {
292         this.currentKey = currentKey;
293     }
294     
295     /**
296      * This is only available late during the flush cycle
297      */

298     public CollectionPersister getLoadedPersister() {
299         return loadedPersister;
300     }
301
302     public Serializable JavaDoc getLoadedKey() {
303         return loadedKey;
304     }
305
306     public void setRole(String JavaDoc role) {
307         this.role = role;
308     }
309
310     public String JavaDoc toString() {
311         String JavaDoc result = "CollectionEntry" +
312                 MessageHelper.collectionInfoString( loadedPersister.getRole(), loadedKey );
313         if (currentPersister!=null) {
314             result += "->" +
315                     MessageHelper.collectionInfoString( currentPersister.getRole(), currentKey );
316         }
317         return result;
318     }
319
320     /**
321      * Get the collection orphans (entities which were removed from the collection)
322      */

323     public Collection JavaDoc getOrphans(String JavaDoc entityName, PersistentCollection collection)
324     throws HibernateException {
325         if (snapshot==null) {
326             throw new AssertionFailure("no collection snapshot for orphan delete");
327         }
328         return collection.getOrphans( snapshot, entityName );
329     }
330
331     public boolean isSnapshotEmpty(PersistentCollection collection) {
332         //TODO: does this really need to be here?
333
// does the collection already have
334
// it's own up-to-date snapshot?
335
return collection.wasInitialized() &&
336             ( getLoadedPersister()==null || getLoadedPersister().isMutable() ) &&
337             collection.isSnapshotEmpty( getSnapshot() );
338     }
339
340 }
Popular Tags