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

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

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * // Copyright (c) 1998, 2007, Oracle. All rights reserved.
 * 
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
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 - 2024 Weber Informatics LLC | Privacy Policy