KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > descriptors > DescriptorIterator


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.internal.descriptors;
23
24 import java.util.*;
25 import oracle.toplink.essentials.exceptions.*;
26 import oracle.toplink.essentials.indirection.*;
27 import oracle.toplink.essentials.internal.helper.*;
28 import oracle.toplink.essentials.mappings.*;
29 import oracle.toplink.essentials.internal.sessions.AbstractSession;
30 import oracle.toplink.essentials.descriptors.ClassDescriptor;
31
32 /**
33  * This class provides a generic way of using the descriptor information
34  * to traverse an object graph.
35  * Define a subclass, or an inner class, that implements at least
36  * #iterate(Object) to implement a new traversal
37  * feature without having to change the mapping classes or the object builder.
38  * It provides functionality such as a cascading depth, a stack of visited object,
39  * and a collection of the visited objects.
40  *
41  * NOTE:
42  * If this works nicely the merge manager, remote traversals, and maybe
43  * even aspects of the commit manager could be converted to use this class.
44  */

45 public abstract class DescriptorIterator {
46     public static final int NoCascading = 1;
47     public static final int CascadePrivateParts = 2;
48     public static final int CascadeAllParts = 3;
49     protected IdentityHashtable visitedObjects;
50     protected Stack visitedStack;
51     protected AbstractSession session;
52     protected DatabaseMapping currentMapping;
53     protected ClassDescriptor currentDescriptor;
54     protected Object JavaDoc result;// this is a work area, typically used as a Collecting Parm
55
protected boolean shouldIterateOverIndirectionObjects;
56     protected boolean shouldIterateOverUninstantiatedIndirectionObjects;
57     protected boolean shouldIterateOverWrappedObjects;
58     protected boolean shouldIterateOnIndirectionObjects;
59     protected boolean shouldIterateOnAggregates;
60     protected boolean shouldIterateOnPrimitives;
61     protected boolean shouldBreak;
62     protected int cascadeDepth;// see static constants below
63

64     /**
65      * Construct a typical iterator:
66      * iterate over all the objects
67      * process the objects contained by "value holders"...
68      * ...but only if they have already been instantiated...
69      * ...and don't process the "value holders" themselves
70      * process "wrapped" objects
71      * skip aggregate objects
72      * skip primitives (Strings, Dates, Integers, etc.)
73      */

74     public DescriptorIterator() {
75         // 2612538 - the default size of IdentityHashtable (32) is appropriate
76
this.visitedObjects = new IdentityHashtable();
77         this.visitedStack = new Stack();
78         this.cascadeDepth = CascadeAllParts;
79         this.shouldIterateOverIndirectionObjects = true;// process the objects contained by ValueHolders...
80
this.shouldIterateOverUninstantiatedIndirectionObjects = false;// ...but only if they have already been instantiated...
81
this.shouldIterateOnIndirectionObjects = false;// ...and don't process the ValueHolders themselves
82
this.shouldIterateOverWrappedObjects = true;// process "wrapped" objects
83
this.shouldIterateOnAggregates = false;
84         this.shouldIterateOnPrimitives = false;
85         this.shouldBreak = false;
86     }
87
88     public int getCascadeDepth() {
89         return cascadeDepth;
90     }
91
92     public ClassDescriptor getCurrentDescriptor() {
93         return currentDescriptor;
94     }
95
96     public DatabaseMapping getCurrentMapping() {
97         return currentMapping;
98     }
99
100     /**
101      * Fetch and return the descriptor for the specified object.
102      */

103     protected ClassDescriptor getDescriptorFor(Object JavaDoc object) {
104         ClassDescriptor result = getSession().getDescriptor(object);
105         if (result == null) {
106             throw DescriptorException.missingDescriptor(object.getClass().getName());
107         }
108         return result;
109     }
110
111     public Object JavaDoc getResult() {
112         return result;
113     }
114
115     public AbstractSession getSession() {
116         return session;
117     }
118
119     /**
120      * Return the second-to-last object visited.
121      */

122     public Object JavaDoc getVisitedGrandparent() {
123         Object JavaDoc parent = getVisitedStack().pop();
124         Object JavaDoc result = getVisitedStack().peek();
125         getVisitedStack().push(parent);
126         return result;
127     }
128
129     public IdentityHashtable getVisitedObjects() {
130         return visitedObjects;
131     }
132
133     /**
134      * Return the last object visited.
135      */

136     public Object JavaDoc getVisitedParent() {
137         return getVisitedStack().peek();
138     }
139
140     public Stack getVisitedStack() {
141         return visitedStack;
142     }
143
144     /**
145      * Iterate an aggregate object
146      * (i.e. an object that is the target of an AggregateMapping).
147      * Override this method if appropriate.
148      */

149     protected void internalIterateAggregateObject(Object JavaDoc aggregateObject) {
150         iterate(aggregateObject);
151     }
152
153     /**
154      * Iterate an indirect container (IndirectList or IndirectMap).
155      * Override this method if appropriate.
156      */

157     protected void internalIterateIndirectContainer(IndirectContainer container) {
158         iterate(container);
159     }
160
161     /**
162      * Iterate a primitive object (String, Date, Integer, etc.).
163      * Override this method if appropriate.
164      */

165     protected void internalIteratePrimitive(Object JavaDoc primitiveValue) {
166         iterate(primitiveValue);
167     }
168
169     /**
170      * Iterate a (a non-Aggregate) reference object.
171      * Override this method if appropriate.
172      */

173     protected void internalIterateReferenceObject(Object JavaDoc referenceObject) {
174         iterate(referenceObject);
175     }
176
177     /**
178      * Iterate a value holder.
179      * Override this method if appropriate.
180      */

181     protected void internalIterateValueHolder(ValueHolderInterface valueHolder) {
182         iterate(valueHolder);
183     }
184
185     /**
186      * To define a new iterator create a subclass and define at least this method.
187      * Given an object or set of the objects, this method will be called on those
188      * objects and any object connected to them by using the descriptors to
189      * traverse the object graph.
190      * Override the assorted #internalIterate*() methods if appropriate.
191      */

192     protected abstract void iterate(Object JavaDoc object);
193
194     /**
195      * Iterate on the mapping's reference object and
196      * recursively iterate on the reference object's
197      * reference objects.
198      * This is used for aggregate and aggregate collection mappings, which are not iterated on by default.
199      */

200     public void iterateForAggregateMapping(Object JavaDoc aggregateObject, DatabaseMapping mapping, ClassDescriptor descriptor) {
201         if (aggregateObject == null) {
202             return;
203         }
204         setCurrentMapping(mapping);
205         // aggregate descriptors are passed in because they could be part of an inheritance tree
206
setCurrentDescriptor(descriptor);
207
208         if (shouldIterateOnAggregates()) {// false by default
209
internalIterateAggregateObject(aggregateObject);
210             if (shouldBreak()) {
211                 setShouldBreak(false);
212                 return;
213             }
214         }
215
216         iterateReferenceObjects(aggregateObject);
217     }
218
219     /**
220      * Iterate on the indirection object for its mapping.
221      */

222     public void iterateIndirectContainerForMapping(IndirectContainer container, DatabaseMapping mapping) {
223         setCurrentMapping(mapping);
224         setCurrentDescriptor(null);
225
226         if (shouldIterateOnIndirectionObjects()) {// false by default
227
internalIterateIndirectContainer(container);
228         }
229
230         if (shouldIterateOverUninstantiatedIndirectionObjects() || (shouldIterateOverIndirectionObjects() && container.isInstantiated())) {
231             // force instantiation only if specified
232
mapping.iterateOnRealAttributeValue(this, container);
233         }
234     }
235
236     /**
237      * Iterate on the primitive value for its mapping.
238      */

239     public void iteratePrimitiveForMapping(Object JavaDoc primitiveValue, DatabaseMapping mapping) {
240         if (primitiveValue == null) {
241             return;
242         }
243         setCurrentMapping(mapping);
244         setCurrentDescriptor(null);
245
246         if (shouldIterateOnPrimitives()) {// false by default
247
internalIteratePrimitive(primitiveValue);
248         }
249     }
250
251     /**
252      * Iterate on the mapping's reference object and
253      * recursively iterate on the reference object's
254      * reference objects.
255      */

256     public void iterateReferenceObjectForMapping(Object JavaDoc referenceObject, DatabaseMapping mapping) {
257         if (!(shouldCascadeAllParts() || (shouldCascadePrivateParts() && mapping.isPrivateOwned()))) {
258             return;
259         }
260
261         // When using wrapper policy in EJB the iteration can stop in certain cases,
262
// this is because EJB forces beans to be registered anyway and clone identity can be violated
263
// and the violated clones references to session objects should not be traversed.
264
ClassDescriptor rd = mapping.getReferenceDescriptor();
265         if ((!shouldIterateOverWrappedObjects()) && (rd != null) && (rd.hasWrapperPolicy())) {
266             return;
267         }
268         if (referenceObject == null) {
269             return;
270         }
271
272         // Check if already processed.
273
if (getVisitedObjects().containsKey(referenceObject)) {
274             return;
275         }
276
277         getVisitedObjects().put(referenceObject, referenceObject);
278         setCurrentMapping(mapping);
279         setCurrentDescriptor(getDescriptorFor(referenceObject));
280
281         internalIterateReferenceObject(referenceObject);
282         if (shouldBreak()) {
283             setShouldBreak(false);
284             return;
285         }
286
287         iterateReferenceObjects(referenceObject);
288     }
289
290     /**
291      * Iterate over the sourceObject's reference objects,
292      * updating the visited stack appropriately.
293      */

294     protected void iterateReferenceObjects(Object JavaDoc sourceObject) {
295         getVisitedStack().push(sourceObject);
296         getCurrentDescriptor().getObjectBuilder().iterate(this);
297         getVisitedStack().pop();
298     }
299
300     /**
301      * Iterate on the value holder for its mapping.
302      */

303     public void iterateValueHolderForMapping(ValueHolderInterface valueHolder, DatabaseMapping mapping) {
304         setCurrentMapping(mapping);
305         setCurrentDescriptor(null);
306
307         if (shouldIterateOnIndirectionObjects()) {// false by default
308
internalIterateValueHolder(valueHolder);
309         }
310
311         if (shouldIterateOverUninstantiatedIndirectionObjects() || (shouldIterateOverIndirectionObjects() && valueHolder.isInstantiated())) {
312             // force instantiation only if specified
313
mapping.iterateOnRealAttributeValue(this, valueHolder.getValue());
314         }
315     }
316
317     public void setCascadeDepth(int cascadeDepth) {
318         this.cascadeDepth = cascadeDepth;
319     }
320
321     public void setCurrentDescriptor(ClassDescriptor currentDescriptor) {
322         this.currentDescriptor = currentDescriptor;
323     }
324
325     public void setCurrentMapping(DatabaseMapping currentMapping) {
326         this.currentMapping = currentMapping;
327     }
328
329     public void setResult(Object JavaDoc result) {
330         this.result = result;
331     }
332
333     public void setSession(AbstractSession session) {
334         this.session = session;
335     }
336
337     public void setShouldBreak(boolean shouldBreak) {
338         this.shouldBreak = shouldBreak;
339     }
340
341     /**
342      * Set whether the aggregate reference objects themselves
343      * should be processed. (The objects referenced by the aggregate
344      * objects will be processed either way.)
345      */

346     public void setShouldIterateOnAggregates(boolean shouldIterateOnAggregates) {
347         this.shouldIterateOnAggregates = shouldIterateOnAggregates;
348     }
349
350     /**
351      * Set whether the indirection objects themselves (e.g. the ValueHolders)
352      * should be processed.
353      */

354     public void setShouldIterateOnIndirectionObjects(boolean shouldIterateOnIndirectionObjects) {
355         this.shouldIterateOnIndirectionObjects = shouldIterateOnIndirectionObjects;
356     }
357
358     /**
359      * Set whether to process primitive reference objects
360      * (e.g. Strings, Dates, ints).
361      */

362     public void setShouldIterateOnPrimitives(boolean shouldIterateOnPrimitives) {
363         this.shouldIterateOnPrimitives = shouldIterateOnPrimitives;
364     }
365
366     /**
367      * Set whether to process the objects contained by indirection objects
368      * (e.g. a ValueHolder's value) - but *without* instantiating them.
369      * @see #setShouldIterateOverUninstantiatedIndirectionObjects()
370      */

371     public void setShouldIterateOverIndirectionObjects(boolean shouldIterateOverIndirectionObjects) {
372         this.shouldIterateOverIndirectionObjects = shouldIterateOverIndirectionObjects;
373     }
374
375     /**
376      * Set whether to *instantiate* and process the objects
377      * contained by indirection objects (e.g. a ValueHolder's value).
378      */

379     public void setShouldIterateOverUninstantiatedIndirectionObjects(boolean shouldIterateOverUninstantiatedIndirectionObjects) {
380         this.shouldIterateOverUninstantiatedIndirectionObjects = shouldIterateOverUninstantiatedIndirectionObjects;
381     }
382
383     public void setShouldIterateOverWrappedObjects(boolean shouldIterateOverWrappedObjects) {
384         this.shouldIterateOverWrappedObjects = shouldIterateOverWrappedObjects;
385     }
386
387     public void setVisitedObjects(IdentityHashtable visitedObjects) {
388         this.visitedObjects = visitedObjects;
389     }
390
391     protected void setVisitedStack(Stack visitedStack) {
392         this.visitedStack = visitedStack;
393     }
394
395     public boolean shouldBreak() {
396         return shouldBreak;
397     }
398
399     public boolean shouldCascadeAllParts() {
400         return getCascadeDepth() == CascadeAllParts;
401     }
402
403     public boolean shouldCascadeNoParts() {
404         return (getCascadeDepth() == NoCascading);
405     }
406
407     public boolean shouldCascadePrivateParts() {
408         return (getCascadeDepth() == CascadeAllParts) || (getCascadeDepth() == CascadePrivateParts);
409     }
410
411     /**
412      * Return whether the aggregate reference objects themselves
413      * should be processed. (The objects referenced by the aggregate
414      * objects will be processed either way.)
415      */

416     public boolean shouldIterateOnAggregates() {
417         return shouldIterateOnAggregates;
418     }
419
420     /**
421      * Return whether the indirection objects themselves (e.g. the ValueHolders)
422      * should be processed.
423      */

424     public boolean shouldIterateOnIndirectionObjects() {
425         return shouldIterateOnIndirectionObjects;
426     }
427
428     /**
429      * Return whether to process primitive reference objects
430      * (e.g. Strings, Dates, ints).
431      */

432     public boolean shouldIterateOnPrimitives() {
433         return shouldIterateOnPrimitives;
434     }
435
436     /**
437      * Return whether to process the objects contained by indirection objects
438      * (e.g. a ValueHolder's value) - but *without* instantiating them.
439      * @see #shouldIterateOverUninstantiatedIndirectionObjects()
440      */

441     public boolean shouldIterateOverIndirectionObjects() {
442         return shouldIterateOverIndirectionObjects;
443     }
444
445     /**
446      * Return whether to *instantiate* and process the objects
447      * contained by indirection objects (e.g. a ValueHolder's value).
448      */

449     public boolean shouldIterateOverUninstantiatedIndirectionObjects() {
450         return shouldIterateOverUninstantiatedIndirectionObjects;
451     }
452
453     public boolean shouldIterateOverWrappedObjects() {
454         return shouldIterateOverWrappedObjects;
455     }
456
457     /**
458      * This is the root method called to start the iteration.
459      */

460     public void startIterationOn(Object JavaDoc sourceObject) {
461         getVisitedObjects().put(sourceObject, sourceObject);
462         setCurrentMapping(null);
463         setCurrentDescriptor(getSession().getDescriptor(sourceObject));
464
465         iterate(sourceObject);
466
467         // start the recursion
468
if ((getCurrentDescriptor() != null) && (!shouldCascadeNoParts()) && !this.shouldBreak()) {
469             iterateReferenceObjects(sourceObject);
470         }
471     }
472 }
473
Popular Tags