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

    /**
     * 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), 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)){
                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)) {
                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.
     */
    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, 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, ((DatasourceAccessor) accessor).getReadStatementsCount());
            getProperties().put(DatasourceAccessor.WRITE_STATEMENTS_COUNT_PROPERTY, ((DatasourceAccessor) accessor).getWriteStatementsCount());
            getProperties().put(DatasourceAccessor.STOREDPROCEDURE_STATEMENTS_COUNT_PROPERTY, ((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.
     *
     */
    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;
    }

}
