FileDocCategorySizeDatePackage
DescriptorIterator.javaAPI DocGlassfish v2 API17773Tue May 22 16:54:22 BST 2007oracle.toplink.essentials.internal.descriptors

DescriptorIterator

public abstract class DescriptorIterator extends Object
This class provides a generic way of using the descriptor information to traverse an object graph. Define a subclass, or an inner class, that implements at least #iterate(Object) to implement a new traversal feature without having to change the mapping classes or the object builder. It provides functionality such as a cascading depth, a stack of visited object, and a collection of the visited objects. NOTE: If this works nicely the merge manager, remote traversals, and maybe even aspects of the commit manager could be converted to use this class.

Fields Summary
public static final int
NoCascading
public static final int
CascadePrivateParts
public static final int
CascadeAllParts
protected IdentityHashtable
visitedObjects
protected Stack
visitedStack
protected AbstractSession
session
protected DatabaseMapping
currentMapping
protected ClassDescriptor
currentDescriptor
protected Object
result
protected boolean
shouldIterateOverIndirectionObjects
protected boolean
shouldIterateOverUninstantiatedIndirectionObjects
protected boolean
shouldIterateOverWrappedObjects
protected boolean
shouldIterateOnIndirectionObjects
protected boolean
shouldIterateOnAggregates
protected boolean
shouldIterateOnPrimitives
protected boolean
shouldBreak
protected int
cascadeDepth
Constructors Summary
public DescriptorIterator()
Construct a typical iterator: iterate over all the objects process the objects contained by "value holders"... ...but only if they have already been instantiated... ...and don't process the "value holders" themselves process "wrapped" objects skip aggregate objects skip primitives (Strings, Dates, Integers, etc.)

// see static constants below

                                                                         
      
        // 2612538 - the default size of IdentityHashtable (32) is appropriate
        this.visitedObjects = new IdentityHashtable();
        this.visitedStack = new Stack();
        this.cascadeDepth = CascadeAllParts;
        this.shouldIterateOverIndirectionObjects = true;// process the objects contained by ValueHolders...
        this.shouldIterateOverUninstantiatedIndirectionObjects = false;// ...but only if they have already been instantiated...
        this.shouldIterateOnIndirectionObjects = false;// ...and don't process the ValueHolders themselves
        this.shouldIterateOverWrappedObjects = true;// process "wrapped" objects
        this.shouldIterateOnAggregates = false;
        this.shouldIterateOnPrimitives = false;
        this.shouldBreak = false;
    
Methods Summary
public intgetCascadeDepth()

        return cascadeDepth;
    
public oracle.toplink.essentials.descriptors.ClassDescriptorgetCurrentDescriptor()

        return currentDescriptor;
    
public oracle.toplink.essentials.mappings.DatabaseMappinggetCurrentMapping()

        return currentMapping;
    
protected oracle.toplink.essentials.descriptors.ClassDescriptorgetDescriptorFor(java.lang.Object object)
Fetch and return the descriptor for the specified object.

        ClassDescriptor result = getSession().getDescriptor(object);
        if (result == null) {
            throw DescriptorException.missingDescriptor(object.getClass().getName());
        }
        return result;
    
public java.lang.ObjectgetResult()

        return result;
    
public oracle.toplink.essentials.internal.sessions.AbstractSessiongetSession()

        return session;
    
public java.lang.ObjectgetVisitedGrandparent()
Return the second-to-last object visited.

        Object parent = getVisitedStack().pop();
        Object result = getVisitedStack().peek();
        getVisitedStack().push(parent);
        return result;
    
public oracle.toplink.essentials.internal.helper.IdentityHashtablegetVisitedObjects()

        return visitedObjects;
    
public java.lang.ObjectgetVisitedParent()
Return the last object visited.

        return getVisitedStack().peek();
    
public java.util.StackgetVisitedStack()

        return visitedStack;
    
protected voidinternalIterateAggregateObject(java.lang.Object aggregateObject)
Iterate an aggregate object (i.e. an object that is the target of an AggregateMapping). Override this method if appropriate.

        iterate(aggregateObject);
    
protected voidinternalIterateIndirectContainer(oracle.toplink.essentials.indirection.IndirectContainer container)
Iterate an indirect container (IndirectList or IndirectMap). Override this method if appropriate.

        iterate(container);
    
protected voidinternalIteratePrimitive(java.lang.Object primitiveValue)
Iterate a primitive object (String, Date, Integer, etc.). Override this method if appropriate.

        iterate(primitiveValue);
    
protected voidinternalIterateReferenceObject(java.lang.Object referenceObject)
Iterate a (a non-Aggregate) reference object. Override this method if appropriate.

        iterate(referenceObject);
    
protected voidinternalIterateValueHolder(oracle.toplink.essentials.indirection.ValueHolderInterface valueHolder)
Iterate a value holder. Override this method if appropriate.

        iterate(valueHolder);
    
protected abstract voiditerate(java.lang.Object object)
To define a new iterator create a subclass and define at least this method. Given an object or set of the objects, this method will be called on those objects and any object connected to them by using the descriptors to traverse the object graph. Override the assorted #internalIterate*() methods if appropriate.

public voiditerateForAggregateMapping(java.lang.Object aggregateObject, oracle.toplink.essentials.mappings.DatabaseMapping mapping, oracle.toplink.essentials.descriptors.ClassDescriptor descriptor)
Iterate on the mapping's reference object and recursively iterate on the reference object's reference objects. This is used for aggregate and aggregate collection mappings, which are not iterated on by default.

        if (aggregateObject == null) {
            return;
        }
        setCurrentMapping(mapping);
        // aggregate descriptors are passed in because they could be part of an inheritance tree
        setCurrentDescriptor(descriptor);

        if (shouldIterateOnAggregates()) {// false by default
            internalIterateAggregateObject(aggregateObject);
            if (shouldBreak()) {
                setShouldBreak(false);
                return;
            }
        }

        iterateReferenceObjects(aggregateObject);
    
public voiditerateIndirectContainerForMapping(oracle.toplink.essentials.indirection.IndirectContainer container, oracle.toplink.essentials.mappings.DatabaseMapping mapping)
Iterate on the indirection object for its mapping.

        setCurrentMapping(mapping);
        setCurrentDescriptor(null);

        if (shouldIterateOnIndirectionObjects()) {// false by default
            internalIterateIndirectContainer(container);
        }

        if (shouldIterateOverUninstantiatedIndirectionObjects() || (shouldIterateOverIndirectionObjects() && container.isInstantiated())) {
            // force instantiation only if specified
            mapping.iterateOnRealAttributeValue(this, container);
        }
    
public voiditeratePrimitiveForMapping(java.lang.Object primitiveValue, oracle.toplink.essentials.mappings.DatabaseMapping mapping)
Iterate on the primitive value for its mapping.

        if (primitiveValue == null) {
            return;
        }
        setCurrentMapping(mapping);
        setCurrentDescriptor(null);

        if (shouldIterateOnPrimitives()) {// false by default
            internalIteratePrimitive(primitiveValue);
        }
    
public voiditerateReferenceObjectForMapping(java.lang.Object referenceObject, oracle.toplink.essentials.mappings.DatabaseMapping mapping)
Iterate on the mapping's reference object and recursively iterate on the reference object's reference objects.

        if (!(shouldCascadeAllParts() || (shouldCascadePrivateParts() && mapping.isPrivateOwned()))) {
            return;
        }

        // When using wrapper policy in EJB the iteration can stop in certain cases,
        // this is because EJB forces beans to be registered anyway and clone identity can be violated
        // and the violated clones references to session objects should not be traversed.
        ClassDescriptor rd = mapping.getReferenceDescriptor();
        if ((!shouldIterateOverWrappedObjects()) && (rd != null) && (rd.hasWrapperPolicy())) {
            return;
        }
        if (referenceObject == null) {
            return;
        }

        // Check if already processed.
        if (getVisitedObjects().containsKey(referenceObject)) {
            return;
        }

        getVisitedObjects().put(referenceObject, referenceObject);
        setCurrentMapping(mapping);
        setCurrentDescriptor(getDescriptorFor(referenceObject));

        internalIterateReferenceObject(referenceObject);
        if (shouldBreak()) {
            setShouldBreak(false);
            return;
        }

        iterateReferenceObjects(referenceObject);
    
protected voiditerateReferenceObjects(java.lang.Object sourceObject)
Iterate over the sourceObject's reference objects, updating the visited stack appropriately.

        getVisitedStack().push(sourceObject);
        getCurrentDescriptor().getObjectBuilder().iterate(this);
        getVisitedStack().pop();
    
public voiditerateValueHolderForMapping(oracle.toplink.essentials.indirection.ValueHolderInterface valueHolder, oracle.toplink.essentials.mappings.DatabaseMapping mapping)
Iterate on the value holder for its mapping.

        setCurrentMapping(mapping);
        setCurrentDescriptor(null);

        if (shouldIterateOnIndirectionObjects()) {// false by default
            internalIterateValueHolder(valueHolder);
        }

        if (shouldIterateOverUninstantiatedIndirectionObjects() || (shouldIterateOverIndirectionObjects() && valueHolder.isInstantiated())) {
            // force instantiation only if specified
            mapping.iterateOnRealAttributeValue(this, valueHolder.getValue());
        }
    
public voidsetCascadeDepth(int cascadeDepth)

        this.cascadeDepth = cascadeDepth;
    
public voidsetCurrentDescriptor(oracle.toplink.essentials.descriptors.ClassDescriptor currentDescriptor)

        this.currentDescriptor = currentDescriptor;
    
public voidsetCurrentMapping(oracle.toplink.essentials.mappings.DatabaseMapping currentMapping)

        this.currentMapping = currentMapping;
    
public voidsetResult(java.lang.Object result)

        this.result = result;
    
public voidsetSession(oracle.toplink.essentials.internal.sessions.AbstractSession session)

        this.session = session;
    
public voidsetShouldBreak(boolean shouldBreak)

        this.shouldBreak = shouldBreak;
    
public voidsetShouldIterateOnAggregates(boolean shouldIterateOnAggregates)
Set whether the aggregate reference objects themselves should be processed. (The objects referenced by the aggregate objects will be processed either way.)

        this.shouldIterateOnAggregates = shouldIterateOnAggregates;
    
public voidsetShouldIterateOnIndirectionObjects(boolean shouldIterateOnIndirectionObjects)
Set whether the indirection objects themselves (e.g. the ValueHolders) should be processed.

        this.shouldIterateOnIndirectionObjects = shouldIterateOnIndirectionObjects;
    
public voidsetShouldIterateOnPrimitives(boolean shouldIterateOnPrimitives)
Set whether to process primitive reference objects (e.g. Strings, Dates, ints).

        this.shouldIterateOnPrimitives = shouldIterateOnPrimitives;
    
public voidsetShouldIterateOverIndirectionObjects(boolean shouldIterateOverIndirectionObjects)
Set whether to process the objects contained by indirection objects (e.g. a ValueHolder's value) - but *without* instantiating them.

see
#setShouldIterateOverUninstantiatedIndirectionObjects()

        this.shouldIterateOverIndirectionObjects = shouldIterateOverIndirectionObjects;
    
public voidsetShouldIterateOverUninstantiatedIndirectionObjects(boolean shouldIterateOverUninstantiatedIndirectionObjects)
Set whether to *instantiate* and process the objects contained by indirection objects (e.g. a ValueHolder's value).

        this.shouldIterateOverUninstantiatedIndirectionObjects = shouldIterateOverUninstantiatedIndirectionObjects;
    
public voidsetShouldIterateOverWrappedObjects(boolean shouldIterateOverWrappedObjects)

        this.shouldIterateOverWrappedObjects = shouldIterateOverWrappedObjects;
    
public voidsetVisitedObjects(oracle.toplink.essentials.internal.helper.IdentityHashtable visitedObjects)

        this.visitedObjects = visitedObjects;
    
protected voidsetVisitedStack(java.util.Stack visitedStack)

        this.visitedStack = visitedStack;
    
public booleanshouldBreak()

        return shouldBreak;
    
public booleanshouldCascadeAllParts()

        return getCascadeDepth() == CascadeAllParts;
    
public booleanshouldCascadeNoParts()

        return (getCascadeDepth() == NoCascading);
    
public booleanshouldCascadePrivateParts()

        return (getCascadeDepth() == CascadeAllParts) || (getCascadeDepth() == CascadePrivateParts);
    
public booleanshouldIterateOnAggregates()
Return whether the aggregate reference objects themselves should be processed. (The objects referenced by the aggregate objects will be processed either way.)

        return shouldIterateOnAggregates;
    
public booleanshouldIterateOnIndirectionObjects()
Return whether the indirection objects themselves (e.g. the ValueHolders) should be processed.

        return shouldIterateOnIndirectionObjects;
    
public booleanshouldIterateOnPrimitives()
Return whether to process primitive reference objects (e.g. Strings, Dates, ints).

        return shouldIterateOnPrimitives;
    
public booleanshouldIterateOverIndirectionObjects()
Return whether to process the objects contained by indirection objects (e.g. a ValueHolder's value) - but *without* instantiating them.

see
#shouldIterateOverUninstantiatedIndirectionObjects()

        return shouldIterateOverIndirectionObjects;
    
public booleanshouldIterateOverUninstantiatedIndirectionObjects()
Return whether to *instantiate* and process the objects contained by indirection objects (e.g. a ValueHolder's value).

        return shouldIterateOverUninstantiatedIndirectionObjects;
    
public booleanshouldIterateOverWrappedObjects()

        return shouldIterateOverWrappedObjects;
    
public voidstartIterationOn(java.lang.Object sourceObject)
This is the root method called to start the iteration.

        getVisitedObjects().put(sourceObject, sourceObject);
        setCurrentMapping(null);
        setCurrentDescriptor(getSession().getDescriptor(sourceObject));

        iterate(sourceObject);

        // start the recursion
        if ((getCurrentDescriptor() != null) && (!shouldCascadeNoParts())  && !this.shouldBreak()) {
            iterateReferenceObjects(sourceObject);
        }