/*
 * Copyright (c) 1998, 2019 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
package org.eclipse.persistence.internal.descriptors;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Iterator;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.InheritancePolicy;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.DataReadQuery;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;

/**
 * INTERNAL:
 */
public class CascadeLockingPolicy {
    protected Class m_parentClass;
    protected ReadObjectQuery m_query;
    protected ClassDescriptor m_descriptor;
    protected ClassDescriptor m_parentDescriptor;
    protected Map<DatabaseField, DatabaseField> m_queryKeyFields;
    protected Map<DatabaseField, DatabaseField> m_mappedQueryKeyFields;
    protected Map<DatabaseField, DatabaseField> m_unmappedQueryKeyFields;
    protected DatabaseMapping m_parentMapping;
    protected boolean m_lookForParentMapping;
    protected boolean m_shouldHandleUnmappedFields;
    protected boolean m_hasCheckedForUnmappedFields;
    protected DataReadQuery m_unmappedFieldsQuery;

    /**
     * INTERNAL:
     */
    public CascadeLockingPolicy(ClassDescriptor parentDescriptor, ClassDescriptor descriptor) {
        m_descriptor = descriptor;
        m_parentDescriptor = parentDescriptor;
        m_parentClass = m_parentDescriptor.getJavaClass();
    }

    /**
     * INTERNAL:
     */
    protected ReadObjectQuery getQuery() {
        if (m_query == null) {
            m_query = new ReadObjectQuery(m_parentClass);

            Expression selectionCriteria = null;
            Iterator keys = m_queryKeyFields.keySet().iterator();
            ExpressionBuilder builder = new ExpressionBuilder();

            while (keys.hasNext()) {
                String keyField = ((DatabaseField) keys.next()).getQualifiedName();

                if (selectionCriteria == null) {
                    selectionCriteria = builder.getField(keyField).equal(builder.getParameter(keyField));
                } else {
                    selectionCriteria.and(builder.getField(keyField).equal(builder.getParameter(keyField)));
                }

                m_query.addArgument(keyField);
            }

            m_query.setSelectionCriteria(selectionCriteria);
            m_query.setShouldUseWrapperPolicy(false);
        }

        return m_query;
    }

    /**
     * INTERNAL:
     */
     protected DatabaseMapping getParentMapping() {
        // If the query is null, then we have not been initialized. Try to
        // look up a parent mapping first if we have lookup fields. For a
        // 1-M we can not perform the getMappingForField until the fields
        // have been initialized.
        // If the parent mapping is not found, a query will be initialized
        // and the following lookup will no longer hit.
        if (m_parentMapping == null && m_lookForParentMapping && m_query == null) {
            Iterator<DatabaseField> itFields = m_queryKeyFields.values().iterator();
            while(itFields.hasNext()) {
                DatabaseMapping mapping = m_descriptor.getObjectBuilder().getMappingForField(itFields.next());

                if(mapping == null) {
                    // at least one field is not mapped therefore no parent mapping exists.
                    m_parentMapping = null;
                    break;
                } else if(mapping.isObjectReferenceMapping()) {
                    if(m_parentMapping == null) {
                        m_parentMapping = mapping;
                    } else {
                        if(m_parentMapping != mapping) {
                            // there's more than one mapping therefore no parent mapping exists.
                            m_parentMapping = null;
                            break;
                        }
                    }
                }
            }
        }

        return m_parentMapping;
     }

     /**
      * Get the descriptor that really represents this object
      * In the case of inheritance, the object may represent a subclass of class the descriptor
      * represents.
      *
      * If there is no InheritancePolicy, we return our parentDescriptor
      * If there is inheritance we will search for a descriptor that represents parentObj and
      * return that descriptor
      * @param parentObj
      * @return
      */
     protected ClassDescriptor getParentDescriptorFromInheritancePolicy(Object parentObj){
         ClassDescriptor realParentDescriptor = m_parentDescriptor;
         if (realParentDescriptor.hasInheritance()){
             InheritancePolicy inheritancePolicy = realParentDescriptor.getInheritancePolicy();
             ClassDescriptor childDescriptor = inheritancePolicy.getDescriptor(parentObj.getClass());
             if (childDescriptor != null){
                 realParentDescriptor = childDescriptor;
             }
         }
         return realParentDescriptor;
     }

    /**
     * INTERNAL:
     */
     protected AbstractRecord getMappedTranslationRow(Object changedObj, UnitOfWorkImpl uow) {
         AbstractRecord translationRow = new DatabaseRecord();
         Iterator<Map.Entry<DatabaseField, DatabaseField>> it = m_mappedQueryKeyFields.entrySet().iterator();
         while(it.hasNext()) {
             Map.Entry<DatabaseField, DatabaseField> entry = it.next();
             Object value = m_descriptor.getObjectBuilder().extractValueFromObjectForField(changedObj, entry.getValue(), uow);
             translationRow.add(entry.getKey(), value);
         }
         return translationRow;
     }

     /**
      * INTERNAL:
      */
      protected AbstractRecord getUnmappedTranslationRow(Object changedObj, UnitOfWorkImpl uow) {
         AbstractRecord unmappedFieldsQueryTranslationRow = new DatabaseRecord();
         Iterator<DatabaseField> itPrimaryKey = m_descriptor.getPrimaryKeyFields().iterator();
         while (itPrimaryKey.hasNext()) {
             DatabaseField primaryKey = itPrimaryKey.next();
             Object value = m_descriptor.getObjectBuilder().extractValueFromObjectForField(changedObj, primaryKey, uow);
             unmappedFieldsQueryTranslationRow.add(primaryKey, value);
         }
         List result = (List)uow.executeQuery(m_unmappedFieldsQuery, unmappedFieldsQueryTranslationRow);
         if(result == null || result.isEmpty()) {
             // the object is not in the db
             return null;
         }

         AbstractRecord unmappedValues = (AbstractRecord)result.get(0);

         AbstractRecord translationRow = new DatabaseRecord();
         Iterator<Map.Entry<DatabaseField, DatabaseField>> it = m_unmappedQueryKeyFields.entrySet().iterator();
         while(it.hasNext()) {
             Map.Entry<DatabaseField, DatabaseField> entry = it.next();
             Object value = unmappedValues.get(entry.getValue());
             translationRow.add(entry.getKey(), value);
         }
         return translationRow;
      }

     /**
      * INTERNAL:
      * Identify mapped and not mapped fields (should be done once).
      * The result - either two non-empty Maps m_unmappedQueryKeyFields and m_mappedQueryKeyFields,
      * or m_unmappedQueryKeyFields == null and m_mappedQueryKeyFields == m_queryKeyFields.
      */
     public void initUnmappedFields(UnitOfWorkImpl uow) {
         if(!m_hasCheckedForUnmappedFields) {
             m_mappedQueryKeyFields = new HashMap<>();
             m_unmappedQueryKeyFields = new HashMap<>();
             Iterator<Map.Entry<DatabaseField, DatabaseField>> it = m_queryKeyFields.entrySet().iterator();
             while(it.hasNext()) {
                 Map.Entry<DatabaseField, DatabaseField> entry = it.next();
                 if(m_descriptor.getObjectBuilder().getMappingForField(entry.getValue()) == null) {
                     m_unmappedQueryKeyFields.put(entry.getKey(), entry.getValue());
                 } else {
                     m_mappedQueryKeyFields.put(entry.getKey(), entry.getValue());
                 }
             }
             if(m_unmappedQueryKeyFields.isEmpty()) {
                 m_unmappedQueryKeyFields = null;
                 m_mappedQueryKeyFields = m_queryKeyFields;
             }
             initUnmappedFieldsQuery(uow);
             m_hasCheckedForUnmappedFields = true;
         }
     }

     /**
      * INTERNAL:
      * This method called in case there are m_unmappedQueryKeyFields.
      * It creates a query that would fetch the values for this fields from the db.
      */
     public void initUnmappedFieldsQuery(UnitOfWorkImpl uow) {
         if(m_unmappedFieldsQuery == null) {
             m_unmappedFieldsQuery = new DataReadQuery();

             Expression whereClause = null;
             Expression builder = new ExpressionBuilder();
             Iterator<DatabaseField> itPrimaryKey = m_descriptor.getPrimaryKeyFields().iterator();
             while (itPrimaryKey.hasNext()) {
                 DatabaseField primaryKey = itPrimaryKey.next();
                 Expression expression = builder.getField(primaryKey).equal(builder.getParameter(primaryKey));
                 whereClause = expression.and(whereClause);
                 m_unmappedFieldsQuery.addArgument(primaryKey.getQualifiedName());
             }

             SQLSelectStatement statement = new SQLSelectStatement();
             Iterator<DatabaseField> itUnmappedFields = m_unmappedQueryKeyFields.values().iterator();
             while (itUnmappedFields.hasNext()) {
                 DatabaseField field = itUnmappedFields.next();
                 statement.addField(field);
             }

             statement.setWhereClause(whereClause);
             statement.normalize(uow.getParent(), m_descriptor);
             m_unmappedFieldsQuery.setSQLStatement(statement);
             m_unmappedFieldsQuery.setSessionName(m_descriptor.getSessionName());
         }
     }

     /**
     * INTERNAL:
     */
    public void lockNotifyParent(Object obj, UnitOfWorkChangeSet changeSet, UnitOfWorkImpl uow) {
        Object parentObj = null;

        // Check for a parent object via the parent (back pointer) mapping first.
        DatabaseMapping parentMapping = getParentMapping();
        if (parentMapping != null && parentMapping.isObjectReferenceMapping()) {
            parentObj = parentMapping.getRealAttributeValueFromObject(obj, uow);
        }

        // If the parent object is still null at this point, try a query.
        // check out why no query keys.
        if (parentObj == null) {
            AbstractRecord translationRow;
            if(m_shouldHandleUnmappedFields) {
                // should look for unmapped fields.
                initUnmappedFields(uow);
                if(m_unmappedQueryKeyFields != null) {
                    // there are some unmapped fields - fetch the values for the from the db.
                    AbstractRecord unmappedTranslationRow = getUnmappedTranslationRow(obj, uow);
                    if(unmappedTranslationRow == null) {
                        // the object is not yet in the db
                        return;
                    } else {
                        // merge mapped and unmapped values into the single translation row.
                        translationRow = getMappedTranslationRow(obj, uow);
                        translationRow.putAll(unmappedTranslationRow);
                    }
                } else {
                    // no unmapped fields
                    translationRow = getMappedTranslationRow(obj, uow);
                }
            } else {
                // no unmapped fields
                translationRow = getMappedTranslationRow(obj, uow);
            }
            // the query is set to return an unwrapped object.
            parentObj = uow.executeQuery(getQuery(), translationRow);

        } else {
            // make sure the parent object is unwrapped.
            if (m_parentDescriptor.hasWrapperPolicy()) {
                m_parentDescriptor.getWrapperPolicy().unwrapObject(parentObj, uow);
            }
        }
        ClassDescriptor realParentDescriptor = m_parentDescriptor;
        if (parentObj != null){
            realParentDescriptor = getParentDescriptorFromInheritancePolicy(parentObj);
        }

        // If we have a parent object, force update the version field if one
        // exists, and keep firing the notification up the chain.
        // Otherwise, do nothing.
        if (parentObj != null) {
            // Need to check if we are a non cascade locking node within a
            // cascade locking policy chain.
            if (realParentDescriptor.usesOptimisticLocking() && realParentDescriptor.getOptimisticLockingPolicy().isCascaded()) {
                ObjectChangeSet ocs = realParentDescriptor.getObjectBuilder().createObjectChangeSet(parentObj, changeSet, uow);

                if (!ocs.hasForcedChangesFromCascadeLocking()) {
                    ocs.setHasForcedChangesFromCascadeLocking(true);
                    changeSet.addObjectChangeSet(ocs, uow, true);
                }
            }

            // Keep sending the notification up the chain ...
            if (realParentDescriptor.hasCascadeLockingPolicies()) {
                for (CascadeLockingPolicy policy : realParentDescriptor.getCascadeLockingPolicies()) {
                    policy.lockNotifyParent(parentObj, changeSet, uow);
                }
            }
        }
    }

    /**
     * INTERNAL:
     */
    public void setQueryKeyFields(Map<DatabaseField, DatabaseField> queryKeyFields) {
        setQueryKeyFields(queryKeyFields, true);
    }

    /**
     * INTERNAL:
     */
    public void setQueryKeyFields(Map<DatabaseField, DatabaseField> queryKeyFields, boolean lookForParentMapping) {
        m_queryKeyFields = queryKeyFields;
        m_mappedQueryKeyFields = m_queryKeyFields;
        this.m_lookForParentMapping = lookForParentMapping;
    }

    /**
     * INTERNAL:
     * Indicates whether to expect unmapped fields.
     * That should be set to true for UnidirectionalOneToManyMapping.
     */
    public void setShouldHandleUnmappedFields(boolean shouldHandleUnmappedFields) {
        m_shouldHandleUnmappedFields = shouldHandleUnmappedFields;
    }

    /**
     * INTERNAL:
     */
    public boolean shouldHandleUnmappedFields() {
        return m_shouldHandleUnmappedFields;
    }
}
