/*
 * 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
     *
     */
    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
     *
     * @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
     *
     */
    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.
     *
     */
    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.
     */
    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.
     *
     */
    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???
        }
    }
}
