/*
 * 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
//     05/28/2008-1.0M8 Andrei Ilitchev
//        - 224964: Provide support for Proxy Authentication through JPA.
//        The class was amended to allow it to instantiate ValueHolders after release method has been called
//        (internalExecuteQuery method no longer throws exception if the uow is dead).
//        Note that release method clears change sets but keeps the cache.
//     02/11/2009-1.1 Michael O'Brien
//        - 259993: 1) Defer a full clear(true) call from entityManager.clear() to release()
//          only if uow lifecycle is 1,2 or 4 (//Pending) and perform a clear of the cache only in this case.
//          2) During mergeClonesAfterCompletion() If the the acquire and release threads are different
//          switch back to the stored acquire thread stored on the mergeManager.
//     17/04/2009-1.1 Michael O'Brien
//         - 272022: For rollback scenarios - If the current thread and the active thread
//            on the mutex do not match for read locks (not yet transitioned to deferred locks) - switch them
//     07/16/2009-2.0 Guy Pelletier
//       - 277039: JPA 2.0 Cache Usage Settings
//     07/15/2011-2.2.1 Guy Pelletier
//       - 349424: persists during an preCalculateUnitOfWorkChangeSet event are lost
//     14/05/2012-2.4 Guy Pelletier
//       - 376603: Provide for table per tenant support for multitenant applications
//     08/11/2012-2.5 Guy Pelletier
//       - 393867: Named queries do not work when using EM level Table Per Tenant Multitenancy.
//     09/03/2015 - Will Dazey
//       - 456067 : Added support for defining query timeout units
//     01/29/2019-3.0 Sureshkumar Balakrishnan
//       - 541873: ENTITYMANAGER.DETACH() TRIGGERS LAZY LOADING INTO THE PERSISTENCE CONTEXT
package org.eclipse.persistence.internal.sessions;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.persistence.annotations.CacheKeyType;
import org.eclipse.persistence.config.ReferenceMode;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorEventManager;
import org.eclipse.persistence.descriptors.changetracking.AttributeChangeTrackingPolicy;
import org.eclipse.persistence.descriptors.changetracking.ObjectChangePolicy;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.EclipseLinkException;
import org.eclipse.persistence.exceptions.OptimisticLockException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.internal.databaseaccess.Accessor;
import org.eclipse.persistence.internal.databaseaccess.DatasourceAccessor;
import org.eclipse.persistence.internal.databaseaccess.Platform;
import org.eclipse.persistence.internal.descriptors.CascadeLockingPolicy;
import org.eclipse.persistence.internal.descriptors.DescriptorIterator;
import org.eclipse.persistence.internal.descriptors.DescriptorIterator.CascadeCondition;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.descriptors.PersistenceEntity;
import org.eclipse.persistence.internal.helper.ConcurrencyManager;
import org.eclipse.persistence.internal.helper.ConcurrencyUtil;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.IdentityHashSet;
import org.eclipse.persistence.internal.helper.IdentityWeakHashMap;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.identitymaps.IdentityMapManager;
import org.eclipse.persistence.internal.indirection.DatabaseValueHolder;
import org.eclipse.persistence.internal.indirection.UnitOfWorkQueryValueHolder;
import org.eclipse.persistence.internal.indirection.UnitOfWorkTransformerValueHolder;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.localization.LoggingLocalization;
import org.eclipse.persistence.internal.sequencing.Sequencing;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.foundation.AbstractTransformationMapping;
import org.eclipse.persistence.platform.server.ServerPlatform;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.DeleteObjectQuery;
import org.eclipse.persistence.queries.DoesExistQuery;
import org.eclipse.persistence.queries.InMemoryQueryIndirectionPolicy;
import org.eclipse.persistence.queries.ModifyAllQuery;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.sessions.coordination.MergeChangeSetCommand;

/**
 * Implementation of org.eclipse.persistence.sessions.UnitOfWork
 * The public interface should be used.
 * @see org.eclipse.persistence.sessions.UnitOfWork
 * <p>
 * <b>Purpose</b>: To allow object level transactions.
 * <p>
 * <b>Description</b>: The unit of work is a session that implements all of the normal
 * protocol of an EclipseLink session. It can be spawned from any other session including another unit of work.
 * Objects can be brought into the unit of work through reading them or through registering them.
 * The unit of work will operate on its own object space, that is the objects within the unit of work
 * will be clones of the original objects.  When the unit of work is committed, all changes to any objects
 * registered within the unit of work will be committed to the database.  A minimal commit/update will
 * be performed and any foreign keys/circular reference/referential integrity will be resolved.
 * If the commit to the database is successful the changed objects will be merged back into the unit of work
 * parent session.
 * <p>
 * <b>Responsibilities</b>:
 * <ul>
 * <li> Allow parallel transactions against a session's objects.
 * <li> Allow nested transactions.
 * <li> Not require the application to write objects that is changes, automatically determine what has changed.
 * <li> Perform a minimal commit/update of all changes that occurred.
 * <li> Resolve foreign keys for newly created objects and maintain referential integrity.
 * <li> Allow for the object transaction to use its own object space.
 * </ul>
 *
 */
public class UnitOfWorkImpl extends AbstractSession implements org.eclipse.persistence.sessions.UnitOfWork {

    //These constants and variables are used in extended thread logging to compare UnitOfWork creation thread and thread which registering object in UnitOfWork
    public final long CREATION_THREAD_ID = Thread.currentThread().getId();
    public final String CREATION_THREAD_NAME = String.copyValueOf(Thread.currentThread().getName().toCharArray());
    public final long CREATION_THREAD_HASHCODE = Thread.currentThread().hashCode();
    private String creationThreadStackTrace;

    /** Fix made for weak caches to avoid garbage collection of the originals. **/
    /** As well as used as lookup in merge algorithm for aggregates and others **/
    protected transient Map<Object, Object> cloneToOriginals;
    protected transient AbstractSession parent;

    /** Map of all the clones.  The key contains the clone of the object. */
    protected Map<Object, Object> cloneMapping;
    protected Map<Object, Object> newObjectsCloneToOriginal;
    protected Map<Object, Object> newObjectsOriginalToClone;
    /**
     * Stores a map from the clone to the original merged object, as a different instance is used as the original for merges.
     */
    protected Map<Object, Object> newObjectsCloneToMergeOriginal;
    protected Map<Object, Object> deletedObjects;

    /** This member variable contains a copy of all of the clones for this particular UOW */
    protected Map<Object, Object> allClones;
    protected Map<Object, Object> objectsDeletedDuringCommit;
    protected Map<Object, Object> removedObjects;
    protected Map<Object, Object> unregisteredNewObjects;
    protected Map<Object, Object> unregisteredNewObjectsInParent;
    protected Map<Object, Object> unregisteredExistingObjects;

    // bug # 3228185
    // this collection is used to store the new objects from the parent.
    // They will not be treated as new in the nested unit of work, so we must
    //store them somewhere specifically to lookup later.
    protected Map<Object, Object> newObjectsInParentOriginalToClone;

    /** Cache references of private owned objects for the removal of private owned orphans */
    protected Map<DatabaseMapping, Set> privateOwnedObjects;

    /** used to store a list of the new objects in the parent */

    //cr 2783
    protected Map<Object, Object> newObjectsInParent;
    protected Map<Object, Object> newAggregates;

    /** This method is used to store the current changeSet for this UnitOfWork. */
    protected UnitOfWorkChangeSet unitOfWorkChangeSet;

    /** This is only used for EJB entity beans to manage beans accessed in a transaction context. */
    protected UnitOfWorkImpl containerUnitOfWork;
    protected Map<Object, Object> containerBeans;

    /** use to track pessimistic locked objects  */
    protected Map<Object, Object> pessimisticLockedObjects;

    /** Used to store the list of locks that this UnitOfWork has acquired for this merge */
    protected transient MergeManager lastUsedMergeManager;

    /**
     * When in transaction batch read objects must use query local
     * to the unit of work.
     */
    protected Map<ReadQuery, ReadQuery> batchQueries;

    /** Read-only class can be used for reference data to avoid cloning when not required. */
    protected Set<Class> readOnlyClasses;

    /** Flag indicating that the transaction for this UOW was already begun. */
    protected boolean wasTransactionBegunPrematurely;

    /** Allow for double merges of new objects by putting them into the cache. */
    protected boolean shouldNewObjectsBeCached;

    /** Flag indicating that deletes should be performed before other updates. */
    protected boolean shouldPerformDeletesFirst;

    /** Flag indicating how to deal with exceptions on conforming queries. **/
    protected int shouldThrowConformExceptions;

    /** The amount of validation can be configured. */
    protected int validationLevel;
    static public final int None = 0;
    static public final int Partial = 1;
    static public final int Full = 2;

    /**
     * With the new synchronized unit of work, need a lifecycle state variable to
     * track birth, committed, pending_merge and death.
     */
    protected int lifecycle;
    public static final int Birth = 0;
    public static final int CommitPending = 1;

    // After a call to writeChanges() but before commit.
    public static final int CommitTransactionPending = 2;

    // After an unsuccessful call to writeChanges().  No recovery at all.
    public static final int WriteChangesFailed = 3;
    public static final int MergePending = 4;
    public static final int Death = 5;
    public static final int AfterExternalTransactionRolledBack = 6;

    /** Used for Conforming Queries */
    public static final int DO_NOT_THROW_CONFORM_EXCEPTIONS = 0;
    public static final int THROW_ALL_CONFORM_EXCEPTIONS = 1;

    //CR 3677 removed option to only throw valueHolderExceptions as this governed by
    //the InMemoryQueryIndirectionPolicy
    public static final String LOCK_QUERIES_PROPERTY = "LockQueriesProperties";

    /** Used for merging dependent values without use of WL SessionAccessor */
    protected static boolean SmartMerge = false;

    /** Kept reference of read lock objects*/
    protected Map<Object, Object> optimisticReadLockObjects;

    /** Used for read lock to determine update the version field with the same value or increment value */
    public static final String ReadLockOnly = "no update";
    public static final String ReadLockUpdateVersion = "update version";

    /** lazy initialization done in storeModifyAllQuery.  For UpdateAllQuery, only clones of all UpdateAllQuery's (deferred and non-deferred) are stored here for validation only.*/
    protected List<ModifyAllQuery> modifyAllQueries;

    /**
     * Contains deferred ModifyAllQuery's that have translation row for execution only.
     * At commit their clones will be added to modifyAllQueries for validation afterwards.
     * Array of the query (ModifyAllQuery) and translationRow (AbstractRecord).
     */
    //Bug4607551
    protected List<Object[]> deferredModifyAllQueries;

    /**
     * Used during the cloning process to track the recursive depth in.  This will
     * be used to determine at which point the process can begin to wait on locks
     * without being concerned about creating deadlock situations.
     */
    protected int cloneDepth;

    /**
     * PERF: Stores the JTA transaction to optimize activeUnitOfWork lookup.
     */
    protected Object transaction;

    /**
     * True if UnitOfWork should be resumed on completion of transaction.
     * Used when UnitOfWork is Synchronized with external transaction control
     */
    protected boolean resumeOnTransactionCompletion;

    /**
     * PERF: Allows discover new objects to be skipped if app always calls persist.
     */
    protected boolean shouldDiscoverNewObjects;

    /**
     * True if either DataModifyQuery or ModifyAllQuery was executed.
     * Gets reset on commit, effects DoesExistQuery behavior and reading.
     */
    protected boolean wasNonObjectLevelModifyQueryExecuted;

    /**
     * True if the value holder for the joined attribute should be triggered.
     * Required by ejb30 fetch join.
     */
    protected boolean shouldCascadeCloneToJoinedRelationship;

    /** PERF: Cache isNestedUnitOfWork check. */
    protected boolean isNestedUnitOfWork;

    /** Determine if does-exist should be performed on persist. */
    protected boolean shouldValidateExistence;

    /** Allow updates and deletes to be ordered by id or changes to avoid possible deadlocks. */
    protected CommitOrderType commitOrder;

    /** This stored the reference mode for this UOW.  If the reference mode is
     * weak then this unit of work will retain only weak references to non new,
     * non-deleted objects allowing for garbage collection.  If ObjectChangeTracking
     * is used then any objects with changes will not be garbage collected.
     */
    protected ReferenceMode referenceMode;

    // This is list is used during change tracking to keep hard references
    // to changed objects that may otherwise have been garbage collected.
    protected Set<Object> changeTrackedHardList;

    /** Used to store objects already deleted from the db and unregistered */
    protected Map<Object, Object> unregisteredDeletedObjectsCloneToBackupAndOriginal;

    /** This attribute records when the preDelete stage of Commit has completed */
    protected boolean preDeleteComplete;

    /** Stores all of the private owned objects that have been removed and may need to cascade deletion */
    protected Map<DatabaseMapping, List<Object>> deletedPrivateOwnedObjects;

    /** temporarily holds a reference to a merge manager that is calling this UnitOfWork during merge **/
    protected transient MergeManager mergeManagerForActiveMerge;

    /** Set of objects that were deleted by database cascade delete constraints. */
    protected Set<Object> cascadeDeleteObjects;

    /**
     * Used to store deleted objects that have reference to other deleted objects.
     * This is need to delete cycles of objects in the correct order.
     */
    protected Map<Object, Set<Object>> deletionDependencies;

    /**
     * INTERNAL:
     */
    public UnitOfWorkImpl() {
    }

    /**
     * INTERNAL:
     * Create and return a new unit of work with the session as its parent.
     */
    public UnitOfWorkImpl(AbstractSession parent, ReferenceMode referenceMode) {
        super();
        this.isLoggingOff = parent.isLoggingOff;
        this.referenceMode = referenceMode;
        this.shouldDiscoverNewObjects = true;
        this.name = parent.name;
        this.parent = parent;
        this.project = parent.project;
        this.profiler = parent.profiler;
        this.isInProfile = parent.isInProfile;
        this.sessionLog = parent.sessionLog;
        if (parent.hasEventManager()) {
            this.eventManager = parent.getEventManager().clone(this);
        }
        this.exceptionHandler = parent.exceptionHandler;
        this.pessimisticLockTimeoutDefault = parent.pessimisticLockTimeoutDefault;
        this.pessimisticLockTimeoutUnitDefault = parent.pessimisticLockTimeoutUnitDefault;
        this.queryTimeoutDefault = parent.queryTimeoutDefault;
        this.queryTimeoutUnitDefault = parent.queryTimeoutUnitDefault;
        this.shouldOptimizeResultSetAccess = parent.shouldOptimizeResultSetAccess;
        this.serializer = parent.serializer;
        this.isConcurrent = parent.isConcurrent;
        // Initialize the readOnlyClasses variable.
        this.setReadOnlyClasses(parent.copyReadOnlyClasses());
        this.validationLevel = Partial;

        // for 3.0.x this conforming queries will not throw exceptions unless explicitly asked to
        this.shouldThrowConformExceptions = DO_NOT_THROW_CONFORM_EXCEPTIONS;

        // initialize lifecycle state variable
        this.lifecycle = Birth;
        // PERF: Cache the write-lock check to avoid cost of checking in every register/clone.
        this.isNestedUnitOfWork = parent.isUnitOfWork();

        if (this.eventManager != null) {
            this.eventManager.postAcquireUnitOfWork();
        }
        this.descriptors = parent.getDescriptors();
        incrementProfile(SessionProfiler.UowCreated);
        // PERF: Cache the write-lock check to avoid cost of checking in every register/clone.
        this.shouldCheckWriteLock = parent.getDatasourceLogin().shouldSynchronizedReadOnWrite() || parent.getDatasourceLogin().shouldSynchronizeWrites();

        // Order updates by id
        this.commitOrder = CommitOrderType.ID;

        // Copy down the table per tenant information.
        this.tablePerTenantDescriptors = parent.tablePerTenantDescriptors;
        this.tablePerTenantQueries = parent.tablePerTenantQueries;

        // Init only if thread extended logging + thread dump is enabled
        creationThreadStackTrace = project.allowExtendedThreadLoggingThreadDump() ? ConcurrencyUtil.SINGLETON.enrichGenerateThreadDumpForCurrentThread() : null;
    }

    /**
     * INTERNAL:
     * Acquires a special historical session for reading objects as of a past time.
     */
    @Override
    public org.eclipse.persistence.sessions.Session acquireHistoricalSession(org.eclipse.persistence.history.AsOfClause clause) throws ValidationException {
        throw ValidationException.cannotAcquireHistoricalSession();
    }

    /**
       * PUBLIC:
       * Return a nested unit of work for this unit of work.
       * A nested unit of work can be used to isolate a subset of work on the unit of work,
       * such as a dialog being open from an editor.  The nested unit of work will only
       * commit change to its objects to its parent unit of work, not the database.
       * Only the parent unit of work will commit to the database.
       *
       * @see UnitOfWorkImpl
       */
    @Override
    public UnitOfWorkImpl acquireUnitOfWork() {
        UnitOfWorkImpl uow = super.acquireUnitOfWork();
        uow.discoverAllUnregisteredNewObjectsInParent();

        return uow;
    }

    /**
     * INTERNAL:
     * Records a private owned object that has been de-referenced and will need to processed
     * for related private owned objects.
     */
    public void addDeletedPrivateOwnedObjects(DatabaseMapping mapping, Object object)
    {
        if(deletedPrivateOwnedObjects == null){
            deletedPrivateOwnedObjects = new IdentityHashMap();
        }
        List<Object> list = deletedPrivateOwnedObjects.get(mapping);
        if(list == null){
            list = new ArrayList<>();
            deletedPrivateOwnedObjects.put(mapping, list);
        }
        list.add(object);
    }

    /**
     * INTERNAL:
     * Register a new aggregate object with the unit of work.
     */
    public void addNewAggregate(Object originalObject) {
        getNewAggregates().put(originalObject, originalObject);
    }

    /**
     * INTERNAL:
     * Add object deleted during root commit of unit of work.
     */
    public void addObjectDeletedDuringCommit(Object object, ClassDescriptor descriptor) {
        // The object's key is keyed on the object, this avoids having to compute the key later on.
        getObjectsDeletedDuringCommit().put(object, keyFromObject(object, descriptor));
        //bug 4730595: changed to add deleted objects to the changesets.
        ((UnitOfWorkChangeSet)getUnitOfWorkChangeSet()).addDeletedObject(object, this);
    }

    /**
     * PUBLIC:
     * Adds the given Java class to the receiver's set of read-only classes.
     * Cannot be called after objects have been registered in the unit of work.
     */
    @Override
    public void addReadOnlyClass(Class theClass) throws ValidationException {
        if (!canChangeReadOnlySet()) {
            throw ValidationException.cannotModifyReadOnlyClassesSetAfterUsingUnitOfWork();
        }

        getReadOnlyClasses().add(theClass);

        ClassDescriptor descriptor = getDescriptor(theClass);

        // Also mark all subclasses as read-only.
        if (descriptor.hasInheritance()) {
            for (ClassDescriptor childDescriptor : descriptor.getInheritancePolicy().getChildDescriptors()) {
                addReadOnlyClass(childDescriptor.getJavaClass());
            }
        }
    }

    /**
     * PUBLIC:
     * Adds the classes in the given Vector to the existing set of read-only classes.
     * Cannot be called after objects have been registered in the unit of work.
     */
    @Override
    public void addReadOnlyClasses(Collection classes) {
        for (Iterator iterator = classes.iterator(); iterator.hasNext();) {
            Class theClass = (Class)iterator.next();
            addReadOnlyClass(theClass);
        }
    }

    /**
     * INTERNAL:
     * Register that an object was removed in a nested unit of work.
     */
    public void addRemovedObject(Object orignal) {
        getRemovedObjects().put(orignal, orignal);// Use as set.
    }

    /**
     * ADVANCED:
     * Assign sequence number to the object.
     * This allows for an object's id to be assigned before commit.
     * It can be used if the application requires to use the object id before the object exists on the database.
     * Normally all ids are assigned during the commit automatically.
     */
    @Override
    public void assignSequenceNumber(Object object) throws DatabaseException {
        ClassDescriptor descriptor = getDescriptor(object);
        Object implementation = descriptor.getObjectBuilder().unwrapObject(object, this);
        assignSequenceNumber(implementation, descriptor);
    }

    /**
     * INTERNAL:
     * Assign sequence number to the object.
     */
    public Object assignSequenceNumber(Object object, ClassDescriptor descriptor) throws DatabaseException {
        Object value = null;

        // This is done outside of a transaction to ensure optimal concurrency and deadlock avoidance in the sequence table.
        if (descriptor.usesSequenceNumbers() && !descriptor.getSequence().shouldAcquireValueAfterInsert()) {
            startOperationProfile(SessionProfiler.AssignSequence);
            ObjectBuilder builder = descriptor.getObjectBuilder();
            try {
                value = builder.assignSequenceNumber(object, this);
            } catch (RuntimeException exception) {
                handleException(exception);
            } finally {
                endOperationProfile(SessionProfiler.AssignSequence);
            }
        }

        return value;
    }

    /**
     * ADVANCED:
     * Assign sequence numbers to all new objects registered in this unit of work,
     * or any new objects reference by any objects registered.
     * This allows for an object's id to be assigned before commit.
     * It can be used if the application requires to use the object id before the object exists on the database.
     * Normally all ids are assigned during the commit automatically.
     */
    @Override
    public void assignSequenceNumbers() throws DatabaseException {
        // This should be done outside of a transaction to ensure optimal concurrency and deadlock avoidance in the sequence table.
        // discoverAllUnregisteredNewObjects() should be called no matter whether sequencing used
        // or not, because collectAndPrepareObjectsForCommit() method (which calls assignSequenceNumbers())
        // needs it.
        // It would be logical to remove discoverAllUnregisteredNewObjects() from  assignSequenceNumbers()
        // and make collectAndPrepareObjectsForCommit() to call discoverAllUnregisteredNewObjects()
        // first and assignSequenceNumbers() next,
        // but assignSequenceNumbers() is a public method which could be called by user - and
        // in this case discoverAllUnregisteredNewObjects() is needed again (though
        // if sequencing is not used the call will make no sense - but no harm, too).
        discoverAllUnregisteredNewObjects();
        if (hasUnregisteredNewObjects()) {
            assignSequenceNumbers(getUnregisteredNewObjects());
        }
        if (hasNewObjects()) {
            assignSequenceNumbers(getNewObjectsCloneToOriginal());
        }
    }

    /**
     * INTERNAL:
     * Assign sequence numbers to all of the objects.
     * This allows for an object's id to be assigned before commit.
     * It can be used if the application requires to use the object id before the object exists on the database.
     * Normally all ids are assigned during the commit automatically.
     */
    protected void assignSequenceNumbers(Map objects) throws DatabaseException {
        if (objects.isEmpty()) {
            return;
        }

        Sequencing sequencing = getSequencing();
        if (sequencing == null) {
            return;
        }
        int whenShouldAcquireValueForAll = sequencing.whenShouldAcquireValueForAll();
        if (whenShouldAcquireValueForAll == Sequencing.AFTER_INSERT) {
            return;
        }
        boolean shouldAcquireValueBeforeInsertForAll = whenShouldAcquireValueForAll == Sequencing.BEFORE_INSERT;
        startOperationProfile(SessionProfiler.AssignSequence);
        Iterator newObjects = objects.keySet().iterator();
        while (newObjects.hasNext()) {
            Object object = newObjects.next();
            ClassDescriptor descriptor = getDescriptor(object);
            if (descriptor.usesSequenceNumbers()
                    && (shouldAcquireValueBeforeInsertForAll || !descriptor.getSequence().shouldAcquireValueAfterInsert())) {
                descriptor.getObjectBuilder().assignSequenceNumber(object, this);
            }
        }
        endOperationProfile(SessionProfiler.AssignSequence);
    }

    /**
     * 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 {
        beginTransaction();
        setWasTransactionBegunPrematurely(true);
    }

    /**
     * INTERNAL:
     * This is internal to the uow, transactions should not be used explicitly in a uow.
     * The uow shares its parents transactions.
     */
    @Override
    public void beginTransaction() throws DatabaseException {
        this.parent.beginTransaction();
    }

    /**
     * INTERNAL:
     * Unregistered new objects have no original so we must create one for commit and resume and
     * to put into the parent.  We can NEVER let the same copy of an object exist in multiple units of work.
     */
    public Object buildOriginal(Object workingClone) {
        ClassDescriptor descriptor = getDescriptor(workingClone);
        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object original = builder.instantiateClone(workingClone, this);

        // If no original exists can mean any of the following:
        // -A RemoteUnitOfWork and cloneToOriginals is transient.
        // -A clone read while in transaction, and built directly from
        // the database row with no intermediary original.
        // -An unregistered new object
        if (checkIfAlreadyRegistered(workingClone, descriptor) != null) {
            getCloneToOriginals().put(workingClone, original);
            return original;
        } else {
            // Assume it is an unregisteredNewObject, but this is worrisome, as
            // it may be an unregistered existing object, not in the parent cache?
            Object backup = builder.instantiateClone(workingClone, this);

            // Original is fine for backup as state is the same.
            getCloneMapping().put(workingClone, backup);

            // Must register new instance / clone as the original.
            getNewObjectsCloneToOriginal().put(workingClone, original);
            getNewObjectsOriginalToClone().put(original, workingClone);

            // no need to register in identity map as the DatabaseQueryMechanism will have
            //placed the object in the identity map on insert.  bug 3431586
        }
        return original;
    }

    /**
     * INTERNAL:
     * <p> This calculates changes in two passes, first on registered objects,
     * second it discovers unregistered new objects on only those objects that changed, and calculates their changes.
     * This also assigns sequence numbers to new objects.
     */
    public UnitOfWorkChangeSet calculateChanges(Map registeredObjects, UnitOfWorkChangeSet changeSet, boolean assignSequences, boolean shouldCloneMap) {
        // Fire the event first which may add to the registered objects. If we
        // need to clone the registered objects, it should be done after this
        // call.
        if (this.eventManager != null) {
            this.eventManager.preCalculateUnitOfWorkChangeSet();
        }

        Map allObjects = (shouldCloneMap) ? cloneMap(registeredObjects) : registeredObjects;

        if (assignSequences && hasNewObjects()) {
            // First assign sequence numbers to new objects.
            assignSequenceNumbers(this.newObjectsCloneToOriginal);
        }

        // Second calculate changes for all registered objects.
        Iterator objects = allObjects.keySet().iterator();
        Map changedObjects = new IdentityHashMap();
        Map visitedNodes = new IdentityHashMap();
        while (objects.hasNext()) {
            Object object = objects.next();

            // Block of code removed because it will never be touched see bug # 2903565

            ClassDescriptor descriptor = getDescriptor(object);

            // Update any derived id's.
            updateDerivedIds(object, descriptor);

            // Block of code removed for code coverage, as it would never have been touched. bug # 2903600

            boolean isNew = isCloneNewObject(object);
            // Use the object change policy to determine if we should run a comparison for this object - TGW.
            if (isNew || descriptor.getObjectChangePolicy().shouldCompareExistingObjectForChange(object, this, descriptor)) {
                ObjectChangeSet changes = null;
                if (isNew) {
                    changes = descriptor.getObjectChangePolicy().calculateChangesForNewObject(object, changeSet, this, descriptor, true);
                } else {
                    changes = descriptor.getObjectChangePolicy().calculateChangesForExistingObject(object, changeSet, this, descriptor, true);
                }
                if (changes != null) {
                    changeSet.addObjectChangeSet(changes, this, true);
                    changedObjects.put(object, object);
                    if (changes.hasChanges() && !changes.hasForcedChangesFromCascadeLocking()) {
                        if (descriptor.hasCascadeLockingPolicies()) {
                            for (CascadeLockingPolicy policy : descriptor.getCascadeLockingPolicies()) {
                                policy.lockNotifyParent(object, changeSet, this);
                            }
                        } else if (descriptor.usesOptimisticLocking() && descriptor.getOptimisticLockingPolicy().isCascaded()) {
                            changes.setHasForcedChangesFromCascadeLocking(true);
                        }
                    }
                } else {
                    // Mark as visited so do not need to traverse.
                    visitedNodes.put(object, object);
                }
            } else {
                // Mark as visited so do not need to traverse.
                visitedNodes.put(object, object);
            }
        }
        if (hasDeletedObjects() && !isNestedUnitOfWork()) {
            for (Object deletedObject : ((IdentityHashMap)((IdentityHashMap)this.deletedObjects).clone()).keySet()) {
                getDescriptor(deletedObject).getObjectBuilder().recordPrivateOwnedRemovals(deletedObject, this, true);
            }
        }
        if ((this.deletedPrivateOwnedObjects != null) && !this.isNestedUnitOfWork) {
            for (Map.Entry<DatabaseMapping, List<Object>> entry : this.deletedPrivateOwnedObjects.entrySet()) {
                DatabaseMapping databasemapping = entry.getKey();
                for (Object deletedObject : entry.getValue()) {
                    databasemapping.getReferenceDescriptor().getObjectBuilder().recordPrivateOwnedRemovals(deletedObject, this, false);
                }
            }
            this.deletedPrivateOwnedObjects.clear();
        }

        if (this.project.hasMappingsPostCalculateChangesOnDeleted()) {
            if (hasDeletedObjects()) {
                for (Iterator deletedObjects = getDeletedObjects().keySet().iterator(); deletedObjects.hasNext();) {
                    Object deletedObject = deletedObjects.next();
                    ClassDescriptor descriptor = getDescriptor(deletedObject);
                    if(descriptor.hasMappingsPostCalculateChangesOnDeleted()) {
                        int size = descriptor.getMappingsPostCalculateChangesOnDeleted().size();
                        for(int i=0; i < size; i++) {
                            DatabaseMapping mapping = descriptor.getMappingsPostCalculateChangesOnDeleted().get(i);
                            mapping.postCalculateChangesOnDeleted(deletedObject, changeSet, this);
                        }
                    }
                }
            }
        }

        if (this.shouldDiscoverNewObjects && !changedObjects.isEmpty()) {
            // Third discover any new objects from the new or changed objects.
            Map newObjects = new IdentityHashMap();
            // Bug 294259 -  Do not replace the existingObjects list
            // Iterate over the changed objects only.
            discoverUnregisteredNewObjects(changedObjects, newObjects, getUnregisteredExistingObjects(), visitedNodes);

            setUnregisteredNewObjects(newObjects);
            if (assignSequences) {
                assignSequenceNumbers(newObjects);
            }
            for (Iterator newObjectsEnum = newObjects.values().iterator(); newObjectsEnum.hasNext(); ) {
                Object object = newObjectsEnum.next();
                ClassDescriptor descriptor = getDescriptor(object);
                ObjectChangeSet changes = descriptor.getObjectChangePolicy().calculateChangesForNewObject(object, changeSet, this, descriptor, true);
                // Since it is new, it will always have a change set.
                changeSet.addObjectChangeSet(changes, this, true);
            }
        }

        // Remove any orphaned privately owned objects from the UnitOfWork and ChangeSets,
        // these are the objects remaining in the UnitOfWork privateOwnedObjects map
        if (hasPrivateOwnedObjects()) {
            Map visitedObjects = new IdentityHashMap();
            for (Set privateOwnedObjects : getPrivateOwnedObjects().values()) {
                for (Object objectToRemove : privateOwnedObjects) {
                    performRemovePrivateOwnedObjectFromChangeSet(objectToRemove, visitedObjects);
                }
            }
            this.privateOwnedObjects.clear();
        }
        if (this.eventManager != null) {
            this.eventManager.postCalculateUnitOfWorkChangeSet(changeSet);
        }
        return changeSet;
    }

    /**
     * INTERNAL:
     * Checks whether the receiver has been used. i.e. objects have been registered.
     *
     * @return true or false depending on whether the read-only set can be changed or not.
     */
    protected boolean canChangeReadOnlySet() {
        return !hasCloneMapping() && !hasDeletedObjects();
    }

    /**
     * INTERNAL:
     * Return if the object is an existing object (but has not been registered),
     * or a new object (that has not be persisted).
     */
    public boolean checkForUnregisteredExistingObject(Object object) {

        ClassDescriptor descriptor = getDescriptor(object.getClass());
        Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, this, true);
        if (primaryKey == null) {
            return false;
        }
        DoesExistQuery existQuery = descriptor.getQueryManager().getDoesExistQuery();

        existQuery = (DoesExistQuery) existQuery.clone();
        existQuery.setObject(object);
        existQuery.setPrimaryKey(primaryKey);
        existQuery.setDescriptor(descriptor);
        existQuery.setIsExecutionClone(true);

        return ((Boolean) executeQuery(existQuery)).booleanValue();
    }

    /**
     * INTERNAL: Register the object and return the clone if it is existing
     * otherwise return null if it is new. The unit of work determines existence
     * during registration, not during the commit.
     */
    public Object checkExistence(Object object) {
        ClassDescriptor descriptor = getDescriptor(object.getClass());
        Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, this, true);
        // PERF: null primary key cannot exist.
        if (primaryKey == null) {
            return null;
        }
        DoesExistQuery existQuery = descriptor.getQueryManager().getDoesExistQuery();

        // PERF: Avoid cost of query execution as normally can determine from checkEarlyReturn.
        Boolean exists = (Boolean)existQuery.checkEarlyReturn(object, primaryKey, this, null);
        if (exists == null) {
            // Need to execute database query.
            existQuery = (DoesExistQuery)existQuery.clone();
            existQuery.setObject(object);
            existQuery.setPrimaryKey(primaryKey);
            existQuery.setDescriptor(descriptor);
            existQuery.setIsExecutionClone(true);
            exists = (Boolean)executeQuery(existQuery);
        }
        if (exists) {
            //we know if it exists or not, now find or register it
            Object objectFromCache = getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, object.getClass(), descriptor);

            if (objectFromCache != null) {
                // Ensure that the registered object is the one from the parent cache.
                if (shouldPerformFullValidation()) {
                    if ((objectFromCache != object) && (this.parent.getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, object.getClass(), descriptor) != object)) {
                        throw ValidationException.wrongObjectRegistered(object, objectFromCache);
                    }
                }

                // Has already been cloned.
                if (!this.isObjectDeleted(objectFromCache))
                    return objectFromCache;
            }
            // This is a case where the object is not in the session cache,
            // so a new cache-key is used as there is no original to use for locking.
            // It read time must be set to avoid it being invalidated.
            CacheKey cacheKey = new CacheKey(primaryKey);
            cacheKey.setReadTime(System.currentTimeMillis());
            cacheKey.setIsolated(true); // if the cache does not have a version then this must be built from the supplied version
            return cloneAndRegisterObject(object, cacheKey, descriptor);
        } else {
            return null;
        }
    }

    /**
     * INTERNAL:
     * Return the value of the object if it already is registered, otherwise null.
     */
    public Object checkIfAlreadyRegistered(Object object, ClassDescriptor descriptor) {
        // Don't register read-only classes
        if (isClassReadOnly(object.getClass(), descriptor)) {
            return null;
        }

        // Check if the working copy is again being registered in which case we return the same working copy
        Object registeredObject = getCloneMapping().get(object);
        if (registeredObject != null) {
            return object;
        }

        // Check if object exists in my new objects if it is in the new objects cache then it means domain object is being
        // re-registered and we should return the same working clone. This check holds only for the new registered objects
        // PERF: Avoid initialization of new objects if none.
        if (hasNewObjects()) {
            registeredObject = getNewObjectsOriginalToClone().get(object);
            if (registeredObject != null) {
                return registeredObject;
            }
        }
        if (this.isNestedUnitOfWork) {
            // bug # 3228185
            //may be a new object from a parent Unit Of Work, let's check our new object in parent list to see
            //if it has already been registered locally
            if (hasNewObjectsInParentOriginalToClone()) {
                registeredObject = getNewObjectsInParentOriginalToClone().get(object);
            }
            if (registeredObject != null) {
                return registeredObject;
            }
        }

        return null;
    }

    /**
     * INTERNAL:
     * Check if the object is invalid and *should* be refreshed.
     * This is used to ensure that no invalid objects are cloned.
     */
    @Override
    public boolean isConsideredInvalid(Object object, CacheKey cacheKey, ClassDescriptor descriptor) {
        if (! isNestedUnitOfWork){
            return getParent().isConsideredInvalid(object, cacheKey, descriptor);
        }
        return false;
    }

    /**
     * ADVANCED:
     * Register the new object with the unit of work.
     * This will register the new object with cloning.
     * Normally the registerObject method should be used for all registration of new and existing objects.
     * This version of the register method can only be used for new objects.
     * This method should only be used if a new object is desired to be registered without an existence Check.
     *
     * @see #registerObject(Object)
     */
    protected Object cloneAndRegisterNewObject(Object original, boolean isShallowClone) {
        ClassDescriptor descriptor = getDescriptor(original);
        //Nested unit of work is not supported for attribute change tracking
        if (this.isNestedUnitOfWork && (descriptor.getObjectChangePolicy() instanceof AttributeChangeTrackingPolicy)) {
            throw ValidationException.nestedUOWNotSupportedForAttributeTracking();
        }
        ObjectBuilder builder = descriptor.getObjectBuilder();

        // bug 2612602 create the working copy object.
        Object clone = builder.instantiateWorkingCopyClone(original, this);

        // Must put in the original to clone to resolve circular refs.
        getNewObjectsOriginalToClone().put(original, clone);
        getNewObjectsCloneToOriginal().put(clone, original);
        // Must put in clone mapping.
        getCloneMapping().put(clone, clone);

        if (isShallowClone) {
            builder.copyInto(original, clone, true);
        } else {
            builder.populateAttributesForClone(original, null, clone, null, this);
        }
        // Must reregister in both new objects.
        registerNewObjectClone(clone, original, descriptor);

        //Build backup clone for DeferredChangeDetectionPolicy or ObjectChangeTrackingPolicy,
        //but not for AttributeChangeTrackingPolicy
        Object backupClone = descriptor.getObjectChangePolicy().buildBackupClone(clone, builder, this);
        getCloneMapping().put(clone, backupClone);// The backup clone must be updated.
        executeDeferredEvents();

        return clone;
    }

    /**
     * INTERNAL:
     * Clone and register the object.
     * The cache key must the cache key from the session cache, as it will be used for locking.
     * The unit of work cache key is passed to the normal cloneAndRegisterObject method.
     */
    public Object cloneAndRegisterObject(Object original, CacheKey parentCacheKey, ClassDescriptor descriptor) {
        CacheKey unitOfWorkCacheKey = null;
        if (parentCacheKey.getKey() == null) {
            // The primary key may be null for nested units of work with new parent objects.
            unitOfWorkCacheKey = new CacheKey(null);
            unitOfWorkCacheKey.setIsolated(true);
            unitOfWorkCacheKey.acquire();
        } else {
            unitOfWorkCacheKey = getIdentityMapAccessorInstance().acquireLock(parentCacheKey.getKey(), original.getClass(), descriptor, false);
        }
        try {
            return cloneAndRegisterObject(original, parentCacheKey, unitOfWorkCacheKey, descriptor);
        } finally {
            unitOfWorkCacheKey.release();
        }
    }

    /**
     * INTERNAL:
     * Clone and register the object.
     * The cache key must the cache key from the session cache,
     * as it will be used for locking.
     */
    public Object cloneAndRegisterObject(Object original, CacheKey parentCacheKey, CacheKey unitOfWorkCacheKey, ClassDescriptor descriptor) {
        ClassDescriptor concreteDescriptor = descriptor;
        // Ensure correct subclass descriptor.
        if (original.getClass() != descriptor.getJavaClass()) {
            concreteDescriptor = getDescriptor(original);
        }
        // Nested unit of work is not supported for attribute change tracking.
        if (this.isNestedUnitOfWork && (concreteDescriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy())) {
            throw ValidationException.nestedUOWNotSupportedForAttributeTracking();
        }

        ObjectBuilder builder = concreteDescriptor.getObjectBuilder();
        Object workingClone = null;

        // The cache/objects being registered must first be locked to ensure
        // that a merge or refresh does not occur on the object while being cloned to
        // avoid cloning a partially merged/refreshed object.
        // If a cache isolation level is used, then lock the entire cache.
        // otherwise lock the object and it related objects (not using indirection) as a unit.
        // If just a simple object (all indirection) a simple read-lock can be used.
        // PERF: Cache if check to write is required.
        boolean identityMapLocked = this.parent.shouldCheckWriteLock && this.parent.getIdentityMapAccessorInstance().acquireWriteLock();
        boolean rootOfCloneRecursion = false;
        if (identityMapLocked) {
            checkAndRefreshInvalidObject(original, parentCacheKey, descriptor);
        } else {
            // Check if we have locked all required objects already.
            if (this.objectsLockedForClone == null) {
                // PERF: If a simple object just acquire a simple read-lock.
                if (concreteDescriptor.shouldAcquireCascadedLocks()) {
                    this.objectsLockedForClone = this.parent.getIdentityMapAccessorInstance().getWriteLockManager().acquireLocksForClone(original, concreteDescriptor, parentCacheKey, this.parent);
                } else {
                    checkAndRefreshInvalidObject(original, parentCacheKey, descriptor);
                    parentCacheKey.acquireReadLock();
                }
                rootOfCloneRecursion = true;
            }
        }
        try {
            // bug:6167576   Must acquire the lock before cloning.
            workingClone = builder.instantiateWorkingCopyClone(original, this);
            // PERF: Cache the primary key if implements PersistenceEntity.
            if (workingClone instanceof PersistenceEntity) {
                ((PersistenceEntity)workingClone)._persistence_setId(parentCacheKey.getKey());
            }

            // This must be registered before it is built to avoid really obscure cycles.
            getCloneMapping().put(workingClone, workingClone);

            // bug # 3228185 & Bug4736360
            // if this is a nested unit of work and the object is new in the parent
            //  and we must store it in the newobject list for lookup later
            if (this.isNestedUnitOfWork && isCloneNewObjectFromParent(original)) {
                getNewObjectsInParentOriginalToClone().put(original, workingClone);
            }

            //store this for look up later
            getCloneToOriginals().put(workingClone, original);
            // just clone it.
            populateAndRegisterObject(original, workingClone, unitOfWorkCacheKey, parentCacheKey, concreteDescriptor);

            //also clone the fetch group reference if applied
            if (concreteDescriptor.hasFetchGroupManager()) {
                concreteDescriptor.getFetchGroupManager().copyFetchGroupInto(original, workingClone, this);
            }
        } finally {
            // If the entire cache was locked, release the cache lock,
            // otherwise either release the cache-key for a simple lock,
            // otherwise release the entire set of locks for related objects if this was the root.
            if (identityMapLocked) {
                this.parent.getIdentityMapAccessorInstance().releaseWriteLock();
            } else {
                if (rootOfCloneRecursion) {
                    if (this.objectsLockedForClone == null) {
                        parentCacheKey.releaseReadLock();
                    } else {
                        for (Iterator iterator = this.objectsLockedForClone.values().iterator(); iterator.hasNext();) {
                            ((CacheKey)iterator.next()).releaseReadLock();
                        }
                        this.objectsLockedForClone = null;
                    }
                    executeDeferredEvents();
                }
            }
        }
        concreteDescriptor.getObjectBuilder().instantiateEagerMappings(workingClone, this);
        return workingClone;
    }

    /**
     * INTERNAL:
     * Prepare for merge in nested uow.
     */
    public Map collectAndPrepareObjectsForNestedMerge() {
        discoverAllUnregisteredNewObjectsInParent();
        return new IdentityHashMap(this.getCloneMapping());
    }

    /**
     * PUBLIC:
     * Commit the unit of work to its parent.
     * For a nested unit of work this will merge any changes to its objects
     * with its parents.
     * For a first level unit of work it will commit all changes to its objects
     * to the database as a single transaction.  If successful the changes to its
     * objects will be merged to its parent's objects.  If the commit fails the database
     * transaction will be rolledback, and the unit of work will be released.
     * If the commit is successful the unit of work is released, and a new unit of work
     * must be acquired if further changes are desired.
     *
     * @see #commitAndResumeOnFailure()
     * @see #commitAndResume()
     * @see #release()
     */
    @Override
    public void commit() throws DatabaseException, OptimisticLockException {
        //CR#2189 throwing exception if UOW try to commit again(XC)
        if (!isActive()) {
            throw ValidationException.cannotCommitUOWAgain();
        }
        if (isAfterWriteChangesFailed()) {
            throw ValidationException.unitOfWorkAfterWriteChangesFailed("commit");
        }

        if (!this.isNestedUnitOfWork) {
            if (isSynchronized()) {
                // If we started the JTS transaction then we have to commit it as well.
                if (this.parent.wasJTSTransactionInternallyStarted()) {
                    commitInternallyStartedExternalTransaction();
                }

                // Do not commit until the JTS wants to.
                return;
            }
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "begin_unit_of_work_commit");
        if (this.lifecycle == CommitTransactionPending) {
            commitAfterWriteChanges();
            return;
        }
        if (this.eventManager != null) {
            this.eventManager.preCommitUnitOfWork();
        }
        setLifecycle(CommitPending);
        if (this.isNestedUnitOfWork) {
            commitNestedUnitOfWork();
        } else {
            commitRootUnitOfWork();
        }
        if (this.eventManager != null) {
            this.eventManager.postCommitUnitOfWork();
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "end_unit_of_work_commit");
        release();
    }

    /**
     * PUBLIC:
     * Commit the unit of work to its parent.
     * For a nested unit of work this will merge any changes to its objects
     * with its parents.
     * For a first level unit of work it will commit all changes to its objects
     * to the database as a single transaction.  If successful the changes to its
     * objects will be merged to its parent's objects.  If the commit fails the database
     * transaction will be rolledback, and the unit of work will be released.
     * The normal commit releases the unit of work, forcing a new one to be acquired if further changes are desired.
     * The resuming feature allows for the same unit of work (and working copies) to be continued to be used.
     *
     * @see #commitAndResumeOnFailure()
     * @see #commit()
     * @see #release()
     */
    @Override
    public void commitAndResume() throws DatabaseException, OptimisticLockException {
        //CR#2189 throwing exception if UOW try to commit again(XC)
        if (!isActive()) {
            throw ValidationException.cannotCommitUOWAgain();
        }

        if (isAfterWriteChangesFailed()) {
            throw ValidationException.unitOfWorkAfterWriteChangesFailed("commit");
        }

        if (!this.isNestedUnitOfWork) {
            if (isSynchronized()) {
                // JTA synchronized units of work, cannot be resumed as there is no
                // JTA transaction to register with after the commit,
                // technically this could be supported if the uow started the transaction,
                // but currently the after completion releases the uow and client session so not really possible.
                throw ValidationException.cannotCommitAndResumeSynchronizedUOW(this);
            }
        }
        if (this.lifecycle == CommitTransactionPending) {
            commitAndResumeAfterWriteChanges();
            return;
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "begin_unit_of_work_commit");// bjv - correct spelling
        if (this.eventManager != null) {
            this.eventManager.preCommitUnitOfWork();
        }
        setLifecycle(CommitPending);
        if (this.parent.isUnitOfWork()) {
            commitNestedUnitOfWork();
        } else {
            commitRootUnitOfWork();
        }
        if (this.eventManager != null) {
            this.eventManager.postCommitUnitOfWork();
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "end_unit_of_work_commit");
        log(SessionLog.FINER, SessionLog.TRANSACTION, "resume_unit_of_work");
        synchronizeAndResume();
        if (this.eventManager != null) {
            this.eventManager.postResumeUnitOfWork();
        }
    }

    /**
     * INTERNAL:
     * This method is used by the MappingWorkbench for their read-only file feature
     * this method must not be exposed to or used by customers until it has been revised
     * and the feature revisited to support OptimisticLocking and Serialization
     */
    public void commitAndResumeWithPreBuiltChangeSet(UnitOfWorkChangeSet uowChangeSet) throws DatabaseException, OptimisticLockException {
        if (!this.isNestedUnitOfWork) {
            if (isSynchronized()) {
                // If we started the JTS transaction then we have to commit it as well.
                if (this.parent.wasJTSTransactionInternallyStarted()) {
                    commitInternallyStartedExternalTransaction();
                }

                // Do not commit until the JTS wants to.
                return;
            }
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "begin_unit_of_work_commit");// bjv - correct spelling
        if (this.eventManager != null) {
            this.eventManager.preCommitUnitOfWork();
        }
        setLifecycle(CommitPending);
        if (this.parent.isUnitOfWork()) {
            commitNestedUnitOfWork();
        } else {
            commitRootUnitOfWorkWithPreBuiltChangeSet(uowChangeSet);
        }
        if (this.eventManager != null) {
            this.eventManager.postCommitUnitOfWork();
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "end_unit_of_work_commit");
        log(SessionLog.FINER, SessionLog.TRANSACTION, "resume_unit_of_work");

        synchronizeAndResume();
        if (this.eventManager != null) {
            this.eventManager.postResumeUnitOfWork();
        }
    }

    /**
     * PUBLIC:
     * Commit the unit of work to its parent.
     * For a nested unit of work this will merge any changes to its objects
     * with its parents.
     * For a first level unit of work it will commit all changes to its objects
     * to the database as a single transaction.  If successful the changes to its
     * objects will be merged to its parent's objects.  If the commit fails the database
     * transaction will be rolledback, but the unit of work will remain active.
     * It can then be retried or released.
     * The normal commit failure releases the unit of work, forcing a new one to be acquired if further changes are desired.
     * The resuming feature allows for the same unit of work (and working copies) to be continued to be used if an error occurs.
     * The UnitOfWork will also remain active if the commit is successful.
     *
     * @see #commit()
     * @see #release()
     */
    @Override
    public void commitAndResumeOnFailure() throws DatabaseException, OptimisticLockException {
        // First clone the identity map, on failure replace the clone back as the cache.
        IdentityMapManager failureManager = (IdentityMapManager)getIdentityMapAccessorInstance().getIdentityMapManager().clone();
        try {
            // Call commitAndResume.
            // Oct 13, 2000 - JED PRS #13551
            // This method will always resume now. Calling commitAndResume will sync the cache
            // if successful. This method will take care of resuming if a failure occurs
            commitAndResume();
        } catch (RuntimeException exception) {
            //reset unitOfWorkChangeSet.  Needed for ObjectChangeTrackingPolicy and DeferredChangeDetectionPolicy
            setUnitOfWorkChangeSet(null);
            getIdentityMapAccessorInstance().setIdentityMapManager(failureManager);
            log(SessionLog.FINER, SessionLog.TRANSACTION, "resuming_unit_of_work_from_failure");
            throw exception;
        }
    }

    /**
     * INTERNAL:
     * Commits a UnitOfWork where the commit process has already been
     * initiated by all call to writeChanges().
     * <p>
     * a.k.a finalizeCommit()
     */
    protected void commitAfterWriteChanges() {
        commitTransactionAfterWriteChanges();
        mergeClonesAfterCompletion();
        setDead();
        release();
    }

    /**
     * INTERNAL:
     * Commits and resumes a UnitOfWork where the commit process has already been
     * initiated by all call to writeChanges().
     * <p>
     * a.k.a finalizeCommit()
     */
    protected void commitAndResumeAfterWriteChanges() {
        commitTransactionAfterWriteChanges();
        mergeClonesAfterCompletion();
        log(SessionLog.FINER, SessionLog.TRANSACTION, "resume_unit_of_work");
        synchronizeAndResume();
        if (this.eventManager != null) {
            this.eventManager.postResumeUnitOfWork();
        }
    }

    /**
     * PROTECTED:
     * Used in commit and commit-like methods to commit
     * internally started external transaction
     */
    protected boolean commitInternallyStartedExternalTransaction() {
        boolean committed = false;
        if (!this.parent.isInTransaction() || (wasTransactionBegunPrematurely() && (this.parent.getTransactionMutex().getDepth() == 1))) {
            committed = this.parent.commitExternalTransaction();
        }
        return committed;
    }

    /**
     * INTERNAL:
     * Commit the changes to any objects to the parent.
     */
    protected void commitNestedUnitOfWork() {
        this.parent.getIdentityMapAccessorInstance().acquireWriteLock();//Ensure concurrency

        try {
            // Iterate over each clone and let the object build merge to clones into the originals.
            // The change set may already exist if using change tracking.
            if (getUnitOfWorkChangeSet() == null) {
                setUnitOfWorkChangeSet(new UnitOfWorkChangeSet(this));
            }
            unitOfWorkChangeSet = calculateChanges(collectAndPrepareObjectsForNestedMerge(), (UnitOfWorkChangeSet)getUnitOfWorkChangeSet(), false, false);
            this.allClones = null;
            mergeChangesIntoParent();

            if (hasDeletedObjects()) {
                for (Iterator deletedObjects = getDeletedObjects().keySet().iterator();
                         deletedObjects.hasNext();) {
                    Object deletedObject = deletedObjects.next();
                    Object originalObject = getOriginalVersionOfObject(deletedObject);

                    // bug # 3132979 if the deleted object is new in the parent
                    //then  unregister in the parent.
                    //else add it to the deleted object list to be removed from the parent's parent
                    //this prevents erroneous insert and delete sql
                    if ((originalObject != null) && ((UnitOfWorkImpl)this.parent).getNewObjectsCloneToOriginal().containsKey(originalObject)) {
                        ((UnitOfWorkImpl)this.parent).unregisterObject(originalObject);
                    } else {
                        ((UnitOfWorkImpl)this.parent).getDeletedObjects().put(originalObject, getId(originalObject));
                    }
                }
            }
            if (hasRemovedObjects()) {
                for (Iterator removedObjects = getRemovedObjects().values().iterator();
                         removedObjects.hasNext();) {
                    ((UnitOfWorkImpl)this.parent).getCloneMapping().remove(removedObjects.next());
                }
            }
        } finally {
            this.parent.getIdentityMapAccessorInstance().releaseWriteLock();
        }
    }

    /**
     * INTERNAL:
     * Commit the changes to any objects to the parent.
     */
    public void commitRootUnitOfWork() throws DatabaseException, OptimisticLockException {
        commitToDatabaseWithChangeSet(true);
        // Merge after commit
        mergeChangesIntoParent();
        this.changeTrackedHardList = null;

    }

    /**
     * INTERNAL:
     * This method is used by the MappingWorkbench read-only files feature
     * It will commit a pre-built unitofwork change set to the database
     */
    public void commitRootUnitOfWorkWithPreBuiltChangeSet(UnitOfWorkChangeSet uowChangeSet) throws DatabaseException, OptimisticLockException {
        //new code no need to check old commit
        commitToDatabaseWithPreBuiltChangeSet(uowChangeSet, true, true);

        // Merge after commit
        mergeChangesIntoParent();
    }

    /**
     * INTERNAL:
     * CommitChanges To The Database from a calculated changeSet
     * @param commitTransaction false if called by writeChanges as intent is
     * not to finalize the transaction.
     */
    protected void commitToDatabase(boolean commitTransaction) {
        try {
            //CR4202 - ported from 3.6.4
            if (wasTransactionBegunPrematurely()) {
                // beginTransaction() has been already called
                setWasTransactionBegunPrematurely(false);
            } else {
                beginTransaction();
            }

            if (commitTransaction) {
                setWasNonObjectLevelModifyQueryExecuted(false);
            }
            this.preDeleteComplete = false;

            List deletedObjects = null;// PERF: Avoid deletion if nothing to delete.
            if (hasDeletedObjects()) {
                deletedObjects = new ArrayList(this.deletedObjects.size());
                for (Object objectToDelete : this.deletedObjects.keySet()) {
                    ClassDescriptor descriptor = getDescriptor(objectToDelete);
                    if (descriptor.hasPreDeleteMappings()) {
                        for (DatabaseMapping mapping : descriptor.getPreDeleteMappings()) {
                            DeleteObjectQuery deleteQuery = descriptor.getQueryManager().getDeleteQuery();
                            if (deleteQuery == null) {
                                deleteQuery = new DeleteObjectQuery();
                                deleteQuery.setDescriptor(descriptor);
                            } else {
                                // Ensure original query has been prepared.
                                deleteQuery.checkPrepare(this, deleteQuery.getTranslationRow());
                                deleteQuery = (DeleteObjectQuery)deleteQuery.clone();
                            }
                            deleteQuery.setIsExecutionClone(true);
                            deleteQuery.setTranslationRow(new DatabaseRecord());
                            deleteQuery.setObject(objectToDelete);
                            deleteQuery.setSession(this);
                            mapping.earlyPreDelete(deleteQuery, objectToDelete);
                        }
                    }
                    deletedObjects.add(objectToDelete);
                }
                this.preDeleteComplete = true;
            }

            if (this.shouldPerformDeletesFirst) {
                if (deletedObjects != null) {
                    // This must go to the commit manager because uow overrides to do normal deletion.
                    getCommitManager().deleteAllObjects(deletedObjects);

                    // Clear change sets of the deleted object to avoid redundant updates.
                    for (Iterator objects = getObjectsDeletedDuringCommit().keySet().iterator();
                             objects.hasNext();) {
                        org.eclipse.persistence.internal.sessions.ObjectChangeSet objectChangeSet = (org.eclipse.persistence.internal.sessions.ObjectChangeSet)this.unitOfWorkChangeSet.getObjectChangeSetForClone(objects.next());
                        if (objectChangeSet != null) {
                            objectChangeSet.clear(true);
                        }
                    }
                }

                // Let the commit manager figure out how to write the objects
                super.writeAllObjectsWithChangeSet(this.unitOfWorkChangeSet);
                // Issue all the SQL for the ModifyAllQuery's, don't touch the cache though
                issueModifyAllQueryList();
            } else {
                // Let the commit manager figure out how to write the objects
                super.writeAllObjectsWithChangeSet(this.unitOfWorkChangeSet);
                if (deletedObjects != null) {
                    // This must go to the commit manager because uow overrides to do normal deletion.
                    getCommitManager().deleteAllObjects(deletedObjects);
                }

                // Issue all the SQL for the ModifyAllQuery's, don't touch the cache though
                issueModifyAllQueryList();
            }

            // Issue prepare event.
            if (this.eventManager != null) {
                this.eventManager.prepareUnitOfWork();
            }

            // writeChanges() does everything but this step.
            // do not lock objects unless we are at the commit stage
            if (commitTransaction) {
                try {
                    acquireWriteLocks();
                    commitTransaction();
                } catch (RuntimeException throwable) {
                    releaseWriteLocks();
                    throw throwable;
                } catch (Error throwable) {
                    releaseWriteLocks();
                    throw throwable;
                }
            } else {
                setWasTransactionBegunPrematurely(true);

                //must let the UnitOfWork know that the transaction was begun
                //before the commit process.
            }
        } catch (RuntimeException exception) {
            // The number of SQL statements been prepared need be stored into UOW
            // before any exception being thrown.
            copyStatementsCountIntoProperties();
            try {
                rollbackTransaction(commitTransaction);
            } catch (RuntimeException ignore) {
                // Ignore
            }
            if (hasExceptionHandler()) {
                getExceptionHandler().handleException(exception);
            } else {
                throw exception;
            }
        }
    }

    /**
     * INTERNAL:
     * Commit the changes to any objects to the parent.
     * @param commitTransaction false if called by writeChanges as intent is
     * not to finalize the transaction.
     */
    protected void commitToDatabaseWithChangeSet(boolean commitTransaction) throws DatabaseException, OptimisticLockException {

        try {
            incrementProfile(SessionProfiler.UowCommits);
            startOperationProfile(SessionProfiler.UowCommit);
            // 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) {
                try{
                    // The sequence numbers are assigned outside of the commit transaction.
                    // This improves concurrency, avoids deadlock and in the case of three-tier will
                    // not leave invalid cached sequences on rollback.
                    // Iterate over each clone and let the object build merge to clones into the originals.
                    // The change set may already exist if using change tracking.
                    if (this.unitOfWorkChangeSet == null) {
                        this.unitOfWorkChangeSet = new UnitOfWorkChangeSet(this);
                    }
                    // PERF: clone is faster than new.
                    calculateChanges(getCloneMapping(), this.unitOfWorkChangeSet, true, true);

                } catch (RuntimeException exception){
                    // The number of SQL statements been prepared need be stored into UOW
                    // before any exception being thrown.
                    copyStatementsCountIntoProperties();
                    throw exception;
                }
                hasChanges = hasModifications();
            }

            // Bug 2834266 only commit to the database if changes were made, avoid begin/commit of transaction
            if (hasChanges) {
                // Also must first set the commit manager active.
                getCommitManager().setIsActive(true);
                commitToDatabase(commitTransaction);
            } else {
                try {
                    // CR#... need to commit the transaction if begun early.
                    if (wasTransactionBegunPrematurely()) {
                        if (commitTransaction) {
                            // 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;
                            }
                        }
                    }
                } catch (RuntimeException exception) {
                    // The number of SQL statements been prepared need be stored into UOW
                    // before any exception being thrown.
                    copyStatementsCountIntoProperties();
                    throw exception;
                }
            }
        } catch (RuntimeException exception) {
            handleException(exception);
        } finally {
            endOperationProfile(SessionProfiler.UowCommit);
        }
    }

    /**
     * INTERNAL:
     * Commit pre-built changeSet to the database changeSet to the database.
     */
    protected void commitToDatabaseWithPreBuiltChangeSet(UnitOfWorkChangeSet uowChangeSet, boolean commitTransaction, boolean isChangeSetFromOutsideUOW) throws DatabaseException, OptimisticLockException {
        try {
            uowChangeSet.setIsChangeSetFromOutsideUOW(isChangeSetFromOutsideUOW);
            // The sequence numbers are assigned outside of the commit transaction.
            // This improves concurrency, avoids deadlock and in the case of three-tier will
            // not leave invalid cached sequences on rollback.
            // Also must first set the commit manager active.
            getCommitManager().setIsActive(true);
            // Iterate over each clone and let the object build merge to clones into the originals.
            setUnitOfWorkChangeSet(uowChangeSet);
            commitToDatabase(commitTransaction);
            uowChangeSet.setIsChangeSetFromOutsideUOW(false);
        } catch (RuntimeException exception) {
            handleException(exception);
        }
    }

    /**
     * INTERNAL:
     * This is internal to the uow, transactions should not be used explicitly in a uow.
     * The uow shares its parents transactions.
     */
    @Override
    public void commitTransaction() throws DatabaseException {
        this.parent.commitTransaction();
    }

    /**
     * INTERNAL:
     * After writeChanges() everything has been done except for committing
     * the transaction.  This allows that execution path to 'catch up'.
     */
    public void commitTransactionAfterWriteChanges() {
        setWasNonObjectLevelModifyQueryExecuted(false);
        if (hasModifications() || wasTransactionBegunPrematurely()) {
             try{
                //gf934: ensuring release doesn't cause an extra rollback call if acquireRequiredLocks throws an exception
                setWasTransactionBegunPrematurely(false);
                acquireWriteLocks();
                commitTransaction();
            } catch (RuntimeException exception) {
                releaseWriteLocks();
                try {
                    rollbackTransaction(false);
                } catch (RuntimeException ignore) {
                    // Ignore
                }
                setLifecycle(WriteChangesFailed);
                handleException(exception);
            } catch (Error throwable) {
                releaseWriteLocks();
                try {
                    rollbackTransaction();
                } catch (RuntimeException ignore) {
                    // Ignore
                }
                throw throwable;
            }
        }
    }

    /**
     * INTERNAL:
     * Acquire the unit of work cache write locks, if required.
     */
    protected void acquireWriteLocks() {
        // If everything is isolated, can bypass merge entirely.
        if (this.project.hasNonIsolatedUOWClasses() || (this.modifyAllQueries != null)) {
            // if we should be acquiring locks before commit let's do that here
            if (getDatasourceLogin().shouldSynchronizeObjectLevelReadWriteDatabase() && (this.unitOfWorkChangeSet != null)) {
                writesCompleted();//flush Batch Statements
                this.lastUsedMergeManager = new MergeManager(this);
                //If we are merging into the shared cache acquire all required locks before merging.
                this.parent.getIdentityMapAccessorInstance().getWriteLockManager().acquireRequiredLocks(this.lastUsedMergeManager, this.unitOfWorkChangeSet);
            }
        }
    }

    /**
     * INTERNAL:
     * Release the unit of work cache write locks, if acquired.
     */
    public void releaseWriteLocks() {
        if (this.lastUsedMergeManager != null) {
            // 272022: If the current thread and the active thread on the mutex do not match - switch them
            verifyMutexThreadIntegrityBeforeRelease();
            // exception occurred during the commit.
            this.parent.getIdentityMapAccessorInstance().getWriteLockManager().releaseAllAcquiredLocks(this.lastUsedMergeManager);
            this.lastUsedMergeManager = null;
        }
    }

    /**
     * INTERNAL:
     * Copy the read only classes from the unit of work.
     */
    // Added Nov 8, 2000 JED for Patch 2.5.1.8, Ref: Prs 24502
    @Override
    public Vector copyReadOnlyClasses() {
        return new Vector(getReadOnlyClasses());
    }

    /**
     * PUBLIC:
     * Merge the attributes of the clone into the unit of work copy.
     * This can be used for objects that are returned from the client through
     * RMI serialization or other serialization mechanisms, because the RMI object will
     * be a clone this will merge its attributes correctly to preserve object identity
     * within the unit of work and record its changes.
     * Everything connected to this object (i.e. the entire object tree where rmiClone
     * is the root) is also merged.
     *
     * @return the registered version for the clone being merged.
     * @see #mergeClone(Object)
     * @see #shallowMergeClone(Object)
     */
    @Override
    public Object deepMergeClone(Object rmiClone) {
        return mergeClone(rmiClone, MergeManager.CASCADE_ALL_PARTS, false);
    }

    /**
     * PUBLIC:
     * Revert the object's attributes from the parent.
     * This reverts everything the object references.
     *
     * @return the object reverted.
     * @see #revertObject(Object)
     * @see #shallowRevertObject(Object)
     */
    @Override
    public Object deepRevertObject(Object clone) {
        return revertObject(clone, MergeManager.CASCADE_ALL_PARTS);
    }

    /**
     * ADVANCED:
     * Unregister the object with the unit of work.
     * This can be used to delete an object that was just created and is not yet persistent.
     * Delete object can also be used, but will result in inserting the object and then deleting it.
     * The method should be used carefully because it will delete all the reachable parts.
     */
    @Override
    public void deepUnregisterObject(Object clone) {
        unregisterObject(clone, DescriptorIterator.CascadeAllParts);
    }

    /**
     * INTERNAL:
     * Search for any objects in the parent that have not been registered.
     * These are required so that the nested unit of work does not add them to the parent
     * clone mapping on commit, causing possible incorrect insertions if they are dereferenced.
     */
    protected void discoverAllUnregisteredNewObjects() {
        // 2612538 - the default size of Map (32) is appropriate
        Map visitedNodes = new IdentityHashMap();
        Map newObjects = new IdentityHashMap();

         // Bug 294259 -  Do not replace the existingObjects list
        // Iterate over the clones.
        discoverUnregisteredNewObjects(new IdentityHashMap(getCloneMapping()), newObjects, getUnregisteredExistingObjects(), visitedNodes);
        setUnregisteredNewObjects(newObjects);

    }

    /**
     * INTERNAL:
     * Search for any objects in the parent that have not been registered.
     * These are required so that the nested unit of work does not add them to the parent
     * clone mapping on commit, causing possible incorrect insertions if they are dereferenced.
     */
    protected void discoverAllUnregisteredNewObjectsInParent() {
        // Iterate over the clones.
        if (this.isNestedUnitOfWork) {
            // 2612538 - the default size of Map (32) is appropriate
            Map visitedNodes = new IdentityHashMap();
            Map newObjects = new IdentityHashMap();
            UnitOfWorkImpl parent = (UnitOfWorkImpl)this.parent;
            parent.discoverUnregisteredNewObjects(((UnitOfWorkImpl)this.parent).getCloneMapping(), newObjects, new IdentityHashMap(), visitedNodes);
            setUnregisteredNewObjectsInParent(newObjects);
        }
    }

    /**
     * INTERNAL:
     * Traverse the object to find references to objects not registered in this unit of work.
     */
    public void discoverUnregisteredNewObjects(Map clones, final Map knownNewObjects, final Map unregisteredExistingObjects, Map visitedObjects) {
        // This define an inner class for process the iteration operation, don't be scared, its just an inner class.
        DescriptorIterator iterator = new DescriptorIterator() {
            @Override
            public void iterate(Object object) {
                // If the object is read-only then do not continue the traversal.
                if (isClassReadOnly(object.getClass(), this.getCurrentDescriptor())) {
                    this.setShouldBreak(true);
                    return;
                }

                /* CR3440: Steven Vo
                 * Include the case that object is original then do nothing.
                 */
                if (isSmartMerge() && isOriginalNewObject(object)) {
                    return;
                } else if (!isObjectRegistered(object)) {// Don't need to check for aggregates, as iterator does not iterate on them by default.
                    if (shouldPerformNoValidation()) {
                        if (checkForUnregisteredExistingObject(object)) {
                            // If no validation is performed and the object exists we need
                            // To keep a record of this object to ignore it, also I need to
                            // Stop iterating over it.
                            unregisteredExistingObjects.put(object, object);
                            this.setShouldBreak(true);
                            return;
                        }
                    } else {
                        // This will validate that the object is not from the parent session, moved from calculate to optimize JPA.
                        getBackupClone(object, getCurrentDescriptor());
                    }
                    // This means it is a unregistered new object
                    knownNewObjects.put(object, object);
                }
            }

            @Override
            public void iterateReferenceObjectForMapping(Object referenceObject, DatabaseMapping mapping) {
                super.iterateReferenceObjectForMapping(referenceObject, mapping);
                if (mapping.isCandidateForPrivateOwnedRemoval()) {
                    removePrivateOwnedObject(mapping, referenceObject);
                }
            }
        };
        // Bug 294259 -  Do not replace the existingObjects list

        iterator.setVisitedObjects(visitedObjects);
        iterator.setResult(knownNewObjects);
        iterator.setSession(this);
        // When using wrapper policy in EJB the iteration should stop on beans,
        // this is because EJB forces beans to be registered anyway and clone identity can be violated
        // and the violated clones references to session objects should not be traversed.
        iterator.setShouldIterateOverWrappedObjects(false);

        for (Iterator clonesEnum = clones.keySet().iterator(); clonesEnum.hasNext(); ) {
            iterator.startIterationOn(clonesEnum.next());
        }
    }

    /**
     * ADVANCED:
     * The unit of work performs validations such as,
     * ensuring multiple copies of the same object don't exist in the same unit of work,
     * ensuring deleted objects are not referred after commit,
     * ensures that objects from the parent cache are not referred in the unit of work cache.
     * The level of validation can be increased or decreased for debugging purposes or under
     * advanced situation where the application requires/desires to violate clone identity in the unit of work.
     * It is strongly suggested that clone identity not be violate in the unit of work.
     */
    @Override
    public void dontPerformValidation() {
        setValidationLevel(None);
    }

    /**
     * INTERNAL:
     * Override From session.  Get the accessor based on the query, and execute call,
     * this is here for session broker.
     */
    @Override
    public Object executeCall(Call call, AbstractRecord translationRow, DatabaseQuery query) throws DatabaseException {
        Collection<Accessor> accessors = query.getSession().getAccessors(call, translationRow, query);
        query.setAccessors(accessors);
        try {
            return basicExecuteCall(call, translationRow, query);
        } finally {
            if (call.isFinished()) {
                query.setAccessor(null);
            }
        }
    }

    /**
     * ADVANCED:
     * Set optimistic read lock on the object.  This feature is override by normal optimistic lock.
     * when the object is changed in UnitOfWork. The cloneFromUOW must be the clone of from this
     * UnitOfWork and it must implements version locking or timestamp locking.
     * The SQL would look like the followings.
     *
     * If shouldModifyVersionField is true,
     * "UPDATE EMPLOYEE SET VERSION = 2 WHERE EMP_ID = 9 AND VERSION = 1"
     *
     * If shouldModifyVersionField is false,
     * "UPDATE EMPLOYEE SET VERSION = 1 WHERE EMP_ID = 9 AND VERSION = 1"
     */
    @Override
    public void forceUpdateToVersionField(Object lockObject, boolean shouldModifyVersionField) {
        ClassDescriptor descriptor = getDescriptor(lockObject);
        if (descriptor == null) {
            throw DescriptorException.missingDescriptor(lockObject.getClass().toString());
        }
        getOptimisticReadLockObjects().put(descriptor.getObjectBuilder().unwrapObject(lockObject, this), Boolean.valueOf(shouldModifyVersionField));
    }

    /**
     * INTERNAL:
     * The uow does not store a local accessor but shares its parents.
     */
    @Override
    public Accessor getAccessor() {
        return this.parent.getAccessor();
    }

    /**
     * INTERNAL:
     * The uow does not store a local accessor but shares its parents.
     */
    @Override
    public Collection<Accessor> getAccessors() {
        return this.parent.getAccessors();
    }

    /**
     * INTERNAL:
     * The commit manager is used to resolve referential integrity on commits of multiple objects.
     * The commit manage is lazy init from parent.
     */
    @Override
    public CommitManager getCommitManager() {
        // PERF: lazy init, not always required for release/commit with no changes.
        if (this.commitManager == null) {
            this.commitManager = new CommitManager(this);
            // Initialize the commit manager
            this.commitManager.setCommitOrder(this.parent.getCommitManager().getCommitOrder());
        }
        return this.commitManager;
    }

    /**
     * INTERNAL:
     * Return the connections to use for the query execution.
     */
    @Override
    public Collection<Accessor> getAccessors(Call call, AbstractRecord translationRow, DatabaseQuery query) {
        return this.parent.getAccessors(call, translationRow, query);
    }

    /**
     * PUBLIC:
     * Return the active unit of work for the current active external (JTS) transaction.
     * This should only be used with JTS and will return null if no external transaction exists.
     */
    @Override
    public org.eclipse.persistence.sessions.UnitOfWork getActiveUnitOfWork() {

        /* Steven Vo:  CR# 2517
           This fixed the problem of returning null when this method is called on a UOW.
           UOW does not copy the parent session's external transaction controller
           when it is acquired but session does  */
        return this.parent.getActiveUnitOfWork();
    }

    /**
     * INTERNAL:
     * Return any new objects matching the expression.
     * Used for in-memory querying.
     */
    public Vector getAllFromNewObjects(Expression selectionCriteria, Class theClass, AbstractRecord translationRow, int valueHolderPolicy) {
        // PERF: Avoid initialization of new objects if none.
        if (!hasNewObjects()) {
            return new Vector(1);
        }

        // bug 327900 - If don't read subclasses is set on the descriptor heed it.
        ClassDescriptor descriptor = getDescriptor(theClass);
        boolean readSubclassesOrNoInheritance = (!descriptor.hasInheritance() || descriptor.getInheritancePolicy().shouldReadSubclasses());

        Vector objects = new Vector();
        for (Iterator newObjectsEnum = getNewObjectsCloneToOriginal().keySet().iterator();
                 newObjectsEnum.hasNext();) {
            Object object = newObjectsEnum.next();
            // bug 327900
            if ((object.getClass() == theClass) || (readSubclassesOrNoInheritance && (theClass.isInstance(object)))) {
                if (selectionCriteria == null) {
                    objects.addElement(object);
                } else if (selectionCriteria.doesConform(object, this, translationRow, valueHolderPolicy)) {
                    objects.addElement(object);
                }
            }
        }
        return objects;
    }

    /**
     * INTERNAL:
     * Return the backup clone for the working clone.
     */
    public Object getBackupClone(Object clone) throws QueryException {
        return getBackupClone(clone, null);
    }

    /**
     * INTERNAL:
     * Return the backup clone for the working clone.
     */
    public Object getBackupClone(Object clone, ClassDescriptor descriptor) throws QueryException {
        Object backupClone = getCloneMapping().get(clone);
        if (backupClone != null) {
            return backupClone;
        }

        /* CR3440: Steven Vo
         * Smart merge if necessary in isObjectRegistered()
         */
        if (isObjectRegistered(clone)) {
            return getCloneMapping().get(clone);

        } else {
            if(descriptor == null) {
                descriptor = getDescriptor(clone);
            }
            Object primaryKey = keyFromObject(clone, descriptor);

            // This happens if clone was from the parent identity map.
            if (this.getParentIdentityMapSession(descriptor, false, true).getIdentityMapAccessorInstance().containsObjectInIdentityMap(primaryKey, clone.getClass(), descriptor)) {
                //cr 3796
                if ((getUnregisteredNewObjects().get(clone) != null) && isMergePending()) {
                    //Another thread has read the new object before it has had a chance to
                    //merge this object.
                    // It also means it is an unregistered new object, so create a new backup clone for it.
                    return descriptor.getObjectBuilder().buildNewInstance();
                }
                if (hasObjectsDeletedDuringCommit() && getObjectsDeletedDuringCommit().containsKey(clone)) {
                    throw QueryException.backupCloneIsDeleted(clone);
                }
                throw QueryException.backupCloneIsOriginalFromParent(clone);
            }
            // Also check that the object is not the original to a registered new object
            // (the original should not be referenced if not smart merge, this is an error.
            else if (hasNewObjects() && getNewObjectsOriginalToClone().containsKey(clone)) {

                /* CR3440: Steven Vo
                 * Check case that clone is original
                 */
                if (isSmartMerge()) {
                    backupClone = getCloneMapping().get(getNewObjectsOriginalToClone().get(clone));

                } else {
                    throw QueryException.backupCloneIsOriginalFromSelf(clone);
                }
            } else {
                // This means it is an unregistered new object, so create a new backup clone for it.
                backupClone = descriptor.getObjectBuilder().buildNewInstance();
            }
        }

        return backupClone;
    }

    /**
     * INTERNAL:
     * Return the backup clone for the working clone.
     */
    public Object getBackupCloneForCommit(Object clone, ClassDescriptor descriptor) {
        Object backupClone = getBackupClone(clone, descriptor);

        /* CR3440: Steven Vo
         * Build new instance only if it was not handled by getBackupClone()
         */
        if (isCloneNewObject(clone)) {
            if(descriptor != null) {
                return descriptor.getObjectBuilder().buildNewInstance();
            } else {
                // Can this ever happen?
                return getDescriptor(clone).getObjectBuilder().buildNewInstance();
            }
        }

        return backupClone;
    }

    /**
     * INTERNAL:
     * Return the backup clone for the working clone.
     */
    public Object getBackupCloneForCommit(Object clone) {
        Object backupClone = getBackupClone(clone);

        /* CR3440: Steven Vo
         * Build new instance only if it was not handled by getBackupClone()
         */
        if (isCloneNewObject(clone)) {
            return getDescriptor(clone).getObjectBuilder().buildNewInstance();
        }

        return backupClone;
    }


    /**
     * ADVANCED:
     * This method Will Calculate the changes for the UnitOfWork.  Without assigning sequence numbers
     * This is a computationally intensive operation and should be avoided unless necessary.
     * A valid changeSet, with sequencenumbers can be collected from the UnitOfWork after the commit
     * is complete by calling unitOfWork.getUnitOfWorkChangeSet()
     */
    @Override
    public org.eclipse.persistence.sessions.changesets.UnitOfWorkChangeSet getCurrentChanges() {
        Map allObjects = collectAndPrepareObjectsForNestedMerge();
        return calculateChanges(allObjects, new UnitOfWorkChangeSet(this), false, false);
    }

    /**
     * INTERNAL:
     * Returns the appropriate IdentityMap session for this descriptor.  Sessions can be
     * chained and each session can have its own Cache/IdentityMap.  Entities can be stored
     * at different levels based on Cache Isolation.  This method will return the correct Session
     * for a particular Entity class based on the Isolation Level and the attributes provided.
     *
     * @param canReturnSelf true when method calls itself.  If the path
     * starting at <code>this</code> is acceptable.  Sometimes true if want to
     * move to the first valid session, i.e. executing on ClientSession when really
     * should be on ServerSession.
     * @param terminalOnly return the last session in the chain where the Enitity is stored.
     * @return Session with the required IdentityMap
     */
    @Override
    public AbstractSession getParentIdentityMapSession(ClassDescriptor descriptor, boolean canReturnSelf, boolean terminalOnly) {
        if (canReturnSelf && !terminalOnly) {
            return this;
        } else {
            return this.parent.getParentIdentityMapSession(descriptor, true, terminalOnly);
        }
    }

    /**
     * INTERNAL:
     * Gets the session which this query will be executed on.
     * Generally will be called immediately before the call is translated,
     * which is immediately before session.executeCall.
     * <p>
     * Since the execution session also knows the correct datasource platform
     * to execute on, it is often used in the mappings where the platform is
     * needed for type conversion, or where calls are translated.
     * <p>
     * Is also the session with the accessor.  Will return a ClientSession if
     * it is in transaction and has a write connection.
     * @return a session with a live accessor
     * @param query may store session name or reference class for brokers case
     */
    @Override
    public AbstractSession getExecutionSession(DatabaseQuery query) {
        // This optimization is only for when executing with a ClientSession in
        // transaction.  In that case log with the UnitOfWork instead of the
        // ClientSession.
        // Note that if actually executing on ServerSession or a registered
        // session of a broker, must execute on that session directly.

        //bug 5201121 Always use the parent or execution session from the parent
        // should never use the unit of work as it does not control the
        //accessors and with a session broker it will not have the correct
        //login info
        return this.parent.getExecutionSession(query);
    }

    /**
     * INTERNAL:
     * Return the clone mapping.
     * The clone mapping contains clone of all registered objects,
     * this is required to store the original state of the objects when registered
     * so that only what is changed will be committed to the database and the parent,
     * (this is required to support parallel unit of work).
     */
    public Map getCloneMapping() {
        // PERF: lazy-init (3286089)
        if (cloneMapping == null) {
            // 2612538 - the default size of Map (32) is appropriate
            cloneMapping = createMap();
        }
        return cloneMapping;
    }

    /**
     * INTERNAL:
     * Return if the unit of work has any clones.
     */
    public boolean hasCloneMapping() {
        return ((cloneMapping != null) && !cloneMapping.isEmpty());
    }

    /**
     * INTERNAL:
     * Map used to avoid garbage collection in weak caches.
     * Also, map used as lookup when originals used for merge when original in
     * identitymap can not be found.  As in a CacheIdentityMap
     */
    public Map getCloneToOriginals() {
        if (cloneToOriginals == null) {// Must lazy initialize for remote.
            // 2612538 - the default size of Map (32) is appropriate
            cloneToOriginals = createMap();
        }
        return cloneToOriginals;
    }

    protected boolean hasCloneToOriginals() {
        return ((cloneToOriginals != null) && !cloneToOriginals.isEmpty());
    }

    /**
     * INTERNAL:
     * This is only used for EJB entity beans to manage beans accessed in a transaction context.
     */
    public Map getContainerBeans() {
        if (containerBeans == null) {
            containerBeans = new IdentityHashMap();
        }
        return containerBeans;
    }

    /**
     * INTERNAL:
     * Return if any container beans exist.
     * PERF: Used to avoid lazy initialization of getContainerBeans().
     */
    public boolean hasContainerBeans() {
        return ((containerBeans != null) && !containerBeans.isEmpty());
    }

    /**
     * INTERNAL:
     * Return any objects have been deleted through database cascade delete constraints.
     */
    public Set<Object> getCascadeDeleteObjects() {
        if (this.cascadeDeleteObjects == null) {
            this.cascadeDeleteObjects = new IdentityHashSet();
        }
        return this.cascadeDeleteObjects;
    }

    /**
     * INTERNAL:
     * Set any objects have been deleted through database cascade delete constraints.
     */
    protected void setCascadeDeleteObjects(Set<Object> cascadeDeleteObjects) {
        this.cascadeDeleteObjects = cascadeDeleteObjects;
    }

    /**
     * INTERNAL:
     * Return if any objects have been deleted through database cascade delete constraints.
     */
    public boolean hasCascadeDeleteObjects() {
        return ((this.cascadeDeleteObjects != null) && !this.cascadeDeleteObjects.isEmpty());
    }

    /**
     * INTERNAL:
     * Return if there are any unregistered new objects.
     * PERF: Used to avoid initialization of new objects map unless required.
     */
    public boolean hasUnregisteredNewObjects() {
        return ((this.unregisteredNewObjects != null) && !this.unregisteredNewObjects.isEmpty());
    }

    /**
     * INTERNAL:
     * Return if there are any registered new objects.
     * This is used for both newObjectsOriginalToClone and newObjectsCloneToOriginal as they are always in synch.
     * PERF: Used to avoid initialization of new objects map unless required.
     */
    public boolean hasNewObjects() {
        return ((newObjectsCloneToOriginal != null) && !newObjectsCloneToOriginal.isEmpty());
    }

    /**
     * INTERNAL:
     * This is only used for EJB entity beans to manage beans accessed in a transaction context.
     */
    public UnitOfWorkImpl getContainerUnitOfWork() {
        if (containerUnitOfWork == null) {
            containerUnitOfWork = this.parent.acquireNonSynchronizedUnitOfWork(ReferenceMode.WEAK);
        }
        return containerUnitOfWork;
    }

    /**
     * INTERNAL: Returns the set of read-only classes that gets assigned to each newly created UnitOfWork.
     *
     * @see org.eclipse.persistence.sessions.Project#setDefaultReadOnlyClasses(Collection)
     */
    @Override
    public Vector getDefaultReadOnlyClasses() {
        return this.parent.getDefaultReadOnlyClasses();
    }

    /**
     * INTERNAL:
     * The deleted objects stores any objects removed during the unit of work.
     * On commit they will all be removed from the database.
     */
    public Map getDeletedObjects() {
        if (deletedObjects == null) {
            // 2612538 - the default size of Map (32) is appropriate
            deletedObjects = new IdentityHashMap();
        }
        return deletedObjects;
    }

    /**
     * INTERNAL:
     * The deleted objects stores any objects removed during the unit of work.
     * On commit they will all be removed from the database.
     */
    public boolean hasDeletedObjects() {
        return ((deletedObjects != null) && !deletedObjects.isEmpty());
    }

    /**
     * INTERNAL:
     * The life cycle tracks if the unit of work is active and is used for JTS.
     */
    public int getLifecycle() {
        return lifecycle;
    }

    /**
     * A reference to the last used merge manager.  This is used to track locked
     * objects.
     */
    public MergeManager getMergeManager() {
        return this.lastUsedMergeManager;
    }

    /**
     * INTERNAL:
     * The map stores any new aggregates that have been cloned.
     */
    public Map getNewAggregates() {
        if (this.newAggregates == null) {
            // 2612538 - the default size of Map (32) is appropriate
            this.newAggregates = new IdentityHashMap();
        }
        return newAggregates;
    }

    /**
     * INTERNAL:
     * The new objects stores any objects newly created during the unit of work.
     * On commit they will all be inserted into the database.
     */
    public Map getNewObjectsCloneToOriginal() {
        if (newObjectsCloneToOriginal == null) {
            // 2612538 - the default size of Map (32) is appropriate
            newObjectsCloneToOriginal = new IdentityHashMap();
        }
        return newObjectsCloneToOriginal;
    }

    /**
     * INTERNAL:
     * The stores a map from new object clones to the original object used from merge.
     */
    public Map getNewObjectsCloneToMergeOriginal() {
        if (newObjectsCloneToMergeOriginal == null) {
            newObjectsCloneToMergeOriginal = new IdentityHashMap();
        }
        return newObjectsCloneToMergeOriginal;
    }

    /**
     * INTERNAL:
     * The returns the list that will hold the new objects from the Parent UnitOfWork
     */
    public Map getNewObjectsInParentOriginalToClone() {
        // PERF: lazy-init (3286089)
        if (newObjectsInParentOriginalToClone == null) {
            // 2612538 - the default size of Map (32) is appropriate
            newObjectsInParentOriginalToClone = new IdentityHashMap();
        }
        return newObjectsInParentOriginalToClone;
    }

    protected boolean hasNewObjectsInParentOriginalToClone() {
        return ((newObjectsInParentOriginalToClone != null) && !newObjectsInParentOriginalToClone.isEmpty());
    }

    /**
     * INTERNAL:
     * Return the privateOwnedRelationships attribute.
     */
    private Map<DatabaseMapping, Set> getPrivateOwnedObjects() {
        if (privateOwnedObjects == null) {
            privateOwnedObjects = new IdentityHashMap<>();
        }
        return privateOwnedObjects;
    }

    /**
     * INTERNAL:
     * Return true if privateOwnedObjects is not null and not empty, false otherwise.
     */
    public boolean hasPrivateOwnedObjects() {
        return privateOwnedObjects != null && !privateOwnedObjects.isEmpty();
    }

    /**
     * INTERNAL:
     * Return if there are any optimistic read locks.
     */
    public boolean hasOptimisticReadLockObjects() {
        return ((optimisticReadLockObjects != null) && !optimisticReadLockObjects.isEmpty());
    }

    /**
     * INTERNAL:
     * The new objects stores any objects newly created during the unit of work.
     * On commit they will all be inserted into the database.
     */
    public Map getNewObjectsOriginalToClone() {
        if (newObjectsOriginalToClone == null) {
            // 2612538 - the default size of Map (32) is appropriate
            newObjectsOriginalToClone = new IdentityHashMap();
        }
        return newObjectsOriginalToClone;
    }

    /**
     * INTERNAL:
     * Return the Sequencing object used by the session.
     */
    @Override
    public Sequencing getSequencing() {
        return this.parent.getSequencing();
    }

    /**
     * INTERNAL:
     * Marked internal as this is not customer API but helper methods for
     * accessing the server platform from within EclipseLink's other sessions types
     * (i.e. not DatabaseSession)
     */
    @Override
    public ServerPlatform getServerPlatform() {
        return this.parent.getServerPlatform();
    }

    /**
     * INTERNAL:
     * Returns the type of session, its class.
     * <p>
     * Override to hide from the user when they are using an internal subclass
     * of a known class.
     * <p>
     * A user does not need to know that their UnitOfWork is a
     * non-deferred UnitOfWork, or that their ClientSession is an
     * IsolatedClientSession.
     */
    @Override
    public String getSessionTypeString() {
        return "UnitOfWork";
    }

    /**
     * INTERNAL:
     * Called after external transaction rolled back.
     */
    public void afterExternalTransactionRollback() {
        // In case jts transaction was internally started but rolled back
        // directly by TransactionManager this flag may still be true during afterCompletion
        this.parent.setWasJTSTransactionInternallyStarted(false);
        //bug#4699614 -- added a new life cycle status so we know if the external transaction was rolledback and we don't try to rollback again later
        setLifecycle(AfterExternalTransactionRolledBack);

        if ((getMergeManager() != null) && (getMergeManager().getAcquiredLocks() != null) && (!getMergeManager().getAcquiredLocks().isEmpty())) {
            // 272022: If the current thread and the active thread on the mutex do not match - switch them
            verifyMutexThreadIntegrityBeforeRelease();
            //may have unreleased cache locks because of a rollback...
            this.parent.getIdentityMapAccessorInstance().getWriteLockManager().releaseAllAcquiredLocks(getMergeManager());
            this.setMergeManager(null);
        }
    }

    /**
     * INTERNAL:
     * Called in the end of beforeCompletion of external transaction synchronization listener.
     * Close the managed sql connection corresponding to the external transaction.
     */
    @Override
    public void releaseJTSConnection() {
        this.parent.releaseJTSConnection();
    }

    /**
     * INTERNAL:
     * Return any new object matching the expression.
     * Used for in-memory querying.
     */
    public Object getObjectFromNewObjects(Class theClass, Object selectionKey) {
        // PERF: Avoid initialization of new objects if none.
        if (!hasNewObjects()) {
            return null;
        }

        // bug 327900 - If don't read subclasses is set on the descriptor heed it.
        ClassDescriptor descriptor = getDescriptor(theClass);
        boolean readSubclassesOrNoInheritance = (!descriptor.hasInheritance() || descriptor.getInheritancePolicy().shouldReadSubclasses());

        ObjectBuilder objectBuilder = descriptor.getObjectBuilder();
        for (Iterator newObjectsEnum = getNewObjectsCloneToOriginal().keySet().iterator();
                 newObjectsEnum.hasNext();) {
            Object object = newObjectsEnum.next();
            // bug 327900
            if ((object.getClass() == theClass) || (readSubclassesOrNoInheritance && (theClass.isInstance(object)))) {
                Object primaryKey = objectBuilder.extractPrimaryKeyFromObject(object, this, true);
                if ((primaryKey != null) && primaryKey.equals(selectionKey)) {
                    return object;
                }
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     * Return any new object matching the expression.
     * Used for in-memory querying.
     */
    public Object getObjectFromNewObjects(Expression selectionCriteria, Class theClass, AbstractRecord translationRow, int valueHolderPolicy) {
        // PERF: Avoid initialization of new objects if none.
        if (!hasNewObjects()) {
            return null;
        }

        // bug 327900 - If don't read subclasses is set on the descriptor heed it.
        ClassDescriptor descriptor = getDescriptor(theClass);
        boolean readSubclassesOrNoInheritance = (!descriptor.hasInheritance() || descriptor.getInheritancePolicy().shouldReadSubclasses());

        for (Object object : getNewObjectsCloneToOriginal().keySet()) {
            // bug 327900
            if ((object.getClass() == theClass) || (readSubclassesOrNoInheritance && (theClass.isInstance(object)))) {
                if (selectionCriteria == null) {
                    return object;
                }
                if (selectionCriteria.doesConform(object, this, translationRow, valueHolderPolicy)) {
                    return object;
                }
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     * Returns all the objects which are deleted during root commit of unit of work.
     */
    public Map getObjectsDeletedDuringCommit() {
        // PERF: lazy-init (3286089)
        if (objectsDeletedDuringCommit == null) {
            // 2612538 - the default size of Map (32) is appropriate
            objectsDeletedDuringCommit = new IdentityHashMap();
        }
        return objectsDeletedDuringCommit;
    }

    protected boolean hasObjectsDeletedDuringCommit() {
        return ((objectsDeletedDuringCommit != null) && !objectsDeletedDuringCommit.isEmpty());
    }

    /**
     * INTERNAL:
     * Return optimistic read lock objects
     */
    public Map getOptimisticReadLockObjects() {
        if (this.optimisticReadLockObjects == null) {
            this.optimisticReadLockObjects = new HashMap(2);
        }
        return this.optimisticReadLockObjects;
    }

    /**
     * INTERNAL:
     * Return the original version of the new object (working clone).
     */
    public Object getOriginalVersionOfNewObject(Object workingClone) {
        // PERF: Avoid initialization of new objects if none.
        if (!hasNewObjects()) {
            return null;
        }
        return getNewObjectsCloneToOriginal().get(workingClone);
    }

    /**
     * ADVANCED:
     * Return the original version of the object(clone) from the parent's identity map.
     */
    @Override
    public Object getOriginalVersionOfObject(Object workingClone) {
        // Can be null when called from the mappings.
        if (workingClone == null) {
            return null;
        }
        Object original = null;
        ClassDescriptor descriptor = getDescriptor(workingClone);
        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object implementation = builder.unwrapObject(workingClone, this);
        CacheKey cacheKey = getParentIdentityMapSession(descriptor, false, false).getCacheKeyFromTargetSessionForMerge(implementation, builder, descriptor, lastUsedMergeManager);
        if (cacheKey != null){
            original = cacheKey.getObject();
        }
        if (original == null) {
            // Check if it is a registered new object.
            original = getOriginalVersionOfNewObject(implementation);
        }

        if (original == null) {
            // For bug 3013948 looking in the cloneToOriginals mapping will not help
            // if the object was never registered.
            if (isClassReadOnly(implementation.getClass(), descriptor)) {
                return implementation;
            }

            // The object could have been removed from the cache even though it was in the unit of work.
            // fix for 2.5.1.3 PWK (1360)
            if (hasCloneToOriginals()) {
                original = getCloneToOriginals().get(workingClone);
            }
        }

        if (original == null) {
            // This means that it must be an unregistered new object, so register a new clone as its original.
            original = buildOriginal(implementation);
        }

        return original;
    }

    /**
     * INTERNAL:
     * Return the original version of the object(clone) from the parent's identity map.
     * PERF: Use the change set to avoid cache lookups.
     */
    public Object getOriginalVersionOfObjectOrNull(Object workingClone, ObjectChangeSet changeSet, ClassDescriptor descriptor, AbstractSession targetSession) {
        // Can be null when called from the mappings.
        if (workingClone == null) {
            return null;
        }

        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object implementation = builder.unwrapObject(workingClone, this);
        Object original = getOriginalVersionOfNewObject(implementation);

        if (original == null) {
            // For bug 3013948 looking in the cloneToOriginals mapping will not help
            // if the object was never registered.
            if (isClassReadOnly(implementation.getClass(), descriptor)) {
                return implementation;
            }

            // The object could have been removed from the cache even though it was in the unit of work.
            // fix for 2.5.1.3 PWK (1360)
            if (hasCloneToOriginals()) {
                original = getCloneToOriginals().get(workingClone);
            }
        }
        return original;
    }

    /**
     * INTERNAL:
     * Return the original version of the object(clone) from the parent's identity map.
     */
    public Object getOriginalVersionOfObjectOrNull(Object workingClone, ClassDescriptor descriptor) {
        // Can be null when called from the mappings.
        if (workingClone == null) {
            return null;
        }
        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object implementation = builder.unwrapObject(workingClone, this);

        Object primaryKey = builder.extractPrimaryKeyFromObject(implementation, this);
        // there's no need to elaborately avoid the readlock like the other getOriginalVersionOfObjectOrNull
        // method as this one is not used during the commit cycle
        Object original = this.parent.getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, implementation.getClass(), descriptor);

        if (original == null) {
            // Check if it is a registered new object.
            original = getOriginalVersionOfNewObject(implementation);
        }

        if (original == null) {
            // For bug 3013948 looking in the cloneToOriginals mapping will not help
            // if the object was never registered.
            if (isClassReadOnly(implementation.getClass(), descriptor)) {
                return implementation;
            }

            // The object could have been removed from the cache even though it was in the unit of work.
            // fix for 2.5.1.3 PWK (1360)
            if (hasCloneToOriginals()) {
                original = getCloneToOriginals().get(workingClone);
            }
        }
        return original;
    }

    /**
     * PUBLIC:
     * Return the parent.
     * This is a unit of work if nested, otherwise a database session or client session.
     */
    @Override
    public AbstractSession getParent() {
        return parent;
    }

    /**
     * INTERNAL:
     * Search for and return the user defined property from this UOW, if it not found then search for the property
     * from parent.
     */
    @Override
    public Object getProperty(String name){
        Object propertyValue = super.getProperties().get(name);
        if (propertyValue == null) {
           propertyValue = this.parent.getProperty(name);
        }
        return propertyValue;
    }

    /**
     * INTERNAL:
     * Return the platform for a particular class.
     */
    @Override
    public Platform getPlatform(Class domainClass) {
        return this.parent.getPlatform(domainClass);
    }

    /**
     * INTERNAL:
     * Return whether to throw exceptions on conforming queries
     */
    public int getShouldThrowConformExceptions() {
        return shouldThrowConformExceptions;
    }

    /**
     * PUBLIC:
     * Return the query from the session pre-defined queries with the given name.
     * This allows for common queries to be pre-defined, reused and executed by name.
     */
    @Override
    public DatabaseQuery getQuery(String name, Vector arguments) {
        DatabaseQuery query = super.getQuery(name, arguments);
        if (query == null) {
            query = this.parent.getQuery(name, arguments);
        }

        return query;
    }

    /**
     * PUBLIC:
     * Return the query from the session pre-defined queries with the given name.
     * This allows for common queries to be pre-defined, reused and executed by name.
     */
    @Override
    public DatabaseQuery getQuery(String name) {
        DatabaseQuery query = super.getQuery(name);
        if (query == null) {
            query = this.parent.getQuery(name);
        }

        return query;
    }

    /**
     * ADVANCED:
     * Returns the set of read-only classes in this UnitOfWork.
     */
    @Override
    public Set getReadOnlyClasses() {
        if (this.readOnlyClasses == null) {
            this.readOnlyClasses = new HashSet();
        }
        return this.readOnlyClasses;
    }

    /**
     * INTERNAL:
     * The removed objects stores any newly registered objects removed during the nested unit of work.
     * On commit they will all be removed from the parent unit of work.
     */
    protected Map getRemovedObjects() {
        // PERF: lazy-init (3286089)
        if (removedObjects == null) {
            // 2612538 - the default size of Map (32) is appropriate
            removedObjects = new IdentityHashMap();
        }
        return removedObjects;
    }

    protected boolean hasRemovedObjects() {
        return ((removedObjects != null) && !removedObjects.isEmpty());
    }

    protected boolean hasModifyAllQueries() {
        return ((modifyAllQueries != null) && !modifyAllQueries.isEmpty());
    }

    protected boolean hasDeferredModifyAllQueries() {
        return ((deferredModifyAllQueries != null) && !deferredModifyAllQueries.isEmpty());
    }

    /**
     * INTERNAL:
     * Find out what the lifecycle state of this UoW is in.
     */
    public int getState() {
        return lifecycle;
    }

    /**
     * INTERNAL:
     * PERF: Return the associated external transaction.
     * Used to optimize activeUnitOfWork lookup.
     */
    public Object getTransaction() {
        return transaction;
    }

    /**
     * INTERNAL:
     * PERF: Set the associated external transaction.
     * Used to optimize activeUnitOfWork lookup.
     */
    public void setTransaction(Object transaction) {
        this.transaction = transaction;
    }

    /**
     * ADVANCED:
     * Returns the currentChangeSet from the UnitOfWork.
     * This is only valid after the UnitOfWOrk has committed successfully
     */
    @Override
    public org.eclipse.persistence.sessions.changesets.UnitOfWorkChangeSet getUnitOfWorkChangeSet() {
        return unitOfWorkChangeSet;
    }

    /**
     * INTERNAL:
     * Used to lazy Initialize the unregistered existing Objects collection.
     * @return Map
     */
    public Map getUnregisteredExistingObjects() {
        if (this.unregisteredExistingObjects == null) {
            // 2612538 - the default size of Map (32) is appropriate
            this.unregisteredExistingObjects = new IdentityHashMap();
        }
        return unregisteredExistingObjects;
    }

    /**
     * INTERNAL:
     * This is used to store unregistered objects discovered in the parent so that the child
     * unit of work knows not to register them on commit.
     */
    protected Map getUnregisteredNewObjects() {
        if (unregisteredNewObjects == null) {
            // 2612538 - the default size of Map (32) is appropriate
            unregisteredNewObjects = new IdentityHashMap();
        }
        return unregisteredNewObjects;
    }

    /**
     * INTERNAL:
     * This is used to store unregistered objects discovered in the parent so that the child
     * unit of work knows not to register them on commit.
     */
    protected Map getUnregisteredNewObjectsInParent() {
        if (unregisteredNewObjectsInParent == null) {
            // 2612538 - the default size of Map (32) is appropriate
            unregisteredNewObjectsInParent = new IdentityHashMap();
        }
        return unregisteredNewObjectsInParent;
    }

    /**
     * ADVANCED:
     * The unit of work performs validations such as,
     * ensuring multiple copies of the same object don't exist in the same unit of work,
     * ensuring deleted objects are not referred after commit,
     * ensures that objects from the parent cache are not referred in the unit of work cache.
     * The level of validation can be increased or decreased for debugging purposes or under
     * advanced situation where the application requires/desires to violate clone identity in the unit of work.
     * It is strongly suggested that clone identity not be violate in the unit of work.
     */
    @Override
    public int getValidationLevel() {
        return validationLevel;
    }

    /**
     * ADVANCED:
     * The Unit of work is capable of preprocessing to determine if any on the clone have been changed.
     * This is computationally expensive and should be avoided on large object graphs.
     */
    @Override
    public boolean hasChanges() {
        if (hasNewObjects()) {
            return true;
        }
        if (hasDeletedObjects()) {
            return true;
        }
        Map allObjects = new IdentityHashMap(getCloneMapping());
        UnitOfWorkChangeSet changeSet = calculateChanges(allObjects, new UnitOfWorkChangeSet(this), false, false);
        return changeSet.hasChanges();
    }

    /**
     * INTERNAL:
     * Does this unit of work have any changes or anything that requires a write
     * to the database and a transaction to be started.
     * Should be called after changes are calculated internally by commit.
     * <p>
     * Note if a transaction was begun prematurely it still needs to be committed.
     */
    protected boolean hasModifications() {
        if (((this.unitOfWorkChangeSet != null) && (this.unitOfWorkChangeSet.hasChanges() || ((org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet)getUnitOfWorkChangeSet()).hasForcedChanges()))
                || hasDeletedObjects() || hasModifyAllQueries() || hasDeferredModifyAllQueries()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * INTERNAL:
     * Set up the IdentityMapManager.  This method allows subclasses of Session to override
     * the default IdentityMapManager functionality.
     */
    @Override
    public void initializeIdentityMapAccessor() {
        this.identityMapAccessor = new UnitOfWorkIdentityMapAccessor(this, new IdentityMapManager(this));
    }

    /**
     * INTERNAL:
     * Return the results from executing the database query.
     * the arguments should be a database row with raw data values.
     */
    @Override
    public Object internalExecuteQuery(DatabaseQuery query, AbstractRecord databaseRow) throws DatabaseException, QueryException {
        if (project.allowExtendedThreadLogging()) {
            Thread currentThread = Thread.currentThread();
            if (this.CREATION_THREAD_HASHCODE != currentThread.hashCode()) {
                log(SessionLog.SEVERE, SessionLog.THREAD, "unit_of_work_thread_info", new Object[]{this.getName(),
                        this.CREATION_THREAD_ID, this.CREATION_THREAD_NAME,
                        currentThread.getId(), currentThread.getName()});
                if (project.allowExtendedThreadLoggingThreadDump()) {
                    log(SessionLog.SEVERE, SessionLog.THREAD, "unit_of_work_thread_info_thread_dump", new Object[]{
                            this.CREATION_THREAD_ID, this.CREATION_THREAD_NAME, this.creationThreadStackTrace,
                            currentThread.getId(), currentThread.getName(), ConcurrencyUtil.SINGLETON.enrichGenerateThreadDumpForCurrentThread()});
                }
            }
        }
        Object result = query.executeInUnitOfWork(this, databaseRow);
        executeDeferredEvents();
        return result;
    }

    /**
     * INTERNAL:
     * Register the object with the unit of work.
     * This does not perform wrapping or unwrapping.
     * This is used for internal registration in the merge manager.
     */
    public Object internalRegisterObject(Object object, ClassDescriptor descriptor, boolean isShallowClone) {
        if (object == null) {
            return null;
        }
        if (descriptor.isDescriptorTypeAggregate()) {
            throw ValidationException.cannotRegisterAggregateObjectInUnitOfWork(object.getClass());
        }
        Object registeredObject = checkIfAlreadyRegistered(object, descriptor);
        if (registeredObject == null) {
            // Nested units of work are special because the parent can be used to determine if the object exists
            // in most case and new object may be in the cache in the parent.
            if (this.isNestedUnitOfWork) {
                UnitOfWorkImpl parentUnitOfWork = (UnitOfWorkImpl)this.parent;

                // If it is not registered in the parent we must go through the existence check.
                if (parentUnitOfWork.isObjectRegistered(object) || isUnregisteredNewObjectInParent(object)) {
                    Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, this);
                    if (this.isCloneNewObjectFromParent(object) || isUnregisteredNewObjectInParent(object)) {
                        // Since it is a new object a new cache-key can be used for both parent and child as not put into the cache.
                        registeredObject = cloneAndRegisterObject(object, new CacheKey(primaryKey), new CacheKey(primaryKey), descriptor);
                    } else {
                        registeredObject = getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, descriptor.getJavaClass(), descriptor);
                    }
                    return registeredObject;
                }
            }
            registeredObject = checkExistence(object);
            if (registeredObject == null) {
                // This means that the object is not in the parent im, so was created under this unit of work.
                // This means that it must be new.
                registeredObject = cloneAndRegisterNewObject(object, isShallowClone);
                if (mergeManagerForActiveMerge != null) {
                    mergeManagerForActiveMerge.getMergedNewObjects().put(registeredObject, registeredObject);
                }
            }
        }

        return registeredObject;
    }

    /**
     * PUBLIC:
     * Return if the unit of work is active. (i.e. has not been released).
     */
    @Override
    public boolean isActive() {
        return this.lifecycle != Death;
    }

    /**
     * INTERNAL:
     * Checks to see if the specified class or descriptor is read-only or not in this UnitOfWork.
     * @return boolean, true if the class is read-only, false otherwise.
     */
    @Override
    public boolean isClassReadOnly(Class theClass, ClassDescriptor descriptor) {
        if ((descriptor != null) && (descriptor.shouldBeReadOnly())) {
            return true;
        }
        if ((theClass != null) && (this.readOnlyClasses != null) && this.readOnlyClasses.contains(theClass)) {
            return true;
        }
        return false;
    }

    /**
     * INTERNAL:
     * Check if the object is already registered in a parent Unit Of Work
     */
    public boolean isCloneNewObjectFromParent(Object clone) {
        if (this.parent.isUnitOfWork()) {
            if (((UnitOfWorkImpl)this.parent).isCloneNewObject(clone)) {
                return true;
            } else {
                if (((UnitOfWorkImpl)this.parent).isObjectRegistered(clone)) {
                    clone = ((UnitOfWorkImpl)this.parent).getCloneToOriginals().get(clone);
                }
                return ((UnitOfWorkImpl)this.parent).isCloneNewObjectFromParent(clone);
            }
        } else {
            return false;
        }
    }

    /**
     * INTERNAL:
     * Check if the object is already registered.
     */
    public boolean isCloneNewObject(Object clone) {
        return (this.newObjectsCloneToOriginal != null) && this.newObjectsCloneToOriginal.containsKey(clone);
    }

    /**
     * INTERNAL:
     * Return if the unit of work is waiting to be committed or in the process of being committed.
     */
    public boolean isCommitPending() {
        return this.lifecycle == CommitPending;
    }

    /**
     * INTERNAL:
     * Return if the unit of work is dead.
     */
    public boolean isDead() {
        return this.lifecycle == Death;
    }

    /**
     * PUBLIC:
     * Return whether the session currently has a database transaction in progress.
     */
    @Override
    public boolean isInTransaction() {
        return this.parent.isInTransaction();
    }

    /**
     * INTERNAL:
     * Return if the unit of work is waiting to be merged or in the process of being merged.
     */
    public boolean isMergePending() {
        return this.lifecycle == MergePending;
    }

    /**
     * INTERNAL:
     * Has writeChanges() been attempted on this UnitOfWork?  It may have
     * either succeeded or failed but either way the UnitOfWork is in a highly
     * restricted state.
     */
    public boolean isAfterWriteChangesButBeforeCommit() {
        return ((this.lifecycle == CommitTransactionPending) || (this.lifecycle == WriteChangesFailed));
    }

    /**
     * INTERNAL:
     * Once writeChanges has failed all a user can do really is rollback.
     */
    protected boolean isAfterWriteChangesFailed() {
        return this.lifecycle == WriteChangesFailed;
    }

    /**
     * PUBLIC:
     * Return whether this session is a nested unit of work or not.
     */
    @Override
    public boolean isNestedUnitOfWork() {
        return isNestedUnitOfWork;
    }

    /**
     * INTERNAL:
     * This method determines if the specified clone is new in the parent UnitOfWork
     */
    public boolean isNewObjectInParent(Object clone) {
        Object original = null;
        if (hasCloneToOriginals()) {
            original = getCloneToOriginals().get(clone);
        }
        if (original != null) {
            //bug 3115160 as a side this method was fixed to perform the correct lookup on the collection
            return ((UnitOfWorkImpl)this.parent).getNewObjectsCloneToOriginal().containsKey(original);
        }
        return false;
    }

    /**
     * INTERNAL:
     * Return if the object has been deleted in this unit of work.
     */
    public boolean isObjectDeleted(Object object) {
        boolean isDeleted = (this.deletedObjects != null) && this.deletedObjects.containsKey(object);

        if (this.parent.isUnitOfWork()) {
            return isDeleted || ((UnitOfWorkImpl)this.parent).isObjectDeleted(object);
        } else {
            return isDeleted;
        }
    }

    /**
     * INTERNAL:
     * This method is used to determine if the clone is a new Object in the UnitOfWork
     */
    public boolean isObjectNew(Object clone) {
        //CR3678 - ported from 4.0
        return (isCloneNewObject(clone) || (!isObjectRegistered(clone) && !isClassReadOnly(clone.getClass()) && !isUnregisteredExistingObject(clone)));
    }

    /**
     * INTERNAL:
     * Return if the object is a known unregistered existing object.
     */
    public boolean isUnregisteredExistingObject(Object object) {
        return (this.unregisteredExistingObjects != null) && this.unregisteredExistingObjects.containsKey(object);
    }

    /**
     * ADVANCED:
     * Return whether the clone object is already registered.
     */
    @Override
    public boolean isObjectRegistered(Object clone) {
        if (getCloneMapping().containsKey(clone)) {
            return true;
        }

        // We do smart merge here
        if (isSmartMerge()){
            ClassDescriptor descriptor = getDescriptor(clone);
            if (this.parent.getIdentityMapAccessorInstance().containsObjectInIdentityMap(keyFromObject(clone, descriptor), clone.getClass(), descriptor) ) {
                mergeCloneWithReferences(clone);

                // don't put clone in  clone mapping since it would result in duplicate clone
                return true;
            }
        }
        return false;
    }

    /**
     * INTERNAL:
     * Return whether the original object is new.
     * It was either registered as new or discovered as a new aggregate
     * within another new object.
     */
    public boolean isOriginalNewObject(Object original) {
        return ((this.newObjectsOriginalToClone != null) && this.newObjectsOriginalToClone.containsKey(original))
                    || ((this.newAggregates != null) && this.newAggregates.containsKey(original));
    }

/**
     * INTERNAL:
     * Return the status of smart merge
     */
    public static boolean isSmartMerge() {
        return SmartMerge;
    }

    /**
     * INTERNAL:
     * For synchronized units of work, dump SQL to database.
     * For cases where writes occur before the end of the transaction don't commit
     */
    public void issueSQLbeforeCompletion() {
        issueSQLbeforeCompletion(true);
    }
    /**
     * INTERNAL:
     * For synchronized units of work, dump SQL to database.
     * For cases where writes occur before the end of the transaction don't commit
     */
    public void issueSQLbeforeCompletion(boolean commitTransaction) {
        if (this.lifecycle == CommitTransactionPending) {
            commitTransactionAfterWriteChanges();
            return;
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "begin_unit_of_work_commit");
        mergeBmpAndWsEntities();
        // CR#... call event and log.
        if (this.eventManager != null) {
            this.eventManager.preCommitUnitOfWork();
        }
        this.lifecycle = CommitPending;
        commitToDatabaseWithChangeSet(commitTransaction);
    }

    /**
     * INTERNAL:
     * Will notify all the deferred ModifyAllQuery's (excluding UpdateAllQuery's) and deferred UpdateAllQuery's to execute.
     */
    protected void issueModifyAllQueryList() {
        if (this.deferredModifyAllQueries != null) {
            int size = this.deferredModifyAllQueries.size();
            for (int index = 0; index < size; index++) {
                Object[] queries = this.deferredModifyAllQueries.get(index);
                ModifyAllQuery query = (ModifyAllQuery)queries[0];
                AbstractRecord translationRow = (AbstractRecord)queries[1];
                this.parent.executeQuery(query, translationRow);
            }
        }
    }

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

    /**
     * INTERNAL:
     * Return if the object was existing but not registered in the parent of the nested unit of work.
     */
    public boolean isUnregisteredNewObjectInParent(Object originalObject) {
        return getUnregisteredNewObjectsInParent().containsKey(originalObject);
    }

    /**
     * INTERNAL:
     * BMP and Websphere CMP entities have to be merged if they are registered in the unit of work.
     * Check to see if there are any such entities and do the merge if required.
     */
    protected void mergeBmpAndWsEntities() {
        // Check for container registered beans that need to be merged.
        // This is required for EJB entity beans.
        // PERF: First check if there are any.
        if (hasContainerBeans()) {
            Iterator containerBeansEnum = getContainerBeans().keySet().iterator();
            while (containerBeansEnum.hasNext()) {
                mergeCloneWithReferences(containerBeansEnum.next());
            }
        }
    }

    /**
     * INTERNAL: Merge the changes to all objects to the parent.
     */
    protected void mergeChangesIntoParent() {
        UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet)getUnitOfWorkChangeSet();
        if (uowChangeSet == null) {
            // No changes.
            return;
        }

        // 3286123 - if no work to be done, skip this part of uow.commit()
        if (!hasModifications()) {
            return;
        }

        boolean isNestedUnitOfWork = this.isNestedUnitOfWork;

        // If everything is isolated, can bypass merge entirely.
        if (!isNestedUnitOfWork && (!this.project.hasNonIsolatedUOWClasses() && (this.modifyAllQueries == null))) {
            return;
        }

        setPendingMerge();
        startOperationProfile(SessionProfiler.Merge);
        // Ensure concurrency if cache isolation requires.
        this.parent.getIdentityMapAccessorInstance().acquireWriteLock();
        MergeManager manager = getMergeManager();
        if (manager == null) {
            // no MergeManager created for locks during commit
            manager = new MergeManager(this);
        }
        try {
            if (!isNestedUnitOfWork) {
                preMergeChanges();
            }

            // Must clone the clone mapping because entries can be added to it during the merging,
            // and that can lead to concurrency problems.if (this.eventManager != null) {
            if (this.parent.hasEventManager()) {
                this.parent.getEventManager().preMergeUnitOfWorkChangeSet(uowChangeSet);
            }
            if (!isNestedUnitOfWork && getDatasourceLogin().shouldSynchronizeObjectLevelReadWrite()) {
                // Note shouldSynchronizeObjectLevelReadWrite is not the default, shouldSynchronizeObjectLevelReadWriteDatabase
                // is the default, and locks are normally acquire before the commit transaction.
                setMergeManager(manager);
                //If we are merging into the shared cache acquire all required locks before merging.
                this.parent.getIdentityMapAccessorInstance().getWriteLockManager().acquireRequiredLocks(getMergeManager(), (UnitOfWorkChangeSet)getUnitOfWorkChangeSet());
            }
            Set<Class> classesChanged = new HashSet<>();
            if (! shouldStoreBypassCache()) {
                for (Map<ObjectChangeSet, ObjectChangeSet> objectChangesList : ((UnitOfWorkChangeSet)getUnitOfWorkChangeSet()).getObjectChanges().values()) {
                    // May be no changes for that class type.
                    for (ObjectChangeSet changeSetToWrite : objectChangesList.values()) {
                        if (changeSetToWrite.hasChanges()) {
                            Object objectToWrite = changeSetToWrite.getUnitOfWorkClone();
                            ClassDescriptor descriptor = changeSetToWrite.getDescriptor();
                            // PERF: Do not merge into the session cache if set to unit of work isolated.
                            if ((!isNestedUnitOfWork) && descriptor.getCachePolicy().shouldIsolateObjectsInUnitOfWork() ) {
                                break;
                            }
                            manager.mergeChanges(objectToWrite, changeSetToWrite, this.getParentIdentityMapSession(descriptor, false, false));
                            classesChanged.add(objectToWrite.getClass());
                        }
                    }
                }
            }

            // Notify the queries to merge into the shared cache
            if (this.modifyAllQueries != null) {
                int size = this.modifyAllQueries.size();
                for (int index = 0; index < size; index++) {
                    ModifyAllQuery query = this.modifyAllQueries.get(index);
                    query.setSession(this.parent);// ensure the query knows which cache to update
                    query.mergeChangesIntoSharedCache();
                }
            }

            if (isNestedUnitOfWork) {
                for (Map<ObjectChangeSet, ObjectChangeSet> objectChangesList : ((UnitOfWorkChangeSet)getUnitOfWorkChangeSet()).getNewObjectChangeSets().values()) {
                    for (ObjectChangeSet changeSetToWrite : objectChangesList.values()) {
                        if (changeSetToWrite.hasChanges()) {
                            Object objectToWrite = changeSetToWrite.getUnitOfWorkClone();
                            manager.mergeChanges(objectToWrite, changeSetToWrite, this.parent);
                        }
                    }
                }
            }
            if (!isNestedUnitOfWork) {
                //If we are merging into the shared cache release all of the locks that we acquired.
                // We will not check If the current thread and the active thread on the mutex do not match
                this.parent.getIdentityMapAccessorInstance().getWriteLockManager().releaseAllAcquiredLocks(manager);
                setMergeManager(null);

                postMergeChanges(classesChanged);

                for (Class changedClass : classesChanged) {
                    this.parent.getIdentityMapAccessorInstance().invalidateQueryCache(changedClass);
                }
                // If change propagation enabled through RemoteCommandManager then go for it
                if (this.parent.shouldPropagateChanges() && (this.parent.getCommandManager() != null)) {
                    if (hasDeletedObjects()) {
                        uowChangeSet.addDeletedObjects(getDeletedObjects(), this);
                    }
                    if (hasObjectsDeletedDuringCommit()) {
                        uowChangeSet.addDeletedObjects(getObjectsDeletedDuringCommit(), this);
                    }
                    if (uowChangeSet.hasChanges()) {
                        UnitOfWorkChangeSet remoteChangeSet = uowChangeSet.buildCacheCoordinationMergeChangeSet(this);
                        if (remoteChangeSet != null) {
                            MergeChangeSetCommand command = new MergeChangeSetCommand();
                            command.setChangeSet(remoteChangeSet);
                            this.parent.getCommandManager().propagateCommand(command);
                        }
                    }
                }
            }
        } finally {
            if (!this.isNestedUnitOfWork && !manager.getAcquiredLocks().isEmpty()) {
                // if the locks have not already been released (!acquiredLocks.empty)
                // then there must have been an error, release all of the locks.
                try{
                    // 272022: If the current thread and the active thread on the mutex do not match - switch them
                    verifyMutexThreadIntegrityBeforeRelease();
                    this.parent.getIdentityMapAccessorInstance().getWriteLockManager().releaseAllAcquiredLocks(manager);
                }catch(Exception ex){
                    //something has gone wrong twice so lets make sure the original exception is raised
                }
                setMergeManager(null);
            }
            this.parent.getIdentityMapAccessorInstance().releaseWriteLock();
            this.parent.getEventManager().postMergeUnitOfWorkChangeSet(uowChangeSet);
            endOperationProfile(SessionProfiler.Merge);
        }
    }

    /**
     * PUBLIC:
     * Merge the attributes of the clone into the unit of work copy.
     * This can be used for objects that are returned from the client through
     * RMI serialization (or another serialization mechanism), because the RMI object
     * will be a clone this will merge its attributes correctly to preserve object
     * identity within the unit of work and record its changes.
     *
     * The object and its private owned parts are merged.
     *
     * @return the registered version for the clone being merged.
     * @see #shallowMergeClone(Object)
     * @see #deepMergeClone(Object)
     */
    @Override
    public Object mergeClone(Object rmiClone) {
        return mergeClone(rmiClone, MergeManager.CASCADE_PRIVATE_PARTS, false);
    }

    /**
     * INTERNAL:
     * Merge the attributes of the clone into the unit of work copy.
     */
    public Object mergeClone(Object rmiClone, int cascadeDepth, boolean forRefresh) {
        if (rmiClone == null) {
            return null;
        }

        //CR#2272
        logDebugMessage(rmiClone, "merge_clone");

        startOperationProfile(SessionProfiler.Merge);
        ObjectBuilder builder = getDescriptor(rmiClone).getObjectBuilder();
        Object implementation = builder.unwrapObject(rmiClone, this);

        MergeManager manager = new MergeManager(this);
        manager.mergeCloneIntoWorkingCopy();
        manager.setCascadePolicy(cascadeDepth);
        manager.setForRefresh(forRefresh);

        Object merged = null;
        try {
            merged = manager.mergeChanges(implementation, null, this);
        } catch (RuntimeException exception) {
            merged = handleException(exception);
        }
        endOperationProfile(SessionProfiler.Merge);

        return merged;
    }

    /**
     * INTERNAL:
     * for synchronized units of work, merge changes into parent
     */
    public void mergeClonesAfterCompletion() {
        // 259993: If the current thread and the active thread on the mutex do not match - switch them
        verifyMutexThreadIntegrityBeforeRelease();
        mergeChangesIntoParent();
        // CR#... call event and log.
        if (this.eventManager != null) {
            this.eventManager.postCommitUnitOfWork();
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "end_unit_of_work_commit");
    }

    /**
     * PUBLIC:
     * Merge the attributes of the clone into the unit of work copy.
     * This can be used for objects that are returned from the client through
     * RMI serialization (or another serialization mechanism), because the RMI object
     * will be a clone this will merge its attributes correctly to preserve object
     * identity within the unit of work and record its changes.
     *
     * The object and its private owned parts are merged. This will include references from
     * dependent objects to independent objects.
     *
     * @return the registered version for the clone being merged.
     * @see #shallowMergeClone(Object)
     * @see #deepMergeClone(Object)
     */
    @Override
    public Object mergeCloneWithReferences(Object rmiClone) {
        return this.mergeCloneWithReferences(rmiClone, MergeManager.CASCADE_PRIVATE_PARTS);
    }

    /**
     * PUBLIC:
     * Merge the attributes of the clone into the unit of work copy.
     * This can be used for objects that are returned from the client through
     * RMI serialization (or another serialization mechanism), because the RMI object
     * will be a clone this will merge its attributes correctly to preserve object
     * identity within the unit of work and record its changes.
     *
     * The object and its private owned parts are merged. This will include references from
     * dependent objects to independent objects.
     *
     * @return the registered version for the clone being merged.
     * @see #shallowMergeClone(Object)
     * @see #deepMergeClone(Object)
     */
    public Object mergeCloneWithReferences(Object rmiClone, int cascadePolicy) {
        return mergeCloneWithReferences(rmiClone, cascadePolicy, false);
    }

    /**
     * INTERNAL:
     * Merge the attributes of the clone into the unit of work copy.
     * This can be used for objects that are returned from the client through
     * RMI serialization (or another serialization mechanism), because the RMI object
     * will be a clone this will merge its attributes correctly to preserve object
     * identity within the unit of work and record its changes.
     *
     * The object and its private owned parts are merged. This will include references from
     * dependent objects to independent objects.
     *
     * @return the registered version for the clone being merged.
     * @see #shallowMergeClone(Object)
     * @see #deepMergeClone(Object)
     */
    public Object mergeCloneWithReferences(Object rmiClone, int cascadePolicy, boolean forceCascade) {
        Object returnValue = null;
        try{
            MergeManager manager = new MergeManager(this);
            manager.mergeCloneWithReferencesIntoWorkingCopy();
            manager.setCascadePolicy(cascadePolicy);
            manager.setForceCascade(forceCascade);
            mergeManagerForActiveMerge = manager;
            returnValue= mergeCloneWithReferences(rmiClone, manager);
        } finally {
            mergeManagerForActiveMerge = null;
        }
        return returnValue;
    }

    /**
     * INTERNAL:
     * Merge the attributes of the clone into the unit of work copy.
     * This can be used for objects that are returned from the client through
     * RMI serialization (or another serialization mechanism), because the RMI object
     * will be a clone this will merge its attributes correctly to preserve object
     * identity within the unit of work and record its changes.
     *
     * The object and its private owned parts are merged. This will include references from
     * dependent objects to independent objects.
     *
     * @return the registered version for the clone being merged.
     * @see #shallowMergeClone(Object)
     * @see #deepMergeClone(Object)
     */
    public Object mergeCloneWithReferences(Object rmiClone, MergeManager manager) {
        if (rmiClone == null) {
            return null;
        }
        ClassDescriptor descriptor = getDescriptor(rmiClone);
        if ((descriptor == null) || descriptor.isDescriptorTypeAggregate()) {
            if (manager.getCascadePolicy() == MergeManager.CASCADE_BY_MAPPING){
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("not_an_entity", new Object[]{rmiClone}));
            }
            return rmiClone;
        }

        //CR#2272
        logDebugMessage(rmiClone, "merge_clone_with_references");

        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object implementation = builder.unwrapObject(rmiClone, this);

        Object mergedObject = manager.mergeChanges(implementation, null, this);
        if (isSmartMerge()) {
            return builder.wrapObject(mergedObject, this);
        } else {
            return mergedObject;
        }
    }

    /**
     * PUBLIC:
     * Return a new instance of the class registered in this unit of work.
     * This can be used to ensure that new objects are registered correctly.
     */
    @Override
    public Object newInstance(Class theClass) {
        //CR#2272
        logDebugMessage(theClass, "new_instance");

        ClassDescriptor descriptor = getDescriptor(theClass);
        Object newObject = descriptor.getObjectBuilder().buildNewInstance();
        return registerObject(newObject);
    }

    /**
     * INTERNAL:
     * This method will perform a delete operation on the provided objects pre-determining
     * the objects that will be deleted by a commit of the UnitOfWork including privately
     * owned objects.  It does not execute a query for the deletion of these objects as the
     * normal deleteobject operation does.  Mainly implemented to provide EJB 3.0 deleteObject
     * support.
     */
    public void performRemove(Object toBeDeleted, Map visitedObjects) {
        if (toBeDeleted == null) {
            return;
        }
        ClassDescriptor descriptor = getDescriptor(toBeDeleted);
        if ((descriptor == null) || descriptor.isDescriptorTypeAggregate()) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("not_an_entity", new Object[] { toBeDeleted }));
        }
        logDebugMessage(toBeDeleted, "deleting_object");

        //bug 4568370+4599010; fix EntityManager.remove() to handle new objects
        if (getDeletedObjects().containsKey(toBeDeleted)){
          return;
        }
        visitedObjects.put(toBeDeleted,toBeDeleted);
        Object registeredObject = checkIfAlreadyRegistered(toBeDeleted, descriptor);
        if (registeredObject == null) {
            Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(toBeDeleted, this);
            DoesExistQuery existQuery = descriptor.getQueryManager().getDoesExistQuery();
            existQuery = (DoesExistQuery)existQuery.clone();
            existQuery.setObject(toBeDeleted);
            existQuery.setPrimaryKey(primaryKey);
            existQuery.setDescriptor(descriptor);
            existQuery.setIsExecutionClone(true);

            existQuery.setCheckCacheFirst(true);
            if (((Boolean)executeQuery(existQuery)).booleanValue()){
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("cannot_remove_detatched_entity", new Object[]{toBeDeleted}));
            }//else, it is a new or previously deleted object that should be ignored (and delete should cascade)
        } else {
            //fire events only if this is a managed object
            if (descriptor.getEventManager().hasAnyEventListeners()) {
                org.eclipse.persistence.descriptors.DescriptorEvent event = new org.eclipse.persistence.descriptors.DescriptorEvent(toBeDeleted);
                event.setEventCode(DescriptorEventManager.PreRemoveEvent);
                event.setSession(this);
                descriptor.getEventManager().executeEvent(event);
            }
            if (hasNewObjects() && getNewObjectsCloneToOriginal().containsKey(registeredObject)){
                unregisterObject(registeredObject, DescriptorIterator.NoCascading);
            } else {
                getDeletedObjects().put(toBeDeleted, toBeDeleted);
            }
        }
        descriptor.getObjectBuilder().cascadePerformRemove(toBeDeleted, this, visitedObjects);
    }

    /**
     * INTERNAL:
     * Cascade remove the private owned object from the owned UnitOfWorkChangeSet
     */
    public void performRemovePrivateOwnedObjectFromChangeSet(Object toBeRemoved, Map visitedObjects) {
        if (toBeRemoved == null) {
            return;
        }
        visitedObjects.put(toBeRemoved, toBeRemoved);
        ClassDescriptor descriptor = getDescriptor(toBeRemoved);

        // remove object from ChangeSet
        UnitOfWorkChangeSet uowChanges = (UnitOfWorkChangeSet)getUnitOfWorkChangeSet();

        if (uowChanges != null) {
            ObjectChangeSet ocs = (ObjectChangeSet)uowChanges.getObjectChangeSetForClone(toBeRemoved);
            if (ocs != null) {
                // remove object change set and object change set from new list
                uowChanges.removeObjectChangeSet(ocs);
                uowChanges.removeObjectChangeSetFromNewList(ocs, this);
            }
        }

        // unregister object and cascade the removal
        unregisterObject(toBeRemoved, DescriptorIterator.NoCascading);

        descriptor.getObjectBuilder().cascadePerformRemovePrivateOwnedObjectFromChangeSet(toBeRemoved, this, visitedObjects);
    }

    /**
     * ADVANCED:
     * The unit of work performs validations such as,
     * ensuring multiple copies of the same object don't exist in the same unit of work,
     * ensuring deleted objects are not referred after commit,
     * ensures that objects from the parent cache are not referred in the unit of work cache.
     * The level of validation can be increased or decreased for debugging purposes or under
     * advanced situation where the application requires/desires to violate clone identity in the unit of work.
     * It is strongly suggested that clone identity not be violate in the unit of work.
     */
    @Override
    public void performFullValidation() {
        setValidationLevel(Full);

    }

    /**
     * ADVANCED:
     * The unit of work performs validations such as,
     * ensuring multiple copies of the same object don't exist in the same unit of work,
     * ensuring deleted objects are not referred after commit,
     * ensures that objects from the parent cache are not referred in the unit of work cache.
     * The level of validation can be increased or decreased for debugging purposes or under
     * advanced situation where the application requires/desires to violate clone identity in the unit of work.
     * It is strongly suggested that clone identity not be violate in the unit of work.
     */
    @Override
    public void performPartialValidation() {
        setValidationLevel(Partial);
    }

    /**
     * INTERNAL:
     * This method is called from clone and register.  It includes the processing
     * required to clone an object, including populating attributes, putting in
     * UOW identitymap and building a backupclone
     */
    protected void populateAndRegisterObject(Object original, Object workingClone, CacheKey unitOfWorkCacheKey, CacheKey parentCacheKey, ClassDescriptor descriptor) {
        // This must be registered before it is built to avoid cycles.
        unitOfWorkCacheKey.setObject(workingClone);
        unitOfWorkCacheKey.setReadTime(parentCacheKey.getReadTime());
        unitOfWorkCacheKey.setWriteLockValue(parentCacheKey.getWriteLockValue());

        //Set ChangeListener for ObjectChangeTrackingPolicy and AttributeChangeTrackingPolicy,
        //but not DeferredChangeDetectionPolicy.  Build backup clone for DeferredChangeDetectionPolicy
        //or ObjectChangeTrackingPolicy, but not for AttributeChangeTrackingPolicy.
        // - Set listener before populating attributes so aggregates can find the parent's listener
        ObjectChangePolicy changePolicy = descriptor.getObjectChangePolicy();
        changePolicy.setChangeListener(workingClone, this, descriptor);
        changePolicy.dissableEventProcessing(workingClone);

        ObjectBuilder builder = descriptor.getObjectBuilder();
        builder.populateAttributesForClone(original, parentCacheKey, workingClone, null, this);
        Object backupClone = changePolicy.buildBackupClone(workingClone, builder, this);
        // PERF: Avoid put if no backup clone.
        if (workingClone != backupClone) {
            getCloneMapping().put(workingClone, backupClone);
        }
        changePolicy.enableEventProcessing(workingClone);
    }

    /**
     * INTERNAL:
     * Remove objects from parent's identity map.
     */
    protected void postMergeChanges(Set classesChanged) {
        //bug 4730595: objects removed during flush are not removed from the cache during commit
        if (this.unitOfWorkChangeSet.hasDeletedObjects()) {
            Map deletedObjects = this.unitOfWorkChangeSet.getDeletedObjects();
            for (Iterator removedObjects = deletedObjects.keySet().iterator(); removedObjects.hasNext(); ) {
                ObjectChangeSet removedObjectChangeSet = (ObjectChangeSet) removedObjects.next();
                Object primaryKey = removedObjectChangeSet.getId();
                ClassDescriptor descriptor = removedObjectChangeSet.getDescriptor();
                // PERF: Do not remove if uow is isolated.
                if (!descriptor.getCachePolicy().shouldIsolateObjectsInUnitOfWork()) {
                    this.parent.getIdentityMapAccessorInstance().removeFromIdentityMap(primaryKey, descriptor.getJavaClass(), descriptor, removedObjectChangeSet.getUnitOfWorkClone());
                    classesChanged.add(descriptor.getJavaClass());
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Remove objects deleted during commit from clone and new object cache so that these are not merged
     */
    protected void preMergeChanges() {
        if (hasObjectsDeletedDuringCommit()) {
            for (Iterator removedObjects = getObjectsDeletedDuringCommit().keySet().iterator();
                     removedObjects.hasNext();) {
                Object removedObject = removedObjects.next();
                getCloneMapping().remove(removedObject);
                // PERF: Avoid initialization of new objects if none.
                if (hasNewObjects()) {
                    Object referenceObjectToRemove = getNewObjectsCloneToOriginal().get(removedObject);
                    if (referenceObjectToRemove != null) {
                        getNewObjectsCloneToOriginal().remove(removedObject);
                        getNewObjectsOriginalToClone().remove(referenceObjectToRemove);
                    }
                }
            }
        }
    }

    /**
     * PUBLIC:
     * Print the objects in the unit of work.
     * The output of this method will be logged to this unit of work's SessionLog at SEVERE level.
     */
    @Override
    public void printRegisteredObjects() {
        if (shouldLog(SessionLog.SEVERE, SessionLog.CACHE)) {
            basicPrintRegisteredObjects();
        }
    }

    /**
     * INTERNAL:
     * This method is used to process delete queries that pass through the unitOfWork
     * It is extracted out of the internalExecuteQuery method to reduce duplication
     */
    public Object processDeleteObjectQuery(DeleteObjectQuery deleteQuery) {
        // We must ensure that we delete the clone not the original, (this can happen in the mappings update)
        if (deleteQuery.getObject() == null) {// Must validate.
            throw QueryException.objectToModifyNotSpecified(deleteQuery);
        }

        ClassDescriptor descriptor = deleteQuery.getDescriptor();
        if(descriptor == null) {
            descriptor = getDescriptor(deleteQuery.getObject());
        }
        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object implementation = builder.unwrapObject(deleteQuery.getObject(), this);

        if (isClassReadOnly(implementation.getClass(), descriptor)) {
            throw QueryException.cannotDeleteReadOnlyObject(implementation);
        }

        if (isCloneNewObject(implementation)) {
            unregisterObject(implementation);
            return implementation;
        }
        Object primaryKey = builder.extractPrimaryKeyFromObject(implementation, this);
        Object clone = getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, implementation.getClass(), descriptor);
        if (clone == null) {
            clone = implementation;
        }

        // Register will wrap so must unwrap again.
        clone = builder.unwrapObject(clone, this);

        deleteQuery.setObject(clone);
        if (!getCommitManager().isActive()) {
            getDeletedObjects().put(clone, primaryKey);
            return clone;
        } else {
            // If the object has already been deleted i.e. private-owned + deleted then don't do it twice.
            if (hasObjectsDeletedDuringCommit()) {
                if (getObjectsDeletedDuringCommit().containsKey(clone)) {
                    return clone;
                }
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     * Print the objects in the unit of work.
     */
    protected void basicPrintRegisteredObjects() {
        String cr = Helper.cr();
        StringWriter writer = new StringWriter();
        writer.write(LoggingLocalization.buildMessage("unitofwork_identity_hashcode", new Object[] { cr, String.valueOf(System.identityHashCode(this)) }));
        if (hasDeletedObjects()) {
            writer.write(cr + LoggingLocalization.buildMessage("deleted_objects"));
            for (Iterator enumtr = getDeletedObjects().keySet().iterator(); enumtr.hasNext();) {
                Object object = enumtr.next();
                writer.write(LoggingLocalization.buildMessage("key_identity_hash_code_object", new Object[] { cr, getDescriptor(object).getObjectBuilder().extractPrimaryKeyFromObject(object, this), "\t", String.valueOf(System.identityHashCode(object)), object }));
            }
        }
        writer.write(cr + LoggingLocalization.buildMessage("all_registered_clones"));
        for (Iterator enumtr = getCloneMapping().keySet().iterator(); enumtr.hasNext();) {
            Object object = enumtr.next();
            writer.write(LoggingLocalization.buildMessage("key_identity_hash_code_object", new Object[] { cr, getDescriptor(object).getObjectBuilder().extractPrimaryKeyFromObject(object, this), "\t", String.valueOf(System.identityHashCode(object)), object }));
        }
        if (hasNewObjectsInParentOriginalToClone()) {
            writer.write(cr + LoggingLocalization.buildMessage("new_objects"));
            for (Iterator enumtr = getNewObjectsCloneToOriginal().keySet().iterator();
                     enumtr.hasNext();) {
                Object object = enumtr.next();
                writer.write(LoggingLocalization.buildMessage("key_identity_hash_code_object", new Object[] { cr, getDescriptor(object).getObjectBuilder().extractPrimaryKeyFromObject(object, this), "\t", String.valueOf(System.identityHashCode(object)), object }));
            }
        }
        log(SessionLog.SEVERE, SessionLog.TRANSACTION, writer.toString(), null, null, false);
    }

    /**
     * PUBLIC:
     * Register the objects with the unit of work.
     * All newly created root domain objects must be registered to be inserted on commit.
     * Also any existing objects that will be edited and were not read from this unit of work
     * must also be registered.
     * Once registered any changes to the objects will be committed to the database on commit.
     *
     * @return is the clones of the original objects, the return value must be used for editing.
     * Editing the original is not allowed in the unit of work.
     */
    @Override
    public Vector registerAllObjects(Collection domainObjects) {
        Vector clones = new Vector(domainObjects.size());
        for (Iterator objectsEnum = domainObjects.iterator(); objectsEnum.hasNext();) {
            clones.addElement(registerObject(objectsEnum.next()));
        }
        return clones;
    }

    /**
     * PUBLIC:
     * Register the objects with the unit of work.
     * All newly created root domain objects must be registered to be inserted on commit.
     * Also any existing objects that will be edited and were not read from this unit of work
     * must also be registered.
     * Once registered any changes to the objects will be committed to the database on commit.
     *
     * @return is the clones of the original objects, the return value must be used for editing.
     * Editing the original is not allowed in the unit of work.
     */
    public Vector registerAllObjects(Vector domainObjects) throws DatabaseException, OptimisticLockException {
        Vector clones = new Vector(domainObjects.size());
        for (Enumeration objectsEnum = domainObjects.elements(); objectsEnum.hasMoreElements();) {
            clones.addElement(registerObject(objectsEnum.nextElement()));
        }
        return clones;
    }

    /**
     * ADVANCED:
     * Register the existing object with the unit of work.
     * This is a advanced API that can be used if the application can guarantee the object exists on the database.
     * When registerObject is called the unit of work determines existence through the descriptor's doesExist setting.
     *
     * @return The clone of the original object, the return value must be used for editing.
     * Editing the original is not allowed in the unit of work.
     */
    @Override
    public Object registerExistingObject(Object existingObject) {
        return this.registerExistingObject(existingObject, false);
    }

    /**
     * ADVANCED:
     * Register the existing object with the unit of work.
     * This is a advanced API that can be used if the application can guarantee the object exists on the database.
     * When registerObject is called the unit of work determines existence through the descriptor's doesExist setting.
     *
     * @return The clone of the original object, the return value must be used for editing.
     * Editing the original is not allowed in the unit of work.
     */
    public Object registerExistingObject(Object existingObject, boolean isFromSharedCache) {
        if (existingObject == null) {
            return null;
        }
        ClassDescriptor descriptor = getDescriptor(existingObject);
        if (descriptor == null) {
            throw DescriptorException.missingDescriptor(existingObject.getClass().toString());
        }
        if (this.isClassReadOnly(descriptor.getJavaClass(), descriptor)) {
            return existingObject;
        }

        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object implementation = builder.unwrapObject(existingObject, this);
        Object registeredObject = this.registerExistingObject(implementation, descriptor, null, isFromSharedCache);

        // Bug # 3212057 - workaround JVM bug (MWN)
        if (implementation != existingObject) {
            return builder.wrapObject(registeredObject, this);
        } else {
            return registeredObject;
        }
    }

    /**
     * INTERNAL:
     * Register the existing object with the unit of work.
     * This is a advanced API that can be used if the application can guarantee the object exists on the database.
     * When registerObject is called the unit of work determines existence through the descriptor's doesExist setting.
     *
     * @return The clone of the original object, the return value must be used for editing.
     * Editing the original is not allowed in the unit of work.
     */
    public Object registerExistingObject(Object objectToRegister, ClassDescriptor descriptor, Object queryPrimaryKey, boolean isFromSharedCache) {
        if (this.isClassReadOnly(descriptor.getJavaClass(), descriptor)) {
            return objectToRegister;
        }
        if (isAfterWriteChangesButBeforeCommit()) {
            throw ValidationException.illegalOperationForUnitOfWorkLifecycle(this.lifecycle, "registerExistingObject");
        }
        if (descriptor.isDescriptorTypeAggregate()) {
            throw ValidationException.cannotRegisterAggregateObjectInUnitOfWork(objectToRegister.getClass());
        }
        CacheKey cacheKey = null;
        Object objectToRegisterId = null;
        Thread currentThread = Thread.currentThread();
        if (project.allowExtendedCacheLogging()) {
            //Not null if objectToRegister exist in cache
            Session rootSession = this.getRootSession(null).getParent() == null ? this.getRootSession(null) : this.getRootSession(null).getParent();
            cacheKey = ((org.eclipse.persistence.internal.sessions.IdentityMapAccessor)rootSession.getIdentityMapAccessor()).getCacheKeyForObject(objectToRegister);
            objectToRegisterId = this.getId(objectToRegister);
            if (cacheKey != null) {
                log(SessionLog.FINEST, SessionLog.CACHE, "cache_hit", new Object[] {objectToRegister.getClass(), objectToRegisterId});
            } else {
                log(SessionLog.FINEST, SessionLog.CACHE, "cache_miss", new Object[] {objectToRegister.getClass(), objectToRegisterId});
            }
            if (cacheKey != null && currentThread.hashCode() != cacheKey.CREATION_THREAD_HASHCODE) {
                log(SessionLog.FINEST, SessionLog.CACHE, "cache_thread_info", new Object[]{objectToRegister.getClass(), objectToRegisterId,
                        cacheKey.CREATION_THREAD_ID, cacheKey.CREATION_THREAD_NAME,
                        currentThread.getId(), currentThread.getName()});
            }
        }
        if (project.allowExtendedThreadLogging()) {
            if (this.CREATION_THREAD_HASHCODE != currentThread.hashCode()) {
                log(SessionLog.SEVERE, SessionLog.THREAD, "unit_of_work_thread_info", new Object[]{this.getName(),
                        this.CREATION_THREAD_ID, this.CREATION_THREAD_NAME,
                        currentThread.getId(), currentThread.getName()});
                if (project.allowExtendedThreadLoggingThreadDump()) {
                    log(SessionLog.SEVERE, SessionLog.THREAD, "unit_of_work_thread_info_thread_dump", new Object[]{
                            this.CREATION_THREAD_ID, this.CREATION_THREAD_NAME, this.creationThreadStackTrace,
                            currentThread.getId(), currentThread.getName(), ConcurrencyUtil.SINGLETON.enrichGenerateThreadDumpForCurrentThread()});
                }
            }
        }
        //CR#2272
        logDebugMessage(objectToRegister, "register_existing");
        Object registeredObject;
        try {
            startOperationProfile(SessionProfiler.Register);
            registeredObject = checkIfAlreadyRegistered(objectToRegister, descriptor);
            if (registeredObject == null) {
                // Check if object is existing, if it is it must be cloned into the unit of work
                // otherwise it is a new object
                Object primaryKey = queryPrimaryKey;
                if (primaryKey == null){
                    primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(objectToRegister, this, true);
                }
                if (descriptor.shouldLockForClone()|| !isFromSharedCache || (descriptor.isProtectedIsolation() && !(objectToRegister instanceof PersistenceEntity))){
                // The primary key may be null for a new object in a nested unit of work (is existing in nested, new in parent).
                    if (primaryKey != null) {
                        // Always check the cache first.
                        registeredObject = getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, objectToRegister, objectToRegister.getClass(), true, descriptor);
                    }
                } else {
                    // perform a check of the UOW identitymap.  This would be done by getFromIdentityMap
                    // but that method also calls back up to the shared cache in case it is not found locally.
                    // and we wish to avoid checking the shared cache twice.
                    CacheKey localCacheKey = getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, objectToRegister.getClass(), descriptor, false);
                    if (localCacheKey != null){
                        registeredObject = localCacheKey.getObject();
                    }
                }
                if (registeredObject == null) {
                    // This is a case where the object is not in the session cache, or the session lookup has been bypassed
                    // check object for cachekey otherwise
                    // a new cache-key is used as there is no original to use for locking.
                    // It read time must be set to avoid it being invalidated.
                    cacheKey = null;
                    if (objectToRegister instanceof PersistenceEntity){
                        cacheKey = ((PersistenceEntity)objectToRegister)._persistence_getCacheKey();
                    }
                    if (cacheKey == null){
                        cacheKey = new CacheKey(primaryKey);
                        cacheKey.setReadTime(System.currentTimeMillis());
                        cacheKey.setIsolated(true); // if the cache does not have a version then this must be built from the supplied version
                    }
                    registeredObject = cloneAndRegisterObject(objectToRegister, cacheKey, descriptor);
                }
            }
            //bug3659327
            //fetch group manager control fetch group support
            if (descriptor.hasFetchGroupManager()) {
                //if the object is already registered in uow, but it's partially fetched (fetch group case)
                if (descriptor.getFetchGroupManager().shouldWriteInto(objectToRegister, registeredObject)) {
                    //there might be cases when reverting/refreshing clone is needed.
                    descriptor.getFetchGroupManager().writePartialIntoClones(objectToRegister, registeredObject, this.getBackupClone(registeredObject, descriptor), this);
                }
            }
        } finally {
            endOperationProfile(SessionProfiler.Register);
        }
        return registeredObject;
    }

    /**
     * INTERNAL:
     * Register the new container bean with the unit of work.
     * Normally the registerObject method should be used for all registration of new and existing objects.
     * This version of the register method can only be used for new container beans.
     *
     * @see #registerObject(Object)
     */
    public Object registerNewContainerBean(Object newObject) {
        if (newObject == null) {
            return null;
        }

        //CR#2272
        logDebugMessage(newObject, "register_new");

        startOperationProfile(SessionProfiler.Register);
        setShouldNewObjectsBeCached(true);
        ClassDescriptor descriptor = getDescriptor(newObject);
        if (descriptor == null) {
            throw DescriptorException.missingDescriptor(newObject.getClass().toString());
        }

        ObjectBuilder builder = descriptor.getObjectBuilder();

        //Pine Beta.  Removed Checking the containerBean collection.  It is not required as these are new objects.
        // Was removed to prevent issue where weblogic would re-use beans from the pool in a single transaction
        // Ensure that the registered object is the one from the parent cache.
        if (shouldPerformFullValidation()) {
            Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(newObject, this);
            Object objectFromCache = this.parent.getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, descriptor.getJavaClass(), descriptor);
            if (objectFromCache != null) {
                throw ValidationException.wrongObjectRegistered(newObject, objectFromCache);
            }
        }

        Object original = builder.buildNewInstance();
        builder.copyInto(newObject, original);

        Object clone = registerObject(original);
        getContainerBeans().put(newObject, clone);

        endOperationProfile(SessionProfiler.Register);

        return newObject;
    }

    /**
     * INTERNAL:
     * Register the new Bean with the unit of work.
     * This will register the new Bean with cloning.
     * Normally the registerObject method should be used for all registration of new and existing objects.
     * This version of the register method can only be used for new objects.
     */
    public Object registerNewContainerBeanForCMP(Object newObject) {
        if (newObject == null) {
            return null;
        }

        //CR#2272
        logDebugMessage(newObject, "register_new_bean");

        startOperationProfile(SessionProfiler.Register);

        Object clone = cloneAndRegisterNewObject(newObject, false);

        endOperationProfile(SessionProfiler.Register);

        return clone;
    }

    /**
     * ADVANCED:
     * Register the new object with the unit of work.
     * This will register the new object without cloning.
     * Normally the registerObject method should be used for all registration of new and existing objects.
     * This version of the register method can only be used for new objects.
     * This method should only be used if a new object is desired to be registered without cloning.
     *
     * @see #registerObject(Object)
     */
    @Override
    public Object registerNewObject(Object newObject) {
        if (newObject == null) {
            return null;
        }
        ClassDescriptor descriptor = getDescriptor(newObject);
        if (descriptor == null) {
            throw DescriptorException.missingDescriptor(newObject.getClass().toString());
        }

        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object implementation = builder.unwrapObject(newObject, this);

        this.registerNewObject(implementation, descriptor);

        if (implementation == newObject) {
            return newObject;
        } else {
            return builder.wrapObject(implementation, this);
        }
    }

    /**
     * INTERNAL:
     * Updated to allow passing in of the object's descriptor
     *
     * Register the new object with the unit of work.
     * This will register the new object without cloning.
     * Normally the registerObject method should be used for all registration of new and existing objects.
     * This version of the register method can only be used for new objects.
     * This method should only be used if a new object is desired to be registered without cloning.
     *
     * @see #registerObject(Object)
     */
    protected Object registerNewObject(Object implementation, ClassDescriptor descriptor) {
        if (isAfterWriteChangesButBeforeCommit()) {
            throw ValidationException.illegalOperationForUnitOfWorkLifecycle(this.lifecycle, "registerNewObject");
        }
        if (descriptor.isDescriptorTypeAggregate()) {
            throw ValidationException.cannotRegisterAggregateObjectInUnitOfWork(implementation.getClass());
        }
        try {
            //CR#2272
            logDebugMessage(implementation, "register_new");

            startOperationProfile(SessionProfiler.Register);
            Object registeredObject = checkIfAlreadyRegistered(implementation, descriptor);
            if (registeredObject == null) {
                // Ensure that the registered object is the one from the parent cache.
                if (shouldPerformFullValidation()) {
                    Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(implementation, this);
                    Object objectFromCache = this.parent.getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, implementation.getClass(), descriptor);
                    if (objectFromCache != null) {
                        throw ValidationException.wrongObjectRegistered(implementation, objectFromCache);
                    }
                }
                ObjectBuilder builder = descriptor.getObjectBuilder();
                // New objects should not have an original until merge.
                Object original = null;

                Object backupClone = implementation;
                if (!descriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy()) {
                    backupClone = builder.buildNewInstance();
                }
                getCloneMapping().put(implementation, backupClone);

                // Check if the new objects should be cached.
                registerNewObjectClone(implementation, original, descriptor); //this method calls registerNewObjectInIdentityMap
            }
        } finally {
            endOperationProfile(SessionProfiler.Register);
        }

        //as this is register new return the object passed in.
        return implementation;
    }

    /**
     * INTERNAL:
     * Discover any new objects referenced from registered objects and persist them.
     * This is similar to persist, except that it traverses (all changed or new) objects
     * during the commit to find any unregistered new objects and persists them.
     * Only objects referenced by cascade persist mappings will be persisted,
     * an error will be thrown from non-cascade persist mappings to new objects (detached existing object are ok...in thoery).
     * This is specific to EJB 3.0 support.
     * @param newObjects any new objects found must be added to this collection.
     * @param cascadePersist determines if this call is cascading from a cascadePersist mapping or not.
     */
    public void discoverAndPersistUnregisteredNewObjects(Object object, boolean cascadePersist, Map newObjects, Map unregisteredExistingObjects, Map visitedObjects, Set cascadeErrors) {
        if (object == null) {
            return;
        }

        if (cascadePersist && isObjectDeleted(object)) {
            // It is deleted but reference by a cascade persist mapping, spec seems to state it should be undeleted, but seems wrong.
            // TODO: Reconsider this.
            undeleteObject(object);
        }

        // EL Bug 343925 - Add all unregistered objects which are not marked as cascade persist
        // to cascadeErrors so that all the registered objects and their mappings are iterated
        // to discover if the object is marked with CascadeType.PERSIST using a different mapping
        // of a different registered object. Throw IllegalStateException only after iterating through
        // all the registered objects and their mappings is completed, and if cascadeErrors
        // collection contains any unregistered object.
        if (visitedObjects.containsKey(object) && !cascadeErrors.contains(object)) {
            return;
        }
        visitedObjects.put(object, object);

        // If this object is deleted, avoid any discovery and return.
        if (isObjectDeleted(object)) {
            return;
        }

        ClassDescriptor descriptor = getDescriptor(object);
        // If the object is read-only or deleted then do not continue the traversal.
        if (isClassReadOnly(object.getClass(), descriptor)) {
            return;
        }
        if (!isObjectRegistered(object)) {
            if (cascadePersist) {
                // It is new and reference by a cascade persist mapping, persist it.
                // This will also throw an exception if it is an unregistered existing object (which the spec seems to state).
                registerNotRegisteredNewObjectForPersist(object, descriptor);
                newObjects.put(object, object);
                if (cascadeErrors.contains(object)) {
                    cascadeErrors.remove(object);
                }
            } else if (checkForUnregisteredExistingObject(object)) {
                // Always ignore unregistered existing objects in JPA (when not cascade persist).
                // If the object exists we need to keep a record of this object to ignore it,
                // also need to stop iterating over it.
                // Spec seems to say this is undefined.
                unregisteredExistingObjects.put(object, object);
                return;
            } else {
                // It is new but not referenced by a cascade persist mapping, throw an error.
                cascadeErrors.add(object);
                return;
            }
        }
        descriptor.getObjectBuilder().cascadeDiscoverAndPersistUnregisteredNewObjects(object, newObjects, unregisteredExistingObjects, visitedObjects, this, cascadeErrors);
    }

    /**
     * INTERNAL:
     * Register the new object with the unit of work.
     * This will register the new object without cloning.
     * Checks based on existence will be completed and the create will be cascaded based on the
     * object's mappings cascade requirements.  This is specific to EJB 3.0 support.
     * @see #registerObject(Object)
     */
    public void registerNewObjectForPersist(Object newObject, Map visitedObjects) {
        if (newObject == null) {
            return;
        }
        if(visitedObjects.containsKey(newObject)) {
            return;
        }
        visitedObjects.put(newObject, newObject);
        ClassDescriptor descriptor = getDescriptor(newObject);
        if ((descriptor == null) || descriptor.isDescriptorTypeAggregate()) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("not_an_entity", new Object[] { newObject }));
        }

        startOperationProfile(SessionProfiler.Register);
        try {
            Object registeredObject = checkIfAlreadyRegistered(newObject, descriptor);
            if (registeredObject == null) {
                registerNotRegisteredNewObjectForPersist(newObject, descriptor);
            } else if (this.isObjectDeleted(newObject)) {
                //if object is deleted and a create is issued on the that object
                // then the object must be transitioned back to existing and not deleted
                this.undeleteObject(newObject);
            }
            descriptor.getObjectBuilder().cascadeRegisterNewForCreate(newObject, this, visitedObjects);
            // After any cascade persists and assigning any sequence numbers,
            // update any derived id attributes on the new object.
            updateDerivedIds(newObject, descriptor);
        } finally {
            endOperationProfile(SessionProfiler.Register);
        }
    }

    /**
     * INTERNAL:
     * Return if the object was deleted previously (in a flush).
     */
    public boolean wasDeleted(Object original) {
        // Implemented by subclass
        return false;
    }

    /**
     * INTERNAL:
     * Called only by registerNewObjectForPersist method,
     * and only if newObject is not already registered.
     * Could be overridden in subclasses.
     */
    protected void registerNotRegisteredNewObjectForPersist(Object newObject, ClassDescriptor descriptor) {
        // Ensure that the registered object is not detached.
        // Only check existence if validating, as only results in an earlier error.
        if (shouldValidateExistence()) {
            DoesExistQuery existQuery = descriptor.getQueryManager().getDoesExistQuery();
            existQuery = (DoesExistQuery)existQuery.clone();
            existQuery.setObject(newObject);
            existQuery.setDescriptor(descriptor);
            existQuery.setIsExecutionClone(true);
            if (((Boolean)executeQuery(existQuery)).booleanValue()) {
                throw ValidationException.cannotPersistExistingObject(newObject, this);
            }
        }

        logDebugMessage(newObject, "register_new_for_persist");

        ObjectBuilder builder = descriptor.getObjectBuilder();
        // New objects should not have an original until merge.
        Object original = null;

        Object backupClone = newObject;
        if (!descriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy()) {
            backupClone = builder.buildNewInstance();
        }
        getCloneMapping().put(newObject, backupClone);
        assignSequenceNumber(newObject, descriptor);

        // Check if the new objects should be cached.
        registerNewObjectClone(newObject, original, descriptor); //this method calls registerNewObjectInIdentityMap
    }

    /**
     * INTERNAL:
     * Register the working copy of a new object and its original.
     * The user must edit the working copy and the original is used to merge into the parent.
     * This mapping is kept both ways because lookup is required in both directions.
     */
    protected void registerNewObjectClone(Object clone, Object original, ClassDescriptor descriptor) {
        // Check if the new objects should be cached.
        registerNewObjectInIdentityMap(clone, original, descriptor);

        getNewObjectsCloneToOriginal().put(clone, original);
        if (original != null) {
            getNewObjectsOriginalToClone().put(original, clone);
        }

        // run prePersist callbacks if any
        if (descriptor.getEventManager().hasAnyEventListeners()) {
            DescriptorEvent event = new DescriptorEvent(clone);
            event.setEventCode(DescriptorEventManager.PrePersistEvent);
            event.setSession(this);
            descriptor.getEventManager().executeEvent(event);
        }
    }

    /**
     * INTERNAL:
     * Add the new object to the cache if set to.
     * This is useful for using mergeclone on new objects.
     */
    protected void registerNewObjectInIdentityMap(Object clone, Object original, ClassDescriptor descriptor) {
        if (shouldNewObjectsBeCached()) {
            // Put new objects in the cache if it has a valid primary key, this allows for double new object merges,
            // and cache hits on pk queries.
            // PERF: Only need to extract key using object builder, it will now return null if the key is not valid.
            Object key = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(clone, this, true);
            if (key != null) {
                getIdentityMapAccessorInstance().putInIdentityMap(clone, key, null, 0, descriptor);
            }
        }
    }

    /**
     * PUBLIC:
     * Register the object with the unit of work.
     * All newly created root domain objects must be registered to be inserted on commit.
     * Also any existing objects that will be edited and were not read from this unit of work
     * must also be registered.
     * Once registered any changes to the objects will be committed to the database on commit.
     *
     * @return the clone of the original object, the return value must be used for editing,
     *
     * ** Editing the original is not allowed in the unit of work. **
     */
    @Override
    public Object registerObject(Object object) {
        if (object == null) {
            return null;
        }
        ClassDescriptor descriptor = getDescriptor(object);
        if (descriptor == null) {
            throw DescriptorException.missingDescriptor(object.getClass().toString());
        }
        if (this.isClassReadOnly(descriptor.getJavaClass(), descriptor)) {
            return object;
        }
        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object implementation = builder.unwrapObject(object, this);
        boolean wasWrapped = implementation != object;
        Object registeredObject = this.registerObject(implementation, descriptor);
        if (wasWrapped) {
            return builder.wrapObject(registeredObject, this);
        } else {
            return registeredObject;
        }
    }

    /**
     * INTERNAL:
     * Allows for calling method to provide the descriptor information for this
     * object.  Prevents double lookup of descriptor.
     *
     *
     * Register the object with the unit of work.
     * All newly created root domain objects must be registered to be inserted on commit.
     * Also any existing objects that will be edited and were not read from this unit of work
     * must also be registered.
     * Once registered any changes to the objects will be committed to the database on commit.
     *
     * calling this method will also sort the objects into different different groups
     * depending on if the object being registered is a bean or a regular Java
     * object and if its updates are deferred, non-deferred or if all modifications
     * are deferred.
     *
     * @return the clone of the original object, the return value must be used for editing,
     */
    protected Object registerObject(Object object, ClassDescriptor descriptor) {
        if (this.isClassReadOnly(descriptor.getJavaClass(), descriptor)) {
            return object;
        }
        if (isAfterWriteChangesButBeforeCommit()) {
            throw ValidationException.illegalOperationForUnitOfWorkLifecycle(this.lifecycle, "registerObject");
        }

        //CR#2272
        logDebugMessage(object, "register");

        Object registeredObject;
        try {
            startOperationProfile(SessionProfiler.Register);

            registeredObject = internalRegisterObject(object, descriptor, false);

        } finally {
            endOperationProfile(SessionProfiler.Register);
        }
        return registeredObject;
    }

    /**
     * INTERNAL:
     * Register a new object from a nested unit of work into its parent.
     */
    public void registerOriginalNewObjectFromNestedUnitOfWork(Object originalObject, Object backupClone, Object newInstance, ClassDescriptor descriptor) {
        getCloneMapping().put(originalObject, backupClone);
        registerNewObjectClone(originalObject, newInstance, descriptor);
    }

    /**
     * INTERNAL:
     * Register this UnitOfWork against an external transaction controller
     */
    public void registerWithTransactionIfRequired() {
        if (this.parent.hasExternalTransactionController() && ! isSynchronized()) {
            //TODO: Throw an exception in case the parent is already synchronized:
            // DatabaseSession or ClientSession may have only one synchronized uow at a time.
            boolean hasAlreadyStarted = this.parent.wasJTSTransactionInternallyStarted();
            this.parent.getExternalTransactionController().registerSynchronizationListener(this, this.parent);

            // CR#2998 - registerSynchronizationListener may toggle the wasJTSTransactionInternallyStarted
            // flag. As a result, we must compare the states and if the state is changed, then we must set the
            // setWasTransactionBegunPrematurely flag to ensure that we handle the transaction depth count
            // appropriately
            if (!hasAlreadyStarted && this.parent.wasJTSTransactionInternallyStarted()) {
                // registerSynchronizationListener caused beginTransaction() called
                // and an external transaction internally started.
                this.setWasTransactionBegunPrematurely(true);
            }
        }
    }

    /**
     * PUBLIC:
     * Release the unit of work. This terminates this unit of work.
     * Because the unit of work operates on its own object space (clones) no work is required.
     * The unit of work should no longer be used or referenced by the application beyond this point
     * so that it can be garbage collected.
     *
     * @see #commit()
     */
    @Override
    public void release() {
        if (isDead()) {
            return;
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "release_unit_of_work");
        if (this.eventManager != null) {
            this.eventManager.preReleaseUnitOfWork();
        }

        RuntimeException exception = null;
        // If already succeeded at a writeChanges(), then transaction still open.
        // As already issued sql must at least mark the external transaction for rollback only.
        if (this.lifecycle == CommitTransactionPending) {
            if (hasModifications() || wasTransactionBegunPrematurely()) {
                try {
                    rollbackTransaction(false);
                } catch (RuntimeException ex) {
                    exception = ex;
                }
                setWasTransactionBegunPrematurely(false);
            }
        } else if (wasTransactionBegunPrematurely() && (!this.isNestedUnitOfWork)) {
            rollbackTransaction();
            setWasTransactionBegunPrematurely(false);
        }
        releaseWriteLocks();
        setDead();
        if (shouldClearForCloseOnRelease()) {
            //uow still could be used for instantiating of ValueHolders after it's released.
            clearForClose(false);
        }
        // To be safe clean up as much state as possible.
        this.batchQueries = null;
        this.parent.releaseUnitOfWork(this);
        if (this.eventManager != null) {
            this.eventManager.postReleaseUnitOfWork();
        }
        incrementProfile(SessionProfiler.UowReleased);
        if (exception != null) {
            throw exception;
        }
    }

    /**
     * PUBLIC:
     * Empties the set of read-only classes.
     * It is illegal to call this method on nested UnitOfWork objects. A nested UnitOfWork
     * cannot have a subset of its parent's set of read-only classes.
     * Also removes classes which are read only because their descriptors are readonly
     */
    @Override
    public void removeAllReadOnlyClasses() throws ValidationException {
        if (this.isNestedUnitOfWork) {
            throw ValidationException.cannotRemoveFromReadOnlyClassesInNestedUnitOfWork();
        }
        getReadOnlyClasses().clear();
    }

    /**
     * ADVANCED:
     * Remove optimistic read lock from the object
     * See forceUpdateToVersionField(Object)
     */
    @Override
    public void removeForceUpdateToVersionField(Object lockObject) {
        getOptimisticReadLockObjects().remove(lockObject);
    }

    /**
     * INTERNAL:
     * Remove a privately owned object from the privateOwnedObjects Map.
     * The UnitOfWork needs to keep track of privately owned objects in order to
     * detect and remove private owned objects which are de-referenced.
     * When an object (which is referenced) is removed from the privateOwnedObjects Map,
     * it is no longer considered for removal from ChangeSets and the UnitOfWork identitymap.
     */
    public void removePrivateOwnedObject(DatabaseMapping mapping, Object privateOwnedObject) {
        if (this.privateOwnedObjects != null) {
            Set objectsForMapping = this.privateOwnedObjects.get(mapping);
            if (objectsForMapping != null){
                objectsForMapping.remove(privateOwnedObject);
                if (objectsForMapping.isEmpty()) {
                    this.privateOwnedObjects.remove(mapping);
                }
            }
        }
    }

    /**
     * PUBLIC:
     * Removes a Class from the receiver's set of read-only classes.
     * It is illegal to try to send this method to a nested UnitOfWork.
     */
    @Override
    public void removeReadOnlyClass(Class theClass) throws ValidationException {
        if (!canChangeReadOnlySet()) {
            throw ValidationException.cannotModifyReadOnlyClassesSetAfterUsingUnitOfWork();
        }
        if (this.isNestedUnitOfWork) {
            throw ValidationException.cannotRemoveFromReadOnlyClassesInNestedUnitOfWork();
        }
        getReadOnlyClasses().remove(theClass);

    }

    /**
     * PUBLIC:
     * Revert all changes made to any registered object.
     * Clear all deleted and new objects.
     * Revert should not be confused with release which it the normal compliment to commit.
     * Revert is more similar to commit and resume, however reverts all changes and resumes.
     * If you do not require to resume the unit of work release should be used instead.
     *
     * @see #commitAndResume()
     * @see #release()
     */
    @Override
    public void revertAndResume() {
        if (isAfterWriteChangesButBeforeCommit()) {
            throw ValidationException.illegalOperationForUnitOfWorkLifecycle(this.lifecycle, "revertAndResume");
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "revert_unit_of_work");

        MergeManager manager = new MergeManager(this);
        manager.mergeOriginalIntoWorkingCopy();
        manager.setForRefresh(true);
        manager.cascadeAllParts();
        for (Iterator cloneEnum = new IdentityHashMap(getCloneMapping()).keySet().iterator(); cloneEnum.hasNext();) {
            Object clone = cloneEnum.next();

            // Revert each clone.
            manager.mergeChanges(clone, null, this);
            ClassDescriptor descriptor = getDescriptor(clone);

            //revert the tracking policy
            descriptor.getObjectChangePolicy().revertChanges(clone, descriptor, this, getCloneMapping(), true);
        }

        // PERF: Avoid initialization of new objects if none.
        if (hasNewObjects()) {
            for (Iterator cloneEnum = getNewObjectsCloneToOriginal().keySet().iterator();
                     cloneEnum.hasNext();) {
                Object clone = cloneEnum.next();

                // De-register the object.
                getCloneMapping().remove(clone);
            }
            if (getUnitOfWorkChangeSet() != null) {
                ((UnitOfWorkChangeSet)getUnitOfWorkChangeSet()).getNewObjectChangeSets().clear();
            }
        }

        // Clear new and deleted objects.
        setNewObjectsCloneToOriginal(null);
        setNewObjectsOriginalToClone(null);
        // Reset the all clones collection
        this.allClones = null;
        // 2612538 - the default size of Map (32) is appropriate
        setObjectsDeletedDuringCommit(new IdentityHashMap());
        setDeletedObjects(new IdentityHashMap());
        setRemovedObjects(new IdentityHashMap());
        setUnregisteredNewObjects(new IdentityHashMap());
        if (this.isNestedUnitOfWork) {
            discoverAllUnregisteredNewObjectsInParent();
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "resume_unit_of_work");
    }

    /**
     * PUBLIC:
     * Revert the object's attributes from the parent.
     * This also reverts the object privately-owned parts.
     *
     * @return the object reverted.
     * @see #shallowRevertObject(Object)
     * @see #deepRevertObject(Object)
     */
    @Override
    public Object revertObject(Object clone) {
        return revertObject(clone, MergeManager.CASCADE_PRIVATE_PARTS);
    }

    /**
     * INTERNAL:
     * Revert the object's attributes from the parent.
     * This uses merging to merge the object changes.
     */
    public Object revertObject(Object clone, int cascadeDepth) {
        if (clone == null) {
            return null;
        }

        //CR#2272
        logDebugMessage(clone, "revert");

        ClassDescriptor descriptor = getDescriptor(clone);
        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object implementation = builder.unwrapObject(clone, this);

        MergeManager manager = new MergeManager(this);
        manager.mergeOriginalIntoWorkingCopy();
        manager.setForRefresh(true);
        manager.setCascadePolicy(cascadeDepth);
        try {
            manager.mergeChanges(implementation, null, this);
        } catch (RuntimeException exception) {
            return handleException(exception);
        }
        if (cascadeDepth != MergeManager.NO_CASCADE) {
            builder.instantiateEagerMappings(clone, this);
        }
        return clone;
    }

    /**
     * INTERNAL:
     * This is internal to the uow, transactions should not be used explicitly in a uow.
     * The uow shares its parents transactions.
     */
    @Override
    public void rollbackTransaction() throws DatabaseException {
        incrementProfile(SessionProfiler.UowRollbacks);
        this.parent.rollbackTransaction();
    }

    /**
     * INTERNAL:
     * rollbackTransaction() with a twist for external transactions.
     * <p>
     * writeChanges() is called outside the JTA beforeCompletion(), so the
     * accompanying exception won't propagate up and cause a rollback by itself.
     * <p>
     * Instead must mark the transaction for rollback only here.
     * <p>
     * If internally started external transaction or no external transaction
     * can still rollback normally.
     * @param intendedToCommitTransaction whether we were inside a commit or just trying to
     * write out changes early.
     */
    protected void rollbackTransaction(boolean intendedToCommitTransaction) throws DatabaseException {
        if (!intendedToCommitTransaction && this.parent.hasExternalTransactionController() && !this.parent.wasJTSTransactionInternallyStarted()) {
            this.parent.getExternalTransactionController().markTransactionForRollback();
        }
        rollbackTransaction();
    }

    /**
     * INTERNAL:
     * Scans the UnitOfWork identity map for conforming instances.
     * <p>
     * Later this method can be made recursive to check all parent units of
     * work also.
     * @param selectionCriteria must be cloned and specially prepared for conforming
     * @return Map to facilitate merging with conforming instances
     * returned from a query on the database.
     */
    public Map<Object, Object> scanForConformingInstances(Expression selectionCriteria, Class referenceClass, AbstractRecord arguments, ObjectLevelReadQuery query) {
        // for bug 3568141 use the painstaking shouldTriggerIndirection if set
        int policy = query.getInMemoryQueryIndirectionPolicyState();
        if (policy != InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION) {
            policy = InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_NOT_CONFORMED;
        }
        Map<Object, Object> indexedInterimResult = new IdentityHashMap<>();
        try {
            List fromCache = null;
            if (selectionCriteria != null) {
                // assume objects that have the compared relationship
                // untriggered do not conform as they have not been changed.
                // bug 2637555
                fromCache = getIdentityMapAccessor().getAllFromIdentityMap(selectionCriteria, referenceClass, arguments, policy);
                for (Object object : fromCache) {
                    if (!isObjectDeleted(object)) {
                        indexedInterimResult.put(object, object);
                    }
                }
            }

            // Add any new objects that conform to the query.
            List newObjects = null;
            newObjects = getAllFromNewObjects(selectionCriteria, referenceClass, arguments, policy);
            for (Object object : newObjects) {
                if (!isObjectDeleted(object)) {
                    indexedInterimResult.put(object, object);
                }
            }
        } catch (QueryException exception) {
            if (getShouldThrowConformExceptions() == THROW_ALL_CONFORM_EXCEPTIONS) {
                throw exception;
            }
        }
        return indexedInterimResult;
    }

    /**
     * INTERNAL:
     * Used to set the collections of all objects in the UnitOfWork.
     * @param objects
     */
    protected void setAllClonesCollection(Map objects) {
        this.allClones = objects;
    }

    /**
     * INTERNAL:
     * Set the clone mapping.
     * The clone mapping contains clone of all registered objects,
     * this is required to store the original state of the objects when registered

     * so that only what is changed will be committed to the database and the parent,
     * (this is required to support parallel unit of work).
     */
    protected void setCloneMapping(Map cloneMapping) {
        this.cloneMapping = cloneMapping;
    }

    /**
     * INTERNAL:
     * This is only used for EJB entity beans to manage beans accessed in a transaction context.
     */
    protected void setContainerBeans(Map containerBeans) {
        this.containerBeans = containerBeans;
    }

    /**
     * INTERNAL:
     * This is only used for EJB entity beans to manage beans accessed in a transaction context.
     */
    protected void setContainerUnitOfWork(UnitOfWorkImpl containerUnitOfWork) {
        this.containerUnitOfWork = containerUnitOfWork;
    }

    /**
     * INTERNAL:
     * set UoW lifecycle state variable to DEATH
     */
    public void setDead() {
        setLifecycle(Death);
    }

    /**
     * INTERNAL:
     * The deleted objects stores any objects removed during the unit of work.
     * On commit they will all be removed from the database.
     */
    protected void setDeletedObjects(Map deletedObjects) {
        this.deletedObjects = deletedObjects;
    }

    /**
     * INTERNAL:
     * The life cycle tracks if the unit of work is active and is used for JTS.
     */
    protected void setLifecycle(int lifecycle) {
        this.lifecycle = lifecycle;
    }

    /**
     * INTERNAL:
     * A reference to the last used merge manager.  This is used to track locked
     * objects.
     */
    public void setMergeManager(MergeManager mergeManager) {
        this.lastUsedMergeManager = mergeManager;
    }

    /**
     * INTERNAL:
     * The new objects stores any objects newly created during the unit of work.
     * On commit they will all be inserted into the database.
     */
    protected void setNewObjectsCloneToOriginal(Map newObjects) {
        this.newObjectsCloneToOriginal = newObjects;
    }

    /**
     * INTERNAL:
     * The new objects stores any objects newly created during the unit of work.
     * On commit they will all be inserted into the database.
     */
    protected void setNewObjectsOriginalToClone(Map newObjects) {
        this.newObjectsOriginalToClone = newObjects;
    }

    /**
     * INTERNAL:
     * Set the objects that have been deleted.
     */
    public void setObjectsDeletedDuringCommit(Map deletedObjects) {
        objectsDeletedDuringCommit = deletedObjects;
    }

    /**
     * INTERNAL:
     * Set the parent.
     * This is a unit of work if nested, otherwise a database session or client session.
     */
    public void setParent(AbstractSession parent) {
        this.parent = parent;
    }

    /**
     * INTERNAL:
     * set UoW lifecycle state variable to PENDING_MERGE
     */
    public void setPendingMerge() {
        setLifecycle(MergePending);
    }

    /**
     * @param preDeleteComplete the preDeleteComplete to set
     */
    public void setPreDeleteComplete(boolean preDeleteComplete) {
        this.preDeleteComplete = preDeleteComplete;
    }

    /**
     * INTERNAL:
     * Gives a new set of read-only classes to the receiver.
     * This set of classes given are checked that subclasses of a read-only class are also
     * in the read-only set provided.
     */
    public void setReadOnlyClasses(List<Class> classes) {
        if (classes.isEmpty()) {
            this.readOnlyClasses = null;
            return;
        }
        int size = classes.size();
        this.readOnlyClasses = new HashSet<>(size);
        for (int index = 0; index < size; index++) {
            this.readOnlyClasses.add(classes.get(index));
        }
    }

    /**
     * INTERNAL:
     * The removed objects stores any newly registered objects removed during the nested unit of work.
     * On commit they will all be removed from the parent unit of work.
     */
    protected void setRemovedObjects(Map removedObjects) {
        this.removedObjects = removedObjects;
    }

    /**
     * INTERNAL:
     * Set if this UnitofWork should be resumed after the end of the transaction
     * Used when UnitOfWork is synchronized with external transaction control
     */
    public void setResumeUnitOfWorkOnTransactionCompletion(boolean resumeUnitOfWork) {
        this.resumeOnTransactionCompletion = resumeUnitOfWork;
    }

    /**
     * INTERNAL:
     * Set if this UnitofWork should discover new objects on commit.
     */
    public boolean shouldDiscoverNewObjects() {
        return this.shouldDiscoverNewObjects;
    }

    /**
     * INTERNAL:
     * Set if this UnitofWork should discover new objects on commit.
     */
    public void setShouldDiscoverNewObjects(boolean shouldDiscoverNewObjects) {
        this.shouldDiscoverNewObjects = shouldDiscoverNewObjects;
    }

    /**
     * INTERNAL:
     * True if the value holder for the joined attribute should be triggered.
     * Required by ejb30 fetch join.
     */
    public void setShouldCascadeCloneToJoinedRelationship(boolean shouldCascadeCloneToJoinedRelationship) {
        this.shouldCascadeCloneToJoinedRelationship = shouldCascadeCloneToJoinedRelationship;
    }

    /**
     * INTERNAL:
     * Calculate whether we should read directly from the database to the UOW.
     * This may be necessary in subclasses of UnitOfWork that have special behavior
     * @see RepeatableWriteUnitOfWork
     */
    public boolean shouldForceReadFromDB(ObjectBuildingQuery query, Object primaryKey){
        return false;
    }

    /**
     * ADVANCED:
     * By default new objects are not cached until the exist on the database.
     * Occasionally if mergeClone is used on new objects and is required to allow multiple merges
     * on the same new object, then if the new objects are not cached, each mergeClone will be
     * interpretted as a different new object.
     * By setting new objects to be cached mergeClone can be performed multiple times before commit.
     * New objects cannot be cached unless they have a valid assigned primary key before being registered.
     * New object with non-null invalid primary keys such as 0 or '' can cause problems and should not be used with this option.
     */
    @Override
    public void setShouldNewObjectsBeCached(boolean shouldNewObjectsBeCached) {
        this.shouldNewObjectsBeCached = shouldNewObjectsBeCached;
    }

    /**
     * ADVANCED:
     * By default deletes are performed last in a unit of work.
     * Sometimes you may want to have the deletes performed before other actions.
     */
    @Override
    public void setShouldPerformDeletesFirst(boolean shouldPerformDeletesFirst) {
        this.shouldPerformDeletesFirst = shouldPerformDeletesFirst;
    }

    /**
     * ADVANCED:
     * Conforming queries can be set to provide different levels of detail about the
     * exceptions they encounter
     * There are two levels:
     *    DO_NOT_THROW_CONFORM_EXCEPTIONS = 0;
     *    THROW_ALL_CONFORM_EXCEPTIONS = 1;
     */
    @Override
    public void setShouldThrowConformExceptions(int shouldThrowExceptions) {
        this.shouldThrowConformExceptions = shouldThrowExceptions;
    }

    /**
     * INTERNAL:
     * Set smart merge flag.  This feature is used in WL to merge dependent values without SessionAccessor
     */
    public static void setSmartMerge(boolean option) {
        SmartMerge = option;
    }

    /**
     * INTERNAL:
     * Set isSynchronized flag to indicate that this session is a synchronized unit of work.
     */
    @Override
    public void setSynchronized(boolean synched) {
        super.setSynchronized(synched);
        this.parent.setSynchronized(synched);
    }

    /**
     * INTERNAL:
     * Sets the current UnitOfWork change set to be the one passed in.
     */
    public void setUnitOfWorkChangeSet(UnitOfWorkChangeSet unitOfWorkChangeSet) {
        this.unitOfWorkChangeSet = unitOfWorkChangeSet;
    }

    /**
     * INTERNAL:
     * Used to set the unregistered existing objects vector used when validation has been turned off.
     * @param newUnregisteredExistingObjects Map
     */
    protected void setUnregisteredExistingObjects(Map newUnregisteredExistingObjects) {
        unregisteredExistingObjects = newUnregisteredExistingObjects;
    }

    /**
     * INTERNAL:
     */
    protected void setUnregisteredNewObjects(Map newObjects) {
        unregisteredNewObjects = newObjects;
    }

    /**
     * INTERNAL:
     */
    protected void setUnregisteredNewObjectsInParent(Map newObjects) {
        unregisteredNewObjectsInParent = newObjects;
    }

    /**
     * ADVANCED:
     * The unit of work performs validations such as,
     * ensuring multiple copies of the same object don't exist in the same unit of work,
     * ensuring deleted objects are not referred after commit,
     * ensures that objects from the parent cache are not referred in the unit of work cache.
     * The level of validation can be increased or decreased for debugging purposes or under
     * advanced situation where the application requires/desires to violate clone identity in the unit of work.
     * It is strongly suggested that clone identity not be violate in the unit of work.
     */
    @Override
    public void setValidationLevel(int validationLevel) {
        this.validationLevel = validationLevel;
    }

    /**
     * INTERNAL:
     * Set a flag in the root UOW to indicate that a pess. locking or non-selecting SQL query was executed
     * and forced a transaction to be started.
     */
    public void setWasTransactionBegunPrematurely(boolean wasTransactionBegunPrematurely) {
        if (this.isNestedUnitOfWork) {
            ((UnitOfWorkImpl)this.parent).setWasTransactionBegunPrematurely(wasTransactionBegunPrematurely);
        }
        this.wasTransactionBegunPrematurely = wasTransactionBegunPrematurely;
    }

    /**
     * PUBLIC:
     * Merge the attributes of the clone into the unit of work copy.
     * This can be used for objects that are returned from the client through
     * RMI serialization (or other serialization mechanisms), because the RMI object will
     * be a clone this will merge its attributes correctly to preserve object identity
     * within the unit of work and record its changes.
     *
     * Only direct attributes are merged.
     *
     * @return the registered version for the clone being merged.
     * @see #mergeClone(Object)
     * @see #deepMergeClone(Object)
     */
    @Override
    public Object shallowMergeClone(Object rmiClone) {
        return mergeClone(rmiClone, MergeManager.NO_CASCADE, false);
    }

    /**
     * PUBLIC:
     * Revert the object's attributes from the parent.
     * This only reverts the object's direct attributes.
     *
     * @return the object reverted.
     * @see #revertObject(Object)
     * @see #deepRevertObject(Object)
     */
    @Override
    public Object shallowRevertObject(Object clone) {
        return revertObject(clone, MergeManager.NO_CASCADE);
    }

    /**
     * ADVANCED:
     * Unregister the object with the unit of work.
     * This can be used to delete an object that was just created and is not yet persistent.
     * Delete object can also be used, but will result in inserting the object and then deleting it.
     * The method will only unregister the clone, none of its parts.
     */
    @Override
    public void shallowUnregisterObject(Object clone) {
        unregisterObject(clone, DescriptorIterator.NoCascading);
    }

    /**
     * INTERNAL:
     * True if the value holder for the joined attribute should be triggered.
     * Required by ejb30 fetch join.
     */
    public boolean shouldCascadeCloneToJoinedRelationship() {
        return shouldCascadeCloneToJoinedRelationship;
    }

    /**
     * ADVANCED:
     * By default new objects are not cached until the exist on the database.
     * Occasionally if mergeClone is used on new objects and is required to allow multiple merges
     * on the same new object, then if the new objects are not cached, each mergeClone will be
     * interpretted as a different new object.
     * By setting new objects to be cached mergeClone can be performed multiple times before commit.
     * New objects cannot be cached unless they have a valid assigned primary key before being registered.
     * New object with non-null invalid primary keys such as 0 or '' can cause problems and should not be used with this option.
     */
    @Override
    public boolean shouldNewObjectsBeCached() {
        return shouldNewObjectsBeCached;
    }

    /**
     * Return the default to determine if does-exist should be performed on persist.
     */
    public boolean shouldValidateExistence() {
        return shouldValidateExistence;
    }

    /**
     * Set the default to determine if does-exist should be performed on persist.
     */
    public void setShouldValidateExistence(boolean shouldValidateExistence) {
        this.shouldValidateExistence = shouldValidateExistence;
    }

    /**
     * ADVANCED:
     * By default all objects are inserted and updated in the database before
     * any object is deleted. If this flag is set to true, deletes will be
     * performed before inserts and updates
     */
    @Override
    public boolean shouldPerformDeletesFirst() {
        return shouldPerformDeletesFirst;
    }

    /**
     * ADVANCED:
     * The unit of work performs validations such as,
     * ensuring multiple copies of the same object don't exist in the same unit of work,
     * ensuring deleted objects are not referred after commit,
     * ensures that objects from the parent cache are not refered in the unit of work cache.
     * The level of validation can be increased or decreased for debugging purposes or under
     * advanced situation where the application requires/desires to violate clone identity in the unit of work.
     * It is strongly suggested that clone identity not be violate in the unit of work.
     */
    @Override
    public boolean shouldPerformFullValidation() {
        return getValidationLevel() == Full;
    }

    /**
     * ADVANCED:
     * The unit of work performs validations such as,
     * ensuring multiple copies of the same object don't exist in the same unit of work,
     * ensuring deleted objects are not referred after commit,
     * ensures that objects from the parent cache are not refered in the unit of work cache.
     * The level of validation can be increased or decreased for debugging purposes or under
     * advanced situation where the application requires/desires to violate clone identity in the unit of work.
     * It is strongly suggested that clone identity not be violated in the unit of work.
     */
    @Override
    public boolean shouldPerformNoValidation() {
        return getValidationLevel() == None;
    }

    /**
     * ADVANCED:
     * The unit of work performs validations such as,
     * ensuring multiple copies of the same object don't exist in the same unit of work,
     * ensuring deleted objects are not refered after commit,
     * ensures that objects from the parent cache are not refered in the unit of work cache.
     * The level of validation can be increased or decreased for debugging purposes or under
     * advanced situation where the application requires/desires to violate clone identity in the unit of work.
     * It is strongly suggested that clone identity not be violate in the unit of work.
     */
    @Override
    public boolean shouldPerformPartialValidation() {
        return getValidationLevel() == Partial;
    }

    /**
     * INTERNAL:
     * Returns true if this UnitofWork should be resumed after the end of the transaction
     * Used when UnitOfWork is synchronized with external transaction control
     */
    public boolean shouldResumeUnitOfWorkOnTransactionCompletion(){
        return this.resumeOnTransactionCompletion;
    }

    /**
     * INTERNAL:
     * This is a JPA setting that is off by default in regular EclipseLink. It's
     * used to avoid updating the shared cache when the cacheStoreMode property
     * is set to BYPASS.
     * @see org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork
     */
    public boolean shouldStoreBypassCache() {
        return false;
    }

    /**
     * INTERNAL:
     * Store the ModifyAllQuery's from the UoW in the list. They are always
     * deferred to commit time
     */
    public void storeModifyAllQuery(DatabaseQuery query) {
        if (this.modifyAllQueries == null) {
            this.modifyAllQueries = new ArrayList<>();
        }

        this.modifyAllQueries.add((ModifyAllQuery)query);
    }

    /**
     * INTERNAL:
     * Store the deferred UpdateAllQuery's from the UoW in the list for execution.
     */
    public void storeDeferredModifyAllQuery(DatabaseQuery query, AbstractRecord translationRow) {
        if (deferredModifyAllQueries == null) {
            deferredModifyAllQueries = new ArrayList();
        }
        deferredModifyAllQueries.add(new Object[]{query, translationRow});
    }

    /**
     * INTERNAL
     * Synchronize the clones and update their backup copies.
     * Called after commit and commit and resume.
     */
    public void synchronizeAndResume() {
        // For pessimistic locking all locks were released by commit.
        this.pessimisticLockedObjects = null;
        if (hasProperties()) {
            getProperties().remove(LOCK_QUERIES_PROPERTY);
        }

        resumeUnitOfWork();

        // The collections of clones may change in the new UnitOfWork
        this.allClones = null;
        this.removedObjects = null;
        //Reset lifecycle
        this.lifecycle = Birth;
        this.isSynchronized = false;
        this.unregisteredNewObjectsInParent = null;
        if (this.isNestedUnitOfWork) {
            discoverAllUnregisteredNewObjectsInParent();
        }
    }


    /**
     * INTERNAL:
     * Resume the unit of work state after a flush, or resume operation.
     * This will occur on commitAndResume, JPA commit and JPA flush.
     */
    public void resumeUnitOfWork() {
        // Resume new objects.
        if (hasNewObjects() && !this.isNestedUnitOfWork) {
            Iterator newEntries = this.newObjectsCloneToOriginal.entrySet().iterator();
            Map cloneToOriginals = getCloneToOriginals();
            while (newEntries.hasNext()) {
                Map.Entry entry = (Map.Entry)newEntries.next();
                Object clone = entry.getKey();
                Object original = entry.getValue();
                if (original != null) {
                    // No longer new to this unit of work, so need to store original.
                    cloneToOriginals.put(clone, original);
                }
            }
            this.newObjectsCloneToOriginal = null;
            this.newObjectsOriginalToClone = null;
        }
        this.unregisteredExistingObjects = null;
        this.unregisteredNewObjects = null;

        Map cloneMapping = getCloneMapping();
        // Clear all changes, reset backup clones.
        // PERF: only clear objects that changed.
        // The change sets include new objects as well.
        if (this.unitOfWorkChangeSet != null) {
            for (Map<ObjectChangeSet, ObjectChangeSet> objectChanges : this.unitOfWorkChangeSet.getObjectChanges().values()) {
                for (ObjectChangeSet changeSet : objectChanges.values()) {
                    Object clone = changeSet.getUnitOfWorkClone();
                    ClassDescriptor descriptor = this.getDescriptor(clone);
                    // Build backup clone for DeferredChangeDetectionPolicy or ObjectChangeTrackingPolicy,
                    // but not for AttributeChangeTrackingPolicy.
                    descriptor.getObjectChangePolicy().revertChanges(clone, descriptor, this, cloneMapping, false);
                }
            }
        }

        // Resume deleted objects.
        // bug 4730595: fix puts deleted objects in the UnitOfWorkChangeSet as they are removed.
        this.deletedObjects = null;
        // Unregister all deleted objects,
        // keep them along with their original and backup values in unregisteredDeletedObjectsCloneToBackupAndOriginal.
        if (hasObjectsDeletedDuringCommit()) {
            if (this.unregisteredDeletedObjectsCloneToBackupAndOriginal == null) {
                this.unregisteredDeletedObjectsCloneToBackupAndOriginal = new IdentityHashMap(this.objectsDeletedDuringCommit.size());
            }
            Iterator iterator = this.objectsDeletedDuringCommit.keySet().iterator();
            Map cloneToOriginals = getCloneToOriginals();
            while (iterator.hasNext()) {
                Object deletedObject = iterator.next();
                Object[] backupAndOriginal = {cloneMapping.get(deletedObject), cloneToOriginals.get(deletedObject)};
                this.unregisteredDeletedObjectsCloneToBackupAndOriginal.put(deletedObject, backupAndOriginal);
                // If object exists in IM remove it from the IM and also from clone mapping.
                getIdentityMapAccessorInstance().removeFromIdentityMap(deletedObject);
                cloneMapping.remove(deletedObject);
            }
        }
        this.objectsDeletedDuringCommit = null;

        // Clean up, new objects are now existing.
        this.unitOfWorkChangeSet = null;
        this.changeTrackedHardList = null;
    }

    /**
     * INTERNAL:
     * This method is used to transition an object from the deleted objects list
     * to be simply be register.
     */
    protected void undeleteObject(Object object) {
        getDeletedObjects().remove(object);
        if (this.parent.isUnitOfWork()) {
            ((UnitOfWorkImpl)this.parent).undeleteObject(object);
        }
    }
    /**
     * PUBLIC:
     * Unregister the object with the unit of work.
     * This can be used to delete an object that was just created and is not yet persistent.
     * Delete object can also be used, but will result in inserting the object and then deleting it.
     * The method will only unregister the object and its privately owned parts
     */
    @Override
    public void unregisterObject(Object clone) {
        unregisterObject(clone, DescriptorIterator.CascadePrivateParts);
    }

    /**
     * INTERNAL:
     * Unregister the object with the unit of work.
     * This can be used to delete an object that was just created and is not yet persistent.
     * Delete object can also be used, but will result in inserting the object and then deleting it.
     */
    public void unregisterObject(Object clone, int cascadeDepth) {
        unregisterObject(clone, cascadeDepth, false);
    }
    /**
     * INTERNAL:
     * Unregister the object with the unit of work.
     * This can be used to delete an object that was just created and is not yet persistent.
     * Delete object can also be used, but will result in inserting the object and then deleting it.
     */
    public void unregisterObject(Object clone, int cascadeDepth, boolean forDetach) {
        // Allow register to be called with null and just return true
        if (clone == null) {
            return;
        }
        //CR#2272
        logDebugMessage(clone, "unregister");
        Object implementation = getDescriptor(clone).getObjectBuilder().unwrapObject(clone, this);

        // This define an inner class for process the itteration operation, don't be scared, its just an inner class.
        DescriptorIterator iterator = new DescriptorIterator() {
            @Override
            public void iterate(Object object) {
                if (isClassReadOnly(object.getClass(), getCurrentDescriptor())) {
                    setShouldBreak(true);
                    return;
                }

                // Check if object exists in the IM.
                Object primaryKey = getCurrentDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, UnitOfWorkImpl.this, true);
                if (primaryKey != null) {
                    // If object exists in IM remove it from the IM and also from clone mapping.
                    getIdentityMapAccessorInstance().removeFromIdentityMap(primaryKey, object.getClass(), getCurrentDescriptor(), object);
                }
                getCloneMapping().remove(object);

                //remove from deleted objects.
                if (hasDeletedObjects()) {
                    getDeletedObjects().remove(object);
                }

                // Remove object from the new object cache
                // PERF: Avoid initialization of new objects if none.
                if (hasNewObjects()) {
                    Object original = getNewObjectsCloneToOriginal().remove(object);
                    if (original != null) {
                        getNewObjectsOriginalToClone().remove(original);
                    }
                    // Also need to remove the original merged object.
                    if (UnitOfWorkImpl.this.newObjectsCloneToMergeOriginal != null) {
                        original = UnitOfWorkImpl.this.newObjectsCloneToMergeOriginal.remove(object);
                        if (original != null) {
                            getNewObjectsOriginalToClone().remove(original);
                        }
                    }
                }
            }
        };

        iterator.setSession(this);
        iterator.setCascadeDepth(cascadeDepth);
        iterator.setForDetach(forDetach);
        if (forDetach){
            CascadeCondition detached = iterator.new CascadeCondition(){
                @Override
                public boolean shouldNotCascade(DatabaseMapping mapping){
                    return ! (mapping.isForeignReferenceMapping() && ((ForeignReferenceMapping)mapping).isCascadeDetach());
                }
            };
            iterator.setCascadeCondition(detached);
            iterator.setShouldIterateOverUninstantiatedIndirectionObjects(false);
        }
        iterator.setShouldIterateOnFetchGroupAttributesOnly(true);
        iterator.startIterationOn(implementation);
    }

    /**
     * INTERNAL:
     * This method is used internally to update the tracked objects if required
     */
    public void updateChangeTrackersIfRequired(Object objectToWrite, ObjectChangeSet changeSetToWrite, UnitOfWorkImpl uow, ClassDescriptor descriptor) {
        //this is a no op in this unitOfWork Class see subclasses for implementation.
    }

    /**
     * INTERNAL:
     * On persist and flush operations we must update any derived id fields.
     */
    protected Object updateDerivedIds(Object clone, ClassDescriptor descriptor) {
        Object key = null;

        if (descriptor.hasDerivedId()) {
            for (DatabaseMapping derivesIdMapping : descriptor.getDerivesIdMappinps()) {
                DatabaseMapping derivedIdMapping = derivesIdMapping.getDerivedIdMapping();

                // If there is no derived id mapping, then there is no update required. Case #1a-#6a
                // from the JPA spec.
                if (derivedIdMapping != null) {
                    ClassDescriptor parentDescriptor = derivesIdMapping.getReferenceDescriptor();
                    Object parentClone = derivesIdMapping.getRealAttributeValueFromObject(clone, this);

                    // If the parent clone is null, we don't have any work to do, continue to the next
                    // mapping. Some mappings may be part of a composite primary key that allows for a
                    // null setting or the mapping may just not be set.
                    if (parentClone != null) {
                        // Recurse up the chain to figure out the key. The first dependent will figure
                        // it out and pass it to its sub-dependents (keeping it the same)
                        if (parentDescriptor.hasDerivedId()) {
                            key = updateDerivedIds(parentClone, parentDescriptor);
                        } else {
                            key = parentDescriptor.getCMPPolicy().createPrimaryKeyInstance(parentClone, this);
                        }

                        if (derivesIdMapping.hasMapsIdValue()) {
                            // Case #1b, #2b and #3b from the JPA spec. The derived id is within our
                            // embedded id. We need to deal with that object and its mapping within the clone.
                            Object aggregateClone = derivedIdMapping.getRealAttributeValueFromObject(clone, this);

                            // If the aggregate clone is null, create one and set it on the clone.
                            if (aggregateClone == null) {
                                aggregateClone = derivedIdMapping.getReferenceDescriptor().getObjectBuilder().buildNewInstance();
                                derivedIdMapping.setRealAttributeValueInObject(clone, aggregateClone);
                            }

                            // Now get the actual derived id mapping from the aggregate and populate it on the aggregate clone.
                            DatabaseMapping aggregateMapping = derivedIdMapping.getReferenceDescriptor().getObjectBuilder().getMappingForAttributeName(derivesIdMapping.getMapsIdValue());
                            aggregateMapping.setRealAttributeValueInObject(aggregateClone, key);

                            // The key should be the aggregate clone when we are done.
                            key = aggregateClone;
                        } else {
                            // Case #4b, #5b, #6b from the JPA spec. Our id mapping is the derived id.
                            // We will deal with the clone provided.
                            derivedIdMapping.setRealAttributeValueInObject(clone, key);
                        }
                    }
                }
            }
        }

        // Return the key once we have had an opportunity to update all the
        // parts of it.
        return key;
    }

    /**
     * ADVANCED:
     * This can be used to help debugging an object-space corruption.
     * An object-space corruption is when your application has incorrectly related a clone to an original object.
     * This method will validate that all registered objects are in a correct state and throw
     * an error if not,  it will contain the full stack of object references in the error message.
     * If you call this method after each register or change you perform it will pin-point where the error was made.
     */
    @Override
    public void validateObjectSpace() {
        log(SessionLog.FINER, SessionLog.TRANSACTION, "validate_object_space");
        // This define an inner class for process the iteration operation, don't be scared, its just an inner class.
        DescriptorIterator iterator = new DescriptorIterator() {
            @Override
            public void iterate(Object object) {
                try {
                    if (isClassReadOnly(object.getClass(), getCurrentDescriptor())) {
                        setShouldBreak(true);
                        return;
                    } else {
                        getBackupClone(object, getCurrentDescriptor());
                    }
                } catch (EclipseLinkException exception) {
                    log(SessionLog.FINEST, SessionLog.TRANSACTION, "stack_of_visited_objects_that_refer_to_the_corrupt_object", getVisitedStack());
                    log(SessionLog.FINER, SessionLog.TRANSACTION, "corrupt_object_referenced_through_mapping", getCurrentMapping());
                    throw exception;
                }
            }
        };

        iterator.setSession(this);
        for (Iterator clonesEnum = getCloneMapping().keySet().iterator(); clonesEnum.hasNext();) {
            iterator.startIterationOn(clonesEnum.next());
        }
    }

    /**
     * INTERNAL:
     * Indicates if a transaction was begun by a pessimistic locking or non-selecting query.
     * Traverse to the root UOW to get value.
     */

    // * 2.5.1.8 Nov 17, 2000 JED
    // * Prs 25751 Changed to make this method public
    public boolean wasTransactionBegunPrematurely() {
        if (this.isNestedUnitOfWork) {
            return ((UnitOfWorkImpl)this.parent).wasTransactionBegunPrematurely();
        }
        return wasTransactionBegunPrematurely;
    }

    /**
     * INTERNAL:
     * A query execution failed due to an invalid query.
     * Re-connect and retry the query.
     */
    @Override
    public Object retryQuery(DatabaseQuery query, AbstractRecord row, DatabaseException databaseException, int retryCount, AbstractSession executionSession) {
        return getParent().retryQuery(query, row, databaseException, retryCount, executionSession);
    }

    /**
     * ADVANCED: Writes all changes now before commit().
     * The commit process will begin and all changes will be written out to the datastore, but the datastore transaction will not
     * be committed, nor will changes be merged into the global cache.
     * <p>
     * A subsequent commit (on UnitOfWork or global transaction) will be required to finalize the commit process.
     * <p>
     * As the commit process has begun any attempt to register objects, or execute object-level queries will
     * generate an exception.  Report queries, non-caching queries, and data read/modify queries are allowed.
     * <p>
     * On exception any global transaction will be rolled back or marked rollback only.  No recovery of this UnitOfWork will be possible.
     * <p>
     * Can only be called once.  It can not be used to write out changes in an incremental fashion.
     * <p>
     * Use to partially commit a transaction outside of a JTA transaction's callbacks.  Allows you to get back any exception directly.
     * <p>
     * Use to commit a UnitOfWork in two stages.
     */
    @Override
    public void writeChanges() {
        if (!isActive()) {
            throw ValidationException.inActiveUnitOfWork("writeChanges");
        }
        if (isAfterWriteChangesButBeforeCommit()) {
            throw ValidationException.cannotWriteChangesTwice();
        }
        if (this.isNestedUnitOfWork) {
            throw ValidationException.writeChangesOnNestedUnitOfWork();
        }
        log(SessionLog.FINER, SessionLog.TRANSACTION, "begin_unit_of_work_flush");
        mergeBmpAndWsEntities();
        if (this.eventManager != null) {
            this.eventManager.preCommitUnitOfWork();
        }
        setLifecycle(CommitPending);
        try {
            commitToDatabaseWithChangeSet(false);
            //bug:5526260 - flush batch mechanisms
            writesCompleted();
        } catch (RuntimeException exception) {
            setLifecycle(WriteChangesFailed);
            throw exception;
        }
        setLifecycle(CommitTransactionPending);
        log(SessionLog.FINER, SessionLog.TRANSACTION, "end_unit_of_work_flush");
    }

    /**
     * INTERNAL:
     * This method notifies the accessor that a particular sets of writes has
     * completed.  This notification can be used for such thing as flushing the
     * batch mechanism
     */
    @Override
    public void writesCompleted() {
        this.parent.writesCompleted();
    }

    /**
     * log the message and debug info if option is set. (reduce the duplicate codes)
     */
    private void logDebugMessage(Object object, String debugMessage) {
        log(SessionLog.FINEST, SessionLog.TRANSACTION, debugMessage, object);
    }

    /**
     * INTERNAL:
     * When in transaction batch read objects must use query local
     * to the unit of work.
     */
    public Map<ReadQuery, ReadQuery> getBatchQueries() {
        if (batchQueries == null) {
            // 2612538 - the default size of Map (32) is appropriate
            batchQueries = createMap();
        }
        return batchQueries;
    }

    /**
     * INTERNAL:
     * When in transaction batch read objects must use query local
     * to the unit of work.
     */
    public void setBatchQueries(Map<ReadQuery, ReadQuery> batchQueries) {
        this.batchQueries = batchQueries;
    }

    /**
     * INTERNAL:
     */
    public Map getPessimisticLockedObjects() {
        if (pessimisticLockedObjects == null) {
            // 2612538 - the default size of Map (32) is appropriate
            pessimisticLockedObjects = new IdentityHashMap();
        }
        return pessimisticLockedObjects;
    }

    public void addToChangeTrackedHardList(Object obj){
        if (this.referenceMode != ReferenceMode.HARD){
            this.getChangeTrackedHardList().add(obj);
        }
    }

    /**
     * INTERNAL:
     */
    public void addPessimisticLockedClone(Object clone) {
        log(SessionLog.FINEST, SessionLog.TRANSACTION, "tracking_pl_object", clone, Integer.valueOf(this.hashCode()));
        getPessimisticLockedObjects().put(clone, clone);
    }

    /**
     * INTERNAL:
     * Add a privately owned object to the privateOwnedObjectsMap.
     * The UnitOfWork needs to keep track of privately owned objects in order to
     * detect and remove private owned objects which are de-referenced.
     */
    public void addPrivateOwnedObject(DatabaseMapping mapping, Object privateOwnedObject) {
        // only allow mapped, non-null objects to be added
        if (privateOwnedObject != null && getDescriptor(privateOwnedObject) != null) {
            Map<DatabaseMapping, Set> privateOwnedObjects = getPrivateOwnedObjects();
            Set objectsForMapping = privateOwnedObjects.get(mapping);
            if (objectsForMapping == null) {
                objectsForMapping = new IdentityHashSet();
                privateOwnedObjects.put(mapping, objectsForMapping);
            }
            objectsForMapping.add(privateOwnedObject);
        }
    }

    /**
     * INTERNAL:
     * Return if the clone has been pessimistic locked in this unit of work.
     */
    public boolean isPessimisticLocked(Object clone) {
        return (this.pessimisticLockedObjects != null )&& this.pessimisticLockedObjects.containsKey(clone);
    }

    /**
     * INTERNAL:
     * Return true if there are any pessimistic locked objects in this unit of work, false otherwise.
     */
    public boolean hasPessimisticLockedObjects() {
        return (this.pessimisticLockedObjects != null) && (this.pessimisticLockedObjects.size() != 0);
    }

    /**
     * @return the preDeleteComplete
     */
    public boolean isPreDeleteComplete() {
        return preDeleteComplete;
    }

    /**
     * INTERNAL:
     * True if either DataModifyQuery or ModifyAllQuery was executed.
     * In absense of transaction the query execution starts one, therefore
     * the flag may only be true in transaction, it's reset on commit or rollback.
     */
    public void setWasNonObjectLevelModifyQueryExecuted(boolean wasNonObjectLevelModifyQueryExecuted) {
        this.wasNonObjectLevelModifyQueryExecuted = wasNonObjectLevelModifyQueryExecuted;
    }

    /**
     * INTERNAL:
     * True if either DataModifyQuery or ModifyAllQuery was executed.
     */
    public boolean wasNonObjectLevelModifyQueryExecuted() {
        return wasNonObjectLevelModifyQueryExecuted;
    }

    /**
      * INTERNAL:
      * Indicates whether readObject should return the object read from the db
      * in case there is no object in uow cache (as opposed to fetching the object from
      * parent's cache). Note that wasNonObjectLevelModifyQueryExecuted()==true implies inTransaction()==true.
      */
    public boolean shouldReadFromDB() {
        return wasNonObjectLevelModifyQueryExecuted();
    }

    /**
     * INTERNAL:
     * Release the read connection to the read connection pool.
     */
    @Override
    public void releaseReadConnection(Accessor connection) {
        //bug 4668234 -- used to only release connections on server sessions but should always release
        this.parent.releaseReadConnection(connection);
    }

    /**
     * INTERNAL:
     * This method will clear all registered objects from this UnitOfWork.
     * If parameter value is 'true' then the cache(s) are cleared, too.
     */
    public void clear(boolean shouldClearCache) {
        this.cloneToOriginals = null;
        this.cloneMapping = null;
        this.newObjectsCloneToOriginal = null;
        this.newObjectsOriginalToClone = null;
        this.deletedObjects = null;
        this.allClones = null;
        this.objectsDeletedDuringCommit = null;
        this.removedObjects = null;
        this.unregisteredNewObjects = null;
        this.unregisteredExistingObjects = null;
        this.newAggregates = null;
        this.unitOfWorkChangeSet = null;
        this.pessimisticLockedObjects = null;
        this.optimisticReadLockObjects = null;
        this.batchQueries = null;
        this.privateOwnedObjects = null;
        this.newObjectsCloneToMergeOriginal = null;
        if(shouldClearCache) {
            clearIdentityMapCache();
        }
    }

    /**
     * INTERNAL:
     * Clear the identityMaps
     */
    private void clearIdentityMapCache() {
        getIdentityMapAccessor().initializeIdentityMaps();
        if (this.parent instanceof IsolatedClientSession) {
            this.parent.getIdentityMapAccessor().initializeIdentityMaps();
        }
    }

    /**
     * INTERNAL:
     * Call this method if the uow will no longer be used for committing transactions:
     * all the change sets will be dereferenced, and (optionally) the cache cleared.
     * If the uow is not released, but rather kept around for ValueHolders, then identity maps shouldn't be cleared:
     * the parameter value should be 'false'. The lifecycle set to Birth so that uow ValueHolder still could be used.
     * Alternatively, if called from release method then everything should go and therefore parameter value should be 'true'.
     * In this case lifecycle won't change - uow.release (optionally) calls this method when it (uow) is already dead.
     * The reason for calling this method from release is to free maximum memory right away:
     * the uow might still be referenced by objects using UOWValueHolders (though they shouldn't be around
     * they still might).
     * We defer a clear() call to release() if the uow lifecycle is 1,2 or 4 (*Pending).
     */
    public void clearForClose(boolean shouldClearCache) {
        clear(shouldClearCache);
        if (isActive()) {
            //Reset lifecycle
            this.lifecycle = Birth;
            this.isSynchronized = false;
        }
    }

    /**
     * INTERNAL:
     * Indicates whether clearForClose method should be called by release method.
     */
    public boolean shouldClearForCloseOnRelease() {
        return false;
    }

    /**
     * INTERNAL:
     * Copy statements counts into UOW properties.
     */
    private void copyStatementsCountIntoProperties(){
        Accessor accessor = null;
        try {
            accessor = getAccessor();
        } catch(DatabaseException exception){
            //ignore for bug 290703
        }
        if(accessor!=null && accessor instanceof DatasourceAccessor){
            getProperties().put(DatasourceAccessor.READ_STATEMENTS_COUNT_PROPERTY,Integer.valueOf(((DatasourceAccessor)accessor).getReadStatementsCount()));
            getProperties().put(DatasourceAccessor.WRITE_STATEMENTS_COUNT_PROPERTY,Integer.valueOf(((DatasourceAccessor)accessor).getWriteStatementsCount()));
            getProperties().put(DatasourceAccessor.STOREDPROCEDURE_STATEMENTS_COUNT_PROPERTY,Integer.valueOf(((DatasourceAccessor)accessor).getStoredProcedureStatementsCount()));
        }
    }

    /**
     * This method is used internally to create a map to hold the persistenceContexts.  A weak map is returned if ReferenceMode is weak.
     */
    protected Map createMap(){
        if (this.referenceMode != null && this.referenceMode != ReferenceMode.HARD) return new IdentityWeakHashMap();
        return new IdentityHashMap();
    }
    /**
     * This method is used internally to create a map to hold the persistenceContexts.  A weak map is returned if ReferenceMode is weak.
     *
     *  @param size
     */
    protected Map createMap(int size){
        if (this.referenceMode != null && this.referenceMode != ReferenceMode.HARD) return new IdentityWeakHashMap(size);
        return new IdentityHashMap(size);
    }
    /**
     * This method is used internally to clone a map that holds the persistenceContexts.  A weak map is returned if ReferenceMode is weak.
     *
     */

    protected Map cloneMap(Map map){
        // bug 270413.  This method is needed to avoid the class cast exception when the reference mode is weak.
        if (this.referenceMode != null && this.referenceMode != ReferenceMode.HARD) return (IdentityWeakHashMap)((IdentityWeakHashMap)map).clone();
        return (IdentityHashMap)((IdentityHashMap)map).clone();
    }


    public ReferenceMode getReferenceMode() {
        return referenceMode;
    }

    /**
     * INTERNAL:
     * Return the list of object with changes.
     * This is used in weak reference mode to avoid garbage collection of changed objects.
     */
    public Set<Object> getChangeTrackedHardList() {
        if (this.changeTrackedHardList == null) {
            this.changeTrackedHardList = new IdentityHashSet();
        }
        return this.changeTrackedHardList;
    }

    /**
     * Get an instance, whose state may be lazily fetched.
     * If the requested instance does not exist in the database, null is returned, or the object will fail when accessed.
     * The instance will be lazy when it does not exist in the cache, and supports fetch groups.
     * @param id The primary key of the object, either as a List, singleton, IdClass or an instance of the object.
     */
    @Override
    public Object getReference(Class theClass, Object id) {
        ClassDescriptor descriptor = getDescriptor(theClass);
        if (descriptor == null || descriptor.isDescriptorTypeAggregate()) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("unknown_bean_class", new Object[] { theClass }));
        }
        Object reference;
        if (id == null) { //gf721 - check for null PK
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_pk"));
        }
        Object primaryKey;
        if (id instanceof List) {
            if (descriptor.getCachePolicy().getCacheKeyType() == CacheKeyType.ID_VALUE) {
                if (((List)id).isEmpty()) {
                    primaryKey = null;
                } else {
                    primaryKey = ((List)id).get(0);
                }
            } else {
                primaryKey = new CacheId(((List)id).toArray());
            }
        } else if (id instanceof CacheId) {
            primaryKey = id;
        } else {
            if (descriptor.getCMPPolicy() != null) {
                if (descriptor.getCMPPolicy().getPKClass() != null && !descriptor.getCMPPolicy().getPKClass().isAssignableFrom(id.getClass())) {
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_pk_class", new Object[] { descriptor.getCMPPolicy().getPKClass(), id.getClass() }));
                }
                primaryKey = descriptor.getCMPPolicy().createPrimaryKeyFromId(id, this);
            } else {
                if (!id.getClass().equals(theClass)) {
                    primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(id, this);
                } else {
                    primaryKey = id;
                }
            }
        }
        // If the class supports fetch groups then return a un-fetched instance.
        if (descriptor.hasFetchGroupManager()) {
            reference = getIdentityMapAccessor().getFromIdentityMap(primaryKey, theClass);
            if (reference == null) {
                if ((id instanceof List) || (id instanceof CacheId) || (descriptor.getCMPPolicy() == null)) {
                    AbstractRecord row = descriptor.getObjectBuilder().buildRowFromPrimaryKeyValues(primaryKey, this);
                    reference = descriptor.getObjectBuilder().buildNewInstance();
                    descriptor.getObjectBuilder().buildPrimaryKeyAttributesIntoObject(reference, row, new ReadObjectQuery(), this);
                } else {
                    reference = descriptor.getCMPPolicy().createBeanUsingKey(id, this);
                }
                descriptor.getFetchGroupManager().getIdEntityFetchGroup().setOnEntity(reference, this);
                reference = registerExistingObject(reference);
            }
        } else {
            ReadObjectQuery query = new ReadObjectQuery(descriptor.getJavaClass());
            query.setSelectionId(primaryKey);
            query.conformResultsInUnitOfWork();
            query.setIsExecutionClone(true);
            reference = executeQuery(query);
        }
        return reference;
    }

    /**
     * INTERNAL:
     * 272022: Avoid releasing locks on the wrong server thread.
     * If the current thread and the active thread on the mutex do not match - switch them
     * Before we release acquired locks (do the same as we do for mergeClonesBeforeCompletion())
     * Check that the current thread is the active thread on all lock managers by
     * checking the cached lockThread on the mergeManager.
     * If we find that these 2 threads are different - then all threads in the acquired locks list are different.
     * Switch the activeThread on the mutex to this current thread for each lock.
     * @return true if threads were switched
     */
    public boolean verifyMutexThreadIntegrityBeforeRelease() {
        if (this.lastUsedMergeManager != null) { // mergeManager may be null in a com.ibm.tx.jta.RegisteredSyncs.coreDistributeAfter() afterCompletion() callback
            Thread currentThread = Thread.currentThread();
            Thread lockThread = this.lastUsedMergeManager.getLockThread();
            if (currentThread != lockThread) {
                if (ConcurrencyManager.getDeferredLockManager(lockThread) != null){
                    // check for transitioned old deferred lock manager and switch to the new thread.
                    ConcurrencyManager.DEFERRED_LOCK_MANAGERS.put(
                        currentThread, ConcurrencyManager.DEFERRED_LOCK_MANAGERS.remove(lockThread));
                }
                ArrayList<CacheKey> locks = this.getMergeManager().getAcquiredLocks();
                if (null != locks) {
                    Iterator<CacheKey> locksIterator = locks.iterator();
                    log(SessionLog.FINER, AbstractSessionLog.CACHE, "active_thread_is_different_from_current_thread",
                            lockThread, getMergeManager(), currentThread);
                    while (locksIterator.hasNext()) {
                        ConcurrencyManager lockMutex = locksIterator.next();
                        if (null != lockMutex) {
                            Thread activeThread = lockMutex.getActiveThread();
                            // check for different acquire and release threads
                            if (currentThread != activeThread) {
                                // Switch activeThread to currentThread - we will release the lock later
                                lockMutex.setActiveThread(currentThread);
                            }
                        }
                    }
                }
            }
            return true;
        } else {
            return false;
        }
    }

    @Override
    public DatabaseValueHolder createCloneQueryValueHolder(ValueHolderInterface attributeValue, Object clone, AbstractRecord row, ForeignReferenceMapping mapping) {
        return new UnitOfWorkQueryValueHolder(attributeValue, clone, mapping, row, this);
    }

    @Override
    public DatabaseValueHolder createCloneTransformationValueHolder(ValueHolderInterface attributeValue, Object original, Object clone, AbstractTransformationMapping mapping) {
        return new UnitOfWorkTransformerValueHolder(attributeValue, original, clone, mapping, this);
    }

    /**
     * INTERNAL:
     * Return deleted objects that have reference to other deleted objects.
     * This is need to delete cycles of objects in the correct order.
     */
    public Map<Object, Set<Object>> getDeletionDependencies() {
        if (this.deletionDependencies == null) {
            this.deletionDependencies = new HashMap<>();
        }
        return this.deletionDependencies;
    }

    /**
     * INTERNAL:
     * Record deleted objects that have reference to other deleted objects.
     * This is need to delete cycles of objects in the correct order.
     */
    public void addDeletionDependency(Object target, Object source) {
        if (this.deletionDependencies == null) {
            this.deletionDependencies = new HashMap<>();
        }
        Set<Object> dependencies = this.deletionDependencies.get(target);
        if (dependencies == null) {
            dependencies = new HashSet<>();
            this.deletionDependencies.put(target, dependencies);
        }
        dependencies.add(source);
    }

    /**
     * INTERNAL:
     * Return references to other deleted objects for this deleted object.
     * This is need to delete cycles of objects in the correct order.
     */
    public Set<Object> getDeletionDependencies(Object deletedObject) {
        if (this.deletionDependencies == null) {
            return null;
        }
        return this.deletionDependencies.get(deletedObject);
    }

    /**
     * ADVANCED:
     * Return the commit order.
     */
    @Override
    public CommitOrderType getCommitOrder() {
        return commitOrder;
    }

    /**
     * ADVANCED:
     * Set the commit order.
     */
    @Override
    public void setCommitOrder(CommitOrderType order) {
        this.commitOrder = order;
    }

}
