/*
 * 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
//     07/15/2011-2.2.1 Guy Pelletier
//       - 349424: persists during an preCalculateUnitOfWorkChangeSet event are lost
package org.eclipse.persistence.internal.sessions.remote;

import java.util.*;

import org.eclipse.persistence.config.ReferenceMode;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorQueryManager;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.internal.sessions.*;
import org.eclipse.persistence.internal.databaseaccess.Platform;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.sessions.remote.*;
import org.eclipse.persistence.logging.SessionLog;

/**
 * Counter part of the unit of work which exists on the client side.
 */
public class RemoteUnitOfWork extends RepeatableWriteUnitOfWork {
    protected List newObjectsCache;
    protected List unregisteredNewObjectsCache;
    protected boolean isOnClient;
    protected transient RemoteSessionController parentSessionController;
    protected boolean isFlush;

    public RemoteUnitOfWork() {
    }

    public RemoteUnitOfWork(RemoteUnitOfWork parent) {
        this(parent, null);
    }

    public RemoteUnitOfWork(DistributedSession parent) {
        this(parent, null);
    }
    public RemoteUnitOfWork(RemoteUnitOfWork parent, ReferenceMode referenceMode) {
        super(parent, referenceMode);
        this.isOnClient = true;
        this.discoverUnregisteredNewObjectsWithoutPersist = true;
    }

    public RemoteUnitOfWork(DistributedSession parent, ReferenceMode referenceMode) {
        super(parent, referenceMode);
        this.isOnClient = true;
        this.discoverUnregisteredNewObjectsWithoutPersist = true;
    }

    public boolean isFlush() {
        return isFlush;
    }

    public void setIsFlush(boolean isFlush) {
        this.isFlush = isFlush;
    }

    /**
     * PUBLIC:
     * Tell the unit of work to begin a transaction now.
     * By default the unit of work will begin a transaction at commit time.
     * The default is the recommended approach, however sometimes it is
     * necessary to start the transaction before commit time.  When the
     * unit of work commits, this transaction will be committed.
     *
     * @see #commit()
     * @see #release()
     */
    @Override
    public void beginEarlyTransaction() throws DatabaseException {
        // Acquire the mutex so session knows it is in a transaction.
        getParent().getTransactionMutex().acquire();
        startOperationProfile(SessionProfiler.Remote, null, SessionProfiler.ALL);
        // This needs a special call for remote, to ensure subsequent queries isolate their data to a unit of work on the server.
        ((DistributedSession)getParent()).getRemoteConnection().beginEarlyTransaction();
        endOperationProfile(SessionProfiler.Remote, null, SessionProfiler.ALL);

        setWasTransactionBegunPrematurely(true);
    }

    /**
     * The nested unit of work must also be remote.
     */
    @Override
    public UnitOfWorkImpl acquireUnitOfWork() {
        return acquireUnitOfWork(null);
    }

    /**
     * The nested unit of work must also be remote.
     */
    @Override
    public UnitOfWorkImpl acquireUnitOfWork(ReferenceMode referenceMode) {
        log(SessionLog.FINER, SessionLog.TRANSACTION, "acquire_unit_of_work");
        setNumberOfActiveUnitsOfWork(getNumberOfActiveUnitsOfWork() + 1);
        RemoteUnitOfWork ruow = new RemoteUnitOfWork(this, referenceMode);
        ruow.discoverAllUnregisteredNewObjectsInParent();
        return ruow;
    }

    /**
     * This is done to maintain correspondence between local new objects and returned new objects from serialization.
     * Object correspondence is maintained by comparing primary keys but for new objects it is possible that primary
     * key value is null as it is still not inserted. The returned new objects from serialization will have primary
     * key value which will be inserted into corresponding local new objects.
     */
    protected List collectNewObjects() {
        if ((this.newObjectsCloneToOriginal == null) || this.newObjectsCloneToOriginal.isEmpty()) {
            return null;
        }
        List newObjects = new ArrayList(this.newObjectsCloneToOriginal.size());
        for (Object newObject : this.newObjectsCloneToOriginal.keySet()) {
            newObjects.add(newObject);
        }
        return newObjects;
    }

    /**
     * This is done to maintain correspondence between local unregistered new objects and returned unregistered new
     * objects from serialization. Object correspondence is maintained by comparing primary keys but for unregistered
     * new objects it is possible that primary key value is null as it is still not inserted. The returned unregistered
     * new objects from serialization will have primary key value which will be inserted into corresponding local new
     * objects.
     */
    protected List collectUnregisteredNewObjects() {
        discoverAllUnregisteredNewObjects();
        return new ArrayList(getUnregisteredNewObjects().values());
    }

    /**
     * The remote unit of work returned after its commit on the server is merged with remote unit of work
     * on the remote side.
     */
    protected void commitIntoRemoteUnitOfWork() {
        UnitOfWorkImpl parent = ((UnitOfWorkImpl)getParent());
        // Must merge the transaction flag.
        parent.setWasTransactionBegunPrematurely(wasTransactionBegunPrematurely());

        MergeManager manager = new MergeManager(this);
        manager.mergeWorkingCopyIntoRemote();

        // Must clone the clone mapping because entries can be added to it during the merging,
        // and that can lead to concurrency problems.
        Iterator cloneIterator = new IdentityHashMap(getCloneMapping()).keySet().iterator();

        Map clones = new IdentityHashMap(this.cloneMapping.size());
        // Iterate over each clone and let the object build merge to clones into the originals.
        while (cloneIterator.hasNext()) {
            Object remoteClone = cloneIterator.next();
            manager.mergeChanges(remoteClone, null, this);
            Object clone = manager.getTargetVersionOfSourceObject(remoteClone, parent.getDescriptor(remoteClone), parent);
            clones.put(remoteClone, clone);
        }

        // Reset the remote change set to be the local one, need to reset all clones to local copy,
        // and reset transient variables.
        parent.setUnitOfWorkChangeSet(this.unitOfWorkChangeSet);
        fixRemoteChangeSet(this.unitOfWorkChangeSet, clones, parent);
        ((RemoteUnitOfWork)parent).setCumulativeUOWChangeSet(this.cumulativeUOWChangeSet);
        fixRemoteChangeSet(this.cumulativeUOWChangeSet, clones, parent);

        // Set the deleted objects into the parent.
        if (this.objectsDeletedDuringCommit != null) {
            Map newDeletedObjects = new IdentityHashMap();
            for (Object deletedObject : this.objectsDeletedDuringCommit.keySet()) {
                Object primaryKey = getId(deletedObject);
                Object clone = clones.get(deletedObject);
                if (clone == null) {
                    clone = parent.getIdentityMapAccessor().getFromIdentityMap(primaryKey, deletedObject.getClass());
                    if (clone == null) {
                        clone = deletedObject;
                    }
                }
                newDeletedObjects.put(clone, primaryKey);
                parent.getIdentityMapAccessor().removeFromIdentityMap(primaryKey, clone.getClass());
            }
            parent.setObjectsDeletedDuringCommit(newDeletedObjects);
        }
    }

    /**
     * Simulate a flush, current just begins a transaction and commits.
     */
    @Override
    public void writeChanges() {
        if (!isOnClient()) {
            super.writeChanges();
            return;
        }
        // Check for a nested flush and return early if we are in one
        if (this.isWithinFlush()) {
            log(SessionLog.WARNING, SessionLog.TRANSACTION, "nested_entity_manager_flush_not_executed_pre_query_changes_may_be_pending", getClass().getSimpleName());
            return;
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "begin_unit_of_work_flush");

        // PERF: If this is an empty unit of work, do nothing (but still may need to commit SQL changes).
        boolean hasChanges = (this.unitOfWorkChangeSet != null) || hasCloneMapping() || hasDeletedObjects() || hasModifyAllQueries() || hasDeferredModifyAllQueries();
        if (hasChanges) {
            // The change set may already exist if using change tracking.
            if (this.unitOfWorkChangeSet == null) {
                this.unitOfWorkChangeSet = new UnitOfWorkChangeSet(this);
            }
            calculateChanges(getCloneMapping(), this.unitOfWorkChangeSet, true, true);
            hasChanges = hasModifications();
        }
        if (!hasChanges) {
            log(SessionLog.FINER, SessionLog.TRANSACTION, "end_unit_of_work_flush");
            return;
        }

        if (!wasTransactionBegunPrematurely()) {
            beginEarlyTransaction();
        }

        // New objects cache is created to maintain the correspondence when they are returned back as different copy
        setNewObjectsCache(collectNewObjects());
        // Unregistered new objects cache is created to maintain the correspondence when they are returned back as different copy
        setUnregisteredNewObjectsCache(collectUnregisteredNewObjects());

        // Commit on the server
        RemoteUnitOfWork remoteUnitOfWork;
        try {
            setIsFlush(true);
            startOperationProfile(SessionProfiler.Remote, null, SessionProfiler.ALL);
            remoteUnitOfWork = ((DistributedSession)getParent()).getRemoteConnection().commitRootUnitOfWork(this);
            endOperationProfile(SessionProfiler.Remote, null, SessionProfiler.ALL);
        } finally {
            setIsFlush(false);
        }

        // Make the returned remote unit of work a nested unit of work and merge it with the local remote unit of work
        remoteUnitOfWork.setParent(this);
        remoteUnitOfWork.setProject(getProject());
        remoteUnitOfWork.prepareForMergeIntoRemoteUnitOfWork();
        remoteUnitOfWork.commitIntoRemoteUnitOfWork();

        log(SessionLog.FINER, SessionLog.TRANSACTION, "end_unit_of_work_flush");

        resumeUnitOfWork();
        log(SessionLog.FINER, SessionLog.TRANSACTION, "resume_unit_of_work");
    }

    /**
     * Starts committing the remote unit of work.
     * This must serialize the unit of work across to the server,
     * commit the unit of work on the server,
     * serialize it back and merge any server-side changes (such as sequence numbers) it into itself,
     * then merge into the parent remote session.
     */
    @Override
    public void commitRootUnitOfWork() {
        if (!isOnClient()) {
            if (isSynchronized()) {
                // If we started the JTS transaction then we have to commit it as well.
                if (getParent().wasJTSTransactionInternallyStarted()) {
                    commitInternallyStartedExternalTransaction();
                }
                // Do not commit until the JTS wants to.
                return;
            }
            if (this.eventManager != null) {
                this.eventManager.preCommitUnitOfWork();
            }
            super.commitRootUnitOfWork(); // On the server the normal commit is done.
            if (this.eventManager != null) {
                this.eventManager.postCommitUnitOfWork();
            }
            return;
        }

        // PERF: If this is an empty unit of work, do nothing (but still may need to commit SQL changes).
        boolean hasChanges = (this.unitOfWorkChangeSet != null) || hasCloneMapping() || hasDeletedObjects() || hasModifyAllQueries() || hasDeferredModifyAllQueries();
        if (hasChanges) {
            // The change set may already exist if using change tracking.
            if (this.unitOfWorkChangeSet == null) {
                this.unitOfWorkChangeSet = new UnitOfWorkChangeSet(this);
            }
            calculateChanges(getCloneMapping(), this.unitOfWorkChangeSet, true, true);
            hasChanges = hasModifications();
        }
        if (!hasChanges && (this.cumulativeUOWChangeSet == null) && (this.classesToBeInvalidated == null)) {
            // If no changes, avoid the remote commit, just return.
            // CR#... need to commit the transaction if begun early.
            if (wasTransactionBegunPrematurely()) {
                // Must be set to false for release to know not to rollback.
                setWasTransactionBegunPrematurely(false);
                setWasNonObjectLevelModifyQueryExecuted(false);
                try {
                    commitTransaction();
                } catch (RuntimeException commitFailed) {
                    try {
                        rollbackTransaction();
                    } catch (RuntimeException ignore) {
                        // Ignore
                    }
                    throw commitFailed;
                } catch (Error error) {
                    try {
                        rollbackTransaction();
                    } catch (RuntimeException ignore) {
                        // Ignore
                    }
                    throw error;
                }
            }
            return;
        }

        // New objects cache is created to maintain the correspondence when they are returned back as different copy
        setNewObjectsCache(collectNewObjects());
        // Unregistered new objects cache is created to maintain the correspondence when they are returned back as different copy
        setUnregisteredNewObjectsCache(collectUnregisteredNewObjects());

        // Commit on the server
        RemoteUnitOfWork remoteUnitOfWork;
        try {
            startOperationProfile(SessionProfiler.Remote, null, SessionProfiler.ALL);
            remoteUnitOfWork = ((DistributedSession)getParent()).getRemoteConnection().commitRootUnitOfWork(this);
            endOperationProfile(SessionProfiler.Remote, null, SessionProfiler.ALL);
        } catch (RuntimeException exception) {
            // Must ensure remote session transaction mutex is correct.
            if (wasTransactionBegunPrematurely()) {
                getParent().getTransactionMutex().release();
            }
            // If an exception occurred, the unit of work will have rolledback the early transaction
            // so must record this incase the unit of work re-commits.
            setWasTransactionBegunPrematurely(false);
            throw exception;
        }

        // Must ensure remote session transaction mutex is correct.
        if (wasTransactionBegunPrematurely()) {
            setWasTransactionBegunPrematurely(false);
            setWasNonObjectLevelModifyQueryExecuted(false);
            getParent().getTransactionMutex().release();
        }
        // Make the returned remote unit of work a nested unit of work and merge it with the local remote unit of work
        remoteUnitOfWork.setParent(this);
        remoteUnitOfWork.setProject(getProject());
        remoteUnitOfWork.prepareForMergeIntoRemoteUnitOfWork();
        remoteUnitOfWork.commitIntoRemoteUnitOfWork();
        // Now commit this unit of work to the parent remote session
        commitRootUnitOfWorkOnClient();
    }

    /**
     * INTERNAL:
     * Changes are calculated on the client, so avoid recalculating them on the server.
     */
    @Override
    public UnitOfWorkChangeSet calculateChanges(Map registeredObjects, UnitOfWorkChangeSet changeSet, boolean assignSequences, boolean shouldCloneMap) {
        if (!this.isOnClient) {
            // The changes are calculated on the client, so don't do them again on the server.
            return changeSet;
        }
        return super.calculateChanges(registeredObjects, changeSet, assignSequences, shouldCloneMap);
    }

    /**
     * INTERNAL:
     * Resume is not required on the server.
     */
    @Override
    public void resumeUnitOfWork() {
        if (!this.isOnClient) {
            // Avoid the resume on the server, only the client should resume.
            return;
        }
        super.resumeUnitOfWork();
    }

    /**
     * Merges remote unit of work to parent remote session.
     */
    protected void commitRootUnitOfWorkOnClient() {
        collectAndPrepareObjectsForNestedMerge();

        //calculate the change set here as we have special behavior for remote
        // in that the new changesets must be updated within the UOWChangeSet as the
        // primary keys have already been assigned.  This was modified for updating
        // new object change set behavior.
        UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet)getUnitOfWorkChangeSet();
        if (uowChangeSet == null) {
            //may be using the old commit process usesOldCommit()
            uowChangeSet = new UnitOfWorkChangeSet(this);
            setUnitOfWorkChangeSet(uowChangeSet);
            calculateChanges(getCloneMapping(), uowChangeSet, false, true);
            this.allClones = null;
        }
        for (Map newList : uowChangeSet.getNewObjectChangeSets().values()) {
            Iterator newChangeSets = new IdentityHashMap(newList).keySet().iterator();
            while (newChangeSets.hasNext()) {
                uowChangeSet.putNewObjectInChangesList((ObjectChangeSet)newChangeSets.next(), this);
            }
        }

        //add the deleted objects
        if (this.objectsDeletedDuringCommit != null) {
            for (Object deletedObject : this.objectsDeletedDuringCommit.keySet()) {
                uowChangeSet.addDeletedObject(deletedObject, this);
            }
        }

        mergeChangesIntoParent();
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     * The named query can be defined on the remote session or the server-side session.
     *
     * @see #addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName) throws DatabaseException {
        return executeQuery(queryName, new Vector(1));
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     * The class is the descriptor in which the query was pre-defined.
     * The query is executed on the server-side session.
     *
     * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, Class domainClass) throws DatabaseException {
        return executeQuery(queryName, domainClass, new Vector(1));
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     * The class is the descriptor in which the query was pre-defined.
     *
     * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, Class domainClass, Vector argumentValues) throws DatabaseException {
        DistributedSession remoteSession = null;
        if (getParent().isRemoteSession()) {
            remoteSession = (DistributedSession)getParent();
        } else {//must be remote unit of work
            RemoteUnitOfWork uow = (RemoteUnitOfWork)getParent();
            while (uow.getParent().isRemoteUnitOfWork()) {
                uow = (RemoteUnitOfWork)uow.getParent();
            }
            remoteSession = (DistributedSession)uow.getParent();
        }

        startOperationProfile(SessionProfiler.Remote, null, SessionProfiler.ALL);
        Transporter transporter = remoteSession.getRemoteConnection().remoteExecuteNamedQuery(queryName, domainClass, argumentValues);
        endOperationProfile(SessionProfiler.Remote, null, SessionProfiler.ALL);
        transporter.getQuery().setSession(this);
        return transporter.getQuery().extractRemoteResult(transporter);
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     *
     * @see #addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, Vector argumentValues) throws DatabaseException {
        if (containsQuery(queryName)) {
            return super.executeQuery(queryName, argumentValues);
        }
        return executeQuery(queryName, null, argumentValues);
    }

    /**
     * Return the table descriptor specified for the class.
     */
    @Override
    public ClassDescriptor getDescriptor(Class domainClass) {
        return getParent().getDescriptor(domainClass);
    }

    /**
     * Return the table descriptor specified for the class.
     */
    @Override
    public ClassDescriptor getDescriptorForAlias(String alias) {
        return getParent().getDescriptorForAlias(alias);
    }

    /**
     * Returns a new object cache
     */
    public List getNewObjectsCache() {
        return newObjectsCache;
    }

    /**
     * INTERNAL:
     * Method returns the parent RemoteSessionController for this Remote UnitOfWork
     * Used to retrieve Valueholders that were used on the client
     */
    public RemoteSessionController getParentSessionController() {
        return this.parentSessionController;
    }

    /**
     * INTERNAL:
     * Return the database platform currently connected to.
     * The platform is used for database specific behavior.
     */
    @Override
    public DatabasePlatform getPlatform() {
        return getParent().getPlatform();
    }

    /**
     * INTERNAL:
     * Return the database platform currently connected to.
     * The platform is used for database specific behavior.
     */
    @Override
    public Platform getDatasourcePlatform() {
        return getParent().getDatasourcePlatform();
    }

    /**
     * Returns an unregistered new object cache
     */
    public List getUnregisteredNewObjectsCache() {
        return unregisteredNewObjectsCache;
    }

    /**
     * INTERNAL:
     * Return the results from exeucting the database query.
     * the arguments should be a database row with raw data values.
     */
    @Override
    public Object internalExecuteQuery(DatabaseQuery query, AbstractRecord Record) throws DatabaseException, QueryException {
        if (isOnClient()) {
            //assert !getCommitManager().isActive();
            // This will either throw an exception or do a logic only operation
            // (i.e. mark for later deletion if a deleteObjet query).
            boolean objectLevelRead = (query.isObjectLevelReadQuery() && !query.isReportQuery() && query.shouldMaintainCache());
            if (objectLevelRead) {
                ObjectLevelReadQuery readQuery = (ObjectLevelReadQuery)query;
                if (isAfterWriteChangesButBeforeCommit()) {
                    throw ValidationException.illegalOperationForUnitOfWorkLifecycle(getLifecycle(), "executeQuery(ObjectLevelReadQuery)");
                }
                Object result = readQuery.checkEarlyReturn(this, Record);

                if (result != null) {
                    if (result == InvalidObject.instance) {
                        return null;
                    }
                    return result;
                }

                // Must use the uow connection in these cases.
                // can be certain that commit manager not active as on client.
                if (readQuery.isLockQuery(this) && !wasTransactionBegunPrematurely()) {
                    beginEarlyTransaction();
                }
            } else if (query.isObjectLevelModifyQuery()) {
                // Delete object queries must be processed locally.
                return query.executeInUnitOfWork(this, Record);
            }

            // Starting a transaction early when on a remote UnitOfWork starts
            // a transaction on the server side client session, and all queries
            // when they arrive they will go down the write connection.

            /* Fix to allow executing non-selecting SQL in a UnitOfWork. - RB */
            if ((!getCommitManager().isActive()) && query.isModifyQuery()) {
                if (!wasTransactionBegunPrematurely()) {
                    beginEarlyTransaction();
                }
            }
            Object result = getParent().executeQuery(query, Record);

            if (objectLevelRead) {
                result = ((ObjectLevelReadQuery)query).registerResultInUnitOfWork(result, this, Record, false);
            }
            if (query.isModifyAllQuery()) {
                storeModifyAllQuery(query);
            }
            return result;
        }
        return query.executeInUnitOfWork(this, Record);
    }

    protected boolean isOnClient() {
        return isOnClient;
    }

    /**
     * Return if this session is a unit of work.
     */
    @Override
    public boolean isRemoteUnitOfWork() {
        return true;
    }

    /**
     * The returned remote unit of work from the server is prepared to merge with local remote unit of work.
     */
    protected void prepareForMergeIntoRemoteUnitOfWork() {
        if (this.newObjectsCache == null) {
            return;
        }
        int size = this.newObjectsCache.size();
        if (size == 0) {
            return;
        }
        Map originalToClone = new IdentityHashMap(size);
        Map cloneToOriginal = new IdentityHashMap(size);

        // For new and unregistered objects the clone from the parent remote unit of work is picked and store as original
        // in the remote unit of work. This is done so that changes are merged into the clone of the parent.
        List remoteNewObjects = ((RemoteUnitOfWork)this.parent).getNewObjectsCache();
        for (int index = 0; index < size; index++) {
            Object cloneFromParent = remoteNewObjects.get(index);
            Object cloneFromSelf = this.newObjectsCache.get(index);
            if (cloneFromSelf != null) {
                originalToClone.put(cloneFromParent, cloneFromSelf);
                cloneToOriginal.put(cloneFromSelf, cloneFromParent);
            }
        }

        List remoteUnregisteredObjects = ((RemoteUnitOfWork)this.parent).getUnregisteredNewObjectsCache();
        size = remoteUnregisteredObjects.size();
        for (int index = 0; index < size; index++) {
            Object cloneFromParent = ((RemoteUnitOfWork)getParent()).getUnregisteredNewObjects().get(remoteUnregisteredObjects.get(index));
            Object cloneFromSelf = getUnregisteredNewObjects().get(this.unregisteredNewObjectsCache.get(index));
            originalToClone.put(cloneFromParent, cloneFromSelf);
            cloneToOriginal.put(cloneFromSelf, cloneFromParent);
        }

        this.newObjectsOriginalToClone = originalToClone;
        this.newObjectsCloneToOriginal = cloneToOriginal;
    }

    /**
     * INTERNAL:
     * Re-initialize for the server-side session.
     * This is done when the uow is passed back to the server for committing.
     */
    public void reinitializeForSession(AbstractSession session, RemoteSessionController parentSessionController) {
        // If a server, acquire a client to commit into as client store connection for commit.
        if (session.isServerSession()) {
            session = ((org.eclipse.persistence.sessions.server.ServerSession)session).acquireClientSession();
        }
        setIsOnClient(false);
        setParentSessionController(parentSessionController);
        setParent(session);
        setProject(session.getProject());
        setProfiler(session.getProfiler());
        if (session.hasEventManager()) {
            setEventManager(session.getEventManager().clone(this));
        }
        //    setShouldLogMessages(session.shouldLogMessages());
        setSessionLog(session.getSessionLog());
        setLog(session.getLog());
        // These are transient so must be reset.
        setCommitManager(new CommitManager(this));
        setTransactionMutex(new ConcurrencyManager());
        getCommitManager().setCommitOrder(session.getCommitManager().getCommitOrder());

        if (session.hasExternalTransactionController()) {
            session.getExternalTransactionController().registerSynchronizationListener(this, session);
        }

        if (this.unitOfWorkChangeSet != null) {
            fixRemoteChangeSet(this.unitOfWorkChangeSet, null, this);
        }
        if (this.cumulativeUOWChangeSet != null) {
            fixRemoteChangeSet(this.cumulativeUOWChangeSet, null, this);
        }
    }

    /**
     * INTERNAL:
     * Fix the transient fields in the serialized change set.
     */
    protected void fixRemoteChangeSet(UnitOfWorkChangeSet uowChangeSet, Map cloneMap, AbstractSession session) {
        if (uowChangeSet == null) {
            return;
        }
        uowChangeSet.setSession(session);
        for (Map.Entry<Class, Map<ObjectChangeSet, ObjectChangeSet>> entry : uowChangeSet.getObjectChanges().entrySet()) {
            ClassDescriptor descriptor = getDescriptor(entry.getKey());
            for (ObjectChangeSet changeSet : entry.getValue().values()) {
                changeSet.setDescriptor(descriptor);
                changeSet.setClassType(entry.getKey());
            }
        }
        for (Map.Entry<Class, Map<ObjectChangeSet, ObjectChangeSet>> entry : uowChangeSet.getNewObjectChangeSets().entrySet()) {
            ClassDescriptor descriptor = getDescriptor(entry.getKey());
            for (ObjectChangeSet changeSet : entry.getValue().values()) {
                changeSet.setDescriptor(descriptor);
                changeSet.setClassType(entry.getKey());
            }
        }
        if (cloneMap == null) {
            for (Map.Entry<Object, ObjectChangeSet> entry : uowChangeSet.getCloneToObjectChangeSet().entrySet()) {
                Object clone = entry.getKey();
                ObjectChangeSet changeSet = entry.getValue();
                changeSet.postSerialize(clone, uowChangeSet, session);
            }
        } else {
            // Also need to reset the remote objects with their local clones.
            int size = uowChangeSet.getCloneToObjectChangeSet().size();
            Map<Object, ObjectChangeSet> newCloneToObjectChangeSet = new IdentityHashMap<>(size);
            Map<ObjectChangeSet, Object> newObjectChangeSetToUOWClone = new IdentityHashMap<>(size);
            for (Map.Entry<Object, ObjectChangeSet> entry : uowChangeSet.getCloneToObjectChangeSet().entrySet()) {
                Object clone = cloneMap.get(entry.getKey());
                // Deleted objects no longer exist, so use remote copy instead.
                if (clone == null) {
                    clone = entry.getKey();
                }
                ObjectChangeSet changeSet = entry.getValue();
                changeSet.postSerialize(clone, uowChangeSet, session);
                newCloneToObjectChangeSet.put(clone, changeSet);
                newObjectChangeSetToUOWClone.put(changeSet, clone);
            }
            uowChangeSet.setCloneToObjectChangeSet(newCloneToObjectChangeSet);
            uowChangeSet.setObjectChangeSetToUOWClone(newObjectChangeSetToUOWClone);
        }
    }

    protected void setIsOnClient(boolean isOnClient) {
        this.isOnClient = isOnClient;
    }

    /**
     * Set a new object cache
     */
    protected void setNewObjectsCache(List newObjectsCache) {
        this.newObjectsCache = newObjectsCache;
    }

    /**
     * INTERNAL:
     * Sets the parent RemoteSessionController for this Remote UnitOfWork
     * Used to retrieve Valueholders that were used on the client
     */
    public void setParentSessionController(RemoteSessionController parentSessionController) {
        this.parentSessionController = parentSessionController;
    }

    /**
     * Set unregistered new object cache
     */
    protected void setUnregisteredNewObjectsCache(List unregisteredNewObjectsCache) {
        this.unregisteredNewObjectsCache = unregisteredNewObjectsCache;
    }

    /**
     * Avoid the toString printing the accessor and platform.
     */
    @Override
    public String toString() {
        return Helper.getShortClassName(getClass()) + "()";
    }

    /**
     * TESTING:
     * This is used by testing code to ensure that a deletion was successful.
     */
    @Override
    public boolean verifyDelete(Object domainObject) {
        return getParent().verifyDelete(domainObject);
    }
}
