/*
 * 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.core.helper.CoreClassConstants;
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<org.eclipse.persistence.sessions.changesets.ChangeRecord> 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<org.eclipse.persistence.sessions.changesets.ChangeRecord> 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 = 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<org.eclipse.persistence.sessions.changesets.ChangeRecord> 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, CoreClassConstants.TIMESTAMP);
            this.initialWriteLockValue = session.getPlatform(descriptor.getJavaClass()).getConversionManager().convertObject(this.initialWriteLockValue, CoreClassConstants.TIMESTAMP);
        } 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);
    }

}

