/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     02/02/2009-2.0 Chris delahunt
//       - 241765: JPA 2.0 Derived identities
//     04/24/2009-2.0 Guy Pelletier
//       - 270011: JPA 2.0 MappedById support
//     10/21/2009-2.0 Guy Pelletier
//       - 290567: mappedbyid support incomplete
//     12/17/2010-2.2 Guy Pelletier
//       - 330755: Nested embeddables can't be used as embedded ids
//     11/10/2011-2.4 Guy Pelletier
//       - 357474: Address primaryKey option from tenant discriminator column
//     14/05/2012-2.4 Guy Pelletier
//       - 376603: Provide for table per tenant support for multitenant applications
//     08/20/2012-2.4 Guy Pelletier
//       - 381079: EclipseLink dynamic entity does not support embedded-id
package org.eclipse.persistence.internal.jpa;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.eclipse.persistence.annotations.CacheKeyType;
import org.eclipse.persistence.descriptors.CMPPolicy;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.indirection.WeavedObjectBasicIndirectionPolicy;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetField;
import org.eclipse.persistence.internal.security.PrivilegedGetMethod;
import org.eclipse.persistence.internal.security.PrivilegedGetValueFromField;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.security.PrivilegedSetValueInField;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.mappings.foundation.AbstractColumnMapping;

/**
 * Defines primary key extraction code for use in JPA. A descriptor should have a CMP3Policy
 * attached to handle basic Id as well as IdClass/EmbeddedId usage.
 *
 * @since TopLink 10.1.3
 */

public class CMP3Policy extends CMPPolicy {

    /** Stores the fields for this classes compound primary key class if required. */
    protected transient KeyElementAccessor[] keyClassFields;

    /** Used to look up the KeyElementAccessor for a specific DatabaseField, used for
      resolving DerivedIds */
    protected transient HashMap<DatabaseField,KeyElementAccessor> fieldToAccessorMap;

    // Store the primary key class name
    protected String pkClassName;

    // Stores the class version of the PKClass
    protected Class pkClass = null;

    public CMP3Policy() {
        super();
    }

    /**
     * INTERNAL:
     * Add the read only mappings for the given field to the allMappings list.
     */
    protected void addWritableMapping(ClassDescriptor aDescriptor, DatabaseField field, List allMappings) {
        DatabaseMapping writableMapping = aDescriptor.getObjectBuilder().getMappingForField(field);

        if (writableMapping != null) {
            // Since it may be another aggregate mapping, add it to
            // the allMappings list so we can drill down on it as
            // well.
            allMappings.add(writableMapping);
        }
    }

    /**
     * INTERNAL:
     * Add the writable mapping for the given field to the allMappings list.
     */
    protected void addReadOnlyMappings(ClassDescriptor aDescriptor, DatabaseField field, List allMappings) {
        List<DatabaseMapping> readOnlyMappings = aDescriptor.getObjectBuilder().getReadOnlyMappingsForField(field);

        if (readOnlyMappings != null) {
            allMappings.addAll(readOnlyMappings);
        }
    }

    /**
     * INTERNAL:
     * Clone the CMP3Policy
     */
    @Override
    public CMP3Policy clone() {
        CMP3Policy policy = new CMP3Policy();
        policy.setPrimaryKeyClassName(getPKClassName());
        policy.setPKClass(getPKClass());
        return policy;
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this object to actual class-based
     * settings. This method is used when converting a project that has been built
     * with class names to a project with classes.
     */
    @Override
    public void convertClassNamesToClasses(ClassLoader classLoader){
        if(getPKClassName() != null){
            try{
                Class aPKClass = null;
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        aPKClass = AccessController.doPrivileged(new PrivilegedClassForName<>(getPKClassName(), true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw new IllegalArgumentException(ExceptionLocalization.buildMessage("pk_class_not_found", new Object[] {this.pkClassName}), exception.getException());

                    }
                } else {
                    aPKClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(getPKClassName(), true, classLoader);
                }
                setPKClass(aPKClass);
            } catch (ClassNotFoundException exc){
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("pk_class_not_found", new Object[] {this.pkClassName}), exc);
            }
        }
    }

    /**
     * INTERNAL:
     * Return if this policy is for CMP3.
     */
    @Override
    public boolean isCMP3Policy() {
        return true;
    }

    /**
     * INTERNAL:
     */
    public void setPrimaryKeyClassName(String pkClassName) {
        this.pkClassName = pkClassName;
    }

    /**
     * INTERNAL:
     * Return the java Class representing the primary key class name
     */
    @Override
    public Class getPKClass() {
        return this.pkClass;
    }

    /**
     * ADVANCED:
     */
    public void setPKClass(Class pkClass) {
        this.pkClass = pkClass;
    }

    /**
     * INTERNAL:
     */
    public String getPKClassName() {
        return pkClassName;
    }

    /**
     * INTERNAL:
     */
    @Override
    public Object getPKClassInstance() {
        try {
            return getPKClass().getConstructor().newInstance();
        } catch (ReflectiveOperationException ex) {
            throw DescriptorException.exceptionAccessingPrimaryKeyInstance(this.getDescriptor(), ex);
        }
    }

    /**
     * INTERNAL:
     * Use the key to create a EclipseLink primary key.
     * If the key is simple (direct mapped) then just add it to a vector,
     * otherwise must go through the inefficient process of copying the key into the bean
     * and extracting the key from the bean.
     */
    @Override
    public Object createPrimaryKeyFromId(Object key, AbstractSession session) {
        // If the descriptor primary key is mapped through direct-to-field mappings,
        // then no elaborate conversion is required.
        // If key is compound, add each value to the vector.
        KeyElementAccessor[] pkElementArray = this.getKeyClassFields();
        Object[] primaryKey = null;
        if (getDescriptor().getCacheKeyType() != CacheKeyType.ID_VALUE) {
            primaryKey = new Object[pkElementArray.length];
        }
        for (int index = 0; index < pkElementArray.length; index++) {
            DatabaseMapping mapping = pkElementArray[index].getMapping();
            Object fieldValue = null;
            if (mapping.isAbstractColumnMapping()) {
                if (pkElementArray[index].isNestedAccessor()) {
                    // We have nested aggregate(s) in the embedded id pkclass.
                    DatabaseField keyField = pkElementArray[index].getDatabaseField();
                    Object keyToUse = key;
                    DatabaseMapping keyMapping = getDescriptor().getObjectBuilder().getMappingForField(keyField);

                    if (keyMapping.isAggregateMapping()) {
                        keyMapping = keyMapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(keyField);

                        // Keep driving down the nested aggregates ...
                        while (keyMapping.isAggregateMapping()) {
                            keyToUse = keyMapping.getRealAttributeValueFromObject(keyToUse, session);
                            keyMapping = keyMapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(keyField);
                        }

                        fieldValue = ((AbstractColumnMapping)mapping).getFieldValue(pkElementArray[index].getValue(keyToUse, session), session);
                    } else {
                        // This should never hit but just in case ... better to get a proper exception rather than a NPE etc.
                        fieldValue = ((AbstractColumnMapping)mapping).getFieldValue(pkElementArray[index].getValue(keyToUse, session), session);
                    }
                } else {
                    fieldValue = ((AbstractColumnMapping)mapping).getFieldValue(pkElementArray[index].getValue(key, session), session);
                }
            } else {
                fieldValue = pkElementArray[index].getValue(key, session);
                if ( (fieldValue !=null) && (pkClass != null) && (mapping.isOneToOneMapping()) ){
                    OneToOneMapping refmapping = (OneToOneMapping)mapping;
                    DatabaseField targetKey = refmapping.getSourceToTargetKeyFields().get(pkElementArray[index].getDatabaseField());
                    CMPPolicy refPolicy = refmapping.getReferenceDescriptor().getCMPPolicy();
                    if (refPolicy.isCMP3Policy()){
                        Class<Object> aPKClass = refPolicy.getPKClass();
                        if ((aPKClass != null) && (aPKClass != fieldValue.getClass()) && (!aPKClass.isAssignableFrom(fieldValue.getClass()))) {
                            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_pk_class", new Object[] { aPKClass, fieldValue.getClass() }));
                        }
                        fieldValue = ((CMP3Policy)refPolicy).getPkValueFromKeyForField(fieldValue, targetKey, session);
                    }
                }
            }
            if (getDescriptor().getCacheKeyType() == CacheKeyType.ID_VALUE) {
                return fieldValue;
            }
            primaryKey[index] = fieldValue;
        }
        return new CacheId(primaryKey);
    }

    /**
     * INTERNAL:
     * @return the field from the class with name equal to fieldName.
     */
    protected Field getField(Class cls, String fieldName) throws NoSuchFieldException {
        Field keyField = null;
        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
            try {
                keyField = AccessController.doPrivileged(new PrivilegedGetField(cls, fieldName, true));
            } catch (PrivilegedActionException exception) {
                throw (NoSuchFieldException) exception.getException();
            }
        } else {
            keyField = PrivilegedAccessHelper.getField(cls, fieldName, true);
        }

        return keyField;
    }

    /**
     * INTERNAL:
     * Use the key to create a bean and initialize its primary key fields.
     * Note: If is a compound PK then a primary key object is being used.
     * This method should only be used for 'templates' when executing
     * queries.  The bean built will not be given an EntityContext and should
     * not be used as an actual entity bean.
     *
     * @param key Object the primary key to use for initializing the bean's
     *            corresponding pk fields
     * @return Object
     */
    @Override
    public Object createBeanUsingKey(Object key, AbstractSession session) {
        try {
            Object bean = this.getDescriptor().getInstantiationPolicy().buildNewInstance();
            KeyElementAccessor[] keyElements = this.getKeyClassFields();
            for (int index = 0; index < keyElements.length; ++index) {
                Object toWriteInto = bean;
                Object keyFieldValue = keyElements[index].getValue(key, session);
                DatabaseField field = keyElements[index].getDatabaseField();
                DatabaseMapping mapping = this.getDescriptor().getObjectBuilder().getMappingForAttributeName(keyElements[index].getAttributeName());
                if (mapping == null) {// must be aggregate
                    mapping = this.getDescriptor().getObjectBuilder().getMappingForField(field);
                }
                while (mapping.isAggregateObjectMapping()) {
                    Object aggregate = mapping.getRealAttributeValueFromObject(toWriteInto, session);
                    if (aggregate == null) {
                        aggregate = mapping.getReferenceDescriptor().getJavaClass().getConstructor().newInstance();
                        mapping.setRealAttributeValueInObject(toWriteInto, aggregate);
                    }
                    mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForAttributeName(keyElements[index].getAttributeName());
                    if (mapping == null) {// must be aggregate
                        mapping = this.getDescriptor().getObjectBuilder().getMappingForField(field);
                    }

                    //change the object to write into to the aggregate for the next stage of the
                    // loop or for when we exit the loop.
                    toWriteInto = aggregate;
                }
                mapping.setRealAttributeValueInObject(toWriteInto, keyFieldValue);
            }
            return bean;
        } catch (Exception e) {
            throw DescriptorException.errorUsingPrimaryKey(key, this.getDescriptor(), e);
        }
    }

    /**
     * INTERNAL:
     * Cache the bean's primary key fields so speed up creating of primary key
     * objects and initialization of beans.
     *
     * Note, we have to re-look up the fields for the bean class since
     * these fields may have been loaded with the wrong loader (thank you Kirk).
     * If the key is compound, we also have to look up the fields for the key.
     */
    protected KeyElementAccessor[] initializePrimaryKeyFields(Class keyClass, AbstractSession session) {
        KeyElementAccessor[] pkAttributes = null;
        ClassDescriptor aDescriptor = this.getDescriptor();

        fieldToAccessorMap = new HashMap<DatabaseField,KeyElementAccessor>();
        int numberOfIDFields = aDescriptor.getPrimaryKeyFields().size();
        pkAttributes = new KeyElementAccessor[numberOfIDFields];
        Iterator<DatabaseField> attributesIter = aDescriptor.getPrimaryKeyFields().iterator();

        // Used fields in case it is an embedded class
        for (int i = 0; attributesIter.hasNext(); i++) {
            DatabaseField field = attributesIter.next();

            // We need to check all mappings for this field, not just the writable one and instead of
            // having multiple sections of duplicate code we'll just add the writable mapping directly
            // to the list.
            List allMappings = new ArrayList(1);
            addReadOnlyMappings(aDescriptor, field, allMappings);
            addWritableMapping(aDescriptor, field, allMappings);

            // This exception will be used to determine if the element (field or method) from
            // the mapping was found on the key class was found or not and throw an exception otherwise.
            Exception noSuchElementException = null;

            // Set the current key class ...
            Class currentKeyClass = keyClass;

            // We always start by looking at the writable mappings first. Our preference is to use the
            // writable mappings unless a derived id mapping is specified in which case we'll want to use
            // that mapping instead when we find it.
            for (int index = (allMappings.size() - 1); index >= 0; --index) {
                DatabaseMapping mapping = (DatabaseMapping) allMappings.get(index);

                // So here is the ugly check to see if we want to further look at this mapping as part of
                // the id or not.
                if (aDescriptor.hasDerivedId() && ! mapping.derivesId()) {
                    // If the mapping is not a derived id, then we need to keep looking for the mapping that
                    // is marked as the derived id mapping. However, in a mapped by id case, we may have
                    // 'extra' non-derived id fields within the embeddable class (and the writable mapping
                    // that we care about at this point will be defined on the embeddable descriptor). Therefore,
                    // we can't bail at this point and must drill down further into the embeddable to make sure
                    // we initialize this portion of the composite id.
                    if (mapping.isAggregateMapping() && allMappings.size() > 1) {
                        // Bail ... more mappings to check.
                        continue;
                    }
                } else if (mapping.isForeignReferenceMapping() && !mapping.isOneToOneMapping()) {
                    // JPA 2.0 allows DerrivedIds, so Id fields are either OneToOne or DirectToField mappings
                    continue;
                }

                if (mapping.isAggregateMapping()) {
                    // Either this aggregate is the key class, or we need to drill down further. Add the read
                    // only and writable mappings from the aggregate.
                    addReadOnlyMappings(mapping.getReferenceDescriptor(), field, allMappings);
                    addWritableMapping(mapping.getReferenceDescriptor(), field, allMappings);

                    // Since we added the mappings from this aggregate mapping, we should remove this aggregate
                    // mapping from the allMappings list. Otherwise, if the mapping for the primary key field is
                    // not found in the aggregate (or nested aggregate) then we will hit an infinite loop when
                    // searching the aggregate and its mappings. Note: This is cautionary, since in reality, this
                    // 'should' never happen, but if it does we certainly would rather throw an exception instead
                    // of causing an infinite loop.
                    allMappings.remove(mapping);

                    // Update the index to parse the next mapping correctly.
                    index = allMappings.size();

                    // Update the key class now ...
                    currentKeyClass = mapping.getReferenceDescriptor().getJavaClass();
                } else {
                    String fieldName = (mapping.hasMapsIdValue()) ? mapping.getMapsIdValue() : mapping.getAttributeName();

                    if (currentKeyClass == null || mapping.isMultitenantPrimaryKeyMapping()) {
                        // Without a currentKeyClass, the primary key is a non compound key but
                        // we may need to add any multitenant primary key mappings that are
                        // defined and we need an accessor for them. The same case will hold
                        // true when we do have a currentKeyClass. Multitenant primary keys
                        // must still be added.
                        pkAttributes[i] = new KeyIsElementAccessor(fieldName, field, mapping);
                        if (mapping.isAbstractDirectMapping()) {
                            setPKClass(ConversionManager.getObjectClass(mapping.getAttributeClassification()));
                        } else if (mapping.isOneToOneMapping()) {
                            ClassDescriptor refDescriptor = mapping.getReferenceDescriptor();
                            // ensure the referenced descriptor was initialized
                            if (!session.isRemoteSession()) {
                                refDescriptor.initialize(session);
                            }
                            CMPPolicy refPolicy = refDescriptor.getCMPPolicy();
                            setPKClass(refPolicy.getPKClass());
                        }
                        fieldToAccessorMap.put(field, pkAttributes[i]);
                        noSuchElementException = null;
                    } else {
                        if (mapping.isOneToOneMapping()){
                            ClassDescriptor refDescriptor = mapping.getReferenceDescriptor();
                            // ensure the referenced descriptor was initialized
                            if (!session.isRemoteSession()) {
                                refDescriptor.initialize(session);
                            }
                            CMPPolicy refPolicy = refDescriptor.getCMPPolicy();
                            if ((refPolicy!=null) && refPolicy.isCMP3Policy() && (refPolicy.getPKClass() == currentKeyClass)){
                                //Since the ref pk class is our pk class, get the accessor we need to pull the value out of the PK class for our field
                                OneToOneMapping refmapping = (OneToOneMapping)mapping;
                                DatabaseField targetKey = refmapping.getSourceToTargetKeyFields().get(field);
                                pkAttributes[i] = ((CMP3Policy)refPolicy).fieldToAccessorMap.get(targetKey);
                                //associate their accessor to our field so we can look it up when we need it
                                this.fieldToAccessorMap.put(field, pkAttributes[i]);
                                noSuchElementException = null;
                                break;
                            }
                        }

                        try {
                            pkAttributes[i] = new FieldAccessor(this, getField(currentKeyClass, fieldName), fieldName, field, mapping, currentKeyClass != keyClass);
                            fieldToAccessorMap.put(field, pkAttributes[i]);
                            noSuchElementException = null;
                        } catch (NoSuchFieldException ex) {
                            String getMethodName = null;
                            String setMethodName = null;
                            if(mapping.isObjectReferenceMapping() && ((ObjectReferenceMapping)mapping).getIndirectionPolicy().isWeavedObjectBasicIndirectionPolicy()) {
                                WeavedObjectBasicIndirectionPolicy weavedIndirectionPolicy = (WeavedObjectBasicIndirectionPolicy)((ObjectReferenceMapping)mapping).getIndirectionPolicy();
                                if (weavedIndirectionPolicy.hasUsedMethodAccess()) {
                                    getMethodName = weavedIndirectionPolicy.getGetMethodName();
                                    setMethodName = weavedIndirectionPolicy.getSetMethodName();
                                }
                            } else {
                                getMethodName = mapping.getGetMethodName();
                                setMethodName = mapping.getSetMethodName();
                            }
                            if (getMethodName != null) {
                                // Must be a property.
                                try {
                                    Method getMethod = null;
                                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                                        try {
                                            getMethod = AccessController.doPrivileged(new PrivilegedGetMethod(currentKeyClass, getMethodName, new Class[] {}, true));
                                        } catch (PrivilegedActionException exception) {
                                            throw (NoSuchMethodException)exception.getException();
                                        }
                                    } else {
                                        getMethod = PrivilegedAccessHelper.getMethod(currentKeyClass, getMethodName, new Class[] {}, true);
                                    }
                                    Method setMethod = null;
                                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                                        try {
                                            setMethod = AccessController.doPrivileged(new PrivilegedGetMethod(currentKeyClass, setMethodName, new Class[] {getMethod.getReturnType()}, true));
                                        } catch (PrivilegedActionException exception) {
                                            throw (NoSuchMethodException)exception.getException();
                                        }
                                    } else {
                                        setMethod = PrivilegedAccessHelper.getMethod(currentKeyClass, setMethodName, new Class[] {getMethod.getReturnType()}, true);
                                    }
                                    pkAttributes[i] = new PropertyAccessor(this, getMethod, setMethod, fieldName, field, mapping, currentKeyClass != keyClass);
                                    this.fieldToAccessorMap.put(field, pkAttributes[i]);
                                    noSuchElementException = null;
                                } catch (NoSuchMethodException exs) {
                                    // not a field not a method, but a pk class is defined.  Check for other mappings
                                    noSuchElementException = exs;
                                }
                            } else {
                                noSuchElementException = ex;
                            }

                            // If we can't load the field or methods and the attribute accessor is a values
                            // accessor then we're dealing with a dynamic entity.
                            if (noSuchElementException != null && mapping.getAttributeAccessor().isValuesAccessor()) {
                                pkAttributes[i] = new ValuesFieldAccessor(fieldName, field, mapping, currentKeyClass != keyClass);
                                noSuchElementException = null;
                            }
                        }
                    }

                    if (mapping.derivesId() || noSuchElementException == null) {
                        // Break out of the loop as we do not need to look for
                        // any more mappings
                        break;
                    }
                }
            } // end for loop

            if (noSuchElementException != null) {
                throw DescriptorException.errorUsingPrimaryKey(keyClass, getDescriptor(), noSuchElementException);
            }
        } // end first for loop

        return pkAttributes;
    }

    /**
     * INTERNAL:
     * @return Returns the keyClassFields.
     */
    @Override
    protected KeyElementAccessor[] getKeyClassFields() {
        return this.keyClassFields;
    }

    // Made static for performance reasons.
    private static abstract class CommonAccessor implements KeyElementAccessor {
        private final String attributeName;
        private final DatabaseField databaseField;
        protected final DatabaseMapping mapping;
        private final boolean isNestedAccessor;

        public CommonAccessor(String attributeName, DatabaseField field, DatabaseMapping mapping, boolean isNestedAccessor) {
            this.attributeName = attributeName;
            this.databaseField = field;
            this.mapping = mapping;
            this.isNestedAccessor = isNestedAccessor;
        }

        @Override
        public String getAttributeName() {
            return this.attributeName;
        }

        @Override
        public DatabaseField getDatabaseField() {
            return this.databaseField;
        }

        @Override
        public DatabaseMapping getMapping() {
            return this.mapping;
        }

        @Override
        public boolean isNestedAccessor() {
            return isNestedAccessor;
        }

    }

    // Made static final for performance reasons.
    /**
     * INTERNAL:
     * This class is used when the key class element is a property
     */
    private static final class PropertyAccessor extends CommonAccessor {
        private final Method getMethod;
        private final Method setMethod;
        private final CMPPolicy policy;

        public PropertyAccessor(CMPPolicy policy, Method getMethod, Method setMethod, String attributeName, DatabaseField databaseField, DatabaseMapping mapping, boolean isNestedAccessor) {
            super(attributeName, databaseField, mapping, isNestedAccessor);
            this.getMethod = getMethod;
            this.setMethod = setMethod;
            this.policy = policy;
        }

        @Override
        public Object getValue(Object object, AbstractSession session) {
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        return AccessController.doPrivileged(new PrivilegedMethodInvoker(this.getMethod, object, new Object[] {  }));
                    } catch (PrivilegedActionException exception) {
                        Exception throwableException = exception.getException();
                        if (throwableException instanceof IllegalAccessException) {
                            throw (IllegalAccessException)throwableException;
                        } else {
                            throw (java.lang.reflect.InvocationTargetException)throwableException;
                        }
                    }
                } else {
                    return PrivilegedAccessHelper.invokeMethod(this.getMethod, object, new Object[] {  });
                }
            } catch (Exception ex) {
                throw DescriptorException.errorUsingPrimaryKey(object, policy.getDescriptor(), ex);
            }
        }

        @Override
        public void setValue(Object object, Object value) {
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        AccessController.doPrivileged(new PrivilegedMethodInvoker(this.setMethod, object, new Object[] {value}));
                    } catch (PrivilegedActionException exception) {
                        Exception throwableException = exception.getException();
                        if (throwableException instanceof IllegalAccessException) {
                            throw (IllegalAccessException)throwableException;
                        } else {
                            throw (java.lang.reflect.InvocationTargetException)throwableException;
                        }
                    }
                } else {
                    PrivilegedAccessHelper.invokeMethod(this.setMethod, object, new Object[] {value});
                }
            } catch (Exception ex) {
                throw DescriptorException.errorUsingPrimaryKey(object, policy.getDescriptor(), ex);
            }
        }
    }

    // Made static final for performance reasons.
    /**
     * INTERNAL:
     * This class will be used when the element of the keyclass is a field
     */
    private static final class FieldAccessor extends CommonAccessor {
        private final Field field;
        private final CMPPolicy policy;

        public FieldAccessor(CMPPolicy policy, Field field, String attributeName, DatabaseField databaseField, DatabaseMapping mapping, boolean isNestedAccessor) {
            super(attributeName, databaseField, mapping, isNestedAccessor);
            this.field = field;
            this.policy = policy;
        }

         @Override
         public Object getValue(Object object, AbstractSession session) {
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        return AccessController.doPrivileged(new PrivilegedGetValueFromField(field, object));
                    } catch (PrivilegedActionException exception) {
                        throw DescriptorException.errorUsingPrimaryKey(object, policy.getDescriptor(), exception.getException());                    }
                } else {
                    return org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getValueFromField(field, object);
                }
            } catch (Exception ex) {
                throw DescriptorException.errorUsingPrimaryKey(object, policy.getDescriptor(), ex);
            }
        }

        @Override
        public void setValue(Object object, Object value) {
            try {
                Field pkField = null;
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        pkField = AccessController.doPrivileged(new PrivilegedGetField(object.getClass(), field.getName(), true));
                        AccessController.doPrivileged(new PrivilegedSetValueInField(pkField, object, value));
                    } catch (PrivilegedActionException exception) {
                        throw DescriptorException.errorUsingPrimaryKey(object, policy.getDescriptor(), exception.getException());
                    }
                } else {
                    pkField = PrivilegedAccessHelper.getField(object.getClass(), field.getName(), true);
                    PrivilegedAccessHelper.setValueInField(pkField, object, value);
                }
            } catch (Exception ex) {
                throw DescriptorException.errorUsingPrimaryKey(object, policy.getDescriptor(), ex);
            }
        }
    }

    // Made static final for performance reasons.
    /**
     * INTERNAL:
     * This class will be used when the element of the keyclass is a virtual field.
     */
    private static final class ValuesFieldAccessor extends CommonAccessor {

        public ValuesFieldAccessor(String attributeName, DatabaseField databaseField, DatabaseMapping mapping, boolean isNestedAccessor) {
            super(attributeName, databaseField, mapping, isNestedAccessor);
        }

        @Override
        public Object getValue(Object object, AbstractSession session) {
        return mapping.getRealAttributeValueFromObject(object, session);
        }

        @Override
        public void setValue(Object object, Object value) {
        mapping.setRealAttributeValueInObject(object, value);
        }
    }

    /**
     * INTERNAL:
     * Pull the value for the field from the key.
     *
     * @param key Object the primary key to use to get the value for the field
     * @param field DatabaseField the field to find a value for
     * @return Object
     */
    public Object getPkValueFromKeyForField(Object key, DatabaseField field, AbstractSession session){
        Object fieldValue = null;
        KeyElementAccessor accessor = this.fieldToAccessorMap.get(field);
        DatabaseMapping mapping = accessor.getMapping();
        if (mapping.isAbstractColumnMapping()) {
            fieldValue = ((AbstractColumnMapping)mapping).getFieldValue(accessor.getValue(key, session), session);
        } else {
            fieldValue = accessor.getValue(key, session);
            if (mapping.isOneToOneMapping()){
                OneToOneMapping refmapping = (OneToOneMapping)mapping;
                DatabaseField targetKey = refmapping.getSourceToTargetKeyFields().get(accessor.getDatabaseField());
                CMPPolicy refPolicy = refmapping.getReferenceDescriptor().getCMPPolicy();
                if (refPolicy.isCMP3Policy()){
                    Class<Object> pkClass = refPolicy.getPKClass();
                    if ((pkClass != null) && (pkClass != fieldValue.getClass()) && (!pkClass.isAssignableFrom(fieldValue.getClass()))) {
                        throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_pk_class", new Object[] { refPolicy.getPKClass(), fieldValue.getClass() }));
                    }
                    fieldValue = ((CMP3Policy)refPolicy).getPkValueFromKeyForField(fieldValue, targetKey, session);
                }
            }
        }
        return fieldValue;
    }

    /**
     * INTERNAL:
     * Initialize the CMPPolicy settings.
     */
    @Override
    public void initialize(ClassDescriptor descriptor, AbstractSession session) throws DescriptorException {
        super.initialize(descriptor, session);

        this.keyClassFields = initializePrimaryKeyFields(this.pkClass, session);
    }

    /**
     * INTERNAL:
     * Initialize the CMPPolicy settings for remote sessions.
     */
    @Override
    public void remoteInitialize(ClassDescriptor descriptor, AbstractSession session) throws DescriptorException {
        super.remoteInitialize(descriptor, session);

        this.keyClassFields = initializePrimaryKeyFields(null, session);
    }
}
