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

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     09/12/2018 - Will Dazey
//       - 391279: Add support for Unidirectional OneToMany mappings with non-nullable values
package org.eclipse.persistence.internal.sessions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.OptimisticLockException;
import org.eclipse.persistence.internal.databaseaccess.DatasourceCall;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.DescriptorCompare;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.localization.ToStringLocalization;
import org.eclipse.persistence.internal.queries.DatabaseQueryMechanism;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.queries.DeleteObjectQuery;
import org.eclipse.persistence.queries.InsertObjectQuery;
import org.eclipse.persistence.queries.UpdateObjectQuery;
import org.eclipse.persistence.queries.WriteObjectQuery;
import org.eclipse.persistence.sessions.UnitOfWork.CommitOrderType;

/**
 * This class maintains a commit stack and resolves circular references.
 */
public class CommitManager {
    /** Order based on mapping foreign key constraints on how to insert objects by class. */
    protected List<Class> commitOrder;

    /**
     * This tracks the commit state for the objects, PENDING, PRE, POST, COMPLETE.
     * The key is the object and the value is the state.
     */
    protected Map<Object, Integer> commitState;

    /** The commit is in progress, but the row has not been written. */
    protected static final Integer PRE = 1;
    /** The commit is in progress, and the row has been written. */
    protected static final Integer POST = 2;
    /** The commit is complete for the object. */
    protected static final Integer COMPLETE = 3;
    /** This object should be ignored. */
    protected static final Integer IGNORE = 4;

    /** Set of objects that had partial row written to resolve constraints. */
    protected Map shallowCommits;

    protected AbstractSession session;

    /** The commit manager is active while writing a set of objects (UOW), it is not active when writing a single object (DB session). */
    protected boolean isActive;

    /** Map of modification events used to defer insertion into m-m, dc, join tables. */
    protected Map<DatabaseMapping, List<Object[]>> dataModifications;

    /**
     * Map of deferred calls groups by their table.
     * This is used to defer multiple table writes for batching and deadlock avoidance.
     */
    protected Map<DatabaseTable, List<Object[]>> deferredCalls;

    /** List of orphaned objects pending deletion. */
    protected List objectsToDelete;

    /** Counter used to keep track of commit depth for non-UOW writes. */
    protected int commitDepth;

    /**
     * Create the commit manager on the session.
     * It must be initialized later on after the descriptors have been added.
     */
    public CommitManager(AbstractSession session) {
        this.session = session;
    }

    /**
     * Add the data query to be performed at the end of the commit.
     * This is done to decrease dependencies and avoid deadlock.
     */
    public void addDataModificationEvent(DatabaseMapping mapping, Object[] event) {
        if (!getDataModifications().containsKey(mapping)) {
            this.dataModifications.put(mapping, new ArrayList());
        }
        this.dataModifications.get(mapping).add(event);
    }

    /**
     * Add the data query to be performed at the end of the commit.
     * This is done to decrease dependencies and avoid deadlock.
     */
    public void addDeferredCall(DatabaseTable table, DatasourceCall call, DatabaseQueryMechanism mechanism) {
        if (!getDeferredCalls().containsKey(table)) {
            this.deferredCalls.put(table, new ArrayList());
        }
        Object[] arguments = new Object[2];
        arguments[0] = call;
        arguments[1] = mechanism;
        this.deferredCalls.get(table).add(arguments);
    }

    /**
     * Deletion are cached until the end.
     */
    public void addObjectToDelete(Object objectToDelete) {
        getObjectsToDelete().add(objectToDelete);
    }

    /**
     * Commit all of the objects as a single transaction.
     * This should commit the object in the correct order to maintain referential integrity.
     */
    public void commitAllObjectsWithChangeSet(UnitOfWorkChangeSet uowChangeSet) throws RuntimeException, DatabaseException, OptimisticLockException {
        reinitialize();
        this.isActive = true;
        this.session.beginTransaction();
        try {
            // PERF: if the number of classes in the project is large this loop can be a perf issue.
            // If only one class types changed, then avoid loop.
            if ((uowChangeSet.getObjectChanges().size() + uowChangeSet.getNewObjectChangeSets().size()) <= 1) {
                Iterator<Class> classes = uowChangeSet.getNewObjectChangeSets().keySet().iterator();
                if (classes.hasNext()) {
                    Class theClass = classes.next();
                    commitNewObjectsForClassWithChangeSet(uowChangeSet, theClass);
                }
                classes = uowChangeSet.getObjectChanges().keySet().iterator();
                if (classes.hasNext()) {
                    Class theClass = classes.next();
                    commitChangedObjectsForClassWithChangeSet(uowChangeSet, theClass);
                }
            } else {
                // The commit order is all of the classes ordered by dependencies, this is done for deadlock avoidance.
                List<Class> commitOrder = getCommitOrder();
                int size = commitOrder.size();
                for (int index = 0; index < size; index++) {
                    Class theClass = (Class)commitOrder.get(index);
                    commitAllObjectsForClassWithChangeSet(uowChangeSet, theClass);
                }
            }

            if (hasDeferredCalls()) {
                // Perform all batched up calls, done to avoid dependencies.
                for (List<Object[]> calls: this.deferredCalls.values()) {
                    for (Object[] argument : calls) {
                        ((DatabaseQueryMechanism)argument[1]).executeDeferredCall((DatasourceCall)argument[0]);
                    }
                }
            }

            if (hasDataModifications()) {
                // Perform all batched up data modifications, done to avoid dependencies.
                for (Map.Entry<DatabaseMapping, List<Object[]>> entry: this.dataModifications.entrySet()) {
                    List<Object[]> events = entry.getValue();
                    int size = events.size();
                    DatabaseMapping mapping = entry.getKey();
                    for (int index = 0; index < size; index++) {
                        Object[] event = events.get(index);
                        mapping.performDataModificationEvent(event, getSession());
                    }
                }
            }

            if (hasObjectsToDelete()) {
                // These are orphaned objects, to be deleted from private ownership updates.
                // TODO: These should be added to the unit of work deleted so they are deleted in the correct order.
                List objects = getObjectsToDelete();
                int size = objects.size();
                reinitialize();
                for (int index = 0; index < size; index++) {
                    this.session.deleteObject(objects.get(index));
                }
            }

            this.session.commitTransaction();
        } catch (RuntimeException exception) {
            this.session.rollbackTransaction();
            throw exception;
        } finally {
            reinitialize();
            this.isActive = false;
        }
    }

    /**
     * Commit all of the objects of the class type in the change set.
     * This allows for the order of the classes to be processed optimally.
     */
    protected void commitAllObjectsForClassWithChangeSet(UnitOfWorkChangeSet uowChangeSet, Class theClass) {
        // Although new objects should be first, there is an issue that new objects get added to non-new after the insert,
        // so the object would be written twice.
        commitChangedObjectsForClassWithChangeSet(uowChangeSet, theClass);
        commitNewObjectsForClassWithChangeSet(uowChangeSet, theClass);
    }

    /**
     * Commit all of the objects of the class type in the change set.
     * This allows for the order of the classes to be processed optimally.
     */
    protected void commitNewObjectsForClassWithChangeSet(UnitOfWorkChangeSet uowChangeSet, Class theClass) {
        Map<ObjectChangeSet, ObjectChangeSet> newObjectChangesList = uowChangeSet.getNewObjectChangeSets().get(theClass);
        if (newObjectChangesList != null) { // may be no changes for that class type.
            AbstractSession session = getSession();
            ClassDescriptor descriptor = session.getDescriptor(theClass);
            List<ObjectChangeSet> newChangeSets = new ArrayList(newObjectChangesList.values());
            int size = newChangeSets.size();
            for (int index = 0; index < size; index++) {
                ObjectChangeSet changeSetToWrite = newChangeSets.get(index);
                Object objectToWrite = changeSetToWrite.getUnitOfWorkClone();
                if (!isProcessedCommit(objectToWrite)) {
                    // PERF: Get the descriptor query, to avoid extra query creation.
                    InsertObjectQuery commitQuery = descriptor.getQueryManager().getInsertQuery();
                    if (commitQuery == null) {
                        commitQuery = new InsertObjectQuery();
                        commitQuery.setDescriptor(descriptor);
                    } else {
                        // Ensure original query has been prepared.
                        commitQuery.checkPrepare(session, commitQuery.getTranslationRow());
                        commitQuery = (InsertObjectQuery)commitQuery.clone();
                    }
                    commitQuery.setIsExecutionClone(true);
                    commitQuery.setObjectChangeSet(changeSetToWrite);
                    commitQuery.setObject(objectToWrite);
                    commitQuery.cascadeOnlyDependentParts();
                    commitQuery.setModifyRow(null);
                    session.executeQuery(commitQuery);
                }
                uowChangeSet.putNewObjectInChangesList(changeSetToWrite, session);
            }
        }
    }

    /**
     * Commit changed of the objects of the class type in the change set.
     * This allows for the order of the classes to be processed optimally.
     */
    protected void commitChangedObjectsForClassWithChangeSet(UnitOfWorkChangeSet uowChangeSet, Class theClass) {
        Map<ObjectChangeSet, ObjectChangeSet> objectChangesList = uowChangeSet.getObjectChanges().get(theClass);
        if (objectChangesList != null) {// may be no changes for that class type.
            ClassDescriptor descriptor = null;
            AbstractSession session = getSession();
            Collection<ObjectChangeSet> changes = objectChangesList.values();
            CommitOrderType order = ((UnitOfWorkImpl)session).getCommitOrder();
            if (order != CommitOrderType.NONE) {
                changes = new ArrayList(objectChangesList.values());
                if (order == CommitOrderType.CHANGES) {
                    Collections.sort((List)changes, new ObjectChangeSet.ObjectChangeSetComparator());
                } else {
                    Collections.sort((List)changes);
                }
            }
            for (ObjectChangeSet changeSetToWrite : changes) {
                Object objectToWrite = changeSetToWrite.getUnitOfWorkClone();
                if (descriptor == null) {
                    descriptor = session.getDescriptor(objectToWrite);
                }
                if (!isProcessedCommit(objectToWrite)) {
                    // Commit and resume on failure can cause a new change set to be in existing, so need to check here.
                    WriteObjectQuery commitQuery = null;
                    if (changeSetToWrite.isNew()) {
                        commitQuery = new InsertObjectQuery();
                    } else {
                        commitQuery = new UpdateObjectQuery();
                    }
                    commitQuery.setIsExecutionClone(true);
                    commitQuery.setDescriptor(descriptor);
                    commitQuery.setObjectChangeSet(changeSetToWrite);
                    commitQuery.setObject(objectToWrite);
                    commitQuery.cascadeOnlyDependentParts();
                    // removed checking session type to set cascade level
                    // will always be a unitOfWork so we need to cascade dependent parts
                    session.executeQuery(commitQuery);
                }
            }
        }
    }

    /**
     * delete all of the objects as a single transaction.
     * This should delete the object in the correct order to maintain referential integrity.
     */
    public void deleteAllObjects(List objects) throws RuntimeException, DatabaseException, OptimisticLockException {
        this.isActive = true;
        AbstractSession session = getSession();
        session.beginTransaction();

        try {
            // PERF: Optimize single object case.
            if (objects.size() == 1) {
                deleteAllObjects(objects.get(0).getClass(), objects, session);
            } else {
                List<Class> commitOrder = getCommitOrder();
                for (int orderIndex = commitOrder.size() - 1; orderIndex >= 0; orderIndex--) {
                    Class theClass = (Class)commitOrder.get(orderIndex);
                    deleteAllObjects(theClass, objects, session);
                }
            }

            session.commitTransaction();
        } catch (RuntimeException exception) {
            try {
                session.rollbackTransaction();
            } catch (Exception ignore) {
            }
            throw exception;
        } finally {
            reinitialize();
            this.isActive = false;
        }
    }

    /**
     * Delete all of the objects with the matching class.
     */
    public void deleteAllObjects(Class theClass, List objects, AbstractSession session) {
        ClassDescriptor descriptor = null;

        if (((UnitOfWorkImpl)session).getCommitOrder() != CommitOrderType.NONE) {// bug 331064 - Sort the delete order
            objects = sort(theClass, objects);
        }

        int size = objects.size();
        for (int index = 0; index < size; index++) {
            Object objectToDelete = objects.get(index);
            if (objectToDelete.getClass() == theClass) {
                if (descriptor == null) {
                    descriptor = session.getDescriptor(theClass);
                }
                // PERF: Get the descriptor query, to avoid extra query creation.
                DeleteObjectQuery deleteQuery = descriptor.getQueryManager().getDeleteQuery();
                if (deleteQuery == null) {
                    deleteQuery = new DeleteObjectQuery();
                    deleteQuery.setDescriptor(descriptor);
                } else {
                    // Ensure original query has been prepared.
                    deleteQuery.checkPrepare(session, deleteQuery.getTranslationRow());
                    deleteQuery = (DeleteObjectQuery)deleteQuery.clone();
                }
                deleteQuery.setIsExecutionClone(true);
                deleteQuery.setObject(objectToDelete);
                session.executeQuery(deleteQuery);
            }
        }
    }

    /**
     * Sort the objects based on PK.
     */
    // bug 331064 - Sort the delete order based on PKs.
    private List sort (Class theClass, List objects) {
        ClassDescriptor descriptor = session.getDescriptor(theClass);
        org.eclipse.persistence.internal.descriptors.ObjectBuilder objectBuilder = descriptor.getObjectBuilder();
        int size = objects.size();
        TreeMap sortedObjects = new TreeMap();
        for (int index = 0; index < size; index++) {
            Object objectToDelete = objects.get(index);
            if (objectToDelete.getClass() == theClass) {
                sortedObjects.put(objectBuilder.extractPrimaryKeyFromObject(objectToDelete, session), objectToDelete);
            }
        }
        return new ArrayList(sortedObjects.values());
    }

    /**
     * Return the order in which objects should be committed to the database.
     * This order is based on ownership in the descriptors and is require for referential integrity.
     * The commit order is a vector of vectors,
     * where the first vector is all root level classes, the second is classes owned by roots and so on.
     */
    public List<Class> getCommitOrder() {
        if (this.commitOrder == null) {
            this.commitOrder = new ArrayList();
        }
        return this.commitOrder;
    }

    /**
     * Return the map of states of the objects being committed.
     * The states are defined as static Integers (PENDING, PRE, POST, COMPLETE).
     */
    protected Map<Object, Integer> getCommitState() {
        if (this.commitState == null) {
            // 2612538 - the default size of Map (32) is appropriate
            this.commitState = new IdentityHashMap();
        }
        return this.commitState;
    }

    protected boolean hasDataModifications() {
        return ((this.dataModifications != null) && (!this.dataModifications.isEmpty()));
    }

    /**
     * Used to store data queries to be performed at the end of the commit.
     * This is done to decrease dependencies and avoid deadlock.
     */
    protected Map<DatabaseMapping, List<Object[]>> getDataModifications() {
        if (dataModifications == null) {
            dataModifications = new LinkedHashMap();
        }
        return dataModifications;
    }

    protected boolean hasDeferredCalls() {
        return ((this.deferredCalls != null) && (!this.deferredCalls.isEmpty()));
    }

    /**
     * Used to store calls to be performed at the end of the commit.
     * This is done for multiple table descriptors to allow batching and avoid deadlock.
     */
    protected Map<DatabaseTable, List<Object[]>> getDeferredCalls() {
        if (this.deferredCalls == null) {
            this.deferredCalls = new LinkedHashMap();
        }
        return this.deferredCalls;
    }

    protected boolean hasObjectsToDelete() {
        return ((objectsToDelete != null) && (!objectsToDelete.isEmpty()));
    }

    /**
     * Deletion are cached until the end.
     */
    public List getObjectsToDelete() {
        if (objectsToDelete == null) {
            objectsToDelete = new ArrayList();
        }
        return objectsToDelete;
    }

    /**
     * Return the session that this is managing commits for.
     */
    protected AbstractSession getSession() {
        return this.session;
    }

    /**
     * Return any objects that have been shallow committed during this commit process.
     */
    protected Map getShallowCommits() {
        if (this.shallowCommits == null) {
            // 2612538 - the default size of Map (32) is appropriate
            this.shallowCommits = new IdentityHashMap();
        }
        return this.shallowCommits;
    }

    /**
     * Reset the commit order from the session's descriptors.
     * This uses the constraint dependencies in the descriptor's mappings,
     * to decide which descriptors are dependent on which other descriptors.
     * Multiple computations of the commit order should produce the same ordering.
     * This is done to improve performance on unit of work writes through decreasing the
     * stack size, and acts as a deadlock avoidance mechanism.
     */
    public void initializeCommitOrder() {
        Vector descriptors = Helper.buildVectorFromMapElements(getSession().getDescriptors());

        // Must ensure uniqueness, some descriptor my be register twice for interfaces.
        descriptors = Helper.addAllUniqueToVector(new Vector(descriptors.size()), descriptors);
        Object[] descriptorsArray = new Object[descriptors.size()];
        for (int index = 0; index < descriptors.size(); index++) {
            descriptorsArray[index] = descriptors.elementAt(index);
        }
        Arrays.sort(descriptorsArray, new DescriptorCompare());
        descriptors = new Vector(descriptors.size());
        for (int index = 0; index < descriptorsArray.length; index++) {
            descriptors.addElement(descriptorsArray[index]);
        }

        CommitOrderCalculator calculator = new CommitOrderCalculator(getSession());
        calculator.addNodes(descriptors);
        calculator.calculateMappingDependencies();
        calculator.orderCommits();
        descriptors = calculator.getOrderedDescriptors();

        calculator = new CommitOrderCalculator(getSession());
        calculator.addNodes(descriptors);
        calculator.calculateSpecifiedDependencies();
        calculator.orderCommits();

        setCommitOrder(calculator.getOrderedClasses());
    }

    /**
     * Return if the commit manager is active.
     */
    public boolean isActive() {
        return isActive;
    }

    /**
     * Return if the object has been processed.
     * This should be called by any query that is writing an object,
     * if true the query should not write the object.
     */
    public boolean isProcessedCommit(Object object) {
        return getCommitState().get(object) != null;
    }

    /**
     * Return if the object has been committed.
     * This should be called by any query that is writing an object,
     * if true the query should not write the object.
     */
    public boolean isCommitCompleted(Object object) {
        return getCommitState().get(object) == COMPLETE;
    }

    /**
     * Return if the object has been committed.
     * This should be called by any query that is writing an object,
     * if true the query should not write the object.
     */
    public boolean isCommitCompletedInPostOrIgnore(Object object) {
        Integer state = getCommitState().get(object);
        return (state == COMPLETE) || (state == POST) || (state == IGNORE);
    }

    /**
     * Return if the object is being in progress of being post modify commit.
     * This should be called by any query that is writing an object.
     */
    public boolean isCommitInPostModify(Object object) {
        return getCommitState().get(object) == POST;
    }

    /**
     * Return if the object is being in progress of being pre modify commit.
     * This should be called by any query that is writing an object,
     * if true the query must force a shallow insert of the object if it is new.
     */
    public boolean isCommitInPreModify(Object objectOrChangeSet) {
        return getCommitState().get(objectOrChangeSet) == PRE;
    }

    /**
     * Return if the object is shallow committed.
     * This is required to resolve bidirectional references.
     */
    public boolean isShallowCommitted(Object object) {
        if (this.shallowCommits == null) {
            return false;
        }
        return this.shallowCommits.containsKey(object);
    }

    /**
     * Mark the commit of the object as being fully completed.
     * This should be called by any query that has finished writing an object.
     */
    public void markCommitCompleted(Object object) {
        this.commitDepth --;
        getCommitState().put(object, COMPLETE);
        // If not in a unit of work commit and the commit of this object is done reset the commit manager.
        if ((!this.isActive) && (this.commitDepth == 0)) {
            reinitialize();
            return;
        }
    }

    public void markIgnoreCommit(Object object){
        getCommitState().put(object, IGNORE);
    }

    /**
     * Add an object as being in progress of being committed.
     * This should be called by any query that is writing an object.
     */
    public void markPostModifyCommitInProgress(Object object) {
        getCommitState().put(object, POST);
    }

    /**
     * Add an object as being in progress of being committed.
     * This should be called by any query that is writing an object.
     */
    public void markPreModifyCommitInProgress(Object object) {
        this.commitDepth ++;
        getCommitState().put(object, PRE);
    }

    /**
     * Mark the object as shallow committed.
     * This is required to resolve bidirectional references.
     */
    public void markShallowCommit(Object object) {
        getShallowCommits().put(object, object); // Use as set.
    }

    /**
     * Reset the commits.
     * This must be done before a new commit process is begun.
     */
    public void reinitialize() {
        this.commitState = null;
        this.commitDepth = 0;
        this.shallowCommits = null;
        this.objectsToDelete = null;
        this.dataModifications = null;
        this.deferredCalls = null;
    }

    /**
     * Set the order in which objects should be committed to the database.
     * This order is based on ownership in the descriptors and is require for referential integrity.
     * The commit order is a vector of vectors,
     * where the first vector is all root level classes, the second is classes owned by roots and so on.
     */
    public void setCommitOrder(List commitOrder) {
        this.commitOrder = commitOrder;
    }

    /**
     * Used to store data queries to be performed at the end of the commit.
     * This is done to decrease dependencies and avoid deadlock.
     */
    protected void setDataModifications(Map<DatabaseMapping, List<Object[]>> dataModifications) {
        this.dataModifications = dataModifications;
    }

    /**
     * Set if the commit manager is active.
     */
    public void setIsActive(boolean isActive) {
        this.isActive = isActive;
    }

    /**
     * Deletion are cached until the end.
     */
    protected void setObjectsToDelete(List objectsToDelete) {
        this.objectsToDelete = objectsToDelete;
    }

    /**
     * Set the session that this is managing commits for.
     */
    protected void setSession(AbstractSession session) {
        this.session = session;
    }

    /**
     * Set any objects that have been shallow committed during this commit process.
     */
    protected void setShallowCommits(Map shallowCommits) {
        this.shallowCommits = shallowCommits;
    }

    /**
     * Print the in progress depth.
     */
    @Override
    public String toString() {
        Object[] args = {this.commitDepth};
        return Helper.getShortClassName(getClass()) + ToStringLocalization.buildMessage("commit_depth", args);
    }
}
