/*
 * Copyright (c) 1998, 2021 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 = 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 = 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???
        }
    }
}
