/*
 * 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.helper;

import commonj.sdo.Property;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.sdo.DefaultValueStore;
import org.eclipse.persistence.sdo.SDOChangeSummary;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOSequence;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.sdo.ValueStore;
import org.eclipse.persistence.exceptions.SDOException;
import commonj.sdo.ChangeSummary;
import commonj.sdo.DataObject;
import commonj.sdo.helper.CopyHelper;
import commonj.sdo.helper.HelperContext;
import commonj.sdo.impl.HelperProvider;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.oxm.sequenced.Setting;

/**
 * <b>Purpose:</b>
 * <ul><li>A helper class for making deep or shallow copies of DataObjects.</li>
 * </ul>
 * <p>
 * <b>Responsibilities:</b>
 * <ul>
 * <li>Perform shallow and deep copy operations on {@link DataObject DataObject}s.</li>
 * </ul>
 *
 * @see org.eclipse.persistence.sdo.SDODataObject
 * @since Oracle TopLink 11.1.1.0.0
 */
public class SDOCopyHelper implements CopyHelper {

    /*
       09/12/06 - Add bidirectional property copy support
       09/16/06 - Use design #1a over #2
                           Modify 1 pass opposite property set algorithm to use 2 passes,
                           the first gathers a list of opposites, the 2nd pass iterates the list after tree completion.
                           Runtime is the same since we still need a hash lookup of the opposite DO
       09/19/06 - Adjust copy algorithm to check for opposites before checking containment
                           cont=false, opp=false -> unidirectional
                           cont=false, opp=true  -> bidirectional
                           cont=true,  opp=false -> normal containment
                           cont=true,  opp=true  -> bidirectional
                           The code for copyPropertyValue() has been moved up to copy()
                           where we use the two cached maps to set non-containment properties
       10/02/06 - Finish isMany 1-n bidirectional/unidirectional support in copy() function
       11/09/06 - Jira#129: implement HelperContext via new HelperProvider.getDefaultContext()
       01/29/07 - #5852525 handle null properties with isSet=true
       02/14/07 - #5878605 do not generate oldSettings during copy of cs with logging=true
       02/15/07 - #5878605 move double iteration of cs list in many case to single iteration
       02/23/07 - #5897730 implement ChangeSummary deep copy
       03/14/07 - p.142 limit scope of while by using for
                        - put isSet() check back into open content part of copyChangeSummary
       04/11/07 - Implement Sequence functionality
       05/01/07 - #6026714: because of enlarged scope, copy of copy sets previous iteration
                          value of unset complex setting
     */

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

    /**
     * INTERNAL:
     * This default constructor must be used in conjunction with the setHelperContext() function.
     * The custom constructor that takes a HelperContext parameter is recommended over this default constructor.
     */
    public SDOCopyHelper() {
    }

    /**
     * Constructor that takes in a HelperContext instance that contains this copyHelper.<br>
     * This is the recommended constructor.
     * @param aContext
     */
    public SDOCopyHelper(HelperContext aContext) {
        aHelperContext = aContext;
    }

    /**
     * Create a shallow copy of the DataObject dataObject:
     *   Creates a new DataObject copiedDataObject with the same values
     *     as the source dataObject for each property where
     *       property.getType().isDataType() is true.
     *   The value of such a Property property in copiedDataObject is:
     *       dataObject.get(property) for single-valued Properties
     *       (copiedDataObject.get(property) equals() dataObject.get(property)), or
     *       a List where each member is equal to the member at the
     *       same index in dataObject for multi-valued Properties
     *        copiedDataObject.getList(property).get(i) equals() dataObject.getList(property).get(i)
     *   The copied Object is unset for each Property where
     *       property.getType().isDataType() is false
     *       since they are not copied.
     *   Read-only properties are copied.
     *   A copied object shares metadata with the source object
     *     sourceDO.getType() == copiedDO.getType()
     *   If a ChangeSummary is part of the source DataObject
     *     the copy has a new, empty ChangeSummary.
     *     Logging state is the same as the source ChangeSummary.
     *
     * @param dataObject to be copied
     * @return copy of dataObject
     */
    @Override
    public DataObject copyShallow(DataObject dataObject) {
        if (null == dataObject) {
            return null;
        }
        SDODataObject copy = (SDODataObject)getHelperContext().getDataFactory().create(dataObject.getType().getURI(), dataObject.getType().getName());

        List ocListOriginal = ((SDODataObject)dataObject)._getOpenContentProperties();
        for (Iterator anOCIterator = ocListOriginal.iterator(); anOCIterator.hasNext();) {
            copy.addOpenContentProperty((Property)anOCIterator.next());
        }

        List ocAttrsListOriginal = ((SDODataObject)dataObject)._getOpenContentPropertiesAttributes();
        for (Iterator anOCAttrIterator = ocAttrsListOriginal.iterator(); anOCAttrIterator.hasNext();) {
            copy.addOpenContentProperty((Property)anOCAttrIterator.next());
        }

        List allProperties = copy.getInstanceProperties();// start iterating all copy's properties
        Iterator iterProperties = allProperties.iterator();
        while (iterProperties.hasNext()) {
            SDOProperty eachProperty = (SDOProperty)iterProperties.next();
            if (dataObject.isSet(eachProperty)) {
                Object o = getValue((SDODataObject)dataObject, eachProperty, null);
                if (eachProperty.getType().isDataType()) {
                    if (!eachProperty.getType().isChangeSummaryType()) {
                        // we defer sequence updates at this point
                        copy.setInternal(eachProperty, o, false);// make copy if current property is datatype
                    }
                }
            }
        }

        if (dataObject.getType().isSequenced()) {
            List settings = ((SDOSequence)dataObject.getSequence()).getSettings();
            for (int index = 0, size = dataObject.getSequence().size(); index < size; index++) {
                Setting nextSetting = (Setting)settings.get(index);

                Property prop = dataObject.getSequence().getProperty(index);
                if (prop == null || prop.getType().isDataType()) {
                    Setting copySetting = nextSetting.copy(copy);
                    copy.getSequence().getSettings().add(copySetting);
                    copy.getSequence().addValueToSettings(copySetting);
                }
            }
        }

        if ((copy != null) && (copy.getChangeSummary() != null) && (copy.getType().getChangeSummaryProperty() != null)) {
            if (((SDODataObject)dataObject).getChangeSummary().isLogging()) {
                copy.getChangeSummary().setLogging(true);
            }
        }

        return copy;
    }

    /**
     * Create a deep copy of the DataObject tree:
     *   Copies the dataObject and all its {@link commonj.sdo.Property#isContainment() contained}
     *     DataObjects recursively.
     *   Values of Properties are copied as in shallow copy,
     *     and values of Properties where
     *       property.getType().isDataType() is false
     *     are copied where each value copied must be a
     *       DataObject contained by the source dataObject.
     *     If a DataObject is outside the DataObject tree and the
     *       property is bidirectional, then the DataObject is skipped.
     *     If a DataObject is outside the DataObject tree and the
     *       property is unidirectional, then the same DataObject is referenced.
     *   Read-only properties are copied.
     *   If any DataObject referenced is not in the containment
     *     tree an IllegalArgumentException is thrown.
     *   If a ChangeSummary is part of the copy tree the new
     *     ChangeSummary refers to objects in the new DataObject tree.
     *     Logging state is the same as the source ChangeSummary.
     *
     * @param dataObject to be copied.
     * @return copy of dataObject
     * @throws IllegalArgumentException if any referenced DataObject
     *   is not part of the containment tree.
     */
    @Override
    public DataObject copy(DataObject dataObject) throws IllegalArgumentException {
        return copy(dataObject, null);
    }

    /**
     * Create a deep copy of the DataObject tree:
     *   Copies the dataObject and all its {@link commonj.sdo.Property#isContainment() contained}
     *     DataObjects recursively.
     *   <p>For each Property where property.type.dataType is true, the values of Properties are
     *       copied as in shallow copy,  and values of Properties where
     *       property.getType().isDataType() is false
     *     are copied where each value copied must be a
     *       DataObject contained by the source dataObject.
     *     <p>If a DataObject is outside the DataObject tree and the
     *       property is bidirectional, then the DataObject is not copied and
     *       references to the object are also not copied.
     *     <p>If a DataObject is outside the DataObject tree and the
     *       property is unidirectional, then the same DataObject is referenced.
     *   <p>Read-only properties are copied.
     *   <p>If any DataObject referenced is not in the containment
     *     tree an IllegalArgumentException is thrown.
     *   <p>If a ChangeSummary is part of the copy tree the new
     *     ChangeSummary refers to objects in the new DataObject tree.
     *     Logging state is the same as the source ChangeSummary.
     *
     * @param dataObject to be copied.
     * @return copy of dataObject
     * @throws IllegalArgumentException if any referenced DataObject
     *    is not part of the containment tree.
     */
    public DataObject copy(DataObject dataObject, SDOChangeSummary cs) throws IllegalArgumentException {
        if (null == dataObject) {
            return null;
        } else {
            // cache one side of opposite property objects as we iterate to the 2nd side - non-deleted objects only
            //* @param doMap (cache original -> copy DataObject instances to set non-containment properties after tree construction)
            HashMap doMap = new HashMap();

            //* @param propMap (cache original DO:non-containment property values to be set after tree construction)
            HashMap ncPropMap = new HashMap();

            // build object instances by recursing the tree
            SDODataObject aCopy = copyPrivate((SDODataObject)dataObject, doMap, ncPropMap, cs);

            // After the copy containment tree has been built
            // Iterate the non-containment nodes and copy all uni/bi-directional properties on the copy.
            processNonContainmentNodesPrivate(doMap, ncPropMap);

            // Iterate the map of containment nodes and populate sequenced objects in the copy.
            processContainmentSequencesPrivate(doMap, cs);

            /**
             * ChangeSummary on Root Case:
             * We only need to handle a single root element - isMany=true root elements are not valid
             * Copy changeSummary state from original to copy on all cs-root elements that are also roots.
             * Setting logging to true only after recursively setting internal properties will not create oldSettings in the copy
             * The setLogging call will create oldContainer/oldContainmentProperty entries in the copy.
             */
            if ((aCopy != null) && (aCopy.getChangeSummary() != null) && (aCopy.getType().getChangeSummaryProperty() != null)) {
                // re-reference copy objects in the copy changeSummary
                if (((SDODataObject)dataObject).getChangeSummary().isLogging()) {// switch and use resume logging
                    (aCopy.getChangeSummary()).resumeLogging();//.setLogging(true);
                }
                copyChangeSummary(((SDODataObject)dataObject).getChangeSummary(),//
                                  aCopy.getChangeSummary(), doMap);
            }
            return aCopy;
        }
    }

    /**
     * INTERNAL:
     * Iterate the non-containment nodes and copy all uni/bi-directional properties on the copy.
     * @param doMap
     * @param ncPropMap
     */
    private void processNonContainmentNodesPrivate(HashMap doMap, HashMap ncPropMap) {
        // for the doMap and ncPropMap we can either deep copy them all now or each one during rereferencing later
        // iterate nc property map and set bidirectional/unidirectional properties that are in scope
        for (Iterator ncIterator = ncPropMap.keySet().iterator(); ncIterator.hasNext();) {// p.142 limit scope of while by using for
            // get current source dataobject (the one we will set properties on)
            DataObject sourceDO = (DataObject)ncIterator.next();

            // get the list of properties for the current do
            ArrayList aList = (ArrayList)ncPropMap.get(sourceDO);

            // iterate property list
            for (Iterator propIterator = aList.iterator(); propIterator.hasNext();) {// p.142 limit scope of while by using for
                // get current property
                SDOProperty aProperty = (SDOProperty)propIterator.next();

                /*
                 * Stored in the map we have
                 * doMap: (a=key, a'=value)
                 * ncPropMap (a=key, (list of props)=value
                 * We get the copy from the doMap
                 * We get the copy of the source by doing a get on the current source do
                 */

                // get original object that sourceDO points to via current property
                Object targetDO = sourceDO.get(aProperty);

                // flag whether the property is inside the copy tree
                boolean isPropertyInsideCopyTreeScope = false;

                // get sourceDO copy that we will be setting the property on
                DataObject sourceDOCopy = null;

                // lookup copy of targetDO in map
                Object targetDOCopy = null;

                /*
                 * Handle 1-n many case
                 * For containment=true
                 *   the DO's will be cached previously, and both bidirectional (one) and unidirectional
                 *   properties will set the copy on the copy object
                 * For containment=false
                 *   the DO's will not be cached (outside the tree), only unidirectional properties
                 *   will be set using the original list
                 */
                if (aProperty.isMany()) {
                    // create new list to hold copied list items
                    ListWrapper targetList = (ListWrapper)targetDO;

                    // get source\DO copy that we will be setting the property on
                    sourceDOCopy = (DataObject)doMap.get(sourceDO);

                    // lookup copy of targetDO in map
                    targetDOCopy = new ArrayList();
                    for (int i = 0, size = targetList.size(); i < size; i++) {
                        // get sourceDO key - used as a lookup in our doMap
                        DataObject sourceDOCopyKey = (DataObject)targetList.get(i);
                        DataObject sourceDOCopyValue = (DataObject)doMap.get(sourceDOCopyKey);

                        // add copy to new list
                        if (sourceDOCopyValue != null) {
                            // bidirectional/unidirectional inside copy tree - use copy object
                            ((List)targetDOCopy).add(sourceDOCopyValue);
                        } else {
                            // non-containment properties are not cached - store original for unidirectional
                            //targetDOCopy.add(sourceDOCopyKey);
                        }
                    }

                    // check if the target copies are in our map (inside copy tree scope)
                    // when containment = false then targetDOCopy is empty
                    // Assume: all items in the list share the same property
                    isPropertyInsideCopyTreeScope = ((List)targetDOCopy).size() > 0;
                } else {
                    // handle 1-1 DataObject
                    // lookup copy of targetDO in map
                    targetDOCopy = doMap.get(targetDO);

                    // get sourceDO copy that we will be setting the property on
                    sourceDOCopy = (DataObject)doMap.get(sourceDO);

                    // check if the target copy is in our map (inside copy tree scope)
                    isPropertyInsideCopyTreeScope = targetDOCopy != null;
                }

                // set nc property if we are in the copy tree
                // check if the target copy is in our map (inside copy tree scope)
                if (isPropertyInsideCopyTreeScope) {
                    ((SDODataObject)sourceDOCopy).set(aProperty, targetDOCopy, false);
                } else {
                    // only set unidirectional properties
                    if (null == aProperty.getOpposite()) {
                        // spec 3.9.4 set property to original object when unidirectional
                        ((SDODataObject)sourceDOCopy).set(aProperty, targetDO, false);
                    }
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Make a copy of all settings on the original sequence onto the copy sequence while using a
     * cross-reference doMap that relates the original DataObject key to the copy DataObject key.
     * This function is used during deep copy and changeSummary copy.
     * @param origSequence
     * @param copySequence
     * @param doMap
     */
    private void replicateAndRereferenceSequenceCopyPrivate(SDOSequence origSequence, SDOSequence copySequence, DataObject dataObject, DataObject copy, Map doMap, SDOChangeSummary cs) {
        if (cs != null && cs.isDeleted(dataObject)) {
            origSequence = cs.getOldSequence(dataObject);
        }

        SDOProperty seqProperty = null;
        try {
            List settings = origSequence.getSettings();
            for (int index = 0, size = origSequence.size(); index < size; index++) {
                Setting nextSetting = (Setting)settings.get(index);
                seqProperty = origSequence.getProperty(nextSetting);

                if ((null == seqProperty) || seqProperty.getType().isDataType()) {
                    Setting copySetting = nextSetting.copy(copy);
                    copySequence.getSettings().add(copySetting);
                    copySequence.addValueToSettings(copySetting);
                } else {
                    Object copySeqValue = null;
                    Object origSeqValue = origSequence.getValue(index);

                    if (cs != null) {
                        Object orig = cs.getReverseDeletedMap().get(origSeqValue);
                        if (orig != null) {
                            origSeqValue = orig;
                        }
                    }

                    if (origSeqValue instanceof XMLRoot) {
                        origSeqValue = ((XMLRoot)origSeqValue).getObject();
                    }

                    // lookup copy if not null, if null then the copySeqValue will be null in the reduced scope assignment above
                    if (null != origSeqValue) {
                        copySeqValue = doMap.get(origSeqValue);
                    } else {
                        // as a secondary verification to the assignment above - make sure the copy is null as well
                        copySeqValue = null;// this assignment is however redundant in our reduced scope assignment above
                    }

                    //now we have the new value
                    Setting copySetting = nextSetting.copy(copy, copySeqValue);
                    copySequence.getSettings().add(copySetting);
                    copySequence.addValueToSettings(copySetting);
                }

                /**
                 * Move assignment inside the loop to minimize scope and to
                 * initialize the variable to null to handle the case where the original is null and
                 * no lookup is performed.
                 * Do not move the scope of this variable outside the for loop or we will end up
                 * with the previous iterations' value set for a complex object that is unset(null).
                 * see #6026714
                 */
            }
        } catch (ClassCastException cce) {// catch any failure of a DataObject cast above
            throw SDOException.foundSimpleValueForNonDataTypeProperty(seqProperty.getName());
        }
    }

    /**
     * INTERNAL:
     * Iterate the map of containment nodes and populate sequenced objects in the copy.
     * @param doMap
     */
    private void processContainmentSequencesPrivate(Map doMap, SDOChangeSummary cs) {

        /**
         * Prerequisites: - the copy tree has been built and the doMap has been
         * fully populated with containment nodes.<p> Iterate the doMap and
         * for each containment dataObject populate the sequence</p>
         */

        // iterate containment nodes
        for (Iterator cIterator = doMap.keySet().iterator(); cIterator.hasNext();) {
            DataObject cObject = (DataObject)cIterator.next();
            DataObject copyDO = (DataObject)doMap.get(cObject);

            // process sequences
            if (cObject.getType().isSequenced()) {
                SDOSequence origSequence = (SDOSequence)cObject.getSequence();

                // iterate the original object sequence - in sequence and create settings on the copy
                replicateAndRereferenceSequenceCopyPrivate(origSequence, (SDOSequence)copyDO.getSequence(), cObject, copyDO, doMap, cs);
            }
        }
    }

    /**
     * INTERNAL: Create a new uninitialized ValueStore.
     *
     * @return
     */
    private ValueStore createValueStore() {
        return new DefaultValueStore();
    }

    /**
     * INTERNAL:
     * Implement ChangeSummary deep copy
     *      Note: a copy with a CS requires the DefautlValueStore implementation
     *      because of changes outside the ValueStore interface for the dataObject field
     * DeepCopy the original changeSummary into the copy dataObject.
     * All deleted keys in originalValueStore, deletedMap, deepCopies are the same original object.
     * We require the following relationships in order to build copies of originals and copies of copies of originals.
     *     origDOtoCopyDOMap
     *         original object (deleted + current) - in original DO : copy of original object - in copy DO
     *     copyDOtoCopyOfDOMap
     *
     *     Assumptions:
     *        Property objects instances are copied only by reference - metadata is the same in the copy.
     *        Deleted objects never exist in the currentValueStore (and are therefore not in the doMap).
     *        Created and modified objects are always in the currentValueStore (and are in the doMap).
     *
     * @param anOriginalCS
     * @param aCopyCS
     * @param doMap (map of original do's (CS1) to their copy do's in (CS2))
     */
    private void copyChangeSummary(ChangeSummary anOriginalCS, ChangeSummary aCopyCS,//
                                   Map origDOCS1toCopyDOCS2Map) {
        // cast interfaces to concrete classes in one place
        SDOChangeSummary originalCS = (SDOChangeSummary)anOriginalCS;
        SDOChangeSummary copyCS = (SDOChangeSummary)aCopyCS;

        // handled by copy constructor
        // map of copy of original ListWrapper (CS2) to its new copy of a copy (CS2) - link ValueStores to Elements
        HashMap copyListWrapperCS2toCopyOfListCS2Map = new HashMap();

        // in the absence of a ListWrapper.getProperty() we keep a map
        HashMap propertyToOriginalListMap = new HashMap();

        /**
         * In 3 parts we add deleted objects to the global doMap and copy modified, created nodes
         **/

        // fields that need re-referencing from original to copy
        DataObject anOriginalObject = null;
        DataObject aCopyOfOriginalObject = null;

        // iterate deleted objects
        for (Iterator anIterator = originalCS.getDeleted().iterator(); anIterator.hasNext();) {
            anOriginalObject = (DataObject)anIterator.next();
            aCopyOfOriginalObject = copy(anOriginalObject, null);
            // fix deletedList
            copyCS.getDeleted().add(aCopyOfOriginalObject);
            // Assumption check do map before a possible re-add - reset()
            if (null == origDOCS1toCopyDOCS2Map.get(anOriginalObject)) {
                // add temp map of original  : copy of original
                origDOCS1toCopyDOCS2Map.put(anOriginalObject, aCopyOfOriginalObject);
            }
        }

        // iterate created objects
        for (Iterator aIterator = originalCS.getCreated().iterator(); aIterator.hasNext();) {
            copyCS.getCreated().add(origDOCS1toCopyDOCS2Map.get(aIterator.next()));
        }

        // add modified objects
        for (Iterator anIterator = originalCS.getModified().iterator(); anIterator.hasNext();) {
            copyCS.getModified().add(origDOCS1toCopyDOCS2Map.get(anIterator.next()));
        }

        /**
         * Fix originalValueStores by deep copying the original dataObject:key and the original valueStore:value
         * key is original deleted object in [deepCopies] - value is copy of the ValueStore
         */
        ValueStore aVSCopy = null;
        ValueStore aVSOriginal = null;
        for (Iterator anIterator = originalCS.getOriginalValueStores().keySet().iterator();
                 anIterator.hasNext();) {
            anOriginalObject = (DataObject)anIterator.next();
            // deep copy to get corresponding copy DataObject (deleted objects were added to doMap)
            aCopyOfOriginalObject = (DataObject)origDOCS1toCopyDOCS2Map.get(anOriginalObject);

            /**
             * Recursively shallow-copy elements (by iterating the ovs map and iterating the properties of each item)
             * Fix the dataObject pointer
             */
            aVSCopy = createValueStore();
            aVSOriginal = (ValueStore)originalCS.getOriginalValueStores().get(anOriginalObject);
            // changes made to the copy VS must not affect the original -hence the dataObject field must be a copy of the original
            aVSCopy.initialize(aCopyOfOriginalObject);
            Object aVSPropertyItem = null;

            // get the # of non-opencontent properties for the object holding the CS - do not use DVS.getTypePropertyValues()
            for (int size = anOriginalObject.getType().getDeclaredProperties().size(), i = 0;
                 i < size; i++) {
                aVSPropertyItem = aVSOriginal.getDeclaredProperty(i);
                // only iterate set properties
                if (aVSOriginal.isSetDeclaredProperty(i)) {
                    // shallow copy the object values
                    // handle single case
                    SDOProperty currentProperty = (SDOProperty) anOriginalObject.getType().getDeclaredProperties().get(i);
                    if (currentProperty.isMany()) {
                        propertyToOriginalListMap.put(aVSPropertyItem, currentProperty);

                        // handle many case - handled by originalElements
                        // container DO must be in our reference map
                        SDODataObject copyContainer = (SDODataObject)origDOCS1toCopyDOCS2Map.get(anOriginalObject);
                        ListWrapper aCopyOfListCopy = (ListWrapper)((DataObject)copyContainer).getList(currentProperty);

                        // add reference of new copy of original List keyed on original List
                        copyListWrapperCS2toCopyOfListCS2Map.put((anOriginalObject).getList(currentProperty), aCopyOfListCopy);
                        aVSCopy.setDeclaredProperty(i, aCopyOfListCopy);
                    } else {
                        // COMPLEX SINGLE
                        if (!currentProperty.getType().isDataType()) {
                            // are we using the cast to DataObject as a sort of instance check that would throw a CCE?
                            aVSCopy.setDeclaredProperty(i, origDOCS1toCopyDOCS2Map.get(aVSPropertyItem));
                        } else {
                            // SIMPLE SINGLE
                            // skip changeSummary property
                            if (!currentProperty.getType().isChangeSummaryType()) {
                                // simple singles set
                                aVSCopy.setDeclaredProperty(i, aVSPropertyItem);
                            }
                        }
                    }
                }
            }

            // create list of unset and current open content properties
            List ocPropertiesList = new ArrayList();
            ocPropertiesList.addAll(originalCS.getUnsetOCProperties(anOriginalObject));
            // add existing properties
            ocPropertiesList.addAll(((SDODataObject)anOriginalObject)._getOpenContentProperties());
            ocPropertiesList.addAll(((SDODataObject)anOriginalObject)._getOpenContentPropertiesAttributes());
            // iterate existing open content properties
            for (Iterator i = ocPropertiesList.iterator(); i.hasNext();) {
                SDOProperty ocProperty = (SDOProperty)i.next();
                if (aVSOriginal.isSetOpenContentProperty(ocProperty)) {
                    // get oc value
                    Object anOCPropertyItem = aVSOriginal.getOpenContentProperty(ocProperty);

                    // get oc copy - shallow copy the object values
                    if (ocProperty.isMany()) {
                        // handle many case - handled by originalElements
                        // container DO must be in our reference map
                        SDODataObject copyContainer = (SDODataObject)origDOCS1toCopyDOCS2Map.get(anOriginalObject);
                        ListWrapper aCopyOfListCopy = (ListWrapper)((DataObject)copyContainer).getList(ocProperty);

                        // add reference of new copy of original List keyed on original List
                        copyListWrapperCS2toCopyOfListCS2Map.put((anOriginalObject).getList(ocProperty), aCopyOfListCopy);
                        aVSCopy.setOpenContentProperty(ocProperty, aCopyOfListCopy);
                    } else {
                        // handle complex single case
                        if (!ocProperty.getType().isDataType()) {
                            aVSCopy.setOpenContentProperty(ocProperty, origDOCS1toCopyDOCS2Map.get(aVSPropertyItem));
                        } else {
                            // simple singles set
                            aVSCopy.setOpenContentProperty(ocProperty, anOCPropertyItem);
                        }
                    }
                }
            }

            // set the copy map entry keyed on copy with value a deep copy of the copy
            copyCS.getOriginalValueStores().put(aCopyOfOriginalObject, aVSCopy);
        }

        // end originalValueStore iteration

        /**
         * Fix originalElements by deep copying the original dataObject:key and the original List:value
         * key is original deleted object in [deepCopies] - value is copy of the elements
         * The instances of ListWrapper inside the valueStores must be the same ones used in the originalElements
         */
        ListWrapper anOriginalListKey = null;
        ListWrapper aCopyListWrapper = null;
        List aCopyList = null;
        for (Iterator anIterator = originalCS.getOriginalElements().keySet().iterator();
                 anIterator.hasNext();) {
            anOriginalListKey = (ListWrapper)anIterator.next();
            // create a new ListWrapper
            SDOProperty aProperty = (SDOProperty) propertyToOriginalListMap.get(anOriginalListKey);
            aCopyListWrapper = (ListWrapper)copyListWrapperCS2toCopyOfListCS2Map.get(anOriginalListKey);
            aCopyList = new ArrayList();

            /**
             * For each key:ListWrapper
             *     - shallow copy all the items in the currentElements list
             *     - replace the dataObject with its copy of the copy
             *     - leave the property as is
             * For each value:ArrayList
             *     - replace all values with their copy
             */
            Object aListItem = null;
            Object aListItemCopy = null;
            for (Iterator anItemIterator = anOriginalListKey.iterator(); anItemIterator.hasNext();) {
                aListItem = anItemIterator.next();
                // for simple many types we use the original in the copy
                if (!aProperty.getType().isDataType()) {
                    // get the copy of the original (in the current valuestore) - we need do not make a copy of this copy
                    // we should have a copy of the copy for List items - ListWrapper.add(item) will remove the item from its original wrapper
                    aListItemCopy = origDOCS1toCopyDOCS2Map.get(aListItem);
                } else {
                    aListItemCopy = aListItem;
                }
                aCopyList.add(aListItemCopy);
            }

            // add element list directly to the ListWrapper and bypass the cs element copy and containment updates
            aCopyListWrapper.setCurrentElements(aCopyList);
            List listValueCopy = new ArrayList();

            // fix ArrayList value
            List listValue = (List)originalCS.getOriginalElements().get(anOriginalListKey);
            aListItem = null;
            aListItemCopy = null;
            for (Iterator aListIterator = listValue.iterator(); aListIterator.hasNext();) {
                aListItem = aListIterator.next();
                // for simple many types we use the original in the copy
                if (!aProperty.getType().isDataType()) {
                    aListItemCopy = origDOCS1toCopyDOCS2Map.get(aListItem);
                } else {
                    aListItemCopy = aListItem;
                }

                // don't add nulls to the listWrapper so an undoChanges will encounter an NPE later
                if (aListItemCopy != null) {
                    listValueCopy.add(aListItemCopy);
                }
            }

            // set the copy map entry keyed on copy with value a deep copy of the copy
            copyCS.getOriginalElements().put(aCopyListWrapper, listValueCopy);
        }

        // end originalist Iteration

        /**
         * fields that are already set when logging is turned on but need to be fixed (deleted objects need references)
         */
        Map oldContainersMap = originalCS.getOldContainers();
        Map copyContainersMap = copyCS.getOldContainers();
        DataObject oldContainerKey = null;
        DataObject copyContainerKey = null;

        // convert any existing entries in the Map - should normally be 0 - unless any OC properties were unset
        for (Iterator anIterator = oldContainersMap.keySet().iterator(); anIterator.hasNext();) {
            oldContainerKey = (DataObject)anIterator.next();
            // get corresponding copy
            copyContainerKey = (SDODataObject)origDOCS1toCopyDOCS2Map.get(oldContainerKey);
            // check existing copyContainers for existing objects - should be 0 - add all objects when pauseLogging() used
            DataObject oldContainerValue = null;
            if (null == copyContainersMap.get(copyContainerKey)) {
                oldContainerValue = (DataObject)oldContainersMap.get(oldContainerKey);
                // set copy key:value pair on copy map directly
                copyContainersMap.put(copyContainerKey, origDOCS1toCopyDOCS2Map.get(oldContainerValue));
            }
        }

        Map oldContainmentPropertyMap = originalCS.getOldContainmentProperty();
        Map copyContainmentPropertyMap = copyCS.getOldContainmentProperty();
        DataObject oldContainmentPropertyKey = null;
        DataObject copyContainmentPropertyKey = null;

        // convert any existing entries in the Map - should normally be 0 - unless any OC properties were unset
        for (Iterator iterContProp = oldContainmentPropertyMap.keySet().iterator();
                 iterContProp.hasNext();) {
            oldContainmentPropertyKey = (DataObject)iterContProp.next();
            // get corresponding copy
            copyContainmentPropertyKey = (SDODataObject)origDOCS1toCopyDOCS2Map.get(oldContainmentPropertyKey);
            // check existing copyContainers for existing objects - should be 0 - add all objects when pauseLogging() used
            if (null == copyContainmentPropertyMap.get(copyContainmentPropertyKey)) {
                // set copy key:value pair on copy map directly
                copyContainmentPropertyMap.put(copyContainmentPropertyKey, oldContainmentPropertyMap.get(oldContainmentPropertyKey));
            }
        }

        Map oldUnsetOCPropertyMap = originalCS.getUnsetOCPropertiesMap();
        SDODataObject oldOCPropertyContainer = null;

        // convert any existing entries in the Map - should normally be 0
        for (Iterator iterContainer = oldUnsetOCPropertyMap.keySet().iterator();
                 iterContainer.hasNext();) {
            // DataObject will be non-Null
            oldOCPropertyContainer = (SDODataObject)iterContainer.next();
            // check existing copyContainers for existing objects - should be 0 - add all objects when pauseLogging() used
            for (Iterator iterUnset = ((List)oldUnsetOCPropertyMap.get(oldOCPropertyContainer)).iterator();
                     iterUnset.hasNext();) {
                // set/create new list on copy Map with corresponding copy of container
                copyCS.setUnsetOCProperty((SDODataObject)origDOCS1toCopyDOCS2Map.get(//
                oldOCPropertyContainer), (Property)iterUnset.next());
            }
        }

        // process sequences

        /**
         * Fix originalSequences by deep copying the original dataObject:key and the original Sequence:value
         * key is original deleted object in [deepCopies] - value is copy of the settings in the sequence.
         * The instances of Sequence inside the originalSequences must be the same ones used in the originalElements
         */

        // iterate the map of <DataObject, Sequence>
        for (Iterator aMapIterator = originalCS.getOriginalSequences().keySet().iterator();
                 aMapIterator.hasNext();) {
            SDODataObject sequenceDataObjectKey = (SDODataObject)aMapIterator.next();
            SDOSequence originalSequence = (SDOSequence)originalCS.getOriginalSequences().get(sequenceDataObjectKey);

            // create a new Sequence with a pointer to the copy of the original DataObject backpointer
            // assume that all dataObject backpointers are containment objects.
            SDODataObject copyOriginalSequenceDataObject = (SDODataObject)origDOCS1toCopyDOCS2Map.get(originalSequence.getDataObject());
            SDOSequence copySequence = new SDOSequence(copyOriginalSequenceDataObject);

            replicateAndRereferenceSequenceCopyPrivate(originalSequence, copySequence, originalSequence.getDataObject(), copyOriginalSequenceDataObject, origDOCS1toCopyDOCS2Map, originalCS);

            // set the copy map entry keyed on copy with value a deep copy of the copy
            copyCS.getOriginalSequences().put(copyOriginalSequenceDataObject, copySequence);
        }

        /**
         * fields to ignore
        // aHelperContext    SDOHelperContext  (id=42)
        // dataGraph    null
        // logging    true
        // loggingMapping    true
        // unsetPropsMap    HashMap<K,V>  (id=117)
        // createdXPaths    null
        // deletedXPaths    null
        // modifiedDoms    null
         */
        /**
         * fields to ignore that are on-demand
         *     oldSettings    HashMap<K,V>  (id=110)
         * reverseDeletedMap    HashMap<K,V>  (id=116)
         * oldSequences    HashMap<K,V>  (id=88)
         */
    }

    /**
     * INTERNAL:
     * Build the copy tree and cache all reachable DataObjects with their copy<br>
     * Cache all non-containment properties - to be set after tree construction<br>
     * Recurse the tree in preorder traversal (root, child1-n)
     * Scope: We do not have to check the copyTree scope when iterating opposites since
     * we will not enter any opposite property dataTree that is outside of the copyTree scope
     * @param doMap (cache original -> copy DataObject instances to set non-containment properties after tree construction)
     * @param ncPropMap (cache original DO:non-containment property values to be set after tree construction)
     */
    private SDODataObject copyPrivate(SDODataObject dataObject, HashMap doMap,//
                                   HashMap ncPropMap, SDOChangeSummary cs) throws IllegalArgumentException {
        // check for null DataObject
        if (null == dataObject) {
            return null;// this is acceptable behavior
        }

        SDODataObject copy = (SDODataObject)getHelperContext()//
        .getDataFactory().create(dataObject.getType().getURI(), dataObject.getType().getName());

        // store current object for reference by the non-containment map
        doMap.put(dataObject, copy);

        List ocListOriginal = dataObject._getOpenContentProperties();
        for (Iterator anOCIterator = ocListOriginal.iterator(); anOCIterator.hasNext();) {
            copy.addOpenContentProperty((Property)anOCIterator.next());
        }

        List ocAttrsListOriginal = dataObject._getOpenContentPropertiesAttributes();
        for (Iterator anOCAttrIterator = ocAttrsListOriginal.iterator(); anOCAttrIterator.hasNext();) {
            copy.addOpenContentProperty((Property)anOCAttrIterator.next());
        }

        //  start iterating all copy's properties
        for (Iterator iterInstanceProperties = copy.getInstanceProperties().iterator();
                 iterInstanceProperties.hasNext();) {
            SDOProperty eachProperty = (SDOProperty)iterInstanceProperties.next();
            boolean isSet = isSet(dataObject, eachProperty, cs);
            if (isSet) {
                Object o = getValue(dataObject, eachProperty, cs);
                if (eachProperty.getType().isDataType()) {
                    if (!eachProperty.getType().isChangeSummaryType()) {

                        /**
                         * ChangeSummaries must be cleared with logging set to the original state without creating oldSettings.
                         * The logging flag from the original will be set on the copy after this copy call completes
                         * and gets set on its container.
                         * The cs is off by default in the copy object.
                         * updateSequence flag is false - we will populate the sequence in order after subtree creation
                         */
                        copy.setInternal(eachProperty, o, false);
                    }
                } else {
                    // case matrix for containment and opposite combinations
                    // cont=false, opp=false -> unidirectional
                    // cont=false, opp=true  -> bidirectional
                    // cont=true,  opp=false -> normal containment
                    // cont=true,  opp=true  -> bidirectional
                    if (eachProperty.isContainment()) {
                        // process containment properties (normal, half of bidirectionals)
                        copyContainmentPropertyValue(copy, eachProperty, o, doMap, ncPropMap, cs);
                    } else {
                        // copy non-containment do (not properties (unidirectional, half of bidirectionals))
                        //copyPropertyValue(dataObject, copy, eachProperty, o, copyRoot, doMap);
                        //cacheNContainmentPropertyValue(copy, eachProperty, o, doMap, ncPropMap);
                        // store non-containment properties
                        ArrayList anArray = (ArrayList)ncPropMap.get(dataObject);
                        if (anArray == null) {
                            anArray = new ArrayList();
                            anArray.add(eachProperty);
                            // store property array into the map for the first time
                            ncPropMap.put(dataObject, anArray);
                        } else {
                            // add to existing array of nc properties in the map
                            anArray.add(eachProperty);
                        }
                    }
                }
            }
        }

        // sequences will not be processed until the entire tree is copied so we can resolve any reference relationships
        return copy;
    }

    /**
     * INTERNAL:
     * Recursive function deep copies all contained properties.
     * Requirements: The value object has isSet=true for all callers.
     * @param copy
     * @param property
     * @param value
     * @param doMap (cache original -> copy DataObject instances to set non-containment properties after tree construction)
     * @param propMap (cache original DO:non-containment property values to be set after tree construction)
     */
    private void copyContainmentPropertyValue(SDODataObject copy, SDOProperty property, Object value,//
                                              HashMap doMap, HashMap ncPropMap, SDOChangeSummary cs) {
        if (property.isMany()) {
            List copyValue = new ArrayList();

            // set the copy to an empty list and add each items from the original in sequence
            // updateSequence flag is false - we will populate the sequence in order after subtree creation
            copy.setInternal(property, copyValue, false);
            for (Iterator iterValues = ((List)value).iterator(); iterValues.hasNext();) {
                SDODataObject o = (SDODataObject)iterValues.next();
                SDODataObject copyO = copyPrivate(o, doMap, ncPropMap, cs);
                ((ListWrapper)copy.getList(property)).add(copyO, false);
                // set changeSummary on all cs-root elements in the list after they are added to the containment tree
                if ((copyO != null) && (copyO.getChangeSummary() != null) && (copyO.getType().getChangeSummaryProperty() != null)) {
                    // re-reference copy objects in the copy changeSummary
                    if (o.getChangeSummary().isLogging()) {
                        (copyO.getChangeSummary()).setLogging(true);
                    }
                    copyChangeSummary(o.getChangeSummary(),//
                                      copyO.getChangeSummary(), doMap);
                }
            }
        } else {// handle non-many case
            // implementers of this function will always pass in a DataObject that may be null
            SDODataObject copyO = copyPrivate((SDODataObject)value, doMap, ncPropMap, cs);

            //  #5852525 handle null properties with isSet=true - fixed 20070130
            // we will set the isSet index in the ValueStore to true for all isSet=true objects, even NULL ones.
            // updateSequence flag is false - we will populate the sequence in order after subtree creation
            copy.setInternal(property, copyO, false);

            // set changeSummary on all cs-root elements in the list after they are added to the containment tree using the original logging value
            if ((copyO != null) && (copyO.getChangeSummary() != null) && (copyO.getType().getChangeSummaryProperty() != null)) {
                // re-reference copy objects in the copy changeSummary
                if (((SDODataObject)value).getChangeSummary().isLogging()) {
                    copyO.getChangeSummary().setLogging(true);
                }
                copyChangeSummary(((SDODataObject)value).getChangeSummary(),//
                                  copyO.getChangeSummary(), doMap);
            }
        }
    }

    /**
     * INTERNAL:
     * Return the helperContext containing this copyHelper.
     * @return
     */
    public HelperContext getHelperContext() {
        if(null == aHelperContext) {
            aHelperContext = HelperProvider.getDefaultContext();
        }
        return aHelperContext;
    }

    /**
     * INTERNAL:
     * Set the helperContext if this copyHelper was created using the default constructor.
     * @param helperContext
     */
    public void setHelperContext(HelperContext helperContext) {
        aHelperContext = helperContext;
    }

    /**
     * INTERNAL:
     * Used during XML Unmarshal.
     * @param dataObject
     * @param property
     * @param cs
     * @return
     */
    private boolean isSet(SDODataObject dataObject, Property property, SDOChangeSummary cs) {
        if (cs != null) {
            return cs.wasSet(dataObject, property);
        }
        return dataObject.isSetInternal(property);
    }

    /**
     * INTERNAL:
     * Used during XML Unmarshal.
     * @param dataObject
     * @param property
     * @param cs
     * @return
     */
    private Object getValue(SDODataObject dataObject, Property property, SDOChangeSummary cs) {
        if (cs != null) {
            Object returnValue = cs.getPropertyInternal(dataObject, property);
            if (property.isMany()) {
                if (cs.getOriginalElements().containsKey(returnValue)) {
                    // are we using the cast to List as a sort of instance check that would throw a CCE?
                    return cs.getOriginalElements().get(returnValue);
                }
            }
            return returnValue;
        }
        return dataObject.get(property);// get the value of current property
    }
}
