FileDocCategorySizeDatePackage
BasicIndirectionPolicy.javaAPI DocGlassfish v2 API14740Tue May 22 16:54:36 BST 2007oracle.toplink.essentials.internal.indirection

BasicIndirectionPolicy

public class BasicIndirectionPolicy extends IndirectionPolicy

Purpose

: BasicIndirectionPolicy implements the behavior necessary for a a ForeignReferenceMapping (or TransformationMapping) to use ValueHolders to delay the reading of objects from the database until they are actually needed.
see
ForeignReferenceMapping
author
Mike Norman
since
TOPLink/Java 2.5

Fields Summary
Constructors Summary
public BasicIndirectionPolicy()
INTERNAL: Construct a new indirection policy.

        super();
    
Methods Summary
public java.lang.ObjectbackupCloneAttribute(java.lang.Object attributeValue, java.lang.Object clone, java.lang.Object backup, oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl unitOfWork)
INTERNAL: Return a backup clone of the attribute.

        //no need to check if the attribute is a valueholder because closeAttribute
        // should always be called first
        ValueHolderInterface valueHolder = (ValueHolderInterface)attributeValue;// cast the value
        ValueHolder result = new ValueHolder();

        // delay instantiation until absolutely necessary
        if ((!(valueHolder instanceof UnitOfWorkValueHolder)) || valueHolder.isInstantiated()) {
            result.setValue(super.backupCloneAttribute(valueHolder.getValue(), clone, backup, unitOfWork));
        } else {
            ((UnitOfWorkValueHolder)valueHolder).setBackupValueHolder(result);
        }

        return result;
    
public java.lang.ObjectcloneAttribute(java.lang.Object attributeValue, java.lang.Object original, java.lang.Object clone, oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl unitOfWork, boolean buildDirectlyFromRow)
INTERNAL: Return a clone of the attribute.

param
buildDirectlyFromRow indicates that we are building the clone directly from a row as opposed to building the original from the row, putting it in the shared cache, and then cloning the original.

        ValueHolderInterface valueHolder = (ValueHolderInterface) attributeValue;
        ValueHolderInterface result;
        
        if (!buildDirectlyFromRow && unitOfWork.isOriginalNewObject(original)) {
            // CR#3156435 Throw a meaningful exception if a serialized/dead value holder is detected.
            // This can occur if an existing serialized object is attempt to be registered as new.
            if ((valueHolder instanceof DatabaseValueHolder)
                    && (! ((DatabaseValueHolder) valueHolder).isInstantiated())
                    && (((DatabaseValueHolder) valueHolder).getSession() == null)
                    && (! ((DatabaseValueHolder) valueHolder).isSerializedRemoteUnitOfWorkValueHolder())) {
                throw DescriptorException.attemptToRegisterDeadIndirection(original, getMapping());
            }
            if (this.getMapping().getRelationshipPartner() == null) {
                result = new ValueHolder();
                result.setValue(this.getMapping().buildCloneForPartObject(valueHolder.getValue(), original, clone, unitOfWork, false));
            } else {
                //if I have a relationsip partner trigger the indiretion so that the value will be inserted
                // because of this call the entire tree should be recursively cloned
                AbstractRecord row = null;
                if (valueHolder instanceof DatabaseValueHolder) {
                    row = ((DatabaseValueHolder)valueHolder).getRow();
                }
                result = this.getMapping().createUnitOfWorkValueHolder(valueHolder, original, clone, row, unitOfWork, buildDirectlyFromRow);

                Object newObject = this.getMapping().buildCloneForPartObject(valueHolder.getValue(), original, clone, unitOfWork, false);
                ((UnitOfWorkValueHolder)result).privilegedSetValue(newObject);
                ((UnitOfWorkValueHolder)result).setInstantiated();
            }
        } else {
            AbstractRecord row = null;
            if (valueHolder instanceof DatabaseValueHolder) {
                row = ((DatabaseValueHolder)valueHolder).getRow();
            }
            result = this.getMapping().createUnitOfWorkValueHolder(valueHolder, original, clone, row, unitOfWork, buildDirectlyFromRow);
        }
        return result;
    
public java.util.VectorextractPrimaryKeyForReferenceObject(java.lang.Object referenceObject, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Return the primary key for the reference object (i.e. the object object referenced by domainObject and specified by mapping). This key will be used by a RemoteValueHolder.

        if (this.objectIsInstantiated(referenceObject)) {
            return super.extractPrimaryKeyForReferenceObject(((ValueHolderInterface)referenceObject).getValue(), session);
        } else {
            return this.getOneToOneMapping().extractPrimaryKeysForReferenceObjectFromRow(this.extractReferenceRow(referenceObject));
        }
    
public oracle.toplink.essentials.internal.sessions.AbstractRecordextractReferenceRow(java.lang.Object referenceObject)
INTERNAL: Return the reference row for the reference object. This allows the new row to be built without instantiating the reference object. Return null if the object has already been instantiated.

        if (this.objectIsInstantiated(referenceObject)) {
            return null;
        } else {
            return ((DatabaseValueHolder)referenceObject).getRow();
        }
    
public java.lang.ObjectgetOriginalIndirectionObject(java.lang.Object unitOfWorkIndirectionObject, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Return the original indirection object for a unit of work indirection object. This is used when building a new object from the unit of work when the original fell out of the cache.

        if (unitOfWorkIndirectionObject instanceof UnitOfWorkValueHolder) {
            ValueHolderInterface valueHolder = ((UnitOfWorkValueHolder)unitOfWorkIndirectionObject).getWrappedValueHolder();
            if ((valueHolder != null) && (valueHolder instanceof DatabaseValueHolder)) {
                ((DatabaseValueHolder)valueHolder).releaseWrappedValueHolder();
            }
            return valueHolder;
        } else {
            return unitOfWorkIndirectionObject;
        }
    
public java.lang.ObjectgetRealAttributeValueFromObject(java.lang.Object object, java.lang.Object attribute)
INTERNAL: Return the "real" attribute value, as opposed to any wrapper. This will trigger the wrapper to instantiate the value.

        // Changed for CR 4245. Use a static reference instead of .class
        if (ClassConstants.ValueHolderInterface_Class.isAssignableFrom(attribute.getClass())) {
            return ((ValueHolderInterface)attribute).getValue();
        } else {
            return attribute;
        }
    
public voiditerateOnAttributeValue(oracle.toplink.essentials.internal.descriptors.DescriptorIterator iterator, java.lang.Object attributeValue)
INTERNAL: Iterate over the specified attribute value,

        iterator.iterateValueHolderForMapping((ValueHolderInterface)attributeValue, this.getMapping());
    
public java.lang.ObjectnullValueFromRow()
INTERNAL: Return the null value of the appropriate attribute. That is, the field from the database is NULL, return what should be placed in the object's attribute as a result. In this case, return an empty ValueHolder.

        return new ValueHolder();
    
public booleanobjectIsInstantiated(java.lang.Object object)
INTERNAL: Return whether the specified object is instantiated.

        return ((ValueHolderInterface)object).isInstantiated();
    
public voidsetRealAttributeValueInObject(java.lang.Object target, java.lang.Object attributeValue)
INTERNAL: Set the value of the appropriate attribute of target to attributeValue. In this case, place the value inside the target's ValueHolder.

        ValueHolderInterface holder = (ValueHolderInterface)this.getMapping().getAttributeValueFromObject(target);
        if (holder == null) {
            holder = new ValueHolder(attributeValue);
        } else {
            holder.setValue(attributeValue); 
        }
        super.setRealAttributeValueInObject(target, holder);
    
protected booleantypeIsValid(java.lang.Class attributeType)
INTERNAL: Return whether the type is appropriate for the indirection policy. In this case, the attribute type MUST be ValueHolderInterface.

        return attributeType == ClassConstants.ValueHolderInterface_Class ||
            attributeType == ClassConstants.WeavedAttributeValueHolderInterface_Class;
    
public java.lang.ObjectvalidateAttributeOfInstantiatedObject(java.lang.Object attributeValue)
INTERNAL: Verify that the value of the attribute within an instantiated object is of the appropriate type for the indirection policy. In this case, the attribute must be non-null and it must be a ValueHolderInterface. If the value is null return a new indirection object to be used for the attribute.

        // PERF: If the value is null, create a new value holder instance for the attribute value,
        // this allows for indirection attributes to not be instantiated in the constructor as they
        // are typically replaced when reading or cloning so is very inefficent to initialize.
        if (attributeValue == null) {
            return new ValueHolder();
        }
        if (!(attributeValue instanceof ValueHolderInterface)) {
            throw DescriptorException.valueHolderInstantiationMismatch(attributeValue, this.getMapping());
        }
        return attributeValue;
    
public voidvalidateDeclaredAttributeType(java.lang.Class attributeType, oracle.toplink.essentials.exceptions.IntegrityChecker checker)
INTERNAL: Verify that attributeType is correct for the indirection policy. If it is incorrect, add an exception to the integrity checker. In this case, the attribute type MUST be ValueHolderInterface.

        super.validateDeclaredAttributeType(attributeType, checker);
        if (!this.typeIsValid(attributeType)) {
            checker.handleError(DescriptorException.attributeAndMappingWithIndirectionMismatch(this.getMapping()));
        }
    
public voidvalidateGetMethodReturnType(java.lang.Class returnType, oracle.toplink.essentials.exceptions.IntegrityChecker checker)
INTERNAL: Verify that getter returnType is correct for the indirection policy. If it is incorrect, add an exception to the integrity checker. In this case, the return type MUST be ValueHolderInterface.

        super.validateGetMethodReturnType(returnType, checker);
        if (!this.typeIsValid(returnType)) {
            checker.handleError(DescriptorException.returnAndMappingWithIndirectionMismatch(this.getMapping()));
        }
    
public voidvalidateSetMethodParameterType(java.lang.Class parameterType, oracle.toplink.essentials.exceptions.IntegrityChecker checker)
INTERNAL: Verify that setter parameterType is correct for the indirection policy. If it is incorrect, add an exception to the integrity checker. In this case, the parameter type MUST be ValueHolderInterface.

        super.validateSetMethodParameterType(parameterType, checker);
        if (!this.typeIsValid(parameterType)) {
            checker.handleError(DescriptorException.parameterAndMappingWithIndirectionMismatch(this.getMapping()));
        }
    
public java.lang.ObjectvalueFromQuery(oracle.toplink.essentials.queryframework.ReadQuery query, oracle.toplink.essentials.internal.sessions.AbstractRecord row, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Return the value to be stored in the object's attribute. This value is determined by the query. In this case, wrap the query in a ValueHolder for later invocation.

        return new QueryBasedValueHolder(query, row, session);
    
public java.lang.ObjectvalueFromRow(java.lang.Object object)
INTERNAL: Return the value to be stored in the object's attribute. This value is determined by the row. In this case, simply wrap the object in a ValueHolder.

        return new ValueHolder(object);