All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oracle.toplink.essentials.internal.indirection.DatabaseValueHolder Maven / Gradle / Ivy

There is a newer version: 2.1-60f
Show newest version
/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the "License").  You may not use this file except 
 * in compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * glassfish/bootstrap/legal/CDDLv1.0.txt or 
 * https://glassfish.dev.java.net/public/CDDLv1.0.html. 
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * HEADER in each file and include the License file at 
 * glassfish/bootstrap/legal/CDDLv1.0.txt.  If applicable, 
 * add the following below this CDDL HEADER, with the 
 * fields enclosed by brackets "[]" replaced with your 
 * own identifying information: Portions Copyright [yyyy] 
 * [name of copyright owner]
 */
// Copyright (c) 1998, 2007, Oracle. All rights reserved.  
package oracle.toplink.essentials.internal.indirection;

import java.io.*;
import oracle.toplink.essentials.internal.helper.*;
import oracle.toplink.essentials.indirection.*;
import oracle.toplink.essentials.exceptions.*;
import oracle.toplink.essentials.internal.localization.*;
import oracle.toplink.essentials.internal.sessions.AbstractRecord;
import oracle.toplink.essentials.internal.sessions.AbstractSession;

/**
 * DatabaseValueHolder wraps a database-stored object and implements
 * behavior to access it. The object is read only once from database
 * after which is cached for faster access.
 *
 * @see ValueHolderInterface
 * @author    Dorin Sandu
 */
public abstract class DatabaseValueHolder implements WeavedAttributeValueHolderInterface, Cloneable, Serializable {

    /** Stores the object after it is read from the database. */
    protected Object value;

    /** Indicates whether the object has been read from the database or not. */
    protected boolean isInstantiated;

    /** Stores the session for the database that contains the object. */
    protected transient AbstractSession session;

    /** Stores the row representation of the object. */
    protected AbstractRecord row;
  
    /**
     * The variable below is used as part of the implementation of WeavedAttributeValueHolderInterface
     * It is used to track whether a valueholder that has been weaved into a class is coordinated
     * with the underlying property
     * Set internally in TopLink when the state of coordination between a weaved valueholder and the underlying property is known
     */
    protected boolean isCoordinatedWithProperty = false;

    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException exception) {
            throw new InternalError();
        }
    }

    /**
     * Return the row.
     */
    public AbstractRecord getRow() {
        return row;
    }

    /**
     * Return the session.
     */
    public AbstractSession getSession() {
        return session;
    }

    /**
     * Return the object.
     */
    public synchronized Object getValue() {
        if (!isInstantiated()) {
            // The value must be set directly because the setValue can also cause instatiation under UOW.
            privilegedSetValue(instantiate());
            setInstantiated();
            resetFields();
        }
        return value;
    }

    /**
     * Instantiate the object.
     */
    protected abstract Object instantiate() throws DatabaseException;

    /**
     * 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. * Note: Implementations of this method are not necessarily thread-safe. They must * be used in a synchronizaed manner */ public abstract Object instantiateForUnitOfWorkValueHolder(UnitOfWorkValueHolder unitOfWorkValueHolder); /** * This method is used as part of the implementation of WeavedAttributeValueHolderInterface * It is used to check whether a valueholder that has been weaved into a class is coordinated * with the underlying property */ public boolean isCoordinatedWithProperty(){ return isCoordinatedWithProperty; } /** * This method is used as part of the implementation of WeavedAttributeValueHolderInterface. * * A DatabaseValueHolder is set up by TopLink and will never be a newly weaved valueholder. * As a result, this method is stubbed out. */ public boolean isNewlyWeavedValueHolder(){ return false; } /** * INTERNAL: * Answers if this valueholder is easy to instantiate. * @return true if getValue() won't trigger a database read. */ public boolean isEasilyInstantiated() { return isInstantiated(); } /** * Return a boolean indicating whether the object * has been read from the database or not. */ public boolean isInstantiated() { return isInstantiated; } /** * 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. * Note: Implementations of this method are not necessarily thread-safe. They must * be used in a synchronizaed manner */ public abstract boolean isPessimisticLockingValueHolder(); /** * Answers if this valueholder is referenced only by a UnitOfWork valueholder. * I.e. it was built in valueFromRow which was called by buildCloneFromRow. *

* Sometimes in transaction a UnitOfWork clone, and all valueholders, are built * directly from the row; however a UnitOfWorkValueHolder does not know how to * instantiate itself so wraps this which does. *

* On a successful merge must be released to the session cache with * releaseWrappedValueHolder. */ protected boolean isTransactionalValueHolder() { return ((session != null) && session.isUnitOfWork()); } /** * 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. */ public boolean isSerializedRemoteUnitOfWorkValueHolder() { return false; } /** * Set the object. This is used only by the privileged methods. One must be very careful in using this method. */ public void privilegedSetValue(Object value) { this.value = value; isCoordinatedWithProperty = false; } /** * 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. */ public void releaseWrappedValueHolder() { AbstractSession session = getSession(); if ((session != null) && session.isUnitOfWork()) { setSession(session.getRootSession(null)); } } /** * Reset all the fields that are not needed after instantiation. */ protected void resetFields() { setRow(null); setSession(null); } /** * This method is used as part of the implementation of WeavedAttributeValueHolderInterface * It is used internally by TopLink to set whether a valueholder that has been weaved into a class is coordinated * with the underlying property */ public void setIsCoordinatedWithProperty(boolean coordinated){ this.isCoordinatedWithProperty = coordinated; } /** * This method is used as part of the implementation of WeavedAttributeValueHolderInterface * * A DatabaseValueHolder is set up by TopLink and will never be a newly weaved valueholder * As a result, this method is stubbed out. */ public void setIsNewlyWeavedValueHolder(boolean isNew){ } /** * Set the instantiated flag to true. */ public void setInstantiated() { isInstantiated = true; } /** * Set the row. */ public void setRow(AbstractRecord row) { this.row = row; } /** * Set the session. */ public void setSession(AbstractSession session) { this.session = session; } /** * Set the instantiated flag to false. */ public void setUninstantiated() { isInstantiated = false; } /** * Set the object. */ public void setValue(Object value) { this.value = value; setInstantiated(); } public String toString() { if (isInstantiated()) { return "{" + getValue() + "}"; } else { return "{" + Helper.getShortClassName(getClass()) + ": " + ToStringLocalization.buildMessage("not_instantiated", (Object[])null) + "}"; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy