KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > sessions > CollectionChangeRecord


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, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.sessions;
23
24 import oracle.toplink.essentials.internal.helper.IdentityHashtable;
25 import java.util.*;
26 import oracle.toplink.essentials.descriptors.ClassDescriptor;
27
28 /**
29  * <p>
30  * <b>Purpose</b>: This class holds the record of the changes made to a collection attribute of
31  * an object.
32  * <p>
33  * <b>Description</b>: Collections must be compared to each other and added and removed objects must
34  * be recorded seperately
35  * @see OtherRelatedClasses prototype.changeset.DirectToFieldChangeRecord,prototype.changeset.SingleObjectChangeRecord
36  */

37 public class CollectionChangeRecord extends ChangeRecord implements oracle.toplink.essentials.changesets.CollectionChangeRecord {
38
39     /**
40      * Contains the added values to the collection and their corresponding ChangeSets.
41      */

42     protected IdentityHashtable addObjectList;
43     
44     /**
45      * Contains the added values to the collection and their corresponding ChangeSets in order.
46      */

47     protected transient Vector orderedAddObjects;
48     
49     /**
50      * Contains the added values index to the collection.
51      */

52     protected IdentityHashtable orderedAddObjectIndices;
53     
54     /**
55      * Contains the removed values to the collection and their corresponding ChangeSets.
56      */

57     protected Hashtable orderedRemoveObjects;
58     
59     /**
60      * Contains the removed values index to the collection.
61      */

62     protected transient Vector orderedRemoveObjectIndices;
63     
64     /**
65      * Contains a list of extra adds. These extra adds are used by attribute change tracking
66      * to replicate behaviour when someone adds the same object to a list and removes it once
67      * In this case the object should still appear once in the change set.
68      */

69      protected transient List addOverFlow;
70
71     /**
72      * Contains the removed values from the collection and their corresponding ChangeSets.
73      */

74     protected IdentityHashtable removeObjectList;
75
76     /**
77      * Contain the same added values as in addObjectList. It is only used by SDK mapping of this change record.
78      */

79     protected transient Vector sdkAddObjects;
80
81     /**
82      * Contain the same added values as in addObjectList. It is only used by SDK mapping of this change record.
83      */

84     protected transient Vector sdkRemoveObjects;
85     
86     /**
87      * Used for change tracking when customer sets entire collection
88      */

89     protected transient Object JavaDoc originalCollection;
90
91     /**
92      * Used for change tracking when customer sets entire collection
93      */

94     protected transient Object JavaDoc latestCollection;
95
96     /**
97      * This default constructor is reference internally by SDK XML project to mapp this class
98      */

99     public CollectionChangeRecord() {
100         super();
101     }
102
103     /**
104      * Constructor for the ChangeRecord representing a collection mapping
105      * @param owner prototype.changeset.ObjectChangeSet the changeSet that uses this record
106      */

107     public CollectionChangeRecord(ObjectChangeSet owner) {
108         this.owner = owner;
109     }
110     
111     /**
112      * This method takes a IdentityHashtable of objects, converts these into
113      * ObjectChangeSets.
114      * @param objectChanges prototype.changeset.ObjectChangeSet
115      */

116     public void addAdditionChange(IdentityHashMap objectChanges, UnitOfWorkChangeSet changeSet, AbstractSession session) {
117         Iterator enumtr = objectChanges.keySet().iterator();
118         while (enumtr.hasNext()) {
119             Object JavaDoc object = enumtr.next();
120             ObjectChangeSet change = session.getDescriptor(object.getClass()).getObjectBuilder().createObjectChangeSet(object, changeSet, session);
121             if (change.hasKeys()){
122                 // if change set has keys this is a map comparison. Maps are
123
// not support in change tracking so do not need to prevent duplicates
124
// when map support is added this will have to be refactored
125
getAddObjectList().put(change, change);
126             }else{
127                 if (getRemoveObjectList().contains(change)){
128                     getRemoveObjectList().remove(change);
129                 }else{
130                     getAddObjectList().put(change, change);
131                 }
132             }
133         }
134     }
135     
136     /**
137      * INTERNAL:
138      * This method takes a Vector of objects and converts them into
139      * ObjectChangeSets. This method should only be called from a
140      * ListContainerPolicy. Additions to the list are made by index, hence,
141      * the second IdentityHashtable of objectChangesIndices.
142      */

143     public void addOrderedAdditionChange(Vector objectChanges, IdentityHashtable objectChangesIndices, UnitOfWorkChangeSet changeSet, AbstractSession session) {
144         Enumeration e = objectChanges.elements();
145         
146         while (e.hasMoreElements()) {
147             Object JavaDoc object = e.nextElement();
148             ObjectChangeSet change = session.getDescriptor(object.getClass()).getObjectBuilder().createObjectChangeSet(object, changeSet, session);
149             
150             getOrderedAddObjects().add(change);
151             getOrderedAddObjectIndices().put(change, (Integer JavaDoc) objectChangesIndices.get(object));
152         }
153     }
154     
155     /**
156      * INTERNAL:
157      * This method takes a Hashtable of objects and converts them into
158      * ObjectChangeSets. This method should only be called from a
159      * ListContainerPolicy. Deletions from the list is made by index, hence,
160      * the second Vector of indicesToRemove.
161      */

162     public void addOrderedRemoveChange(Vector indicesToRemove, Hashtable objectChanges, UnitOfWorkChangeSet changeSet, AbstractSession session) {
163         orderedRemoveObjectIndices = indicesToRemove;
164         Enumeration e = orderedRemoveObjectIndices.elements();
165         
166         while (e.hasMoreElements()) {
167             Integer JavaDoc index = (Integer JavaDoc) e.nextElement();
168             Object JavaDoc object = objectChanges.get(index);
169             ObjectChangeSet change = session.getDescriptor(object.getClass()).getObjectBuilder().createObjectChangeSet(object, changeSet, session);
170
171             getOrderedRemoveObjects().put(index, change);
172         }
173     }
174
175     /**
176      * This method takes a IdentityHashtable of objects, converts these into ObjectChangeSets.
177      * @param objectChanges prototype.changeset.ObjectChangeSet
178      */

179     public void addRemoveChange(IdentityHashMap objectChanges, UnitOfWorkChangeSet changeSet, AbstractSession session) {
180         // There is no need to keep track of removed new objects because it will not be in the backup,
181
// It will not be in the backup because it is new.
182
Iterator enumtr = objectChanges.keySet().iterator();
183         while (enumtr.hasNext()) {
184             Object JavaDoc object = enumtr.next();
185             ClassDescriptor descriptor = session.getDescriptor(object.getClass());
186             ObjectChangeSet change = descriptor.getObjectBuilder().createObjectChangeSet(object, changeSet, session);
187             if (change.hasKeys()){
188                 // if change set has keys this is a map comparison. Maps are
189
// not support in change tracking so do not need to prevent duplicates
190
// when map support is added this will have to be refactored
191
getRemoveObjectList().put(change, change);
192             }else{
193                 if (getAddObjectList().contains(change)){
194                     getAddObjectList().remove(change);
195                 }else{
196                     getRemoveObjectList().put(change, change);
197                 }
198             }
199         }
200     }
201
202     /**
203      * ADVANCED:
204      * This method returns the collection of ChangeSets that were added to the collection.
205      * @return java.util.Vector
206      */

207     public IdentityHashtable getAddObjectList() {
208         if (addObjectList == null) {
209             // 2612538 - the default size of IdentityHashtable (32) is appropriate
210
addObjectList = new IdentityHashtable();
211         }
212         return addObjectList;
213     }
214
215      /**
216      * ADVANCED:
217      * This method returns the collection of ChangeSets that were added to the collection.
218      * @return java.util.Vector
219      */

220     public List getAddOverFlow() {
221         if (addOverFlow == null) {
222             addOverFlow = new ArrayList();
223         }
224         return addOverFlow;
225     }
226
227    /**
228      * ADVANCED:
229      * This method returns the IdentityHashtable that contains the removed values from the collection
230      * and their corresponding ChangeSets.
231      * @return java.util.Vector
232      */

233     public IdentityHashtable getRemoveObjectList() {
234         if (removeObjectList == null) {
235             // 2612538 - the default size of IdentityHashtable (32) is appropriate
236
removeObjectList = new IdentityHashtable();
237         }
238         return removeObjectList;
239     }
240
241     /**
242      * returns true if the change set has changes
243      */

244     public boolean hasChanges() {
245         return (!( getAddObjectList().isEmpty() &&
246                     getRemoveObjectList().isEmpty() &&
247                     getOrderedAddObjects().isEmpty() &&
248                     getOrderedRemoveObjects().isEmpty()))
249                 || getOwner().isNew();
250     }
251
252     /**
253      * INTERNAL:
254      * This method will be used to merge one record into another
255      */

256     public void mergeRecord(ChangeRecord mergeFromRecord, UnitOfWorkChangeSet mergeToChangeSet, UnitOfWorkChangeSet mergeFromChangeSet) {
257         Enumeration addEnum = ((CollectionChangeRecord)mergeFromRecord).getAddObjectList().keys();
258         while (addEnum.hasMoreElements()) {
259             ObjectChangeSet mergingObject = (ObjectChangeSet)addEnum.nextElement();
260             ObjectChangeSet localChangeSet = mergeToChangeSet.findOrIntegrateObjectChangeSet(mergingObject, mergeFromChangeSet);
261             if (getRemoveObjectList().containsKey(localChangeSet)) {
262                 getRemoveObjectList().remove(localChangeSet);
263             } else {
264                 getAddObjectList().put(localChangeSet, localChangeSet);
265             }
266         }
267         Enumeration removeEnum = ((CollectionChangeRecord)mergeFromRecord).getRemoveObjectList().keys();
268         while (removeEnum.hasMoreElements()) {
269             ObjectChangeSet mergingObject = (ObjectChangeSet)removeEnum.nextElement();
270             ObjectChangeSet localChangeSet = mergeToChangeSet.findOrIntegrateObjectChangeSet(mergingObject, mergeFromChangeSet);
271             if (getAddObjectList().containsKey(localChangeSet)) {
272                 getAddObjectList().remove(localChangeSet);
273             } else {
274                 getRemoveObjectList().put(localChangeSet, localChangeSet);
275             }
276         }
277     }
278
279     /**
280      * Sets the Added objects list
281      * @param newValue java.util.Vector
282      */

283     public void setAddObjectList(IdentityHashtable objectChangesList) {
284         this.addObjectList = objectChangesList;
285     }
286
287     /**
288      * Sets the removed objects list
289      * @param newValue java.util.Vector
290      */

291     public void setRemoveObjectList(IdentityHashtable objectChangesList) {
292         this.removeObjectList = objectChangesList;
293     }
294     
295     /**
296      * INTERNAL:
297      * This method will be used to update the objectsChangeSets references
298      */

299     public void updateReferences(UnitOfWorkChangeSet mergeToChangeSet, UnitOfWorkChangeSet mergeFromChangeSet) {
300         IdentityHashtable addList = new IdentityHashtable(getAddObjectList().size());
301         IdentityHashtable removeList = new IdentityHashtable(getRemoveObjectList().size());
302         
303         // If we have ordered lists we need to iterate through those.
304
if (getOrderedAddObjects().size() > 0 || getOrderedRemoveObjectIndices().size() > 0) {
305             // Do the ordered adds first ...
306
Vector orderedAddList = new Vector(getOrderedAddObjects().size());
307             IdentityHashtable orderedAddListIndices = new IdentityHashtable(getOrderedAddObjectIndices().size());
308             
309             for (int i = 0; i < getOrderedAddObjects().size(); i++) {
310                 ObjectChangeSet changeSet = (ObjectChangeSet) getOrderedAddObjects().elementAt(i);
311                 ObjectChangeSet localChangeSet = mergeToChangeSet.findOrIntegrateObjectChangeSet(changeSet, mergeFromChangeSet);
312                 
313                 orderedAddList.add(localChangeSet);
314                 orderedAddListIndices.put(localChangeSet, getOrderedAddObjectIndices().get(changeSet));
315                 
316                 // Object was actually added and not moved.
317
if (getAddObjectList().contains(changeSet)) {
318                     addList.put(localChangeSet, localChangeSet);
319                 }
320             }
321             
322             setOrderedAddObjects(orderedAddList);
323             setOrderedAddObjectIndices(orderedAddListIndices);
324             
325             // Do the ordered removes now ...
326
Hashtable orderedRemoveList = new Hashtable(getOrderedRemoveObjects().size());
327             Enumeration changes = getOrderedRemoveObjects().keys();
328             
329             while (changes.hasMoreElements()) {
330                 Object JavaDoc index = changes.nextElement();
331                 ObjectChangeSet changeSet = (ObjectChangeSet) getOrderedRemoveObjects().get(index);
332                 ObjectChangeSet localChangeSet = mergeToChangeSet.findOrIntegrateObjectChangeSet(changeSet, mergeFromChangeSet);
333                 
334                 orderedRemoveList.put(index, localChangeSet);
335                 
336                 // Object was actually removed and not moved.
337
if (getRemoveObjectList().contains(changeSet)) {
338                     removeList.put(localChangeSet, localChangeSet);
339                 }
340             }
341             
342             setOrderedRemoveObjects(orderedRemoveList);
343             // Don't need to worry about the vector of indices (Integer's), just leave them as is.
344
} else {
345             Enumeration changes = getAddObjectList().elements();
346             while (changes.hasMoreElements()) {
347                 ObjectChangeSet localChangeSet = mergeToChangeSet.findOrIntegrateObjectChangeSet((ObjectChangeSet)changes.nextElement(), mergeFromChangeSet);
348                 addList.put(localChangeSet, localChangeSet);
349             }
350         
351             changes = getRemoveObjectList().elements();
352             while (changes.hasMoreElements()) {
353                 ObjectChangeSet localChangeSet = mergeToChangeSet.findOrIntegrateObjectChangeSet((ObjectChangeSet)changes.nextElement(), mergeFromChangeSet);
354                 removeList.put(localChangeSet, localChangeSet);
355             }
356         }
357         
358         setAddObjectList(addList);
359         setRemoveObjectList(removeList);
360     }
361
362     /**
363      * INTERNAL:
364      * This method used by SDK mapping that only supports Collection type not IdentityHashtable.
365      * This method is mapped in oracle.toplink.essentials.internal.remotecommand.CommandProject
366      * @return java.util.Vector
367      */

368     public Vector getAddObjectsForSDK() {
369         if (sdkAddObjects == null) {
370             sdkAddObjects = new Vector();
371
372             for (Enumeration enumtr = this.getAddObjectList().keys(); enumtr.hasMoreElements();) {
373                 sdkAddObjects.add(enumtr.nextElement());
374             }
375         }
376         return sdkAddObjects;
377     }
378
379     /**
380      * INTERNAL:
381      * This method used by SDK mapping that only supports Collection type not IdentityHashtable.
382      * This method is mapped in oracle.toplink.essentials.internal.remotecommand.CommandProject
383      * @param java.util.Vector addObjects
384      */

385     public void setAddObjectsForSDK(Vector addObjects) {
386         sdkAddObjects = addObjects;
387
388         // build the equivalent addObjectList
389
IdentityHashtable newList = new IdentityHashtable();
390         for (int i = 0; i < sdkAddObjects.size(); i++) {
391             Object JavaDoc change = sdkAddObjects.elementAt(i);
392             newList.put(change, change);
393         }
394         this.setAddObjectList(newList);
395     }
396
397     /**
398      * INTERNAL:
399      * This method used by SDK mapping that only supports Collection type not IdentityHashtable.
400      * This method is mapped in oracle.toplink.essentials.internal.remotecommand.CommandProject
401      * @return java.util.Vector
402      */

403     public Vector getRemoveObjectsForSDK() {
404         if (sdkRemoveObjects == null) {
405             sdkRemoveObjects = new Vector();
406
407             for (Enumeration enumtr = this.getRemoveObjectList().keys(); enumtr.hasMoreElements();) {
408                 sdkRemoveObjects.add(enumtr.nextElement());
409             }
410         }
411         return sdkRemoveObjects;
412     }
413
414     /**
415      * INTERNAL:
416      * This method used by SDK mapping that only supports Collection type not IdentityHashtable.
417      * This method is mapped in oracle.toplink.essentials.internal.remotecommand.CommandProject
418      * @param java.util.Vector removeObjects
419      */

420     public void setRemoveObjectsForSDK(Vector removeObjects) {
421         sdkRemoveObjects = removeObjects;
422
423         // build the equivalent removeObjectList
424
IdentityHashtable newList = new IdentityHashtable();
425         for (int i = 0; i < sdkRemoveObjects.size(); i++) {
426             Object JavaDoc change = sdkRemoveObjects.elementAt(i);
427             newList.put(change, change);
428         }
429         this.setRemoveObjectList(newList);
430     }
431
432     /**
433      * Used for change tracking when cutomer sets entire collection
434      * This is the last collection that was set on the object
435      */

436     public Object JavaDoc getLatestCollection() {
437         return latestCollection;
438     }
439     
440     /**
441      * ADVANCED:
442      * This method returns the collection of ChangeSets in the order they were
443      * added to the collection. This list includes those objects that were
444      * moved within the collection.
445      */

446     public Vector getOrderedAddObjects() {
447         if (orderedAddObjects == null) {
448             orderedAddObjects = new Vector();
449         }
450         
451         return orderedAddObjects;
452     }
453     
454     /**
455      * ADVANCED:
456      * This method returns the index of an object added to the collection.
457      */

458     public Integer JavaDoc getOrderedAddObjectIndex(ObjectChangeSet changes) {
459         return (Integer JavaDoc) getOrderedAddObjectIndices().get(changes);
460     }
461     
462     /**
463      * ADVANCED:
464      * This method returns the collection of ChangeSets that they were
465      * added to the collection.
466      */

467     public IdentityHashtable getOrderedAddObjectIndices() {
468         if (orderedAddObjectIndices == null) {
469             orderedAddObjectIndices = new IdentityHashtable();
470         }
471         
472         return orderedAddObjectIndices;
473     }
474     
475     /**
476      * ADVANCED:
477      * This method returns the ordered list of indices to remove from the
478      * collection.
479      */

480     public Vector getOrderedRemoveObjectIndices() {
481         if (orderedRemoveObjectIndices == null) {
482             orderedRemoveObjectIndices = new Vector();
483         }
484         
485         return orderedRemoveObjectIndices;
486     }
487     
488     /**
489      * ADVANCED:
490      * This method returns the index of an object removed from the collection.
491      */

492     public Object JavaDoc getOrderedRemoveObject(Integer JavaDoc index) {
493         return getOrderedRemoveObjects().get(index);
494     }
495     
496     /**
497      * ADVANCED:
498      * This method returns the collection of ChangeSets of objects removed from
499      * the collection.
500      */

501     public Hashtable getOrderedRemoveObjects() {
502         if (orderedRemoveObjects == null) {
503             orderedRemoveObjects = new Hashtable();
504         }
505         
506         return orderedRemoveObjects;
507     }
508
509     /**
510      * Used for change tracking when cutomer sets entire collection
511      * This is the last collection that was set on the object
512      */

513     public void setLatestCollection(Object JavaDoc latestCollection) {
514         this.latestCollection = latestCollection;
515     }
516     
517     /**
518      * ADVANCED:
519      * Sets collection of ChangeSets (and their respective index) that they
520      * were added to the collection.
521      */

522     public void setOrderedAddObjectIndices(IdentityHashtable orderedAddObjectIndices) {
523         this.orderedAddObjectIndices = orderedAddObjectIndices;
524     }
525     
526     /**
527      * ADVANCED:
528      * Sets collection of ChangeSets that they were added to the collection.
529      */

530     public void setOrderedAddObjects(Vector orderedAddObjects) {
531         this.orderedAddObjects = orderedAddObjects;
532     }
533     
534     /**
535      * ADVANCED:
536      * Sets collection of ChangeSets that they were remvoved from the collection.
537      */

538     public void setOrderedRemoveObjects(Hashtable orderedRemoveObjects) {
539         this.orderedRemoveObjects = orderedRemoveObjects;
540     }
541
542     /**
543      * Used for change tracking when cutomer sets entire collection
544      * This is the original collection that was set on the object when it was cloned
545      */

546     public Object JavaDoc getOriginalCollection() {
547         return originalCollection;
548     }
549
550     /**
551      * Used for change tracking when cutomer sets entire collection
552      * This is the original collection that was set on the object when it was cloned
553      */

554     public void setOriginalCollection(Object JavaDoc originalCollection) {
555         this.originalCollection = originalCollection;
556     }
557 }
558
Popular Tags