/*
 * 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.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 {@code Map<DataObject, Sequence>} */
    private Map oldSequences;// Key is DataObject, value is Sequence

    /** Map of originalSequence {@code 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();
    }

}
