Package org.jpox.jpa

Source Code of org.jpox.jpa.JPAAdapter

/**********************************************************************
Copyright (c) 2006 Erik Bengtson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:
     ...
**********************************************************************/
package org.jpox.jpa;

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

import javax.jdo.JDOHelper;
import javax.jdo.identity.ByteIdentity;
import javax.jdo.identity.CharIdentity;
import javax.jdo.identity.IntIdentity;
import javax.jdo.identity.LongIdentity;
import javax.jdo.identity.ObjectIdentity;
import javax.jdo.identity.ShortIdentity;
import javax.jdo.identity.SingleFieldIdentity;
import javax.jdo.identity.StringIdentity;
import javax.jdo.spi.Detachable;
import javax.jdo.spi.JDOImplHelper;
import javax.jdo.spi.PersistenceCapable;

import org.jpox.ClassLoaderResolver;
import org.jpox.ObjectManager;
import org.jpox.StateManager;
import org.jpox.api.ApiAdapter;
import org.jpox.exceptions.JPOXException;
import org.jpox.jdo.JDOClassNameConstants;
import org.jpox.jdo.JPOXJDOHelper;
import org.jpox.jpa.state.LifeCycleStateFactory;
import org.jpox.metadata.AbstractClassMetaData;
import org.jpox.state.JDOStateManagerImpl;
import org.jpox.state.LifeCycleState;
import org.jpox.util.JPOXLogger;
import org.jpox.util.Localiser;

/**
* Adapter for the JPA API, to allow the JPOX core runtime to expose multiple APIs to clients.
*
* @version $Revision: 1.29 $
*/
public class JPAAdapter implements ApiAdapter
{
    protected static final Localiser LOCALISER = Localiser.getInstance("org.jpox.Localisation",
        JPOXJPAHelper.class.getClassLoader());

    // ------------------------------ Object Lifecycle --------------------------------

    /**
     * Method to create a new StateManager for the ObjectManager and class.
     * @param om ObjectManager
     * @param acmd MetaData for the class/interface
     */
    public StateManager newStateManager(ObjectManager om, AbstractClassMetaData acmd)
    {
        // TODO Change to JPAStateManager when we have one
        return new JDOStateManagerImpl(om, acmd);
    }

    /**
     * Returns the LifeCycleState for the state constant.
     * @param stateType the type as integer
     * @return the type as LifeCycleState object
     */
    public LifeCycleState getLifeCycleState(int stateType)
    {
        return LifeCycleStateFactory.getLifeCycleState(stateType);
    }

    /**
     * Accessor for whether the passed object is persistent.
     * @param obj The object
     * @return Whether it is persistent
     */
    public boolean isPersistent(Object obj)
    {
        // Relay through to JDOHelper - TODO Change this when we JPOX-JPA doesnt depend on JDO
        return JDOHelper.isPersistent(obj);
    }

    /**
     * Accessor for whether the passed object is new.
     * @param obj The object
     * @return Whether it is new
     */
    public boolean isNew(Object obj)
    {
        // Relay through to JDOHelper - TODO Change this when we JPOX-JPA doesnt depend on JDO
        return JDOHelper.isNew(obj);
    }

    /**
     * Accessor for whether the passed object is dirty.
     * @param obj The object
     * @return Whether it is dirty
     */
    public boolean isDirty(Object obj)
    {
        // Relay through to JDOHelper - TODO Change this when we JPOX-JPA doesnt depend on JDO
        return JDOHelper.isDirty(obj);
    }

    /**
     * Accessor for whether the passed object is deleted.
     * @param obj The object
     * @return Whether it is deleted
     */
    public boolean isDeleted(Object obj)
    {
        // Relay through to JDOHelper - TODO Change this when we JPOX-JPA doesnt depend on JDO
        return JDOHelper.isDeleted(obj);
    }

    /**
     * Accessor for whether the passed object is detached.
     * @param obj The object
     * @return Whether it is detached
     */
    public boolean isDetached(Object obj)
    {
        // Relay through to JDOHelper - TODO Change this when we JPOX-JPA doesnt depend on JDO
        return JDOHelper.isDetached(obj);
    }

    /**
     * Accessor for whether the passed object is transactional.
     * @param obj The object
     * @return Whether it is transactional
     */
    public boolean isTransactional(Object obj)
    {
        // Relay through to JDOHelper - TODO Change this when we JPOX-JPA doesnt depend on JDO
        return JDOHelper.isTransactional(obj);
    }

    /**
     * Method to return if the passed object is persistable using this API.
     * @param obj The object
     * @return Whether it is persistable
     */
    public boolean isPersistable(Object obj)
    {
        if (obj == null)
        {
            return false;
        }

        // TODO Change this to org.jpox.jpa.Persistable when we enhance to that
        return (obj instanceof PersistenceCapable);
    }

    /**
     * Utility method to check if the specified class is of a type that can be persisted for this API.
     * @param cls The class to check
     * @return Whether the class is persistable
     */
    public boolean isPersistable(Class cls)
    {
        if (cls == null)
        {
            return false;
        }
        // TODO Change this to org.jpox.jpa.Persistable when we enhance to that
        return (PersistenceCapable.class.isAssignableFrom(cls));
    }

    /**
     * Method to return if the passed object is detachable using this API.
     * Returns whether the object is an instance of javax.jdo.spi.Detachable.
     * @param obj The object
     * @return Whether it is detachable
     */
    public boolean isDetachable(Object obj)
    {
        if (obj == null)
        {
            return false;
        }

        // TODO Change this to org.jpox.jpa.Persistable when we enhance to that
        return (obj instanceof Detachable);
    }

    /**
     * Accessor for the object state.
     * @param obj Object
     * @return The state ("persistent-clean", "detached-dirty" etc)
     */
    public String getObjectState(Object obj)
    {
        // TODO This should use JPOXJPAHelper at some point
        return JPOXJDOHelper.getObjectStateAsString(obj);
    }

    // ------------------------------ Object Identity  --------------------------------

    /**
     * Method to return the object identity for the passed persistable object.
     * Returns null if it is not persistable, or has no identity.
     * @param obj The object
     * @return The identity
     */
    public Object getIdForObject(Object obj)
    {
        if (!isPersistable(obj))
        {
            return null;
        }
        // TODO Change this to org.jpox.jpa.Persistable when we enhance to that
        return ((PersistenceCapable)obj).jdoGetObjectId();
    }

    /**
     * Method to return the object version for the passed persistable object.
     * Returns null if it is not persistable, or not versioned.
     * @param obj The object
     * @return The version
     */
    public Object getVersionForObject(Object obj)
    {
        if (!isPersistable(obj))
        {
            return null;
        }
        // TODO Change this to org.jpox.jpa.Persistable when we enhance to that
        return ((PersistenceCapable)obj).jdoGetVersion();
    }

    /**
     * Utility to check if a primary-key class is valid.
     * Will throw a InvalidPrimaryKeyException if it is invalid, otherwise returning true.
     * @param pkClass The Primary Key class
     * @param cmd AbstractClassMetaData for the PersistenceCapable class
     * @param clr the ClassLoaderResolver
     * @param noOfPkFields Number of primary key fields
     * @return Whether it is valid
     */
    public boolean isValidPrimaryKeyClass(Class pkClass, AbstractClassMetaData cmd, ClassLoaderResolver clr, int noOfPkFields)
    {
        return true;
    }

    /**
     * Accessor for whether the passed identity is a valid single-field application-identity for this API.
     * @return Whether it is valid
     */
    public boolean isSingleFieldIdentity(Object id)
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        return (id instanceof SingleFieldIdentity);
    }

    /**
     * Checks whether the passed class name is valid for a single field application-identity for this API.
     * @param className the full class name
     * @return Whether it is a single field class
     */
    public boolean isSingleFieldIdentityClass(String className)
    {
        if (className == null || className.length() < 1)
        {
            return false;
        }

        // TODO Use JPOX-internal SingleFieldIdentity
        return (className.equals(JDOClassNameConstants.JAVAX_JDO_IDENTITY_BYTE_IDENTITY) ||
                className.equals(JDOClassNameConstants.JAVAX_JDO_IDENTITY_CHAR_IDENTITY) ||
                className.equals(JDOClassNameConstants.JAVAX_JDO_IDENTITY_INT_IDENTITY) ||
                className.equals(JDOClassNameConstants.JAVAX_JDO_IDENTITY_LONG_IDENTITY) ||
                className.equals(JDOClassNameConstants.JAVAX_JDO_IDENTITY_OBJECT_IDENTITY) ||
                className.equals(JDOClassNameConstants.JAVAX_JDO_IDENTITY_SHORT_IDENTITY) ||
                className.equals(JDOClassNameConstants.JAVAX_JDO_IDENTITY_STRING_IDENTITY));
    }

    /**
     * Accessor for the class name to use for identities when there is a single Long/long field.
     * @return Class name of identity class
     */
    public String getSingleFieldIdentityClassNameForLong()
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        return JDOClassNameConstants.JAVAX_JDO_IDENTITY_LONG_IDENTITY;
    }

    /**
     * Accessor for the class name to use for identities when there is a single Integer/int field.
     * @return Class name of identity class
     */
    public String getSingleFieldIdentityClassNameForInt()
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        return JDOClassNameConstants.JAVAX_JDO_IDENTITY_INT_IDENTITY;
    }

    /**
     * Accessor for the class name to use for identities when there is a single Short/short field.
     * @return Class name of identity class
     */
    public String getSingleFieldIdentityClassNameForShort()
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        return JDOClassNameConstants.JAVAX_JDO_IDENTITY_SHORT_IDENTITY;
    }

    /**
     * Accessor for the class name to use for identities when there is a single Byte/byte field.
     * @return Class name of identity class
     */
    public String getSingleFieldIdentityClassNameForByte()
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        return JDOClassNameConstants.JAVAX_JDO_IDENTITY_BYTE_IDENTITY;
    }

    /**
     * Accessor for the class name to use for identities when there is a single Character/char field.
     * @return Class name of identity class
     */
    public String getSingleFieldIdentityClassNameForChar()
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        return JDOClassNameConstants.JAVAX_JDO_IDENTITY_CHAR_IDENTITY;
    }

    /**
     * Accessor for the class name to use for identities when there is a single String field.
     * @return Class name of identity class
     */
    public String getSingleFieldIdentityClassNameForString()
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        return JDOClassNameConstants.JAVAX_JDO_IDENTITY_STRING_IDENTITY;
    }

    /**
     * Accessor for the class name to use for identities when there is a single Object field.
     * @return Class name of identity class
     */
    public String getSingleFieldIdentityClassNameForObject()
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        return JDOClassNameConstants.JAVAX_JDO_IDENTITY_OBJECT_IDENTITY;
    }

    /**
     * Accessor for the target class for the specified single field application-identity.
     * @param id The identity
     * @return The target class
     */
    public Class getTargetClassForSingleFieldIdentity(Object id)
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        if (id instanceof SingleFieldIdentity)
        {
            return ((SingleFieldIdentity)id).getTargetClass();
        }
        return null;
    }

    /**
     * Accessor for the target class name for the specified single field identity.
     * @param id The identity
     * @return The target class name
     */
    public String getTargetClassNameForSingleFieldIdentity(Object id)
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        if (id instanceof SingleFieldIdentity)
        {
            return ((SingleFieldIdentity)id).getTargetClassName();
        }
        return null;
    }

    /**
     * Accessor for the key object for the specified single field application-identity.
     * @param id The identity
     * @return The key object
     */
    public Object getTargetKeyForSingleFieldIdentity(Object id)
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        if (id instanceof SingleFieldIdentity)
        {
            return ((SingleFieldIdentity)id).getKeyAsObject();
        }
        return null;
    }

    /**
     * Accessor for the type of the single field application-identity key given the single field identity type.
     * @param idType Single field identity type
     * @return key type
     */
    public Class getKeyTypeForSingleFieldIdentityType(Class idType)
    {
        if (idType == null)
        {
            return null;
        }
        if (!isSingleFieldIdentityClass(idType.getName()))
        {
            return null;
        }

        // TODO Use JPOX-internal SingleFieldIdentity
        if (LongIdentity.class.isAssignableFrom(idType))
        {
            return Long.class;
        }
        else if (IntIdentity.class.isAssignableFrom(idType))
        {
            return Integer.class;
        }
        else if (ShortIdentity.class.isAssignableFrom(idType))
        {
            return Short.class;
        }
        else if (ByteIdentity.class.isAssignableFrom(idType))
        {
            return Byte.class;
        }
        else if (CharIdentity.class.isAssignableFrom(idType))
        {
            return Character.class;
        }
        else if (StringIdentity.class.isAssignableFrom(idType))
        {
            return String.class;
        }
        else if (ObjectIdentity.class.isAssignableFrom(idType))
        {
            return Object.class;
        }
        return null;
    }

    /**
     * Utility to create a new SingleFieldIdentity using reflection when you know the
     * type of the PersistenceCapable, and also which SingleFieldIdentity, and the value of the key.
     * @param idType Type of SingleFieldIdentity
     * @param pcType Type of the PersistenceCapable
     * @param value The value for the identity (the Long, or Int, or ... etc).
     * @return Single field identity
     * @throws JPOXException if invalid input is received
     */
    public Object getNewSingleFieldIdentity(Class idType, Class pcType, Object value)
    {
        // TODO Use JPOX-internal SingleFieldIdentity
        if (idType == null)
        {
            throw new JPOXException(LOCALISER.msg("029001", pcType)).setFatal();
        }
        if (pcType == null)
        {
            throw new JPOXException(LOCALISER.msg("029000", idType)).setFatal();
        }
        if (value == null)
        {
            throw new JPOXException(LOCALISER.msg("029003", idType, pcType)).setFatal();
        }
        if (!SingleFieldIdentity.class.isAssignableFrom(idType))
        {
            throw new JPOXException(LOCALISER.msg("029002", idType.getName(), pcType.getName())).setFatal();
        }

        SingleFieldIdentity id = null;
        Class keyType = null;
        if (idType == LongIdentity.class)
        {
            keyType = Long.class;
            if (!(value instanceof Long))
            {
                throw new JPOXException(LOCALISER.msg("029004", idType.getName(),
                    pcType.getName(), value.getClass().getName(), "Long")).setFatal();
            }
        }
        else if (idType == IntIdentity.class)
        {
            keyType = Integer.class;
            if (!(value instanceof Integer))
            {
                throw new JPOXException(LOCALISER.msg("029004", idType.getName(),
                    pcType.getName(), value.getClass().getName(), "Integer")).setFatal();
            }
        }
        else if (idType == StringIdentity.class)
        {
            keyType = String.class;
            if (!(value instanceof String))
            {
                throw new JPOXException(LOCALISER.msg("029004", idType.getName(),
                    pcType.getName(), value.getClass().getName(), "String")).setFatal();
            }
        }
        else if (idType == ByteIdentity.class)
        {
            keyType = Byte.class;
            if (!(value instanceof Byte))
            {
                throw new JPOXException(LOCALISER.msg("029004", idType.getName(),
                    pcType.getName(), value.getClass().getName(), "Byte")).setFatal();
            }
        }
        else if (idType == ShortIdentity.class)
        {
            keyType = Short.class;
            if (!(value instanceof Short))
            {
                throw new JPOXException(LOCALISER.msg("029004", idType.getName(),
                    pcType.getName(), value.getClass().getName(), "Short")).setFatal();
            }
        }
        else if (idType == CharIdentity.class)
        {
            keyType = Character.class;
            if (!(value instanceof Character))
            {
                throw new JPOXException(LOCALISER.msg("029004", idType.getName(),
                    pcType.getName(), value.getClass().getName(), "Character")).setFatal();
            }
        }
        else
        {
            // ObjectIdentity
            keyType = Object.class;
        }

        try
        {
            Class[] ctrArgs = new Class[] {Class.class, keyType};
            Constructor ctr = idType.getConstructor(ctrArgs);

            Object[] args = new Object[] {pcType, value};
            id = (SingleFieldIdentity)ctr.newInstance(args);
        }
        catch (Exception e)
        {
            JPOXLogger.PERSISTENCE.error("Error encountered while creating SingleFieldIdentity instance of type \"" + idType.getName() + "\"");
            JPOXLogger.PERSISTENCE.error(e);

            return null;
        }

        return id;
    }

    /**
     * Method to create a new object identity for the passed object with the supplied MetaData.
     * Only applies to application-identity cases.
     * @param pc The persistable object
     * @param cmd Its metadata
     * @return The new identity object
     */
    public Object getNewApplicationIdentityObjectId(Object pc, AbstractClassMetaData cmd)
    {
        if (pc == null || cmd == null)
        {
            return null;
        }

        // TODO Change this to Persistable
        Object id = ((PersistenceCapable)pc).jdoNewObjectIdInstance();
        if (!cmd.usesSingleFieldIdentityClass())
        {
            ((PersistenceCapable)pc).jdoCopyKeyFieldsToObjectId(id);
        }
        return id;
    }

    /**
     * Method to return a new object identity for the specified class, and key (possibly toString() output).
     * @param cls Persistable class
     * @param key form of the object id
     * @return The object identity
     */
    public Object getNewApplicationIdentityObjectId(Class cls, Object key)
    {
        // TODO Replace this with a non-JDO method
        return JDOImplHelper.getInstance().newObjectIdInstance(cls, key);
    }

    // ------------------------------ Persistence --------------------------------

    /**
     * Whether the API allows (re-)persistence of a deleted object.
     * @return Whether you can call persist on a deleted object
     */
    public boolean allowPersistOfDeletedObject()
    {
        // JPA allows re-persist of deleted objects
        return true;
    }

    /**
     * Whether the API allows deletion of a non-persistent object.
     * @return Whether you can call delete on an object not yet persisted
     */
    public boolean allowDeleteOfNonPersistentObject()
    {
        // JPA allows delete of transient objects so they cascade to all persistent objects
        return true;
    }

    /**
     * Whether the API allows reading a field of a deleted object.
     * @return Whether you can read after deleting
     */
    public boolean allowReadFieldOfDeletedObject()
    {
        return true;
    }

    /**
     * Whether the API requires clearing of the fields of an object when it is deleted.
     * @return Whether to clear loaded fields at delete
     */
    public boolean clearLoadedFlagsOnDeleteObject()
    {
        return false;
    }

    /**
     * Returns the default cascade-persist setting. JPA defaults to not persisting by reachability.
     * @return The default cascade-persist (false)
     */
    public boolean getDefaultCascadePersistForField()
    {
        return false;
    }

    /**
     * Returns the default cascade-update setting. JPA defaults to not updating by reachability.
     * @return The default cascade-update (false)
     */
    public boolean getDefaultCascadeUpdateForField()
    {
        return false;
    }

    /**
     * Returns the default cascade-delete setting. JPA defaults to not deleting by reachability.
     * @return The default cascade-delete (false)
     */
    public boolean getDefaultCascadeDeleteForField()
    {
        return false;
    }

    /**
     * Returns the default cascade-refresh setting.
     * @return The default cascade-refresh (false)
     */
    public boolean getDefaultCascadeRefreshForField()
    {
        return false;
    }

    /**
     * Method to return the default factory properties for this API.
     * @return The default props
     */
    public Map getDefaultFactoryProperties()
    {
        Map<String, String> props = new HashMap<String, String>();
        props.put("org.jpox.NontransactionalRead", "true"); // Non-tx read in JPA
        props.put("org.jpox.NontransactionalWrite", "true"); // Non-tx write in JPA
        props.put("org.jpox.DetachAllOnCommit", "true"); // detachAllOnCommit in JPA
        props.put("org.jpox.Optimistic", "true"); // JPA uses optimistic txns
        props.put("org.jpox.identifierFactory", "jpa"); // JPA identifier naming
        props.put("org.jpox.persistenceByReachabilityAtCommit", "false"); // No PBR at commit with JPA
        props.put("org.jpox.rdbms.query.containsUsesExistsAlways", "true");
        props.put("org.jpox.rdbms.stringDefaultLength", "255");
        props.put("org.jpox.rdbms.sql.allowAllSQLStatements", "true"); // No restrictions on SQL statements in JPA
        return props;
    }

    /**
     * Accessor for the object id from the StateManager for this object.
     * @param sm StateManager
     * @return object id
     */
    public Object getObjectId(StateManager sm)
    {
        // TODO Replace this with a non-JDO class
        return sm.getObjectId((PersistenceCapable)sm.getObject());
    }

    /**
     * Accessor for the version from the StateManager for this object.
     * @param sm StateManager
     */
    public Object getVersion(StateManager sm)
    {
        // TODO Replace this with a non-JDO class
        return sm.getVersion((PersistenceCapable)sm.getObject());
    }

    /**
     * Accessor for whether a field is loaded for the object managed by the StateManager
     * @param sm StateManager
     * @param fieldNumber Number of the field
     * @return Whether it is loaded
     */
    public boolean isLoaded(StateManager sm, int fieldNumber)
    {
        // TODO Replace this with a non-JDO class
        return sm.isLoaded((PersistenceCapable)sm.getObject(), fieldNumber);
    }

    /**
     * Accessor for the persistence manager for this object.
     * The returned object will be a JPA EntityManager or null if not managed.
     * @param obj The object
     * @return The persistence manager
     */
    public Object getPersistenceManager(Object obj)
    {
        // TODO Replace this with a non-JDO class
        if (obj instanceof PersistenceCapable)
        {
            return ((PersistenceCapable)obj).jdoGetPersistenceManager();
        }
        return null;
    }

    /**
     * Method to make the field dirty in the object.
     * @param obj Object
     * @param fieldName Name of the field to make dirty
     */
    public void makeFieldDirty(Object obj, String fieldName)
    {
        // TODO Replace this with a non-JDO class
        ((PersistenceCapable)obj).jdoMakeDirty(fieldName);
    }
}
TOP

Related Classes of org.jpox.jpa.JPAAdapter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.