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

UnitOfWorkValueHolder

public abstract class UnitOfWorkValueHolder extends DatabaseValueHolder
A UnitOfWorkValueHolder is put in a clone object. It wraps the value holder in the original object to delay cloning the attribute in a unit of work until it is needed by the application. This value holder is used only in the unit of work.
author
Sati

Fields Summary
protected transient ValueHolderInterface
wrappedValueHolder
The value holder in the original object.
protected transient DatabaseMapping
mapping
The mapping for the attribute.
protected ValueHolder
backupValueHolder
The value holder stored in the backup copy, should not be transient.
protected UnitOfWorkImpl
remoteUnitOfWork
These cannot be transient because they are required for a remote unit of work. When the remote uow is serialized to the server to be committed, these are used to reconstruct the value holder on the server. They should be null for non-remote sessions.
protected Object
sourceObject
protected transient Object
relationshipSourceObject
This attribute is used specifically for relationship support. It mimicks the sourceObject attribute which is used for RemoteValueholder
protected String
sourceAttributeName
protected ObjID
wrappedValueHolderRemoteID
Constructors Summary
protected UnitOfWorkValueHolder(ValueHolderInterface attributeValue, Object clone, DatabaseMapping mapping, UnitOfWorkImpl unitOfWork)

        this.wrappedValueHolder = attributeValue;
        this.mapping = mapping;
        this.session = unitOfWork;
        this.sourceAttributeName = mapping.getAttributeName();
        this.relationshipSourceObject = clone;
    
Methods Summary
protected abstract java.lang.ObjectbuildBackupCloneFor(java.lang.Object cloneAttributeValue)
Backup the clone attribute value.

public abstract java.lang.ObjectbuildCloneFor(java.lang.Object originalAttributeValue)
Clone the original attribute value.

protected oracle.toplink.essentials.indirection.ValueHoldergetBackupValueHolder()

        return backupValueHolder;
    
protected oracle.toplink.essentials.mappings.DatabaseMappinggetMapping()

        return mapping;
    
protected java.lang.ObjectgetRelationshipSourceObject()

        return this.relationshipSourceObject;
    
protected oracle.toplink.essentials.internal.sessions.UnitOfWorkImplgetRemoteUnitOfWork()

        return remoteUnitOfWork;
    
protected java.lang.StringgetSourceAttributeName()

        return sourceAttributeName;
    
protected java.lang.ObjectgetSourceObject()

        return sourceObject;
    
protected oracle.toplink.essentials.internal.sessions.UnitOfWorkImplgetUnitOfWork()

        return (UnitOfWorkImpl)getSession();
    
protected java.lang.ObjectgetValueFromServerObject()
This is used for a remote unit of work. If the value holder is sent back to the server uninstantiated and it needs to be instantiated, then we must find the original object and get the appropriate attribute from it.

        setSession(getRemoteUnitOfWork());
        Vector primaryKey = getSession().keyFromObject(getSourceObject());
        Object originalObject = getUnitOfWork().getParent().getIdentityMapAccessor().getFromIdentityMap(primaryKey, getSourceObject().getClass());
        if (originalObject == null) {
            originalObject = getUnitOfWork().getParent().readObject(getSourceObject());
        }
        ClassDescriptor descriptor = getSession().getDescriptor(originalObject);
        DatabaseMapping mapping = descriptor.getObjectBuilder().getMappingForAttributeName(getSourceAttributeName());
        setMapping(mapping);
        return getMapping().getRealAttributeValueFromObject(originalObject, getSession());
    
public oracle.toplink.essentials.indirection.ValueHolderInterfacegetWrappedValueHolder()

        return wrappedValueHolder;
    
public java.rmi.server.ObjIDgetWrappedValueHolderRemoteID()
returns wrapped ValueHolder ObjID if available

        return this.wrappedValueHolderRemoteID;
    
protected java.lang.Objectinstantiate()
Get the value from the wrapped value holder, instantiating it if necessary, and clone it.

        UnitOfWorkImpl unitOfWork;
        if (isSerializedRemoteUnitOfWorkValueHolder()) {
            unitOfWork = getRemoteUnitOfWork();
        } else {
            unitOfWork = getUnitOfWork();
        }
        if (unitOfWork == null){
            throw ValidationException.instantiatingValueholderWithNullSession();
        }
        if (unitOfWork.isAfterWriteChangesButBeforeCommit()) {
            throw ValidationException.illegalOperationForUnitOfWorkLifecycle(unitOfWork.getLifecycle(), "ValueHolder.instantiate()");
        }

        Object originalAttributeValue;
        Object cloneAttributeValue;

        // the wrapped value holder is transient, so it will be null for a remote UOW
        if (isSerializedRemoteUnitOfWorkValueHolder()) {
            originalAttributeValue = getValueFromServerObject();
            cloneAttributeValue = buildCloneFor(originalAttributeValue);
        } else {
            cloneAttributeValue = instantiateImpl();
        }

        // Set the value in the backup clone also.
        // In some cases we may want to force instantiation before the backup is built
        if (getBackupValueHolder() != null) {
            getBackupValueHolder().setValue(buildBackupCloneFor(cloneAttributeValue));
        }
        return cloneAttributeValue;
    
public java.lang.ObjectinstantiateForUnitOfWorkValueHolder(oracle.toplink.essentials.internal.indirection.UnitOfWorkValueHolder unitOfWorkValueHolder)
Triggers UnitOfWork valueholders directly without triggering the wrapped valueholder (this).

When in transaction and/or for pessimistic locking the UnitOfWorkValueHolder needs to be triggered directly without triggering the wrapped valueholder. However only the wrapped valueholder knows how to trigger the indirection, i.e. it may be a batchValueHolder, and it stores all the info like the row and the query.

        // This abstract method needs to be implemented but is not meaningfull for
        // this subclass.
        return instantiate();
    
protected java.lang.ObjectinstantiateImpl()
a.k.a getValueFromWrappedValueholder. The old name is no longer correct, as query based valueholders are now sometimes triggered directly without triggering the underlying valueholder.

        if (getWrappedValueHolder() instanceof DatabaseValueHolder) {
            // Bug 3835202 - Ensure access to valueholders is thread safe.  Several of the methods
            // called below are not threadsafe alone.
            synchronized(getWrappedValueHolder()){
                DatabaseValueHolder wrapped = (DatabaseValueHolder)getWrappedValueHolder();
                UnitOfWorkImpl unitOfWork = getUnitOfWork();
                if (!wrapped.isEasilyInstantiated()) {
                    if (wrapped.isPessimisticLockingValueHolder()) {
                        if (!unitOfWork.getCommitManager().isActive() && !unitOfWork.wasTransactionBegunPrematurely()) {
                            unitOfWork.beginEarlyTransaction();
                        }
                        unitOfWork.log(SessionLog.FINEST, SessionLog.TRANSACTION, "instantiate_pl_relationship");
                    }
                    if (unitOfWork.getCommitManager().isActive() || unitOfWork.wasTransactionBegunPrematurely()) {
                        // At this point the wrapped valueholder is not triggered,
                        // and we are in transaction.  So just trigger the
                        // UnitOfWork valueholder on the UnitOfWork only.
                        return wrapped.instantiateForUnitOfWorkValueHolder(this);
                    }
                }
            }
        }
        Object originalAttributeValue = getWrappedValueHolder().getValue();
        return buildCloneFor(originalAttributeValue);
    
public booleanisEasilyInstantiated()
INTERNAL: Answers if this valueholder is easy to instantiate.

return
true if getValue() won't trigger a database read.

        return isInstantiated() || ((getWrappedValueHolder() != null) && (getWrappedValueHolder() instanceof DatabaseValueHolder) && ((DatabaseValueHolder)getWrappedValueHolder()).isEasilyInstantiated());
    
public booleanisPessimisticLockingValueHolder()
INTERNAL: Answers if this valueholder is a pessimistic locking one. Such valueholders are special in that they can be triggered multiple times by different UnitsOfWork. Each time a lock query will be issued. Hence even if instantiated it may have to be instantiated again, and once instantatiated all fields can not be reset.

        // This abstract method needs to be implemented but is not meaningfull for
        // this subclass.
        return ((getWrappedValueHolder() != null) && (getWrappedValueHolder() instanceof DatabaseValueHolder) && ((DatabaseValueHolder)getWrappedValueHolder()).isPessimisticLockingValueHolder());
    
public booleanisSerializedRemoteUnitOfWorkValueHolder()
Used to determine if this is a remote uow value holder that was serialized to the server. It has no reference to its wrapper value holder, so must find its original object to be able to instantiate.

        return (getRemoteUnitOfWork() != null) && (getRemoteUnitOfWork().getParent() != null) && (getWrappedValueHolder() == null);
    
public voidreleaseWrappedValueHolder()
Releases a wrapped valueholder privately owned by a particular unit of work.

When unit of work clones are built directly from rows no object in the shared cache points to this valueholder, so it can store the unit of work as its session. However once that UnitOfWork commits and the valueholder is merged into the shared cache, the session needs to be reset to the root session, ie. the server session.

        // On UnitOfWork dont want to do anything.
        return;
    
protected voidresetFields()
Reset all the fields that are not needed after instantiation.

        //do nothing.  nothing should be reset to null;
    
public voidsetBackupValueHolder(oracle.toplink.essentials.indirection.ValueHolder backupValueHolder)

        this.backupValueHolder = backupValueHolder;
    
protected voidsetMapping(oracle.toplink.essentials.mappings.DatabaseMapping mapping)

        this.mapping = mapping;
    
protected voidsetRelationshipSourceObject(java.lang.Object relationshipSourceObject)

        this.relationshipSourceObject = relationshipSourceObject;
    
protected voidsetRemoteUnitOfWork(oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl remoteUnitOfWork)

        this.remoteUnitOfWork = remoteUnitOfWork;
    
protected voidsetSourceAttributeName(java.lang.String name)

        sourceAttributeName = name;
    
protected voidsetSourceObject(java.lang.Object sourceObject)

        this.sourceObject = sourceObject;
    
protected voidsetWrappedValueHolder(oracle.toplink.essentials.internal.indirection.DatabaseValueHolder valueHolder)

        wrappedValueHolder = valueHolder;