/*
 * Copyright (c) 1998, 2020 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.sdo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import commonj.sdo.ChangeSummary;
import commonj.sdo.DataGraph;
import commonj.sdo.DataObject;
import commonj.sdo.Property;
import commonj.sdo.Sequence;
import commonj.sdo.helper.HelperContext;
import org.eclipse.persistence.sdo.helper.ListWrapper;
import org.eclipse.persistence.sdo.helper.SDOCopyHelper;

/**
 * <p><b>Purpose</b>:A change summary is used to record changes to DataObjects.
 * <p><b>Responsibilities</b>:<ul>
 * <li> Track changes to DataObjects that are within the scope of this ChangeSummary (based on the root object of the Changesummary).
 * <li> Track if those DataObjects are created, modified or deleted.
 * <li> Return the values at the time that ChangeSummary logging was turned on for DataObjects in scope.
 * </ul>
 * <p>This class is implemented as a Memento (283) [GOF - Gamma, Helm, Johnson, Vlissides] Design Pattern.<br>
 * (Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.)<br>
 * <p>The class also realizes some aspects of the Command (233) Pattern - the undo-able operation part (from the first change).<br>
 * (Encapsulate a request as an object, thereby letting you parameterize clients with different requests,
 * queue or log requests, and support undo-able operations.)
 */
public class SDOChangeSummary implements ChangeSummary {
    private SDODataObject rootDataObject;
    private boolean logging;

    //loggingMapping is the boolean that's mapped in OX, we don't really want to turn
    //on logging until after the XML has all been processed at which time we set the
    //real logging boolean
    private boolean loggingMapping;
    private DataGraph dataGraph;
    private List createdList;
    private List deletedList;
    private Map deepCopies;
    private List createdXPaths;//for ox mapping

    /** The deletedXPaths field is picked up reflectively during marshal/unmarshal operations. */
    @SuppressWarnings("unused") private List deletedXPaths; //for ox mapping
    private List modifiedDoms;
    private Map unsetPropsMap;

    /** To implement ChangeSummary undo we require a copy of the original state of our model.
     * The originalValueStores will be populated when we start logging - it will then point to the
     * currentValueStore while the currentValueStore will be shallow copied (its child ValueStores
     * are shared between both ValueStores)
     */
    private Map originalValueStores;// HashMap<DataObject, ValueStore>
    private Map originalElements;

    // old values
    private Map oldContainer;// Key is DataObject, value is DataObject
    private Map oldContainmentProperty;// Key is DataObject, value is Property

    /** Cache map of originalSequences Map<DataObject, Sequence> */
    private Map oldSequences;// Key is DataObject, value is Sequence

    /** Map of originalSequence Map<DataObject, Sequence> */
    private Map originalSequences;// Key is DataObject, value is Sequence
    private Map unsetOCPropsMap;

    /** A HashMap of List objects keyed off SDODataObject, null key:value permitted */
    private Map oldSettings;// List of SDOSettings

    /** */
    private Map reverseDeletedMap;

    /** Hold the context containing all helpers so that we can preserve inter-helper relationships */
    private HelperContext aHelperContext;

    public SDOChangeSummary() {
        // HelperContext is set during unmarshalling in SDOUnmarshalListener
        createdList = new ArrayList();
        deepCopies = new HashMap();
        deletedList = new ArrayList();
        oldSettings = new HashMap();
        oldContainer = new HashMap();
        oldContainmentProperty = new HashMap();
        unsetPropsMap = new HashMap();
        unsetOCPropsMap = new HashMap();
        originalValueStores = new HashMap();
        originalElements = new HashMap();
        reverseDeletedMap = new HashMap();
    }

    public SDOChangeSummary(SDODataObject dataObject, HelperContext aContext) {
        this();
        aHelperContext = aContext;
        rootDataObject = dataObject;
    }

    public SDOChangeSummary(SDODataGraph dataGraph, HelperContext aContext) {
        this();
        aHelperContext = aContext;
        this.dataGraph = dataGraph;
    }

    /**
     * Indicates whether change logging is on (<code>true</code>) or off (<code>false</code>).
     * @return <code>true</code> if change logging is on.
     * @see #beginLogging
     * @see #endLogging
     */
    @Override
    public boolean isLogging() {
        return logging;
    }

    /**
     * INTERNAL:
    * Set flag created value.
    * @param created   flag created's new value.
    */
    public void setCreated(DataObject anObject, boolean created) {
        if (getRootObject() == anObject) {
            return;
        }

        // Explicitly clear the flag
        if (isLogging() && !created) {
            createdList.remove(anObject);
        }

        if (isLogging() && !isCreated(anObject)) {
            if (created) {
                // remove from other sets
                deletedList.remove(anObject);
                // add to set
                createdList.add(anObject);
            }
        }
    }

    /**
     * INTERNAL:
    * Set flag modified value.
    * @param deleted   flag modified's new value.
    */
   public boolean setDeleted(DataObject anObject, boolean deleted) {
        if (getRootObject() == anObject) {
            return false;
        }

        // Explicitly clear the flag
        if (isLogging() && !deleted) {
            deletedList.remove(anObject);
        }

        if (isLogging() && !this.isDeleted(anObject)) {
            if (deleted) {
                // remove from other sets
                if(isCreated(anObject)){
                  createdList.remove(anObject);

                  oldSettings.remove(anObject);
                  originalValueStores.remove(anObject);
                  originalElements.remove(anObject);
                  return false;
                }else {
                  pauseLogging();
                  deletedList.add(anObject);
                  resumeLogging();
                }
            }
        }
        return true;
    }

    /**
      * INTERNAL:
     * @param aKey
     * @param aValue
     * void
     */
    public void setOldContainer(SDODataObject aKey, DataObject aValue) {
        oldContainer.put(aKey, aValue);
    }

    /**
     * INTERNAL:
     *
     * @return
     */
    public Map getOldContainers() {
        return oldContainer;
    }

    /**
     * INTERNAL:
     * @param aKey DataObject
     * @param aValue Property
     * void
     *
     */
    public void setOldContainmentProperty(SDODataObject aKey, Property aValue) {
        oldContainmentProperty.put(aKey, aValue);
    }

    /**
     * INTERNAL:
     * @param aKey DataObject
     * @param aValue Property
     * void
     *
     */
    public void setOldSequence(SDODataObject aKey, Sequence aValue) {
        getOldSequences().put(aKey, aValue);
    }

    /**
     * Returns the {@link DataGraph data graph} associated with this change summary or null.
     * @return the data graph.
     * @see DataGraph#getChangeSummary
     */
    @Override
    public DataGraph getDataGraph() {
        return dataGraph;
    }

    /**
     * Returns a list consisting of all the {@link DataObject data objects} that have been changed while {@link #isLogging logging}.
     * <p>
     * The {@link #isCreated new} and {@link #isModified modified} objects in the List are references to objects
     * associated with this ChangeSummary.
     * The {@link #isDeleted deleted} objects in the List are references to objects
     * at the time that event logging was enabled;
     * <p> Each changed object must have exactly one of the following methods return true:
     *   {@link #isCreated isCreated},
     *   {@link #isDeleted isDeleted}, or
     *   {@link #isModified isModified}.
     * @return a list of changed data objects.
     * @see #isCreated(DataObject)
     * @see #isDeleted(DataObject)
     * @see #isModified(DataObject)
     */
    @Override
    public List getChangedDataObjects() {
        // merge all the sets
        ArrayList aList = new ArrayList();
        aList.addAll(getModified());
        if (deletedList != null) {
            aList.addAll(deletedList);
        }
        if (createdList != null) {
            aList.addAll(createdList);
        }
        return aList;
    }

    /**
     * INTERNAL:
     * Return all modified objects
     * @return
     * Set
     */
    public List getModified() {
        ArrayList modifiedList = new ArrayList();
        getModified(rootDataObject, modifiedList);
        return modifiedList;
    }

    private void getModified(SDODataObject sdoDataObject, List modifiedList) {
        if(null == sdoDataObject) {
            return;
        }

        if(isModified(sdoDataObject)) {
            modifiedList.add(sdoDataObject);
        }
        List<Property> properties = sdoDataObject.getInstanceProperties();
        for(int x=0; x<properties.size(); x++) {
            Property property = properties.get(x);
            if(property.isContainment()) {
                if(property.isMany()) {
                    List<SDODataObject> dataObjects = sdoDataObject.getList(property);
                    for(int y=0; y<dataObjects.size(); y++) {
                        getModified(dataObjects.get(y), modifiedList);
                    }
                } else {
                    if ((property.getType() != null) && !(((SDOType)property.getType()).isChangeSummaryType())) {
                        getModified(sdoDataObject.getDataObject(property), modifiedList);
                    }
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Return all deleted objects
     * @return
     * Set
     */
    public List getDeleted() {
        return deletedList;
    }

    /**
     * INTERNAL:
     * Return all created objects
     * @return
     * Set
     */
    public List getCreated() {
        return createdList;
    }

    /**
     * Returns whether or not the specified data object was created while {@link #isLogging logging}.
     * Any object that was added to the scope
     * but was not in the scope when logging began,
     * will be considered created.
     * @param dataObject the data object in question.
     * @return <code>true</code> if the specified data object was created.
     * @see #getChangedDataObjects
     */
    @Override
    public boolean isCreated(DataObject dataObject) {
        return (createdList != null) && createdList.contains(dataObject);
    }

    /**
     * Returns whether or not the specified data object was deleted while {@link #isLogging logging}.
     * Any object that is not in scope but was in scope when logging began
     * will be considered deleted.
     * @param dataObject the data object in question.
     * @return <code>true</code> if the specified data object was deleted.
     * @see #getChangedDataObjects
     */
    @Override
    public boolean isDeleted(DataObject dataObject) {
        return (deletedList != null) && deletedList.contains(dataObject);
    }

    /**
     * Returns whether or not the specified data object was updated while {@link #isLogging logging}.
     * An object that was contained in the scope when logging began
     * and remains in the scope when logging ends will be considered potentially modified.
     * <p> An object considered modified must have at least one old value setting.
     * @param dataObject the data object in question.
     * @return <code>true</code> if the specified data object was modified.
     * @see #getChangedDataObjects
     */
    @Override
    public boolean isModified(DataObject dataObject) {
        // a modified data object is present in the original value
        // stores list and has not been deleted
        if (this.originalValueStores.get(dataObject) == null || isDeleted(dataObject)) {
            return false;
        }
        return true;
    }

    /**
     * Returns a list of {@link ChangeSummary.Setting settings}
     * that represent the property values of the given <code>dataObject</code>
     * at the point when logging {@link #beginLogging() began}.
     * <p>In the case of a {@link #isDeleted(DataObject) deleted} object,
     * the List will include settings for all the Properties.
     * <p> An old value setting indicates the value at the
     * point logging begins.  A setting is only produced for
     * {@link #isModified modified} objects if
     * either the old value differs from the current value or
     * if the isSet differs from the current value.
     * <p> No settings are produced for {@link #isCreated created} objects.
     * @param dataObject the object in question.
     * @return a list of settings.
     * @see #getChangedDataObjects
     */
    @Override
    public List getOldValues(DataObject dataObject) {
        if ((dataObject == null) || (!isDeleted(dataObject) && ((((SDODataObject)dataObject).getChangeSummary() != null) && (((SDODataObject)dataObject).getChangeSummary() != this)))) {
            return new ArrayList();
        }
        if (!isCreated(dataObject) && isDirty(dataObject)) {
            List oldSettingsList = new ArrayList();
            for (int i = 0; i < dataObject.getInstanceProperties().size(); i++) {
                SDOProperty nextProp = (SDOProperty)dataObject.getInstanceProperties().get(i);
                Setting setting = getOldValueForChangedDataObject(dataObject, nextProp);
                if (setting != null) {
                    oldSettingsList.add(setting);
                }
            }

            List openProps = (List)getUnsetOCPropertiesMap().get(dataObject);
            if(openProps != null){
              for(int i=0; i< openProps.size(); i++){
                SDOProperty nextProp = (SDOProperty)openProps.get(i);
                Setting setting = getOldValueForChangedDataObject(dataObject, nextProp);
                  if (setting != null) {
                      oldSettingsList.add(setting);
                  }
              }
            }

            return oldSettingsList;
        }

        return new ArrayList();// Note: spec did not mention null value case.
    }

    /**
     * INTERNAL:
     *
     * @param dataObject
     * @return
     */
    public List getUnsetProps(DataObject dataObject) {
        //call getOldValues to populate oldSettings which will populate unsetPropsMap
        getOldValues(dataObject);
        Object value = unsetPropsMap.get(dataObject);
        if (value == null) {
            return new ArrayList();
        }
        return (List)value;

    }

    /**
     * INTERNAL:
     * Return the entire HashMap of lists of open content properties that were unset
     * keyed on dataObject
     * @return
     */
    public Map getUnsetOCPropertiesMap() {
        return unsetOCPropsMap;
    }

    /**
     * INTERNAL:
     * Return a List containing all open content properties that were unset
     * @param dataObject
     * @return
     */
    public List getUnsetOCProperties(DataObject dataObject) {
        Object value = unsetOCPropsMap.get(dataObject);
        if (null == value) {
            return new ArrayList();
        }
        return (List)value;
    }

    /**
     * INTERNAL:
     * Add an open content property that has been unset to the list keyed on dataObject
     * @param dataObject
     * @param ocKey
     */
    public void setUnsetOCProperty(DataObject dataObject, Property ocKey) {
        Object value = unsetOCPropsMap.get(dataObject);
        if (null == value) {
            // create a new list and populate
            List aList = new ArrayList();
            aList.add(ocKey);
            unsetOCPropsMap.put(dataObject, aList);
        } else {
            // dont replace existing key (ie we readd a previously unset oc property)
            if (!((List)value).contains(ocKey)) {
                ((List)value).add(ocKey);
            }
        }
    }

    /**
     * INTERNAL:
     * Delete an open content property from the list of unset oc properties keyed on dataObject
     * @param dataObject
     * @param ocKey
     */
    public void removeUnsetOCProperty(DataObject dataObject, Property ocKey) {
        Object value = unsetOCPropsMap.get(dataObject);
        if (value != null) {
            // if we referenced the property - check if it is the only one left in the map value
            if (((List)value).remove(ocKey)) {
                if(!(((List)value).size() > 0)) {
                    unsetOCPropsMap.remove(dataObject);
                }
            }
        }
    }

    /**
     * Clears the List of {@link #getChangedDataObjects changes} and turns change logging on.
     * No operation occurs if logging is already on.
     * @see #endLogging
     * @see #isLogging
     */
    @Override
    public void beginLogging() {
        if (!logging) {
            logging = true;
            loggingMapping = true;
            resetChanges();
            rootDataObject.resetChanges();
        }
    }

    /**
     * INTERNAL:
     * Turn both logging flags back on.
     */
    public void resumeLogging() {
        if (!logging) {
            logging = true;
            loggingMapping = true;
        }
    }

    /**
     * An implementation that requires logging may throw an UnsupportedOperationException.
     * Turns change logging off.  No operation occurs if logging is already off.
     * @see #beginLogging
     * @see #isLogging
     */
    @Override
    public void endLogging() {
        logging = false;
        loggingMapping = false;
        //October 12, 1007 - as per the spec do not clear anything on Changesummary on endLogging
    }

    /**
     * INTERNAL:
     * Turn both logging flags on.
     */
    public void pauseLogging() {
        logging = false;
        loggingMapping = false;
    }

    /**
     * INTERNAL:
     * Called from beginLogging and undoChanges
     */
    private void resetChanges() {
        createdList.clear();
        deletedList.clear();
        // See spec. p.30 "List of changed DataObjects cleared"
        oldSettings.clear();
        deepCopies.clear();
        oldContainer.clear();
        oldContainmentProperty.clear();
        unsetPropsMap.clear();
        unsetOCPropsMap.clear();
        originalValueStores.clear();
        originalElements.clear();
        reverseDeletedMap.clear();
        getOldSequences().clear();
        getOriginalSequences().clear();
    }

    /**
     * Returns the ChangeSummary root DataObject - the object from which
     * changes are tracked.
     * When a DataGraph is used, this is the same as getDataGraph().getRootObject().
     * @return the ChangeSummary root DataObject
     */
    @Override
    public SDODataObject getRootObject() {
        return rootDataObject;
    }

    /**
     * Returns a {@link ChangeSummary.Setting setting} for the specified property
     * representing the property value of the given <code>dataObject</code>
     * at the point when logging {@link #beginLogging() began}.
     * <p>Returns null if the property was not modified and
     * has not been {@link #isDeleted(DataObject) deleted}.
     * @param dataObject the object in question.
     * @param property the property of the object.
     * @return the Setting for the specified property.
     * @see #getChangedDataObjects
     */
    @Override
    public SDOChangeSummary.Setting getOldValue(DataObject dataObject, Property property) {
        if ((dataObject == null) || (!isDeleted(dataObject) && ((((SDODataObject)dataObject).getChangeSummary() != null) && (((SDODataObject)dataObject).getChangeSummary() != this)))) {
            return null;
        }

        if (!isCreated(dataObject) && isDirty(dataObject)) {
            return getOldValueForChangedDataObject(dataObject, (SDOProperty) property);
        }
        return null;
    }

    /**
     * INTERNAL:
    * @param dataObject which is not null and not created and is dirty in the scope of this changesummary
    * @param property
    * @return new or already existing Setting
    */
    private ChangeSummary.Setting getOldValueForChangedDataObject(DataObject dataObject, SDOProperty property) {
        if ((null == property) || property.getType().isChangeSummaryType()) {
            return null;
        }
        Setting setting = getPropertyInOldSettings(dataObject, property);
        if (setting == null) {
            SDODataObject sdoDataObject = ((SDODataObject)dataObject);
            boolean isDeleted = isDeleted(dataObject);
            Object oldValue = getPropertyInternal(sdoDataObject, property);
            Object currentValue = sdoDataObject.getPropertyInternal(property);
            boolean isSet = sdoDataObject.isSetInternal(property);
            boolean wasSet = wasSet(sdoDataObject, property);

            if (property.isMany()) {
                currentValue = ((ListWrapper)currentValue).getCurrentElements();
                if (isDirty(((ListWrapper)oldValue))) {
                    List elements = (List)getOriginalElements().get(oldValue);
                    oldValue = new ArrayList(elements);

                    if (!property.getType().isDataType()) {
                        for (int i = 0; i < ((List)oldValue).size(); i++) {
                            Object next = ((List)oldValue).get(i);

                            Object deepCopy = getOrCreateDeepCopy((DataObject)next);
                            ((List)oldValue).set(i, deepCopy);
                        }
                    }
                } else {
                    oldValue = currentValue;
                }
            }
            if (isDeleted || ((wasSet != isSet) || (oldValue != currentValue))) {
                if ((oldValue != null) && !property.getType().isDataType()) {
                    if (oldValue instanceof DataObject) {
                        oldValue = getOrCreateDeepCopy((DataObject)oldValue);
                    }
                }
                setting = buildAndAddOldSetting((SDODataObject)dataObject, property, oldValue, wasSet);
            }
        }
        return setting;
    }

    /**
     * INTERNAL:
     *
     * @param dataObject
     * @param property
     * @param value
     * @param isSet
     * @return
     */
    private Setting buildAndAddOldSetting(SDODataObject dataObject, Property property, Object value, boolean isSet) {
        SDOSetting setting = new SDOSetting(property, value);
        setting.setIsSet(isSet);

        if (oldSettings.get(dataObject) == null) {
            List aList = new ArrayList();
            aList.add(setting);
            oldSettings.put(dataObject, aList);
        } else {
            List theList = (List)oldSettings.get(dataObject);
            theList.add(setting);
        }

        if (!setting.isSet()) {
            List theList = (List)unsetPropsMap.get(dataObject);
            if (theList == null) {
                List aList = new ArrayList();
                aList.add(setting.getProperty().getName());
                unsetPropsMap.put(dataObject, aList);
            } else {
                if (!theList.contains(setting.getProperty().getName())) {
                    theList.add(setting.getProperty().getName());
                }
            }
        }

        return setting;
    }

    /**
     * Returns the value of the {@link DataObject#getContainer container} data object
     * at the point when logging {@link #beginLogging() began}.
     * @param dataObject the object in question.
     * @return the old container data object.
     */
    @Override
    public SDODataObject getOldContainer(DataObject dataObject) {
        return (SDODataObject) oldContainer.get(dataObject);
    }

    /**
     * Returns the value of the {@link DataObject#getContainmentProperty containment property} data object property
     * at the point when logging {@link #beginLogging() began}.
     * @param dataObject the object in question.
     * @return the old containment property.
     */
    @Override
    public SDOProperty getOldContainmentProperty(DataObject dataObject) {
        return (SDOProperty) oldContainmentProperty.get(dataObject);
    }

    /**
     * Returns the value of the {@link DataObject#getSequence sequence} for the data object
     * at the point when logging {@link #beginLogging() began}.
     * @param dataObject the object in question.
     * @return the old containment property.
     */
    @Override
    public SDOSequence getOldSequence(DataObject dataObject) {
        if ((dataObject == null) || (!isDeleted(dataObject) && ((((SDODataObject)dataObject).getChangeSummary() != null) && (((SDODataObject)dataObject).getChangeSummary() != this)))) {
            return null;
        }
        if (!isCreated(dataObject) && dataObject.getType().isSequenced()) {
            // check cache first
            if (getOldSequences().containsKey(dataObject)) {
                return (SDOSequence) getOldSequences().get(dataObject);
            }

            // no sequence - get from the original sequence map
            SDOSequence originalSeq = (SDOSequence) getOriginalSequences().get(dataObject);
            if (originalSeq == null) {
                originalSeq = (SDOSequence) dataObject.getSequence();
            }

            SDOSequence seqWithDeepCopies = new SDOSequence((SDODataObject) dataObject);
            for (int i = 0; i < originalSeq.size(); i++) {
                // setting/value may be null in some cases
                Object nextOriginalSettingValue = originalSeq.getValue(i);
                if (nextOriginalSettingValue == null) {
                    continue;
                }

                // property may be null if the setting contains unstructured text
                SDOProperty nextOriginalSettingProp = originalSeq.getProperty(i);
                if (nextOriginalSettingProp == null) {
                    // handle unstructured text
                    seqWithDeepCopies.addText(nextOriginalSettingValue.toString());
                } else if (nextOriginalSettingProp.getType().isDataType()) {
                    // handle simple types
                    seqWithDeepCopies.addSettingWithoutModifyingDataObject(nextOriginalSettingProp, nextOriginalSettingValue, false);
                } else {
                    // handle complex types
                    seqWithDeepCopies.addSettingWithoutModifyingDataObject(nextOriginalSettingProp, getOrCreateDeepCopy((DataObject) nextOriginalSettingValue), false);
                }
            }
            // store deep copy of old sequence in cache
            getOldSequences().put(dataObject, seqWithDeepCopies);
            return seqWithDeepCopies;
        }
        return null;
    }

    /**
     * This method is intended for use by service implementations only.
     * Undoes all changes in the log to restore the tree of
     * DataObjects to its original state when logging began.
     * isLogging() is unchanged.  The log is cleared.
     * @see #beginLogging
     * @see #endLogging
     * @see #isLogging
     */
    @Override
    public void undoChanges() {

        /**
         * See Jira SDO-109/107 and 125/225 for open issues with move optimization
         * See bug#5882923 for smart local undo via set()/unset()
         */
        Property oldProp = getOldContainmentProperty(rootDataObject);
        String oldName = null;
        if (oldProp != null) {
            oldName = oldProp.getName();
        }
        rootDataObject.undoChanges(true, this, getOldContainer(rootDataObject), oldName);
        resetChanges();
        rootDataObject.resetChanges();
    }

    /**
     * INTERNAL:
     * Set the root DataObject for this ChangeSummary.
     * @param dataObject  the root of DataObject tree this ChangeSummary belongs to
     */
    public void setRootDataObject(DataObject dataObject) {
        rootDataObject = (SDODataObject)dataObject;
    }

    /**
     * INTERNAL:
    * Used by CopyHelper to set logging when creating a copy of a changesummary
    * @param logging      logging status
    */
    public void setLogging(boolean logging) {
        if (logging) {
            beginLogging();
        } else {
            endLogging();
        }

        this.loggingMapping = logging;
    }

    /**
     * INTERNAL:
     * Check if a property is in its DataObject's oldsetting list
     * @param dataObject      property's owner
     * @param property        property to be checked
     * @return                property's Setting if this property is in list
     */
    private ChangeSummary.Setting getPropertyInOldSettings(DataObject dataObject, Property property) {
        Iterator iterOldSettings = null;
        List aList = (List)oldSettings.get(dataObject);
        if (aList != null) {
            iterOldSettings = aList.iterator();
            ChangeSummary.Setting curSetting;
            while (iterOldSettings.hasNext()) {
                curSetting = (ChangeSummary.Setting)iterOldSettings.next();
                if (curSetting.getProperty().equals(property)) {
                    return curSetting;
                }
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     * Set the helperContext if the default SDOChangeSummary constructor was used
     * @param helperContext
     */
    public void setHelperContext(HelperContext helperContext) {
        aHelperContext = helperContext;
    }

    /**
     * INTERNAL:
     *
     * @param createdXPathsList
     */
    public void setCreatedXPaths(List createdXPathsList) {
        createdXPaths = createdXPathsList;
    }

    /**
     * INTERNAL:
     *
     * @return
     */
    public List getCreatedXPaths() {
        return createdXPaths;
    }

    /**
     * INTERNAL:
     * Return the logging state during mapping operations
     * @return logging state
     */
    public boolean isLoggingMapping() {
        return loggingMapping;
    }

    /**
     * INTERNAL:
     *
     * @param modifiedDomsList
     */
    public void setModifiedDoms(List modifiedDomsList) {
        modifiedDoms = modifiedDomsList;
    }

    /**
     * INTERNAL:
     *
     * @return
     */
    public List getModifiedDoms() {
        return modifiedDoms;
    }

    /**
     * INTERNAL:
     * The deletedXPaths field is picked up reflectively during marshal/unmarshal operations.
     * @param deletedXPathsList
     */
    public void setDeletedXPaths(List deletedXPathsList) {
        deletedXPaths = deletedXPathsList;
    }

    public Map getOldContainmentProperty() {
        return oldContainmentProperty;
    }

    public Map getOldContainer() {
        return oldContainer;
    }

    /**
     * INTERNAL:
     *
     * @param dataObject
     * @param property
     * @return
     */
    public boolean wasSet(DataObject dataObject, Property property) {
        ValueStore vs = (ValueStore)originalValueStores.get(dataObject);
        if (null == vs) {
            vs = ((SDODataObject)dataObject)._getCurrentValueStore();
        }
        if (property.isOpenContent()) {
            return vs.isSetOpenContentProperty(property);
        } else {
            return vs.isSetDeclaredProperty(((SDOProperty)property).getIndexInType());
        }
    }

    /**
     * INTERNAL:
     *
     * @param dataObject
     * @param property
     * @return
     */
    public Object getPropertyInternal(DataObject dataObject, Property property) {
        ValueStore vs = (ValueStore)originalValueStores.get(dataObject);

        if (null == vs) {
            vs = ((SDODataObject)dataObject)._getCurrentValueStore();
        }

        if (property.isOpenContent()) {
            return vs.getOpenContentProperty(property);
        } else {
            return vs.getDeclaredProperty(((SDOProperty)property).getIndexInType());
        }
    }

    /**
     * INTERNAL:
     *
     * @param dataObject
     * @param property
     * @param value
     */
    public void setPropertyInternal(DataObject dataObject, Property property, Object value) {
        ValueStore vs = (ValueStore)originalValueStores.get(dataObject);
        if (property.isOpenContent()) {
            vs.setOpenContentProperty(property, value);
        } else {
            vs.setDeclaredProperty(((SDOProperty)property).getIndexInType(), value);
        }
    }

    /**
     * INTERNAL:
     * Return the map of original ValueStores keyed on
     * @return
     */
    public Map getOriginalValueStores() {
        return originalValueStores;
    }

    /**
     * INTERNAL:
     * Return whether the <code>dataObject</code> has been modified.
     * @param dataObject
     * @return
     */
    public boolean isDirty(DataObject dataObject) {
        ValueStore vs = (ValueStore)originalValueStores.get(dataObject);
        return vs != null;
    }

    /**
     * INTERNAL:
     * Return whether the <code>aListWrapper</code> has been modified.
     * @param aListWrapper
     * @return
     */
    public boolean isDirty(ListWrapper aListWrapper) {
        Object originalList = getOriginalElements().get(aListWrapper);
        return originalList != null;
    }

    /**
     * INTERNAL:
     * Return whether the <code>aSequence</code> has been modified.
     * @param aSequence
     * @return
     */
    public boolean isDirty(SDOSequence aSequence) {
        Object originalSequence = getOriginalSequences().get(aSequence.getDataObject());
        return originalSequence != null;
    }

    /**
     * INTERNAL:
     *
     * @param dataObject
     * @param property
     */
  public void unsetPropertyInternal(DataObject dataObject, Property property) {
        ValueStore vs = (ValueStore)originalValueStores.get(dataObject);
        if (property.isMany()) {
            ListWrapper currentValue = (ListWrapper)dataObject.getList(property);
            originalElements.put(currentValue, new ArrayList());
            if (property.isOpenContent()) {
                vs.unsetOpenContentProperty(property);
            } else {
                vs.unsetDeclaredProperty(((SDOProperty)property).getIndexInType());
            }
        } else {
            if (property.isOpenContent()) {
                vs.unsetOpenContentProperty(property);
            } else {
                vs.unsetDeclaredProperty(((SDOProperty)property).getIndexInType());
            }
        }
    }

    /**
    * INTERNAL:
    * @return Map of original elements, key and value are both listwrappers
    */
    public Map getOriginalElements() {
        return originalElements;
    }

    /**
     * INTERNAL:
     * @param original
     * @return
     */
    private DataObject getOrCreateDeepCopy(DataObject original) {
        DataObject value = (DataObject)getDeepCopies().get(original);
        if (null == value) {
            DataObject undoneCopy = ((SDOCopyHelper)aHelperContext.getCopyHelper()).copy(original, this);

            // if original is null we will create only 1 key:value null:null pair
            getDeepCopies().put(original, undoneCopy);
            getReverseDeletedMap().put(undoneCopy, original);
            return undoneCopy;
        } else {
            return value;
        }
    }

    /**
     * INTERNAL:
     * @return Map of deep copies of DataObjects key is original dataobject
     */
    public Map getDeepCopies() {
        return deepCopies;
    }

    /**
     * INTERNAL:
     * @return Map of deep copies of DataObjects key is copy of dataobject
     */
    public Map getReverseDeletedMap() {
        return reverseDeletedMap;
    }

    /**
      * INTERNAL:
      * Return a map of original sequences keyed on DataObject.
      * @return Map of old Sequences
      */
    public Map getOriginalSequences() {
        if (null == originalSequences) {
            originalSequences = new HashMap();
        }
        return originalSequences;
    }

    /**
    * INTERNAL:
    * Return a map of original sequences keyed on DataObject (cached values).
    * @return Map of old Sequences that have deep copies of all DataObjects
    */
    public Map getOldSequences() {
        if (null == oldSequences) {
            oldSequences = new HashMap();
        }
        return oldSequences;
    }

    /**
     * INTERNAL:
     * Return the string representation of the receiver.
     */
    @Override
    public String toString() {
        StringBuffer aBuffer = new StringBuffer();
        aBuffer.append("ChangeSummary@");
        aBuffer.append(getClass().hashCode());
        aBuffer.append(" [logging: ");
        aBuffer.append(logging);
        aBuffer.append(", root: ");
        aBuffer.append(rootDataObject);
        List aList = getChangedDataObjects();
        if (aList != null) {
            aBuffer.append(", ");
            aBuffer.append(aList.size());
            aBuffer.append(" changes: <");
            boolean first = true;
            for (Iterator i = aList.iterator(); i.hasNext();) {
                if (first) {
                    first = false;
                } else {
                    aBuffer.append(", ");
                }
                aBuffer.append(i.next());// null values are handled
            }
        }
        aBuffer.append(">]");
        return aBuffer.toString();
    }

}
