/*
 * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2018 IBM Corporation. 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
//     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
//     03/23/2016-2.6_WAS Will Dazey
//       - 490114: Add support for PersistenceUnitUtil.getIdentifier with nested embeddables in EmbeddedId class
package org.eclipse.persistence.descriptors;

import java.io.Serializable;
import java.security.AccessController;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.persistence.annotations.CacheKeyType;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedNewInstanceFromClass;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.mappings.foundation.AbstractColumnMapping;
import org.eclipse.persistence.queries.UpdateObjectQuery;

/**
 * <p>
 * <b>Description</b>: Place holder for CMP specific information.  This class can be set on the ClassDescriptor.
 *
 * @see org.eclipse.persistence.descriptors.PessimisticLockingPolicy
 *
 * @since TopLink 10.1.3
 */
public class CMPPolicy implements java.io.Serializable, Cloneable {

    protected Boolean forceUpdate;
    protected Boolean updateAllFields;

    /** Allow the bean to always be locked as it enters a new transaction. */
    protected PessimisticLockingPolicy pessimisticLockingPolicy;


    /** Class originally mapped, before anything was generated. */
    protected Class mappedClass;
    protected ClassDescriptor descriptor;

    /** The object deferral level.  This controls when objects changes will be sent to the Database. */
    protected int modificationDeferralLevel = ALL_MODIFICATIONS;

    /** defer no changes */
    public static final int NONE = 0;

    /** defer updates */
    public static final int UPDATE_MODIFICATIONS = 1;

    /** defer all modifications, inserts and deletes included (default) */
    public static final int ALL_MODIFICATIONS = 2;

    /** This setting will allow customers to control when Toplink will issue the insert SQL for CMP beans. */
    protected int nonDeferredCreateTime = UNDEFINED;

    /** undefined if it is non-deferred issue sql at create */
    public static final int UNDEFINED = 0;

    /** issue SQL after ejbCreate but before ejbPostCreate */
    public static final int AFTER_EJBCREATE = 1;

    /** issue SQL after ejbPostCreate */
    public static final int AFTER_EJBPOSTCREATE = 2;

    public CMPPolicy() {
        this.forceUpdate = null;
        this.updateAllFields = null;
    }

    /**
     * ADVANCED:
     * This setting is only available for CMP beans that are not being deferred.
     * Using it will allow TopLink to  determine if the INSERT SQL should be sent to
     * the database before or after the postCreate call.
     */
    public int getNonDeferredCreateTime() {
        return this.nonDeferredCreateTime;
    }

    /**
     * PUBLIC:
     * Return the policy for bean pessimistic locking
     * @see org.eclipse.persistence.descriptors.PessimisticLockingPolicy
     */
    public PessimisticLockingPolicy getPessimisticLockingPolicy() {
        return pessimisticLockingPolicy;
    }

    /**
     * ADVANCED:
     * This can be set to control when changes to objects are submitted to the database
     * This is only applicable to TopLink's CMP implementation and not available within
     * the core.
     */
    public void setDeferModificationsUntilCommit(int deferralLevel) {
        this.modificationDeferralLevel = deferralLevel;
    }

    /**
     * PUBLIC:
     * Define the mapped class. This is the class which was originally mapped in the MW
     *
     * @param newMappedClass
     */
    public void setMappedClass(Class newMappedClass) {
        mappedClass = newMappedClass;
    }

    /**
     * PUBLIC:
     * Answer the mapped class. This is the class which was originally mapped in the MW
     *
     */
    public Class getMappedClass() {
        return mappedClass;
    }

    /**
     * ADVANCED:
     * This setting is only available for CMP beans that are not being deferred.
     * Using it will allow TopLink to  determine if the INSERT SQL should be sent to
     * the database before or after the postCreate call.
     */
    public void setNonDeferredCreateTime(int createTime) {
        this.nonDeferredCreateTime = createTime;
    }

    /**
     * PUBLIC:
     * Configure bean pessimistic locking
     *
     * @param policy
     * @see org.eclipse.persistence.descriptors.PessimisticLockingPolicy
     */
    public void setPessimisticLockingPolicy(PessimisticLockingPolicy policy) {
        pessimisticLockingPolicy = policy;
    }

    /**
     * PUBLIC:
     * Return true if bean pessimistic locking is configured
     */
    public boolean hasPessimisticLockingPolicy() {
        return pessimisticLockingPolicy != null;
    }

    /**
     * ADVANCED:
     * This can be used to control when changes to objects are submitted to the database
     * This is only applicable to TopLink's CMP implementation and not available within
     * the core.
     */
    public int getDeferModificationsUntilCommit() {
        return this.modificationDeferralLevel;
    }

    /**
     * ADVANCED:
     * Return true if descriptor is set to always update all registered objects of this type
     */
    public boolean getForceUpdate() {
        // default to false
        return (Boolean.TRUE.equals(this.forceUpdate));
    }

    /**
     * ADVANCED:
     * Configure whether TopLink should always update all registered objects of
     * this type.  NOTE: if set to true, then updateAllFields must also be set
     * to true
     *
     * @param shouldForceUpdate
     */
    public void setForceUpdate(boolean shouldForceUpdate) {
        this.forceUpdate = Boolean.valueOf(shouldForceUpdate);
    }

    /**
     * ADVANCED:
     * Return true if descriptor is set to update all fields for an object of this
     * type when an update occurs.
     */
    public boolean getUpdateAllFields() {
        // default to false
        return Boolean.TRUE.equals(this.updateAllFields);
    }

    /**
     * ADVANCED:
     * Configure whether TopLink should update all fields for an object of this
     * type when an update occurs.
     *
     * @param shouldUpdatAllFields
     */
    public void setUpdateAllFields(boolean shouldUpdatAllFields) {
        this.updateAllFields = Boolean.valueOf(shouldUpdatAllFields);
    }

    /**
     * INTERNAL:
     * return internal tri-state value so we can decide whether to inherit or not at init time.
     */
    public Boolean internalGetForceUpdate() {
        return this.forceUpdate;
    }

    /**
     * INTERNAL:
     * return internal tri-state value so we can decide whether to inherit or not at init time.
     */
    public Boolean internalGetUpdateAllFields() {
        return this.updateAllFields;
    }

    /**
     * INTERNAL:
     * internal method to set the tri-state value. This is done in InheritancePolicy at init time.
     */
    public void internalSetForceUpdate(Boolean newForceUpdateValue) {
        this.forceUpdate = newForceUpdateValue;
    }

    /**
     * INTERNAL:
     * internal method to set the tri-state value. This is done in InheritancePolicy at init time.
     */
    public void internalSetUpdateAllFields(Boolean newUpdateAllFieldsValue) {
        this.updateAllFields = newUpdateAllFieldsValue;
    }

    /**
     * INTERNAL:
     * Initialize the CMPPolicy settings.
     */
    public void initialize(ClassDescriptor descriptor, AbstractSession session) throws DescriptorException {
        // updateAllFields is true so set custom query in DescriptorQueryManager
        // to force full SQL.  Don't overwrite a user defined query
        if (this.getUpdateAllFields() && !descriptor.getQueryManager().hasUpdateQuery()) {
            descriptor.getQueryManager().setUpdateQuery(new UpdateObjectQuery());
        }

        // make sure updateAllFields is set if forceUpdate is true
        if (this.getForceUpdate() && !this.getUpdateAllFields()) {
            throw DescriptorException.updateAllFieldsNotSet(descriptor);
        }
    }

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

    /**
     * INTERNAL:
     * @return Returns the owningDescriptor.
     */
    public ClassDescriptor getDescriptor() {
        return descriptor;
    }

    /**
     * INTERNAL:
     * @param owningDescriptor The owningDescriptor to set.
     */
    public void setDescriptor(ClassDescriptor owningDescriptor) {
        this.descriptor = owningDescriptor;
    }

    /**
     * INTERNAL:
     * Recursive method to set a field value in the given key instance.
     */
    protected void setFieldValue(KeyElementAccessor accessor, Object keyInstance, DatabaseMapping mapping, AbstractSession session, int[] elementIndex, Object ... keyElements) {
        if (mapping.isAggregateMapping()) {
            Object nestedObject = mapping.getRealAttributeValueFromObject(keyInstance, session);

            if (nestedObject == null) {
                nestedObject = getClassInstance(mapping.getReferenceDescriptor().getJavaClass());
                mapping.setRealAttributeValueInObject(keyInstance, nestedObject);
            }

            // keep drilling down the nested mappings ...
            setFieldValue(accessor, nestedObject, mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(accessor.getDatabaseField()), session, elementIndex, keyElements);
        } else {
            Object fieldValue = null;

            if (mapping.isAbstractColumnMapping()) {
                fieldValue = keyElements[elementIndex[0]];
                Converter converter = ((AbstractColumnMapping) mapping).getConverter();
                if (converter != null){
                    fieldValue = converter.convertDataValueToObjectValue(fieldValue, session);
                }
                ++elementIndex[0];
            } else if (mapping.isObjectReferenceMapping()) {
                // what if mapping comes from derived ID. need to get the derived mapping.
                // get reference descriptor and extract pk from target cmp policy
                fieldValue = mapping.getReferenceDescriptor().getCMPPolicy().createPrimaryKeyInstanceFromPrimaryKeyValues(session, elementIndex, keyElements);
            }

            accessor.setValue(keyInstance, fieldValue);
        }
    }

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

    /**
     * INTERNAL:
     * Clone the CMPPolicy
     */
    @Override
    public CMPPolicy clone() {
       try {
            return (CMPPolicy) super.clone();
        } catch (CloneNotSupportedException exception) {
            throw new InternalError(exception.getMessage());
        }
    }

    /**
     * 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.
     * @param classLoader
     */
    public void convertClassNamesToClasses(ClassLoader classLoader){
    }

    /**
     * INTERNAL:
     * Create an instance of the composite primary key class for the key object.
     */
    public Object createPrimaryKeyInstanceFromId(Object key, AbstractSession session) {
        if (this.descriptor.getCachePolicy().getCacheKeyType() == CacheKeyType.CACHE_ID) {
            return createPrimaryKeyInstanceFromPrimaryKeyValues(session, new int[]{0}, ((CacheId)key).getPrimaryKey());
        } else {
            return createPrimaryKeyInstanceFromPrimaryKeyValues(session, new int[]{0}, key);
        }
    }

    /**
     * INTERNAL:
     * Create an instance of the composite primary key class for the key object.
     * Yes the elementIndex looks strange but this is just a simple way to get the index to be pass-by-reference
     */
    public Object createPrimaryKeyInstanceFromPrimaryKeyValues(AbstractSession session, int[] elementIndex, Object ... keyElements ) {
        Object keyInstance = null;
        KeyElementAccessor[] pkElementArray = getKeyClassFields();
        if (isSingleKey(pkElementArray)) {
            for (KeyElementAccessor accessor: pkElementArray){
                DatabaseMapping mapping = getDescriptor().getObjectBuilder().getMappingForAttributeName(accessor.getAttributeName());
                if (mapping != null && !mapping.isMultitenantPrimaryKeyMapping()){
                    if (mapping.isAbstractColumnMapping()) {
                        Converter converter = ((AbstractColumnMapping) mapping).getConverter();
                        if (converter != null){
                            return converter.convertDataValueToObjectValue(keyElements[elementIndex[0]], session);
                        }
                        keyInstance = keyElements[elementIndex[0]];
                    } else if (mapping.isObjectReferenceMapping()) { // what if mapping comes from derived ID.  need to get the derived mapping.
                        //get reference descriptor and extract pk from target cmp policy
                        keyInstance = mapping.getReferenceDescriptor().getCMPPolicy().createPrimaryKeyInstanceFromPrimaryKeyValues(session, elementIndex, keyElements);
                    }
                    ++elementIndex[0]; // remove processed key in case keys are complex and derived
                }
                if (keyInstance != null){
                    return keyInstance;
                }
            }
        } else {
            keyInstance = getPKClassInstance();
            ObjectBuilder objectBuilder = getDescriptor().getObjectBuilder();
            //get clone of Key so we can remove values.
            for (int index = 0; index < pkElementArray.length; index++) {
                KeyElementAccessor accessor = pkElementArray[index];
                DatabaseMapping mapping = getDescriptor().getObjectBuilder().getMappingForAttributeName(accessor.getAttributeName());
                if (mapping == null) {
                    mapping = objectBuilder.getMappingForField(accessor.getDatabaseField());
                    if (! mapping.isAggregateObjectMapping() && ! mapping.isAbstractDirectMapping()) {
                        // Found a mapping for the database field but it's not an aggregate (embedded ID) or a direct mapping so maybe the mappings
                        // have been mapped multiple times.  Check read-only mappings for dtf or aggregate
                        List<DatabaseMapping> readOnlyMappings = objectBuilder.getReadOnlyMappingsForField(accessor.getDatabaseField());
                        for (DatabaseMapping readOnlyMapping : readOnlyMappings) {
                            if (readOnlyMapping.isAggregateObjectMapping() || readOnlyMapping.isDirectToFieldMapping()) {
                                mapping = readOnlyMapping;
                                break;
                            }
                        }

                    }
                }

                if (accessor.isNestedAccessor()) {
                    // Need to recursively build all the nested objects.
                    setFieldValue(accessor, keyInstance, mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(accessor.getDatabaseField()), session, elementIndex, keyElements);
                } else {
                    // Not nested but may be a single layer aggregate so check.
                    if (mapping.isAggregateMapping()) {
                        DatabaseMapping nestedMapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(accessor.getDatabaseField());
                        if (nestedMapping == null) {
                            //must be a read only mapping
                            List<DatabaseMapping> readOnlyMappings = mapping.getReferenceDescriptor().getObjectBuilder().getReadOnlyMappingsForField(accessor.getDatabaseField());
                            for (DatabaseMapping readOnlyMapping : readOnlyMappings) {
                                if (readOnlyMapping.isAbstractDirectMapping()) {
                                    mapping = readOnlyMapping;
                                    break;
                                }
                            }
                        } else {
                            mapping = nestedMapping;
                        }
                    }

                    setFieldValue(accessor, keyInstance, mapping, session, elementIndex, keyElements);
                }
            }
        }

        return keyInstance;
    }

    /**
     * INTERNAL:
     * Create an instance of the Id class or value from the object.
     */
    public Object createPrimaryKeyInstance(Object object, AbstractSession session) {
        KeyElementAccessor[] pkElementArray = this.getKeyClassFields();
        ObjectBuilder builder = getDescriptor().getObjectBuilder();
        if (pkElementArray.length == 1 && pkElementArray[0] instanceof KeyIsElementAccessor){
            DatabaseMapping mapping = builder.getMappingForAttributeName(pkElementArray[0].getAttributeName());
            Object fieldValue = mapping.getRealAttributeValueFromObject(object, session);
            if (mapping.isObjectReferenceMapping()){
                fieldValue = mapping.getReferenceDescriptor().getCMPPolicy().createPrimaryKeyInstance(fieldValue, session);
            }
            return  fieldValue;
        }

        Object keyInstance = getPKClassInstance();
        Set<ObjectReferenceMapping> usedObjectReferenceMappings = new HashSet<>();
        for (int index = 0; index < pkElementArray.length; index++) {
            Object keyObj = object;
            KeyElementAccessor accessor = pkElementArray[index];
            DatabaseField field = accessor.getDatabaseField();
            DatabaseMapping mapping = builder.getMappingForField(field);
            Object nestedKeyInstance = keyInstance;
            // With session validation, the mapping shouldn't be null at this
            // point, don't bother checking.
            if (!mapping.isObjectReferenceMapping() || !usedObjectReferenceMappings.contains(mapping)){
                while (mapping.isAggregateObjectMapping()) {
                    keyObj = mapping.getRealAttributeValueFromObject(keyObj, session);
                    mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(field);

                    //Check for embedded Id values
                    if (mapping.isAggregateMapping()) {
                        Object nestedObject = mapping.getRealAttributeValueFromObject(nestedKeyInstance, session);
                        if (nestedObject == null) {
                            nestedObject = getClassInstance(mapping.getReferenceDescriptor().getJavaClass());
                        }
                        mapping.setRealAttributeValueInObject(nestedKeyInstance, nestedObject);
                        nestedKeyInstance = nestedObject;
                    }
                }
                Object fieldValue = mapping.getRealAttributeValueFromObject(keyObj, session);
                if (mapping.isObjectReferenceMapping()){
                    fieldValue = mapping.getReferenceDescriptor().getCMPPolicy().createPrimaryKeyInstance(fieldValue, session);
                    usedObjectReferenceMappings.add((ObjectReferenceMapping)mapping);
                }
                accessor.setValue(nestedKeyInstance, fieldValue);
            }
        }

        return keyInstance;
    }

    /**
     * INTERNAL:
     * Return a new instance of the class provided.
     */
    public Object getClassInstance(Class cls) {
        if (cls != null){
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    return AccessController.doPrivileged(new PrivilegedNewInstanceFromClass(cls));
                } else {
                    return org.eclipse.persistence.internal.security.PrivilegedAccessHelper.newInstanceFromClass(cls);
                }
            } catch (Exception e) {
                throw ValidationException.reflectiveExceptionWhileCreatingClassInstance(cls.getName(), e);
            }
        }

        return null;
    }

    /**
     * INTERNAL:
     */
    public Object getPKClassInstance() {
        // TODO fix this exception so that it is more descriptive
        // This method only works in CMP3Policy but was added here for separation
        // of components
        throw new RuntimeException("Should not get here.");
    }

    /**
     * INTERNAL:
     */
    public Class getPKClass() {
        // TODO fix this exception so that it is more descriptive
        // This method only works in CMP3Policy but was added here for separation
        // of components
        throw new RuntimeException("Should not get here.");
    }

    /**
     * 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.
     */
    public Object createPrimaryKeyFromId(Object key, AbstractSession session) {
        // TODO fix this exception so that it is more descriptive
        // This method only works in CMP3Policy but was added here for separation
        // of components
        throw new RuntimeException("Should not get here.");
    }

    /**
     * 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
     */
    public Object createBeanUsingKey(Object key, AbstractSession session) {
        // TODO fix this exception so that it is more descriptive
        // This method only works in CMP3Policy but was added here for separation
        // of components
        throw new RuntimeException("Should not get here.");
    }

    /**
     * INTERNAL:
     * @return Returns the keyClassFields.
     */
    protected KeyElementAccessor[] getKeyClassFields() {
        // TODO fix this exception so that it is more descriptive
        // This method only works in CMP3Policy but was added here for separation
        // of components
        throw new RuntimeException("Should not get here.");
    }

    /**
     * Check to see if there is a single key element.  Iterate through the list of primary key elements
     * and count only keys that are not part of the Multitenant identifier.
     *
     * @param pkElementArray
     * @return
     */
    protected boolean isSingleKey(KeyElementAccessor[] pkElementArray){
        if ((pkElementArray.length == 1) && (pkElementArray[0] instanceof KeyIsElementAccessor)) {
            return true;
        }
        boolean foundFirstElement = false;
        for (KeyElementAccessor accessor: pkElementArray){
            if (!(accessor instanceof KeyIsElementAccessor)){
                return false;
            }
            if (!accessor.getMapping().isMultitenantPrimaryKeyMapping()){
                if (foundFirstElement){
                    return false;
                }
                foundFirstElement = true;
            }
        }
        return true;
    }

    /**
     * INTERNAL:
     * This is the interface used to encapsulate the the type of key class element
     */
    protected static interface KeyElementAccessor {
        String getAttributeName();
        DatabaseField getDatabaseField();
        DatabaseMapping getMapping();
        Object getValue(Object object, AbstractSession session);
        void setValue(Object object, Object value);
        boolean isNestedAccessor();
    }

    /**
     * INTERNAL:
     * This class will be used when the keyClass is a primitive
     */
    protected static final class KeyIsElementAccessor implements KeyElementAccessor, Serializable {
        protected String attributeName;
        protected DatabaseField databaseField;
        protected DatabaseMapping mapping;

        public KeyIsElementAccessor(String attributeName, DatabaseField databaseField, DatabaseMapping mapping) {
            this.attributeName = attributeName;
            this.databaseField = databaseField;
            this.mapping = mapping;
        }

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

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

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

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

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

        @Override
        public void setValue(Object object, Object value) {
            // WIP - do nothing for now???
        }
    }
}
