/*
 * 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
package org.eclipse.persistence.internal.sessions;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.FetchGroupManager;
import org.eclipse.persistence.descriptors.TimestampLockingPolicy;
import org.eclipse.persistence.descriptors.VersionLockingPolicy;
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.ReadObjectQuery;

/**
 * <p>
 * <b>Purpose</b>: Hold the Records of change for a particular instance of an object.
 * </p><p>
 * <b>Description</b>: This class uses the Primary Keys of the Object it represents,
 * and the class.
 * </p>
 */
public class ObjectChangeSet implements Serializable, Comparable<ObjectChangeSet>, org.eclipse.persistence.sessions.changesets.ObjectChangeSet {
    /** Allow change sets to be compared by changes for batching. */
    public static class ObjectChangeSetComparator implements Comparator, Serializable {

        private static final long serialVersionUID = -7902750710186726851L;

        /**
         * Determine if the receiver is greater or less than the change set.
         */
        @Override
        public int compare(Object object1, Object object2) {
            if (object1 == object2) {
                return 0;
            }
            ObjectChangeSet left = (ObjectChangeSet)object1;
            ObjectChangeSet right = (ObjectChangeSet)object2;
            // Sort by changes to keep same SQL together for batching.
            if ((left.changes != null) && right.changes != null) {
                int size = left.changes.size();
                List otherChanges = right.changes;
                int otherSize = otherChanges.size();
                if (size > otherSize) {
                    return 1;
                } else if (size < otherSize) {
                    return -1;
                }
                for (int index = 0; index < size; index++) {
                    ChangeRecord record = (ChangeRecord)left.changes.get(index);
                    ChangeRecord otherRecord = (ChangeRecord)otherChanges.get(index);
                    int compare = record.getAttribute().compareTo(otherRecord.getAttribute());
                    if (compare != 0) {
                        return compare;
                    }
                }
            }
            return left.compareTo(right);
        }
    }

    /** This is the collection of changes */
    protected List<org.eclipse.persistence.sessions.changesets.ChangeRecord> changes;
    protected transient Map<String, ChangeRecord> attributesToChanges;
    protected boolean shouldBeDeleted;
    protected Object id;
    protected transient Class classType;
    protected String className;
    protected boolean isNew;
    protected boolean isAggregate;
    protected Object oldKey;
    protected Object newKey;
    protected AbstractRecord protectedForeignKeys;

    /** This member variable holds the reference to the parent UnitOfWork Change Set **/
    protected transient UnitOfWorkChangeSet unitOfWorkChangeSet;
    /** Used in mergeObjectChanges method for writeLock and initialWriteLock comparison of the merged change sets **/
    protected transient OptimisticLockingPolicy optimisticLockingPolicy;
    protected Object initialWriteLockValue;
    protected Object writeLockValue;
    /** Invalid change set shouldn't be merged into object in cache, rather the object should be invalidated **/
    protected boolean isInvalid;
    protected transient Object cloneObject;
    protected boolean hasVersionChange;
    /** Contains optimisticReadLockObject corresponding to the clone, non-null indicates forced changes **/
    protected Boolean shouldModifyVersionField;
    /** For CMP only: indicates that the object should be force updated (whether it has OptimisticLocking or not): getCmpPolicy().getForcedUpdate()==true**/
    protected transient boolean hasCmpPolicyForcedUpdate;
    protected transient boolean hasChangesFromCascadeLocking;

    /**
     * This is used during attribute level change tracking when a particular
     * change was detected but that change can not be tracked (ie customer set
     * entire collection in object).
     */
    protected transient Set<String> deferredSet;

    /**
     * Used to store the type of cache synchronization used for this object
     * This variable is set just before the change set is serialized.
     */
    protected int cacheSynchronizationType;

    /** PERF: Cache the session cacheKey during the merge to avoid duplicate lookups. */
    protected transient CacheKey activeCacheKey;

    /** Cache the descriptor as it is useful and required in some places. */
    protected transient ClassDescriptor descriptor;

    /** return whether this change set should be recalculated after an event changes the object */
    protected transient boolean shouldRecalculateAfterUpdateEvent = true;

    //This controls how long the thread can wait for other thread to put Entity instance in cache
    //This is not final to allow a way for the value to be changed without supporting API
    public static final int MAX_TRIES = 18000;

    /**
     * The default constructor.
     */
    public ObjectChangeSet() {    }

    /**
     * This constructor is used to create an ObjectChangeSet that represents a regular object.
     */
    public ObjectChangeSet(Object primaryKey, ClassDescriptor descriptor, Object cloneObject, UnitOfWorkChangeSet parent, boolean isNew) {
        this.cacheSynchronizationType = ClassDescriptor.UNDEFINED_OBJECT_CHANGE_BEHAVIOR;
        this.cloneObject = cloneObject;
        this.isNew = isNew;
        this.shouldBeDeleted = false;
        this.id = primaryKey;
        this.classType = descriptor.getJavaClass();
        this.className = this.classType.getName();
        this.descriptor = descriptor;
        this.cacheSynchronizationType = descriptor.getCachePolicy().getCacheSynchronizationType();
        this.unitOfWorkChangeSet = parent;
        this.isAggregate = false;
    }

    public ClassDescriptor getDescriptor() {
        return descriptor;
    }

    public void setDescriptor(ClassDescriptor descriptor) {
        this.descriptor = descriptor;
    }

    /**
     * INTERNAL:
     * This method will clear the changerecords from a changeSet
     */
    public void clear(boolean clearKeys) {
        this.shouldBeDeleted = false;
        this.changes = null;
        this.attributesToChanges = null;
        this.deferredSet = null;
        if (clearKeys){
            this.setOldKey(null);
            this.setNewKey(null);
        }
    }

    /**
     * Add the attribute change record.
     */
    public void addChange(ChangeRecord changeRecord) {
        if (changeRecord == null) {
            return;
        }
        String attributeName = changeRecord.getAttribute();
        Map attributeToChanges = getAttributesToChanges();
        List changes = getChanges();
        ChangeRecord existingChangeRecord = (ChangeRecord)attributeToChanges.get(attributeName);
        // change tracking may add a change to an existing attribute fix that here.
        if (existingChangeRecord != null) {
            changes.remove(existingChangeRecord);
        }
        changes.add(changeRecord);
        attributeToChanges.put(attributeName, changeRecord);
        dirtyUOWChangeSet();

        // now let's do some house keeping.
        DatabaseMapping mapping = changeRecord.getMapping();
        OptimisticLockingPolicy olp = getDescriptor().getOptimisticLockingPolicy();
        if (olp != null){
            if ((olp.shouldUpdateVersionOnOwnedMappingChange() && mapping.isOwned()) || (olp.shouldUpdateVersionOnMappingChange())){
                this.shouldModifyVersionField = true;  // must update version field when owned mapping changes
            }
        }
    }

    /**
     * INTERNAL:
     * This method is used during attribute level change tracking when a particular
     * change was detected but that change can not be tracked (ie customer set
     * entire collection in object).  In this case flag this attribute for
     * deferred change detection at commit time.
     */
    public void deferredDetectionRequiredOn(String attributeName){
        getDeferredSet().add(attributeName);
    }

    /**
     * INTERNAL:
     * Convenience method used to query this change set after it has been sent by
     * cache synchronization.
     * @return true if this change set should contain all change information, false if only
     * the identity information should be available.
     */
    public boolean containsChangesFromSynchronization() {
        return ((cacheSynchronizationType == ClassDescriptor.SEND_NEW_OBJECTS_WITH_CHANGES) || (cacheSynchronizationType == ClassDescriptor.SEND_OBJECT_CHANGES));
    }

    /**
     * Ensure change sets with the same primary key are equal.
     */
    @Override
    public boolean equals(Object object) {
        if (object instanceof ObjectChangeSet) {
            return equals((ObjectChangeSet)object);
        }
        return false;
    }

    /**
     * Ensure change sets with the same primary key are equal.
     */
    public boolean equals(ObjectChangeSet objectChange) {
        if (this == objectChange) {
            return true;
        } else if (this.id == null) {
            //new objects are compared based on identity
            return false;
        }

        return (this.id.equals(objectChange.id));
    }

    /**
     * Determine if the receiver is greater or less than the change set.
     */
    @Override
    public int compareTo(ObjectChangeSet changeSet) {
        if (this == changeSet) {
            return 0;
        }
        if (this.id == null) {
            if (changeSet.id != null) {
                return -1;
            } else {
                return 0;
            }
        } else if (changeSet.id == null) {
            return 1;
        }
        try {
            return ((Comparable)this.id).compareTo(changeSet.id);
        } catch (Exception exception) {
            return 0;
        }
    }

    /**
     * INTERNAL:
     * stores the change records indexed by the attribute names
     */
    public Map getAttributesToChanges() {
        if (this.attributesToChanges == null) {
            this.attributesToChanges = new HashMap();
        }
        return this.attributesToChanges;
    }

    /**
     * INTERNAL:
     * returns the change record for the specified attribute name
     */
    @Override
    public org.eclipse.persistence.sessions.changesets.ChangeRecord getChangesForAttributeNamed(String attributeName) {
        return (ChangeRecord)this.getAttributesToChanges().get(attributeName);
    }

    /**
     * ADVANCED:
     * This method will return a collection of the attributes changed in the object.
     */
    @Override
    public List<String> getChangedAttributeNames() {
        List<String> names = new ArrayList<>();
        for (org.eclipse.persistence.sessions.changesets.ChangeRecord changeRecord : getChanges()) {
            names.add(changeRecord.getAttribute());
        }
        return names;
    }

    /**
     * INTERNAL:
     * This method returns a reference to the collection of changes within this changeSet.
     */
    @Override
    public List<org.eclipse.persistence.sessions.changesets.ChangeRecord> getChanges() {
        if (this.changes == null) {
            this.changes = new ArrayList<>();
        }
        return changes;
    }

    /**
     * INTERNAL:
     * This method returns the class type that this changeSet represents.
     * The class type must be initialized, before this method is called.
     * @return java.lang.Class or null if the class type isn't initialized.
     */
    public Class getClassType() {
        return classType;
    }

    /**
     * ADVANCE:
     * This method returns the class type that this changeSet Represents.
     * This requires the session to reload the class on serialization.
     */
    @Override
    public Class getClassType(org.eclipse.persistence.sessions.Session session) {
        if (classType == null) {
            classType = (Class) session.getDatasourcePlatform().getConversionManager().convertObject(getClassName(), ClassConstants.CLASS);
        }
        return classType;
    }

    /**
     * ADVANCE:
     * This method returns the class type that this changeSet Represents.
     * The class type should be used if the class is desired.
     */
    @Override
    public String getClassName() {
        return className;
    }

    /**
     * INTERNAL:
     * This method is used to return the initial lock value of the object this changeSet represents.
     */
    public Object getInitialWriteLockValue() {
        return initialWriteLockValue;
    }

    /**
     * This method returns the key value that this object was stored under in it's
     * Respective hashmap.
     */
    @Override
    public Object getOldKey() {
        return this.oldKey;
    }

    /**
     * This method returns the key value that this object will be stored under in it's
     * Respective hashmap.
     */
    @Override
    public Object getNewKey() {
        return this.newKey;
    }

    /**
     * ADVANCED:
     * This method returns the primary key for the object that this change set represents.
     */
    @Override
    public Object getId() {
        return this.id;
    }

    public Object getOldValue() {
        AbstractSession session = null;
        if(this.unitOfWorkChangeSet != null) {
            session = this.unitOfWorkChangeSet.getSession();
        }
        return getOldValue(session);
    }
    public Object getOldValue(AbstractSession session) {
        if (this.isNew) {
            return null;
        }
        if (this.changes == null || this.changes.isEmpty()) {
            // object has not changed
            return this.cloneObject;
        } else {
            if(this.cloneObject != null && session != null) {
                Object oldValue = this.descriptor.getObjectBuilder().buildNewInstance();
                FetchGroup fetchGroup = null;
                FetchGroupManager fetchGroupManager = this.descriptor.getFetchGroupManager();
                if(fetchGroupManager != null) {
                    fetchGroup = fetchGroupManager.getObjectFetchGroup(this.cloneObject);
                }
                for(DatabaseMapping mapping : this.descriptor.getMappings()) {
                    String attributeName = mapping.getAttributeName();
                    if(fetchGroup == null || fetchGroup.containsAttributeInternal(attributeName)) {
                        ChangeRecord changeRecord = (ChangeRecord)getChangesForAttributeNamed(attributeName);
                        if(changeRecord != null) {
                            mapping.setRealAttributeValueInObject(oldValue, changeRecord.getOldValue());
                        } else {
                            mapping.setAttributeValueInObject(oldValue, mapping.getAttributeValueFromObject(this.cloneObject));
                        }
                    }
                }
                return oldValue;
            }
        }
        return null;
    }

    public int getSynchronizationType() {
        return cacheSynchronizationType;
    }

    /**
     * INTERNAL:
     * This method is used to return the complex object specified within the change record.
     * The object is collected from the session which, in this case, is the unit of work.
     * The object's changed attributes will be merged and added to the identity map.
     */
    public Object getTargetVersionOfSourceObject(MergeManager mergeManager, AbstractSession session) {
        return getTargetVersionOfSourceObject(mergeManager, session, false);
    }

    /**
     * INTERNAL:
     * This method is used to return the complex object specified within the change record.
     * The object is collected from the session which, in this case, is the unit of work.
     * The object's changed attributes will be merged and added to the identity map
     * @param shouldRead boolean if the object can not be found should it be read in from the database.
     */
    public Object getTargetVersionOfSourceObject(MergeManager mergeManager, AbstractSession targetSession, boolean shouldRead) {
        Object attributeValue = null;
        ClassDescriptor descriptor = getDescriptor();
        if (descriptor == null) {
            descriptor = targetSession.getDescriptor(getClassType(targetSession));
        }

        if (descriptor != null) {
            if (mergeManager.getSession().isUnitOfWork()) {
                // The unit of works will have a copy or a new instance must be made
                if (((UnitOfWorkImpl)mergeManager.getSession()).getLifecycle() == UnitOfWorkImpl.MergePending) {
                    // We are merging the unit of work into the original.
                    attributeValue = getObjectForMerge(mergeManager, targetSession, getId(), descriptor);
                    if (attributeValue == null){
                        // Bug 502085
                        UnitOfWorkImpl uow = (UnitOfWorkImpl)mergeManager.getSession();
                        if (this.isNew()) {
                            attributeValue = uow.getOriginalVersionOfObject(getUnitOfWorkClone());
                        } else {
                            attributeValue = uow.getOriginalVersionOfObjectOrNull(getUnitOfWorkClone(), this, descriptor, targetSession);
                        }
                    }
                } else {
                    // We are merging something else within the unit of work.
                    // this is most likely because we are updating a backup clone and can retrieve
                    // the working clone as the result.
                    attributeValue = getUnitOfWorkClone();
                }
            } else {
                // It is not a unitOfWork so we must be merging into a distributed cache.
                attributeValue = getObjectForMerge(mergeManager, targetSession, getId(), descriptor);
            }

            if ((attributeValue == null) && (shouldRead)) {
                // If the cache does not have a copy and I should read it from the database
                // Then load the object if possible
                ReadObjectQuery query = new ReadObjectQuery();
                query.setShouldUseWrapperPolicy(false);
                query.setReferenceClass(getClassType(targetSession));
                query.setSelectionId(getId());
                attributeValue = targetSession.executeQuery(query);
            }
        }

        return attributeValue;
    }

    /**
     * INTERNAL:
     * For use within the distributed merge process, this method will get an object from the shared
     * cache using a readlock.  If a readlock is unavailable then the merge manager will be
     * transitioned to deferred locks and a deferred lock will be used.
     */
    protected Object getObjectForMerge(MergeManager mergeManager, AbstractSession session, Object primaryKey, ClassDescriptor descriptor) {
        Object domainObject = null;
        if (primaryKey == null) {
            this.activeCacheKey = null;
            return null;
        }
        CacheKey cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, descriptor.getJavaClass(), descriptor, true);
        if (cacheKey != null) {
            if (cacheKey.acquireReadLockNoWait()) {
                domainObject = cacheKey.getObject();
                cacheKey.releaseReadLock();
            } else {
                if (!mergeManager.isTransitionedToDeferredLocks()) {
                    session.getIdentityMapAccessorInstance().getWriteLockManager().transitionToDeferredLocks(mergeManager);
                }
                cacheKey.acquireDeferredLock();
                domainObject = cacheKey.getObject();
                int tries = 0;
                while (domainObject == null) {
                    ++tries;
                    if (tries > MAX_TRIES){
                        session.getParent().log(SessionLog.SEVERE, SessionLog.CACHE, "entity_not_available_during_merge", new Object[]{descriptor.getJavaClassName(), cacheKey.getKey(), Thread.currentThread().getName(), cacheKey.getActiveThread()});
                        break;
                    }
                    synchronized (cacheKey) {
                        if (cacheKey.isAcquired()) {
                            try {
                                cacheKey.wait(10);
                            } catch (InterruptedException e) {
                                //ignore and return
                            }
                        }
                        domainObject = cacheKey.getObject();
                    }
                }
                cacheKey.releaseDeferredLock();
            }
        } else {
            domainObject = mergeManager.registerExistingObjectOfReadOnlyClassInNestedTransaction(getUnitOfWorkClone(), descriptor, session);
            // There is no need to get the cache key in this case because UOW is performing
            // a nested UOW merge, and no locking occurs.
        }

        // Set activeCacheKey.
        this.activeCacheKey = cacheKey;
        return domainObject;
    }

    /**
     * INTERNAL:
     * Returns the UnitOfWork Clone that this ChangeSet was built for.
     */
    public Object getUnitOfWorkClone() {
        return this.cloneObject;
    }

    /**
     * INTERNAL:
     * Sets the UnitOfWork Clone that this ChangeSet was built for.
     */
    public void setUnitOfWorkClone(Object cloneObject) {
        this.cloneObject = cloneObject;
    }

    /**
     * ADVANCED:
     * This method is used to return the parent UnitOfWorkChangeSet.
     */
    @Override
    public org.eclipse.persistence.sessions.changesets.UnitOfWorkChangeSet getUOWChangeSet() {
        return unitOfWorkChangeSet;
    }

    /**
     * INTERNAL:
     * This method is used to return the lock value of the object this changeSet represents.
     */
    @Override
    public Object getWriteLockValue() {
        return writeLockValue;
    }

    /**
     * ADVANCED:
     * This method will return true if the specified attribute has been changed.
     * @param attributeName the name of the attribute to search for.
     */
    @Override
    public boolean hasChangeFor(String attributeName) {
        for (org.eclipse.persistence.sessions.changesets.ChangeRecord changeRecord : getChanges()) {
            if (changeRecord.getAttribute().equals(attributeName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * ADVANCED:
     * Returns true if this particular changeSet has changes.
     */
    @Override
    public boolean hasChanges() {
        // a change set must also be considered dirty if only the version number has been updated
        // and the version is not a mapped field.  This is required to propagate the change
        // set via cache sync. to avoid opt. lock exceptions on the remote servers.
        return this.isNew || this.hasVersionChange || ((this.changes != null) && (!this.changes.isEmpty()));
    }

    /**
     * INTERNAL:
     * Returns true if this particular changeSet has forced SQL changes.  This is true whenever
     * CMPPolicy.getForceUpdate() == true or if the object has been marked for opt. read
     * lock (uow.forceUpdateToVersionField).  Kept separate from 'hasChanges' because we don't
     * want to merge or cache sync. a change set that has no 'real' changes.
     */
    public boolean hasForcedChanges() {
        return this.shouldModifyVersionField != null || this.hasCmpPolicyForcedUpdate;
    }

    /**
     * INTERNAL:
     * Holds a Boolean indicating whether version field should be modified.
     * This Boolean is set by forcedUpdate into uow.getOptimisticReadLockObjects()
     * for the clone object and copied here (so don't need to search for it again
     * in uow.getOptimisticReadLockObjects()).
     */
    public void setShouldModifyVersionField(Boolean shouldModifyVersionField) {
        this.shouldModifyVersionField = shouldModifyVersionField;
        if(shouldModifyVersionField != null && shouldModifyVersionField) {
            // mark the version number as 'dirty'
            // Note that at this point there is no newWriteLockValue - it will be set later.
            // This flag is set to indicate that the change set WILL have changes.
            this.hasVersionChange = true;
        }
    }

    /**
     * INTERNAL:
     * Holds a Boolean indicating whether version field should be modified.
     */
    public Boolean shouldModifyVersionField() {
        return this.shouldModifyVersionField;
    }

    /**
     * INTERNAL:
     */
    public void setHasCmpPolicyForcedUpdate(boolean hasCmpPolicyForcedUpdate) {
        this.hasCmpPolicyForcedUpdate = hasCmpPolicyForcedUpdate;
    }

    /**
     * INTERNAL:
     */
    public boolean hasCmpPolicyForcedUpdate() {
        return this.hasCmpPolicyForcedUpdate;
    }

    /**
     * INTERNAL:
     * Returns true if this particular changeSet has forced SQL changes because
     * of a cascade optimistic locking policy.
     */
    public boolean hasForcedChangesFromCascadeLocking() {
        return this.hasChangesFromCascadeLocking;
    }

    /**
     * INTERNAL:
     * Used by calculateChanges to mark this ObjectChangeSet as having to be
     * flushed to the db stemming from a cascade optimistic locking policy.
     */
    public void setHasForcedChangesFromCascadeLocking(boolean newValue) {
        this.setShouldModifyVersionField(Boolean.TRUE);
        this.hasChangesFromCascadeLocking = newValue;
    }

    /**
     * This method overrides the hashcode method.  If this set has a cacheKey then return the hashcode of the
     * cache key, otherwise return the identity hashcode of this object.
     */
    @Override
    public int hashCode() {
        if (getId() == null) {
            //new objects are compared based on identity
            return System.identityHashCode(this);
        }
        return getId().hashCode();
    }

    /**
     * INTERNAL:
     * Returns true if this particular changeSet has a Key.
     */
    public boolean hasKeys() {
        return (this.newKey != null) || (this.oldKey != null);
    }

    /**
     * INTERNAL:
     * Used to determine if the object change set represents an aggregate object.
     */
    public boolean isAggregate() {
        return isAggregate;
    }

    /**
     * ADVANCED:
     * Returns true if this ObjectChangeSet represents a new object.
     */
    @Override
    public boolean isNew() {
        return isNew;
    }

    /**
     * INTERNAL:
     * Indicates whether the change set is invalid.
     */
    public boolean isInvalid() {
        return isInvalid;
    }

    /**
     * INTERNAL:
     * This method will be used to merge changes from a supplied ObjectChangeSet
     * into this changeSet.
     */
    public void mergeObjectChanges(ObjectChangeSet changeSetToMergeFrom, UnitOfWorkChangeSet mergeToChangeSet, UnitOfWorkChangeSet mergeFromChangeSet) {
        if (this == changeSetToMergeFrom || this.isInvalid()) {
            return;
        }
        if(changeSetToMergeFrom.optimisticLockingPolicy != null) {
            // optimisticLockingPolicy != null guarantees initialWriteLockValue != null
            if(this.optimisticLockingPolicy == null) {
                this.optimisticLockingPolicy = changeSetToMergeFrom.optimisticLockingPolicy;
                this.initialWriteLockValue = changeSetToMergeFrom.initialWriteLockValue;
                this.writeLockValue = changeSetToMergeFrom.writeLockValue;
            } else {
                // optimisticLockingPolicy != null guarantees initialWriteLockValue != null
                Object writeLockValueToCompare = this.writeLockValue;
                if(writeLockValueToCompare == null) {
                    writeLockValueToCompare = this.initialWriteLockValue;
                }
                // In this merge initialWriteLockValue of this changeSet differs from
                // writeLockValue of the changeSetToMergeFrom into which the merge was performed.
                // Example:
                // Original registered with version 1, the clone changed to version 2, uow.writeChanges is called:
                // the corresponding "this" changeSet has initialWriteLockValue = 1 and writeLockValue = 2;
                // custom update performed next changing the version of the object in the db to 3;
                // the clone is refreshed in the uow - now it's version is 3;
                // the cloned is changed to version 4, uow.commit is called:
                // the corresponding changeSetToMergeFrom has initialWriteLockValue = 3 and writeLockValue = 4.
                // This change set should be invalidated - the custom update would not be reflected after merge,
                // therefore no merge into cache should be performed but rather the object in the cache should be invalidated.
                if(this.optimisticLockingPolicy.compareWriteLockValues(writeLockValueToCompare, changeSetToMergeFrom.initialWriteLockValue) != 0) {
                    this.isInvalid = true;
                    return;
                }

                // Don't blindly overrite a write lock value with null. A
                // consecutive change set may not have caused a version change,
                // therefore the write lock value will be null in this case.
                // E.g. Attribute change tracking does not discover a change
                // across a relational mapping (unless a cascaded optimistic
                // locking policy is used).
                if (changeSetToMergeFrom.writeLockValue != null) {
                    this.writeLockValue = changeSetToMergeFrom.writeLockValue;
                }
            }
        }
        List changesToMerge = changeSetToMergeFrom.getChanges();
        int size = changesToMerge.size();
        for (int index = 0; index < size; ++index) {
            ChangeRecord record = (ChangeRecord)changesToMerge.get(index);
            ChangeRecord thisRecord = (ChangeRecord) getChangesForAttributeNamed(record.getAttribute());
            if (thisRecord == null) {
                record.updateReferences(mergeToChangeSet, mergeFromChangeSet);
                record.setOwner(this);
                this.addChange(record);
            } else {
                thisRecord.mergeRecord(record, mergeToChangeSet, mergeFromChangeSet);
            }
        }
        this.shouldBeDeleted = changeSetToMergeFrom.shouldBeDeleted;
        this.setOldKey(changeSetToMergeFrom.oldKey);
        this.setNewKey(changeSetToMergeFrom.newKey);
        this.hasVersionChange = changeSetToMergeFrom.hasVersionChange;
        this.shouldModifyVersionField = changeSetToMergeFrom.shouldModifyVersionField;
        this.hasCmpPolicyForcedUpdate = changeSetToMergeFrom.hasCmpPolicyForcedUpdate;
        this.hasChangesFromCascadeLocking = changeSetToMergeFrom.hasChangesFromCascadeLocking;
        this.deferredSet = changeSetToMergeFrom.deferredSet;
    }

    /**
     * INTERNAL:
     * Helper method used by readObject to read a completely serialized change set from
     * the stream.
     */
    public void readCompleteChangeSet(java.io.ObjectInputStream stream) throws java.io.IOException, ClassNotFoundException {
        readIdentityInformation(stream);
        // bug 3526981 - avoid side effects of setter methods by directly assigning variables
        // still calling setOldKey to avoid duplicating the code in that method
        this.changes = (List)stream.readObject();
        this.oldKey = stream.readObject();
        this.newKey = stream.readObject();
        this.protectedForeignKeys = (AbstractRecord)stream.readObject();
    }

    /**
     * INTERNAL:
     * Helper method used by readObject to read just the information about object identity
     * from a serialized stream.
     */
    public void readIdentityInformation(java.io.ObjectInputStream stream) throws java.io.IOException, ClassNotFoundException {
        // bug 3526981 - avoid side effects of setter methods by directly assigning variables
        this.id = stream.readObject();
        this.className = (String)stream.readObject();
        this.writeLockValue = stream.readObject();
        this.initialWriteLockValue = stream.readObject();
    }

    /**
     * INTERNAL:
     * Override the default serialization.  Object Change Sets will be serialized differently
     * depending on the type of cache synchronization they use.
     */
    private void readObject(java.io.ObjectInputStream stream) throws java.io.IOException, ClassNotFoundException {
        int cacheSyncType = stream.read();
        this.cacheSynchronizationType = cacheSyncType;
        // The boolean variables have been assembled into a byte.
        // Extract them here
        this.shouldBeDeleted = stream.readBoolean();
        this.isInvalid = stream.readBoolean();
        this.isNew = stream.readBoolean();
        this.isAggregate = stream.readBoolean();
        this.shouldModifyVersionField = (Boolean)stream.readObject();
        this.hasVersionChange = stream.readBoolean();

        // Only the identity information is sent with a number of cache synchronization types
        // Here we decide what to read.
        if (this.shouldBeDeleted || (cacheSyncType == ClassDescriptor.DO_NOT_SEND_CHANGES) || (cacheSyncType == ClassDescriptor.INVALIDATE_CHANGED_OBJECTS)) {
            readIdentityInformation(stream);
        } else {
            readCompleteChangeSet(stream);
        }
    }

    /**
     * Set the id of the object for this change set.
     */
    public void setId(Object id) {
        this.id = id;
    }

    /**
     * Set the changes.
     */
    public void setChanges(List changesList) {
        this.changes = changesList;
        updateUOWChangeSet();
    }

    /**
     * Set the class type.
     */
    public void setClassType(Class newValue) {
        this.classType = newValue;
    }

    /**
     * INTERNAL:
     * Set the class name.  The name is used for serialization with cache coordination.
     */
    public void setClassName(String newValue) {
        this.className = newValue;
    }

    /**
     * INTERNAL:
     * Set if this object change Set represents an aggregate
     * @param isAggregate boolean true if the ChangeSet represents an aggregate
     */
    public void setIsAggregate(boolean isAggregate) {
        this.isAggregate = isAggregate;
    }

    /**
     * INTERNAL:
     * Set whether this ObjectChanges represents a new Object
     * @param newIsNew boolean true if this ChangeSet represents a new object
     */
    public void setIsNew(boolean newIsNew) {
        isNew = newIsNew;
    }

    /**
     * This method is used to set the value that this object was stored under in its respected
     * map collection
     */
    public void setOldKey(Object key) {
        //may be merging changeSets lets make sure that we can remove based on the
        //old key when we finally merge.
        if ((key == null) || (this.oldKey == null)) {
            this.oldKey = key;
        }
    }

    /**
     * This method is used to set the value that this object will be stored under in its respected
     * map collection
     */
    public void setNewKey(Object key) {
        this.newKey = key;
    }

    /**
     * This method was created in VisualAge.
     * @param newValue boolean
     */
    public void setShouldBeDeleted(boolean newValue) {
        this.shouldBeDeleted = newValue;
    }

    public void setSynchronizationType(int type) {
        cacheSynchronizationType = type;
    }

    /**
     * INTERNAL:
     * Used to set the parent change Set.
     */
    public void setUOWChangeSet(UnitOfWorkChangeSet newUnitOfWorkChangeSet) {
        unitOfWorkChangeSet = newUnitOfWorkChangeSet;
    }

    /**
     * INTERNAL:
     * This method should ONLY be used to set the initial writeLock value for
     * an ObjectChangeSet when it is first built.
     */
    public void setOptimisticLockingPolicyAndInitialWriteLockValue(OptimisticLockingPolicy optimisticLockingPolicy, AbstractSession session) {
        // ignore optimistic locking policy if it can't compare lock values (like FieldsLockingPolicy).
        if(optimisticLockingPolicy.supportsWriteLockValuesComparison()) {
            this.optimisticLockingPolicy = optimisticLockingPolicy;
            this.initialWriteLockValue = optimisticLockingPolicy.getWriteLockValue(cloneObject, getId(), session);
        }
    }

    /**
     * ADVANCED:
     * This method is used to set the writeLock value for an ObjectChangeSet
     * Any changes to the write lock value
     * should to through setWriteLockValue(Object obj) so that the change set is
     * marked as being dirty.
     */
    public void setWriteLockValue(java.lang.Object newWriteLockValue) {
        this.writeLockValue = newWriteLockValue;

        // mark the version number as 'dirty'
        this.hasVersionChange = true;
        updateUOWChangeSet();
    }

    /**
     * ADVANCED:
     * This method is used to set the initial writeLock value for an ObjectChangeSet.
     * The initial value will only be set once, and can not be overwritten.
     */
    public void setInitialWriteLockValue(Object initialWriteLockValue) {
        if (this.initialWriteLockValue == null) {
            this.initialWriteLockValue = initialWriteLockValue;
        }
    }

    /**
     * Mark change set for a deleted object.
     */
    public boolean shouldBeDeleted() {
        return shouldBeDeleted;
    }

    @Override
    public String toString() {
        return this.getClass().getSimpleName() + "(" + hashCode() + ", " + this.getClassName() + ")" + getChanges().toString();
    }

    /**
     * INTERNAL:
     * Used to update a changeRecord that is stored in the CHangeSet with a new value.
     */
    public void updateChangeRecordForAttribute(String attributeName, Object value) {
        ChangeRecord changeRecord = (ChangeRecord)getChangesForAttributeNamed(attributeName);
        if (changeRecord != null) {
            changeRecord.updateChangeRecordWithNewValue(value);
        }
    }

    /**
     * ADVANCED:
     * Used to update a changeRecord that is stored in the CHangeSet with a new value.
     * Used when the new value is a mapped object.
     */
    public void updateChangeRecordForAttributeWithMappedObject(String attributeName, Object value, AbstractSession session) {
        ObjectChangeSet referenceChangeSet = (ObjectChangeSet)this.getUOWChangeSet().getObjectChangeSetForClone(value);
        if (referenceChangeSet == null) {
            ClassDescriptor descriptor = session.getDescriptor(value.getClass());
            if (descriptor != null) {
                referenceChangeSet = descriptor.getObjectBuilder().createObjectChangeSet(value, (UnitOfWorkChangeSet)this.getUOWChangeSet(), false, session);
            }
        }
        updateChangeRecordForAttribute(attributeName, referenceChangeSet);
    }

    /**
     * INTERNAL:
     * Used to update a changeRecord that is stored in the CHangeSet with a new value.
     */
    public void updateChangeRecordForAttribute(DatabaseMapping mapping, Object value, AbstractSession session, Object oldValue) {
        String attributeName = mapping.getAttributeName();
        ChangeRecord changeRecord = (ChangeRecord)getChangesForAttributeNamed(attributeName);

        // bug 2641228 always ensure that we convert the value to the correct type
        if (mapping.isDirectToFieldMapping()) {
            value = ((AbstractDirectMapping)mapping).getObjectValue(value, session);
        }
        if (changeRecord != null) {
            changeRecord.updateChangeRecordWithNewValue(value);
        } else if (mapping.isDirectToFieldMapping()) {
            // If it is direct to field then this is most likely the result of a forced update and
            // we will need to merge this object.
            changeRecord = new DirectToFieldChangeRecord(this);
            changeRecord.setAttribute(attributeName);
            changeRecord.setMapping(mapping);
            ((DirectToFieldChangeRecord)changeRecord).setNewValue(value);
            ((DirectToFieldChangeRecord)changeRecord).setOldValue(oldValue);
            this.addChange(changeRecord);
        }
    }

    /**
     * INTERNAL:
     * This method will be used when merging changesets into other changesets.
     * It will fix references within a changeSet so that it's records point to
     * changesets within this UOWChangeSet.
     */
    public void updateReferences(UnitOfWorkChangeSet localChangeSet, UnitOfWorkChangeSet mergingChangeSet) {
        int size = getChanges().size();
        for (int index = 0; index < size; ++index) {
            ChangeRecord record = (ChangeRecord)getChanges().get(index);
            record.updateReferences(localChangeSet, mergingChangeSet);
            record.setOwner(this);
        }
    }

    /**
     * INTERNAL:
     * Override the default serialization since different parts of an ObjectChangeSet will
     * be serialized depending on the type of CacheSynchronizationType
     */
    private void writeObject(java.io.ObjectOutputStream stream) throws java.io.IOException {
        stream.write(this.cacheSynchronizationType);
        stream.writeBoolean(this.shouldBeDeleted);
        stream.writeBoolean(this.isInvalid);
        stream.writeBoolean(this.isNew);
        stream.writeBoolean(this.isAggregate);
        stream.writeObject(this.shouldModifyVersionField);
        stream.writeBoolean(this.hasVersionChange);
        if (this.shouldBeDeleted || (this.cacheSynchronizationType == ClassDescriptor.DO_NOT_SEND_CHANGES) || (this.cacheSynchronizationType == ClassDescriptor.INVALIDATE_CHANGED_OBJECTS)) {
            writeIdentityInformation(stream);
        } else {
            writeCompleteChangeSet(stream);
        }
    }

    /**
     * INTERNAL:
     * Helper method to writeObject.  Write only the information necessary to identify this
     * ObjectChangeSet to the stream
     */
    public void writeIdentityInformation(java.io.ObjectOutputStream stream) throws java.io.IOException {
        stream.writeObject(this.id);
        stream.writeObject(this.className);
        stream.writeObject(this.writeLockValue);
        stream.writeObject(this.initialWriteLockValue);
    }

    /**
     * INTERNAL:
     * Helper method to readObject.  Completely write this ObjectChangeSet to the stream
     */
    public void writeCompleteChangeSet(java.io.ObjectOutputStream stream) throws java.io.IOException {
        writeIdentityInformation(stream);
        stream.writeObject(this.changes);
        stream.writeObject(this.oldKey);
        stream.writeObject(this.newKey);
        stream.writeObject(this.protectedForeignKeys);
    }

    /**
     * INTERNAL:
     * Reset the change set's transient variables after serialization.
     */
    public void postSerialize(Object clone, UnitOfWorkChangeSet uowChangeSet, AbstractSession session) {
        this.unitOfWorkChangeSet = uowChangeSet;
        // Clone is null for recursive aggregate call, (clone will be set from root call,
        // but descriptor and mapping needs to be set here.
        if (clone != null) {
            this.cloneObject = clone;
            if (this.descriptor == null) {
                this.descriptor = session.getDescriptor(clone);
                this.classType = clone.getClass();
            }
        }
        if ((this.attributesToChanges == null) && (this.changes != null)) {
            for (ChangeRecord change : (List<ChangeRecord>)(List)this.changes) {
                getAttributesToChanges().put(change.getAttribute(), change);
            }
        }
        // Aggregates should only be cascaded to, as they need the correct descriptor from the mapping.
        if ((this.changes != null) && (this.descriptor != null) && ((clone == null) || !this.descriptor.isAggregateDescriptor())) {
            for (ChangeRecord change : (List<ChangeRecord>)(List)this.changes) {
                DatabaseMapping mapping = this.descriptor.getObjectBuilder().getMappingForAttributeName(change.getAttribute());
                change.setMapping(mapping);
                if ((mapping != null) && mapping.isAggregateObjectMapping()) {
                    AggregateChangeRecord aggregate = (AggregateChangeRecord)change;
                    ObjectChangeSet aggregateCacheSet = (ObjectChangeSet)aggregate.getChangedObject();
                    if (aggregateCacheSet != null) {
                        aggregateCacheSet.setDescriptor(mapping.getReferenceDescriptor());
                        aggregateCacheSet.postSerialize(null, uowChangeSet, session);
                    }
                }
            }
        }
    }

    /**
     * This set contains the list of attributes that must be calculated at commit time.
     */
    public Set<String> getDeferredSet() {
        if (deferredSet == null){
            this.deferredSet = new HashSet<>();
        }
        return deferredSet;
    }

    /**
     * Check to see if there are any attributes that must be calculated at commit time.
     */
    public boolean hasDeferredAttributes() {
        return ! (deferredSet == null  || this.deferredSet.isEmpty());
    }

    protected void dirtyUOWChangeSet() {
        // PERF: Set the unit of work change set to dirty avoid unnecessary message sends.
        UnitOfWorkChangeSet unitOfWorkChangeSet = (UnitOfWorkChangeSet)getUOWChangeSet();
        if (unitOfWorkChangeSet != null) {
            unitOfWorkChangeSet.setHasChanges(true);
        }
    }

    protected void updateUOWChangeSet() {
        // needed to explicitly mark parent uow as having changes.  This is needed in the
        // case of Optimistic read locking and ForceUpdate.  In these scenarios, the object
        // change set can be modified to contain 'real' changes after the uow change set has
        // computed its 'hasChanges' flag.  If not done, the change set will not be merged.
        if (getUOWChangeSet() != null) {
            ((org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet)this.getUOWChangeSet()).setHasChanges(this.hasChanges());
        }
    }

    /**
     * Rebuild writeLockValue to the expected type from user format i.e XML change set has all values as String.
     */
    protected void rebuildWriteLockValueFromUserFormat(ClassDescriptor descriptor, AbstractSession session) {
        if (descriptor.getOptimisticLockingPolicy() instanceof TimestampLockingPolicy) {
            this.writeLockValue = session.getPlatform(descriptor.getJavaClass()).getConversionManager().convertObject(this.writeLockValue, ClassConstants.JavaSqlTimestamp_Class);
            this.initialWriteLockValue = session.getPlatform(descriptor.getJavaClass()).getConversionManager().convertObject(this.initialWriteLockValue, ClassConstants.JavaSqlTimestamp_Class);
        } else if (descriptor.getOptimisticLockingPolicy() instanceof VersionLockingPolicy) {
            this.writeLockValue = session.getPlatform(descriptor.getJavaClass()).getConversionManager().convertObject(this.writeLockValue, ClassConstants.BIGDECIMAL);
            this.initialWriteLockValue = session.getPlatform(descriptor.getJavaClass()).getConversionManager().convertObject(this.initialWriteLockValue, ClassConstants.BIGDECIMAL);
        }
    }

    /**
     * INTERNAL:
     * Remove the change.
     * Used by the event mechanism to reset changes after client has updated the object within an event.
     */
    public void removeChange(String attributeName){
        Object record = getChangesForAttributeNamed(attributeName);
        if (record != null) {
            getChanges().remove(record);
            this.attributesToChanges.remove(attributeName);
        }
    }

    /**
     * Remove object represent this change set from identity map.  If change set is in XML format, rebuild pk to the correct class type from String
     */
    protected void removeFromIdentityMap(AbstractSession session) {
        session.getIdentityMapAccessor().removeFromIdentityMap(getId(), getClassType(session));
    }

    /**
     * INTERNAL:
     * Indicates whether the object in session cache should be invalidated.
     * @param original Object is from session's cache into which the changes are about to be merged, non null.
     * @param session AbstractSession into which the changes are about to be merged;
     */
    public boolean shouldInvalidateObject(Object original, AbstractSession session) {
        // Either no optimistic locking or no version change.
        if (optimisticLockingPolicy == null) {
            return false;
        }
        if (session.isRemoteSession()){
            //remote unit of work not supported as version values in UOW will be updated
            //when the committed UOW is received on the client.  That updated value will be
            //set in the UOW cache when the changeset is calculated giving the changeset the
            //incorrect initialWriteLockValue value
            //version number comparison will still be completed later.
            return false;
        }

        if(isInvalid()) {
            return true;
        }

        Object originalWriteLockValue = optimisticLockingPolicy.getWriteLockValue(original, getId(), session);

        // initialWriteLockValue and originalWriteLockValue are not equal.
        // Example:
        // original registered in uow with version 1 (originalWriteLockValue);
        // uow.beginEarlyTransaction();
        // custom update run through the uow changes the version on the object in the db to 2;
        // the clone is refreshed - now it has version 2;
        // on uow.commit or uow.writeChanges changeSet is created with initialWriteLockValue = 2;
        // The original in the cache should be invalidated - the custom update would not be reflected after merge.
        if (this.initialWriteLockValue == null){
            if (this.hasChanges()){
                return true; // no initial version was available but we will be merging changes with unknown version force invalidation
            }else{
                return false;  // don't invalidate as we are not merging anything anyway
            }
        }

        if (originalWriteLockValue != null && optimisticLockingPolicy.compareWriteLockValues(initialWriteLockValue, originalWriteLockValue) != 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * INTERNAL:
     * PERF: Return the session cache-key, cached during the merge.
     */
    public CacheKey getActiveCacheKey()  {
        return activeCacheKey;
    }

    /**
     * INTERNAL:
     * PERF: Set the session cache-key, cached during the merge.
     */
    public void setActiveCacheKey(CacheKey activeCacheKey)  {
        this.activeCacheKey = activeCacheKey;
    }

    /**
     * ADVANCED
     * Returns true if this ObjectChangeSet should be recalculated after changes in event
     */
    @Override
    public boolean shouldRecalculateAfterUpdateEvent() {
        return shouldRecalculateAfterUpdateEvent;
    }

    /**
     * ADVANCED
     * Set whether this ObjectChangeSet should be recalculated after changes in event
     */
    @Override
    public void setShouldRecalculateAfterUpdateEvent(boolean shouldRecalculateAfterUpdateEvent) {
        this.shouldRecalculateAfterUpdateEvent = shouldRecalculateAfterUpdateEvent;
    }

    public boolean hasVersionChange() {
        return hasVersionChange;
    }

    public void setHasVersionChange(boolean hasVersionChange) {
        this.hasVersionChange = hasVersionChange;
    }

    public int getCacheSynchronizationType() {
        return cacheSynchronizationType;
    }

    public void setCacheSynchronizationType(int cacheSynchronizationType) {
        this.cacheSynchronizationType = cacheSynchronizationType;
    }

    public void setIsInvalid(boolean isInvalid) {
        this.isInvalid = isInvalid;
    }
    
    public AbstractRecord getProtectedForeignKeys() {
        return this.protectedForeignKeys;
    }
    
    public void setProtectedForeignKeys(AbstractRecord protectedForeignKeys) {
        this.protectedForeignKeys = protectedForeignKeys;
    }
    
    public boolean hasProtectedForeignKeys() {
        return (this.protectedForeignKeys != null) && (this.protectedForeignKeys.size() > 0);
    }

}

