/*
 * 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 = 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 = 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);
    }
}
