/*
 * 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.testing.sdo.model.changesummary;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import junit.textui.TestRunner;
import org.eclipse.persistence.sdo.SDOChangeSummary;
import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOSetting;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.sdo.ValueStore;
import org.eclipse.persistence.sdo.helper.ListWrapper;
import org.eclipse.persistence.testing.sdo.SDOTestCase;
import commonj.sdo.ChangeSummary;
import commonj.sdo.DataObject;
import commonj.sdo.Property;
import commonj.sdo.Type;
import commonj.sdo.helper.XMLDocument;

/**
 *
 * MODIFIED    (MM/DD/YY)
 *   dmahar      09/18/07 -
 *   mfobrien    05/01/07 -
 *   dmahar      04/10/07 -
 *   mfobrien    03/16/07 -
 *   dmahar      03/14/07 -
 *   dmahar      03/14/07 -
 *   mfobrien    02/14/07 - cs.undoChanges is the same as a detach/reset
 *                                           testDetachAndResetYardToSamePlace() mod assertEquals(0, shipToSettings.size()); from 1
 *
 */
public class ChangeSummaryXSDTestCases extends SDOTestCase {
    private DataObject rootObject;
    private ChangeSummary cs;

    public static final String OPEN_CONTENT_NS_URI = "";
    public static final String OC_PROP1SimpleSingleNAME = "open1";
    public static final String OC_PROP1SimpleSingleVALUE = "open1-val";
    public static final String OC_PROP2SimpleSingleNAME = "open2";
    public static final String OC_PROP2SimpleSingleVALUE = "open2-val";
    public static final String OC_PROP3DataObjectNAME = "open-do";
    public static final String OC_PROP3DataObjectVALUE = "open-do-val";

    public static final String PROPERTY_NAME_PO_ITEMS = "items";
    public static final String PROPERTY_NAME_PO_ITEMS_ITEM1 = "items/item[1]";
    public static final String PROPERTY_NAME_PO_SHIPTO = "shipTo";
    public static final String PROPERTY_NAME_PO_SHIPTO_PHONE2 = "shipTo/phone[2]";

    public ChangeSummaryXSDTestCases(String name) {
        super(name);
    }

    public static void main(String[] args) {
        String[] arguments = { "-c", "org.eclipse.persistence.testing.sdo.model.changesummary.ChangeSummaryXSDTestCases" };
        TestRunner.main(arguments);
    }

    @Override
    public void setUp() {
        super.setUp();// watch setup redundancy
        //define types from deep with cs
        try {
            InputStream is = new FileInputStream("org/eclipse/persistence/testing/sdo/helper/xmlhelper/PurchaseOrderDeepWithCS.xsd");
            xsdHelper.define(is, null);
            XMLDocument document = xmlHelper.load(new FileInputStream("org/eclipse/persistence/testing/sdo/helper/xmlhelper/PurchaseOrderDeepWithCS.xml"));
            rootObject = document.getRootObject();
            cs = rootObject.getChangeSummary();
            cs.endLogging();
        } catch (Exception e) {
            e.printStackTrace();
            fail("An error occurred loading the xsd");
        }
    }

    public void writeXML(DataObject anObject) {
        // verify save
        super.writeXML(rootObject, ChangeSummaryOnRootTestCases.URINAME,//
                       ChangeSummaryOnRootTestCases.TYPENAME,//
                       System.out);
    }

    public DataObject marshalUnmarshalObject(DataObject anObject) {
        DataObject copy = null;
        try {
            String s = xmlHelper.save(anObject, "http://example.org",// this uri does not affect unmarshal
                                      "dataObject");// this name is overridden by the xsi:type
            XMLDocument document = xmlHelper.load(s);
            copy = document.getRootObject();
        } catch (Exception e) {
            e.printStackTrace();
            fail("An error occurred loading the xml file");
        }
        return copy;
    }


    /**
     * Test multiple oc properties that were deleted and how they are returned to the DO after an undoChanges
     *
     */
    public void testMultipleOCPropsUndoChangesDeepCopyObjectWithCSLoggingOnWithComboDeleteSingleCreateManyModifyRootChangesInTheDeepCopy() {
        List preOrderList = null;
        int numberOfDataObjectsInSubTree = 0;

        // unset isMany=true (to fill unsetPropsMap and createdList later when we (re)set it back)
        SDODataObject shipTo = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO);

        // use index 2 to avoid a swap later
        SDODataObject phone2 = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO_PHONE2);
        shipTo.unset("phone[2]");

        // save size of tree before CS was turned on
        preOrderList = preOrderTraversalDataObjectList((SDODataObject)rootObject, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        int numberOfNodesInRootBeforeCSon = 14;
        assertEquals(numberOfNodesInRootBeforeCSon, numberOfDataObjectsInSubTree);

        SDOProperty openRootProperty = new SDOProperty(aHelperContext);
        openRootProperty.setName(OC_PROP1SimpleSingleNAME);
        openRootProperty.setType(SDOConstants.SDO_STRING);
        //aRootTypeOC.setOpen(true);
        ((SDOType)rootObject.getType()).setOpen(true);
        rootObject.set(openRootProperty, OC_PROP1SimpleSingleVALUE);

        // set an Open Content property and delete it
        SDOProperty openRootPropertyToBeDeleted = new SDOProperty(aHelperContext);
        openRootPropertyToBeDeleted.setName(OC_PROP2SimpleSingleNAME);
        openRootPropertyToBeDeleted.setType(SDOConstants.SDO_STRING);
        //aRootTypeOC.setOpen(true);
        rootObject.set(openRootPropertyToBeDeleted, OC_PROP2SimpleSingleVALUE);

        // set an Open Content property and delete it
        SDOProperty openRootPropertyToBeDeleted2 = new SDOProperty(aHelperContext);
        openRootPropertyToBeDeleted2.setName(OC_PROP2SimpleSingleNAME + "1");
        openRootPropertyToBeDeleted2.setType(SDOConstants.SDO_STRING);
        //aRootTypeOC.setOpen(true);
        rootObject.set(openRootPropertyToBeDeleted2, OC_PROP2SimpleSingleVALUE + "1");

        // set an Open Content property and delete it
        SDOProperty openRootPropertyToBeDeleted3 = new SDOProperty(aHelperContext);
        openRootPropertyToBeDeleted3.setName(OC_PROP2SimpleSingleNAME + "2");
        openRootPropertyToBeDeleted3.setType(SDOConstants.SDO_STRING);
        //aRootTypeOC.setOpen(true);
        rootObject.set(openRootPropertyToBeDeleted3, OC_PROP2SimpleSingleVALUE + "2");

        // verify logging is on
        // turn on logging
        cs.beginLogging();
        assertTrue(cs.isLogging());

        // do some changes

        // delete an Open Content property
        rootObject.unset(openRootPropertyToBeDeleted);
        rootObject.unset(openRootPropertyToBeDeleted2);
        rootObject.unset(openRootPropertyToBeDeleted3);
        //ChangeSummary.Setting setting = cs.getOldValue(rootObject, openRootPropertyToBeDeleted);
        //assertEquals("openTest", setting.getValue());


        SDODataObject items = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_ITEMS);

        // detach isMany=false (to fill deletedList and modifiedList)
        //items.detach();
        items.delete();
        // (re)set isMany=true (to fill createdList, unsetPropsMap)
        List phones = (List)shipTo.get("phone");
        phones.add(phone2);
        // get an oldSetting in order to enable caching to fill the oldSettings hash map in the cs
        //Object oldValueItems = cs.getOldValue(rootObject, rootObject.getInstanceProperty("items")).getValue();
        //assertNotNull(oldValueItems);
        //assertNull(rootObject.get("items"));
        // save fields lengths for later comparision
        List<DataObject> changedObjects = cs.getChangedDataObjects();
        int changedObjectsLength = changedObjects.size();
        //int itemsOldValuesSize = cs.getOldValues(items).size();// invoke usage of the reverseDeletedMap

        // take an object with CS on and deep copy it
        SDODataObject copy = (SDODataObject)copyHelper.copy(rootObject);

        // copy the copy - so we are sure that the copy has enough in the cs to do an undo of the 2nd level copy
        SDODataObject copyOfCopy = (SDODataObject)copyHelper.copy(copy);

        //SDODataObject copy = (SDODataObject)marshalUnmarshalObject(rootObject);
        // verify that logging is still on
        ChangeSummary cs2 = copy.getChangeSummary();
        assertNotNull(cs2);
        assertTrue(cs2.isLogging());
        ChangeSummary cs3 = copyOfCopy.getChangeSummary();
        assertNotNull(cs3);
        assertTrue(cs3.isLogging());

        // verify saved field lengths from above
        assertEquals(changedObjectsLength, cs2.getChangedDataObjects().size());

        // no cache entries yet = 0 oldValues
        //assertEquals(itemsOldValuesSize, cs2.getOldValues(items).size());
        // check shallow equality
        assertEquals(rootObject.getInstanceProperties().size(), copy.getInstanceProperties().size());

        boolean isEqual = equalityHelper.equalShallow(rootObject, copy);
        assertTrue(isEqual);

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copy));
        assertTrue(equalityHelper.equalShallow(rootObject, copyOfCopy));

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copyOfCopy));

        // verify that all objects referenced in the copy changeSummary are from the copy not the original
        // verify createdList
        // verify deepCopies
        // verify deletedList
        // verify modifiedList
        // verify oldContainer
        // verify oldContainmentProperty
        // verify originalElements
        // verify originalValueStores
        Map originalValueStores = ((SDOChangeSummary)cs).getOriginalValueStores();
        Map originalValueStoresCopy = ((SDOChangeSummary)cs2).getOriginalValueStores();

        // verify originally deleted items is referencing a copy and a copy of its valuestore
        // verify reverseDeletedMap
        // verify rootDataObject
        assertEquals(copy, cs2.getRootObject());
        // verify unsetPropsMap
        SDODataObject items2 = (SDODataObject)copy.get(PROPERTY_NAME_PO_ITEMS);

        // check new phone copy
        SDODataObject phone2c = (SDODataObject)copy.get(PROPERTY_NAME_PO_SHIPTO_PHONE2);
        assertNotNull(phone2);
        // get original new phone
        SDODataObject phone2o = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO_PHONE2);
        assertNotNull(phone2);
        assertFalse(phone2o == phone2c);
        assertFalse(phone2o._getCurrentValueStore() == phone2c._getCurrentValueStore());

        // check new phone copy (in oldSettings) is == to currentValueStore phone (both are the same deepcopies of the original)
        List createdListCopy = ((SDOChangeSummary)cs2).getCreated();
        assertNotNull(createdListCopy);
        assertEquals(1, createdListCopy.size());
        SDODataObject phone2cInCreatedList = (SDODataObject)createdListCopy.get(0);
        assertNotNull(phone2cInCreatedList);
        assertNotNull(phone2cInCreatedList);
        assertTrue(phone2c == phone2cInCreatedList); // test cs.createList iterator makes deep copies
        assertTrue(phone2c._getCurrentValueStore() == phone2cInCreatedList._getCurrentValueStore());

        // get an oldSetting in order to enable caching to fill the hash map in the cs
        //Object oldValueItems2 = cs2.getOldValue(copy, copy.getInstanceProperty("items"));
        // verify that we have oldSettings in the new copy
        //        assertNotNull(oldValueItems2);
        //        assertNotNull(((SDOSetting)oldValueItems2).getValue());
        //        assertNull(copy.get("items"));
        // deleted objects are 9
        // verify that we have transferred the logged changes during the copy (we dont have to worry about nested changesummaries)
        assertEquals(changedObjectsLength, cs2.getChangedDataObjects().size());
        preOrderList = preOrderTraversalDataObjectList(copy, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        // assume that for logging=true copies we should have oldContainer, oldContProperties
        assertEquals(6, numberOfDataObjectsInSubTree);// 16 - 10
        assertEquals(((SDOChangeSummary)cs).getOldContainer().size(),//
                     copy.getChangeSummary().getOldContainer().size());
        assertEquals(((SDOChangeSummary)cs).getOldContainmentProperty().size(),//
                     copy.getChangeSummary().getOldContainmentProperty().size());

        // no oldSetting for simple object

        // verify oc props that were deleted are in oldSettings
        Property oc2cProp = openRootPropertyToBeDeleted;//(Property)copy.getOpenContentPropertiesMap().get(OC_PROP2SimpleSingleNAME);
        assertNotNull(oc2cProp);
        Object oc2cSetting = cs2.getOldValue(copy, oc2cProp);
        assertNotNull(oc2cSetting);
        String oc2cValue = (String)((SDOSetting)oc2cSetting).getValue();
        assertNotNull(oc2cValue);
        assertEquals(OC_PROP2SimpleSingleVALUE, oc2cValue);

        // verify unsetOC map
        List<Property> ocUnsetList = ((SDOChangeSummary)cs2).getUnsetOCProperties(copy);
        assertNotNull(ocUnsetList);
        Property oc2cProp_ocUnsetMap = ocUnsetList.get(0);
        assertNotNull(oc2cProp_ocUnsetMap);
        // verify that we are pointing to the same global property
        assertEquals(oc2cProp_ocUnsetMap, openRootPropertyToBeDeleted);
        String oc2cValue_ocUnsetMap = oc2cProp_ocUnsetMap.getName();
        assertNotNull(oc2cValue_ocUnsetMap);
        assertSame(openRootPropertyToBeDeleted.getName(), oc2cValue_ocUnsetMap);

        // verify oldContainer <key, value> are both deep copies
        // we an old setting first
        //DataObject anOldContainerValue = cs2.getOldContainer(items2);
        //assertTrue(copy == anOldContainerValue);



        // perform an undo on the copy and compare to the undone original (not the undone copy)
        cs2.undoChanges();
        // verify that original was unaffected by undo on copy
        items = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_ITEMS);
        assertNull(items);
        // get back "items" that has been reset
        items2 = (SDODataObject)copy.get(PROPERTY_NAME_PO_ITEMS);
        assertNotNull(items2);

        assertEquals(0, cs2.getChangedDataObjects().size());
        preOrderList = preOrderTraversalDataObjectList(copy, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        // assume that for logging=true copies we should have oldContainer, oldContProperties
        assertEquals(14, numberOfDataObjectsInSubTree);

        // undo changes on original
        cs.undoChanges();
        assertEquals(0, cs.getChangedDataObjects().size());
        // the items:do in the original and copy should not be the same object (different valueStores)
        // verify that original was unaffected by undo on copy
        items = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_ITEMS);
        assertFalse(items == items2);
        assertFalse(items._getCurrentValueStore() == items2._getCurrentValueStore());

        assertEquals(0, cs2.getChangedDataObjects().size());
        preOrderList = preOrderTraversalDataObjectList(copy, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        // assume that for logging=true copies we should have oldContainer, oldContProperties
        assertEquals(14, numberOfDataObjectsInSubTree);// 16 - 10

        // verify deep objects item[*] are distince between original and copy
        SDODataObject item1o = (SDODataObject)items.get("item[1]");
        SDODataObject item1c = (SDODataObject)items2.get("item[1]");
        assertNotNull(item1o);
        assertNotNull(item1c);
        assertFalse(item1o == item1c);
        assertFalse(item1o._getCurrentValueStore() == item1c._getCurrentValueStore());

        // verify listwrappers hashes are the same between two equal objects in the cs
        // verify simple Many integrity
        ListWrapper origComments = (ListWrapper)rootObject.get("items/item[1]/comment");
        assertNotNull(origComments);
        assertEquals(2, origComments.size());

        ListWrapper copyComments = (ListWrapper)copy.get("items/item[1]/comment");
        assertNotNull(copyComments);
        assertEquals(2, copyComments.size());
        //writeXML(copy);
        // check shallow equality
        assertTrue(equalityHelper.equalShallow(rootObject, copy));

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copy));

        // verify equality and undo the copyOfCopy to ensure that the csCopyOfCopy has enough info to do an undo
        copyOfCopy.getChangeSummary().undoChanges();
        assertTrue(equalityHelper.equalShallow(rootObject, copyOfCopy));

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copyOfCopy));
        assertTrue(equalityHelper.equal(copy, copyOfCopy));

        // Verify CS undo of oc props
        // verify oc props that are copied
        Object oc1cProp = copy.get(OC_PROP1SimpleSingleNAME);
        assertNotNull(oc1cProp);
        assertEquals(OC_PROP1SimpleSingleVALUE, oc1cProp);

        // verify that deleted oc props were returned being set after an undo - use saved Property object (outside of this object)
        Object oc2cPropUndo = rootObject.get(openRootPropertyToBeDeleted);
        assertNotNull (oc2cPropUndo);
        assertEquals(oc2cPropUndo, OC_PROP2SimpleSingleVALUE);


        // test undo for oc - not implemented yet see #5928954
        // verify that deleted oc props were returned being set after an undo - do not used saved Property object -use getPath
        oc2cPropUndo = rootObject.get(openRootPropertyToBeDeleted.getName());
        assertNotNull(oc2cPropUndo);
        assertEquals(oc2cPropUndo, OC_PROP2SimpleSingleVALUE);

        // verify oc Property is in valueStore
        String openRootPropertyToBeDeletedAfterUndo = (String)((SDODataObject)rootObject)._getCurrentValueStore()//
            .getOpenContentProperty(openRootPropertyToBeDeleted);
        assertNotNull(openRootPropertyToBeDeletedAfterUndo);
        assertEquals(openRootPropertyToBeDeletedAfterUndo, OC_PROP2SimpleSingleVALUE);

        // verify that deleted oc props were returned being set after an undo - use saved Property object (outside of this object)
        Object oc2cPropUndo2 = rootObject.get(openRootPropertyToBeDeleted2);
        assertNotNull (oc2cPropUndo2);
        assertEquals(oc2cPropUndo2, OC_PROP2SimpleSingleVALUE + "1");

        oc2cPropUndo2 = rootObject.get(openRootPropertyToBeDeleted2.getName());
        assertNotNull(oc2cPropUndo2);
        assertEquals(oc2cPropUndo2, OC_PROP2SimpleSingleVALUE + "1");

        // verify oc Property is in valueStore
        String openRootPropertyToBeDeletedAfterUndo2 = (String)((SDODataObject)rootObject)._getCurrentValueStore()//
            .getOpenContentProperty(openRootPropertyToBeDeleted2);
        assertNotNull(openRootPropertyToBeDeletedAfterUndo2);
        assertEquals(openRootPropertyToBeDeletedAfterUndo2, OC_PROP2SimpleSingleVALUE + "1");

        // verify that deleted oc props were returned being set after an undo - use saved Property object (outside of this object)
        Object oc2cPropUndo3 = rootObject.get(openRootPropertyToBeDeleted3);
        assertNotNull (oc2cPropUndo3);
        assertEquals(oc2cPropUndo3, OC_PROP2SimpleSingleVALUE + "2");

        oc2cPropUndo3 = rootObject.get(openRootPropertyToBeDeleted3.getName());
        assertNotNull(oc2cPropUndo3);
        assertEquals(oc2cPropUndo3, OC_PROP2SimpleSingleVALUE + "2");

        // verify oc Property is in valueStore
        String openRootPropertyToBeDeletedAfterUndo3 = (String)((SDODataObject)rootObject)._getCurrentValueStore()//
            .getOpenContentProperty(openRootPropertyToBeDeleted3);
        assertNotNull(openRootPropertyToBeDeletedAfterUndo3);
        assertEquals(openRootPropertyToBeDeletedAfterUndo3, OC_PROP2SimpleSingleVALUE + "2");

    }

    public void testUndoWithLoggingOffDeepCopyObjectWithCSLoggingOnWithComboDeleteSingleCreateManyModifyRootChangesInTheDeepCopy() {

        List preOrderList = null;
        int numberOfDataObjectsInSubTree = 0;

        // unset isMany=true (to fill unsetPropsMap and createdList later when we (re)set it back)
        SDODataObject shipTo = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO);

        // use index 2 to avoid a swap later
        SDODataObject phone2 = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO_PHONE2);
        shipTo.unset("phone[2]");

        // save size of tree before CS was turned on
        preOrderList = preOrderTraversalDataObjectList((SDODataObject)rootObject, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        int numberOfNodesInRootBeforeCSon = 14;
        assertEquals(numberOfNodesInRootBeforeCSon, numberOfDataObjectsInSubTree);

        SDOProperty openRootProperty = new SDOProperty(aHelperContext);
        openRootProperty.setName(OC_PROP1SimpleSingleNAME);
        openRootProperty.setType(SDOConstants.SDO_STRING);
        //aRootTypeOC.setOpen(true);
        ((SDOType)rootObject.getType()).setOpen(true);
        rootObject.set(openRootProperty, OC_PROP1SimpleSingleVALUE);

        // set an Open Content property and delete it
        SDOProperty openRootPropertyToBeDeleted = new SDOProperty(aHelperContext);
        openRootPropertyToBeDeleted.setName(OC_PROP2SimpleSingleNAME);
        openRootPropertyToBeDeleted.setType(SDOConstants.SDO_STRING);
        //aRootTypeOC.setOpen(true);
        rootObject.set(openRootPropertyToBeDeleted, OC_PROP2SimpleSingleVALUE);

        // verify logging is on
        // turn on logging
        cs.beginLogging();
        assertTrue(cs.isLogging());

        // do some changes

        // delete an Open Content property
        rootObject.unset(openRootPropertyToBeDeleted);
        //ChangeSummary.Setting setting = cs.getOldValue(rootObject, openRootPropertyToBeDeleted);
        //assertEquals("openTest", setting.getValue());


        SDODataObject items = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_ITEMS);

        // detach isMany=false (to fill deletedList and modifiedList)
        //items.detach();
        items.delete();
        // (re)set isMany=true (to fill createdList, unsetPropsMap)
        List phones = (List)shipTo.get("phone");
        phones.add(phone2);
        // get an oldSetting in order to enable caching to fill the oldSettings hash map in the cs
        //Object oldValueItems = cs.getOldValue(rootObject, rootObject.getInstanceProperty("items")).getValue();
        //assertNotNull(oldValueItems);
        //assertNull(rootObject.get("items"));
        // save fields lengths for later comparision
        List<DataObject> changedObjects = cs.getChangedDataObjects();
        int changedObjectsLength = changedObjects.size();
        //int itemsOldValuesSize = cs.getOldValues(items).size();// invoke usage of the reverseDeletedMap

        // take an object with CS on and deep copy it
        SDODataObject copy = (SDODataObject)copyHelper.copy(rootObject);

        // copy the copy - so we are sure that the copy has enough in the cs to do an undo of the 2nd level copy
        SDODataObject copyOfCopy = (SDODataObject)copyHelper.copy(copy);

        //SDODataObject copy = (SDODataObject)marshalUnmarshalObject(rootObject);
        // verify that logging is still on
        ChangeSummary cs2 = copy.getChangeSummary();
        assertNotNull(cs2);
        assertTrue(cs2.isLogging());
        ChangeSummary cs3 = copyOfCopy.getChangeSummary();
        assertNotNull(cs3);
        assertTrue(cs3.isLogging());

        // verify saved field lengths from above
        assertEquals(changedObjectsLength, cs2.getChangedDataObjects().size());

        // no cache entries yet = 0 oldValues
        //assertEquals(itemsOldValuesSize, cs2.getOldValues(items).size());
        // check shallow equality
        assertEquals(rootObject.getInstanceProperties().size(), copy.getInstanceProperties().size());

        boolean isEqual = equalityHelper.equalShallow(rootObject, copy);
        assertTrue(isEqual);

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copy));
        assertTrue(equalityHelper.equalShallow(rootObject, copyOfCopy));

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copyOfCopy));

        // verify that all objects referenced in the copy changeSummary are from the copy not the original
        // verify createdList
        // verify deepCopies
        // verify deletedList
        // verify modifiedList
        // verify oldContainer
        // verify oldContainmentProperty
        // verify originalElements
        // verify originalValueStores
        Map originalValueStores = ((SDOChangeSummary)cs).getOriginalValueStores();
        Map originalValueStoresCopy = ((SDOChangeSummary)cs2).getOriginalValueStores();

        // verify originally deleted items is referencing a copy and a copy of its valuestore
        // verify reverseDeletedMap
        // verify rootDataObject
        assertEquals(copy, cs2.getRootObject());
        // verify unsetPropsMap
        SDODataObject items2 = (SDODataObject)copy.get(PROPERTY_NAME_PO_ITEMS);

        // check new phone copy
        SDODataObject phone2c = (SDODataObject)copy.get(PROPERTY_NAME_PO_SHIPTO_PHONE2);
        assertNotNull(phone2);
        // get original new phone
        SDODataObject phone2o = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO_PHONE2);
        assertNotNull(phone2);
        assertFalse(phone2o == phone2c);
        assertFalse(phone2o._getCurrentValueStore() == phone2c._getCurrentValueStore());

        // check new phone copy (in oldSettings) is == to currentValueStore phone (both are the same deepcopies of the original)
        List createdListCopy = ((SDOChangeSummary)cs2).getCreated();
        assertNotNull(createdListCopy);
        assertEquals(1, createdListCopy.size());
        SDODataObject phone2cInCreatedList = (SDODataObject)createdListCopy.get(0);
        assertNotNull(phone2cInCreatedList);
        assertNotNull(phone2cInCreatedList);
        assertTrue(phone2c == phone2cInCreatedList); // test cs.createList iterator makes deep copies
        assertTrue(phone2c._getCurrentValueStore() == phone2cInCreatedList._getCurrentValueStore());

        // get an oldSetting in order to enable caching to fill the hash map in the cs
        //Object oldValueItems2 = cs2.getOldValue(copy, copy.getInstanceProperty("items"));
        // verify that we have oldSettings in the new copy
        //        assertNotNull(oldValueItems2);
        //        assertNotNull(((SDOSetting)oldValueItems2).getValue());
        //        assertNull(copy.get("items"));
        // deleted objects are 9
        // verify that we have transferred the logged changes during the copy (we dont have to worry about nested changesummaries)
        assertEquals(changedObjectsLength, cs2.getChangedDataObjects().size());
        preOrderList = preOrderTraversalDataObjectList(copy, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        // assume that for logging=true copies we should have oldContainer, oldContProperties
        assertEquals(6, numberOfDataObjectsInSubTree);// 16 - 10
        assertEquals(((SDOChangeSummary)cs).getOldContainer().size(),//
                     copy.getChangeSummary().getOldContainer().size());
        assertEquals(((SDOChangeSummary)cs).getOldContainmentProperty().size(),//
                     copy.getChangeSummary().getOldContainmentProperty().size());

        // no oldSetting for simple object

        // verify oc props that were deleted are in oldSettings
        Property oc2cProp = openRootPropertyToBeDeleted;//(Property)copy.getOpenContentPropertiesMap().get(OC_PROP2SimpleSingleNAME);
        assertNotNull(oc2cProp);
        Object oc2cSetting = cs2.getOldValue(copy, oc2cProp);
        assertNotNull(oc2cSetting);
        String oc2cValue = (String)((SDOSetting)oc2cSetting).getValue();
        assertNotNull(oc2cValue);
        assertEquals(OC_PROP2SimpleSingleVALUE, oc2cValue);

        // verify unsetOC map
        List<Property> ocUnsetList = ((SDOChangeSummary)cs2).getUnsetOCProperties(copy);
        assertNotNull(ocUnsetList);
        Property oc2cProp_ocUnsetMap = ocUnsetList.get(0);
        assertNotNull(oc2cProp_ocUnsetMap);
        // verify that we are pointing to the same global property
        assertEquals(oc2cProp_ocUnsetMap, openRootPropertyToBeDeleted);
        String oc2cValue_ocUnsetMap = oc2cProp_ocUnsetMap.getName();
        assertNotNull(oc2cValue_ocUnsetMap);
        assertSame(openRootPropertyToBeDeleted.getName(), oc2cValue_ocUnsetMap);

        // turn off logging
        cs.endLogging();
        //restart logging to clear cs (to reproduce that we used to clear CS on endLogging)
        assertFalse(cs.isLogging());
        cs.beginLogging();

        // perform an undo on the copy and compare to the undone original (not the undone copy)
        cs2.undoChanges();
        // verify that original was unaffected by undo on copy
        items = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_ITEMS);
        assertNull(items);
        // get back "items" that has been reset
        items2 = (SDODataObject)copy.get(PROPERTY_NAME_PO_ITEMS);
        assertNotNull(items2);

        assertEquals(0, cs2.getChangedDataObjects().size());
        preOrderList = preOrderTraversalDataObjectList(copy, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        // assume that for logging=true copies we should have oldContainer, oldContProperties
        assertEquals(14, numberOfDataObjectsInSubTree);

        // undo changes on original with logging off = do nothing because all of the cs is cleared
        cs.undoChanges();
        assertEquals(0, cs.getChangedDataObjects().size());
        // the items:do in the original and copy should not be the same object (different valueStores)
        // verify that original was unaffected by undo on copy
        items = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_ITEMS);
        assertFalse(items == items2);
        //assertFalse(items._getCurrentValueStore() == items2._getCurrentValueStore());

        assertEquals(0, cs2.getChangedDataObjects().size());
        preOrderList = preOrderTraversalDataObjectList(copy, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        // assume that for logging=true copies we should have oldContainer, oldContProperties
        assertEquals(14, numberOfDataObjectsInSubTree);// 16 - 10


        // verify listwrappers hashes are the same between two equal objects in the cs
        // verify simple Many integrity
        ListWrapper origComments = (ListWrapper)rootObject.get("items/item[1]/comment");
        assertNull(origComments);
        //assertEquals(2, origComments.size());

        ListWrapper copyComments = (ListWrapper)copy.get("items/item[1]/comment");
        assertNotNull(copyComments);
        assertEquals(2, copyComments.size());
        //writeXML(copy);
        // check shallow equality
        assertFalse(equalityHelper.equalShallow(rootObject, copy));

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertFalse(equalityHelper.equal(rootObject, copy));

        // verify equality and undo the copyOfCopy to ensure that the csCopyOfCopy has enough info to do an undo
        copyOfCopy.getChangeSummary().undoChanges();
        assertFalse(equalityHelper.equalShallow(rootObject, copyOfCopy));

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertFalse(equalityHelper.equal(rootObject, copyOfCopy));
        assertTrue(equalityHelper.equal(copy, copyOfCopy));

        // Verify CS undo of oc props
        // verify oc props that are copied
        Object oc1cProp = copy.get(OC_PROP1SimpleSingleNAME);
        assertNotNull(oc1cProp);
        assertEquals(OC_PROP1SimpleSingleVALUE, oc1cProp);

        // verify that deleted oc props were returned being set after an undo - use saved Property object (outside of this object)
        Object oc2cPropUndo = rootObject.get(openRootPropertyToBeDeleted);
        assertNull (oc2cPropUndo);
        //assertEquals(oc2cPropUndo, OC_PROP2SimpleSingleVALUE);


        // test undo for oc - not implemented yet see #5928954
        // verify that deleted oc props were returned being set after an undo - do not used saved Property object -use getPath
        oc2cPropUndo = rootObject.get(openRootPropertyToBeDeleted.getName());
        assertNull(oc2cPropUndo);
        //assertEquals(oc2cPropUndo, OC_PROP2SimpleSingleVALUE);

        // verify oc Property is in valueStore
        String openRootPropertyToBeDeletedAfterUndo = (String)((SDODataObject)rootObject)._getCurrentValueStore()//
            .getOpenContentProperty(openRootPropertyToBeDeleted);
        assertNull(openRootPropertyToBeDeletedAfterUndo);
        //assertEquals(openRootPropertyToBeDeletedAfterUndo, OC_PROP2SimpleSingleVALUE);
    }

    public void testDeepCopyObjectWithCSLoggingOnWithComboDeleteSingleCreateManyModifyRootChangesInTheDeepCopy() {

        List preOrderList = null;
        int numberOfDataObjectsInSubTree = 0;

        // unset isMany=true (to fill unsetPropsMap and createdList later when we (re)set it back)
        SDODataObject shipTo = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO);

        // use index 2 to avoid a swap later
        SDODataObject phone2 = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO_PHONE2);
        shipTo.unset("phone[2]");

        // save size of tree before CS was turned on
        preOrderList = preOrderTraversalDataObjectList((SDODataObject)rootObject, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        int numberOfNodesInRootBeforeCSon = 14;
        assertEquals(numberOfNodesInRootBeforeCSon, numberOfDataObjectsInSubTree);

        SDOProperty openRootProperty = new SDOProperty(aHelperContext);
        openRootProperty.setName(OC_PROP1SimpleSingleNAME);
        openRootProperty.setType(SDOConstants.SDO_STRING);
        //aRootTypeOC.setOpen(true);
        ((SDOType)rootObject.getType()).setOpen(true);
        rootObject.set(openRootProperty, OC_PROP1SimpleSingleVALUE);

        // set an Open Content property and delete it
        SDOProperty openRootPropertyToBeDeleted = new SDOProperty(aHelperContext);
        openRootPropertyToBeDeleted.setName(OC_PROP2SimpleSingleNAME);
        openRootPropertyToBeDeleted.setType(SDOConstants.SDO_STRING);
        //aRootTypeOC.setOpen(true);
        rootObject.set(openRootPropertyToBeDeleted, OC_PROP2SimpleSingleVALUE);

        // verify logging is on
        // turn on logging
        cs.beginLogging();
        assertTrue(cs.isLogging());

        // do some changes

        // delete an Open Content property
        rootObject.unset(openRootPropertyToBeDeleted);
        //ChangeSummary.Setting setting = cs.getOldValue(rootObject, openRootPropertyToBeDeleted);
        //assertEquals("openTest", setting.getValue());


        SDODataObject items = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_ITEMS);

        // detach isMany=false (to fill deletedList and modifiedList)
        //items.detach();
        items.delete();
        // (re)set isMany=true (to fill createdList, unsetPropsMap)
        List phones = (List)shipTo.get("phone");
        phones.add(phone2);
        // get an oldSetting in order to enable caching to fill the oldSettings hash map in the cs
        //Object oldValueItems = cs.getOldValue(rootObject, rootObject.getInstanceProperty("items")).getValue();
        //assertNotNull(oldValueItems);
        //assertNull(rootObject.get("items"));
        // save fields lengths for later comparision
        List<DataObject> changedObjects = cs.getChangedDataObjects();
        int changedObjectsLength = changedObjects.size();
        //int itemsOldValuesSize = cs.getOldValues(items).size();// invoke usage of the reverseDeletedMap

        // take an object with CS on and deep copy it
        SDODataObject copy = (SDODataObject)copyHelper.copy(rootObject);

        // copy the copy - so we are sure that the copy has enough in the cs to do an undo of the 2nd level copy
        SDODataObject copyOfCopy = (SDODataObject)copyHelper.copy(copy);

        //SDODataObject copy = (SDODataObject)marshalUnmarshalObject(rootObject);
        // verify that logging is still on
        ChangeSummary cs2 = copy.getChangeSummary();
        assertNotNull(cs2);
        assertTrue(cs2.isLogging());
        ChangeSummary cs3 = copyOfCopy.getChangeSummary();
        assertNotNull(cs3);
        assertTrue(cs3.isLogging());

        // verify saved field lengths from above
        assertEquals(changedObjectsLength, cs2.getChangedDataObjects().size());

        // no cache entries yet = 0 oldValues
        //assertEquals(itemsOldValuesSize, cs2.getOldValues(items).size());
        // check shallow equality
        assertEquals(rootObject.getInstanceProperties().size(), copy.getInstanceProperties().size());

        boolean isEqual = equalityHelper.equalShallow(rootObject, copy);
        assertTrue(isEqual);

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copy));
        assertTrue(equalityHelper.equalShallow(rootObject, copyOfCopy));

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copyOfCopy));

        // verify that all objects referenced in the copy changeSummary are from the copy not the original
        // verify createdList
        // verify deepCopies
        // verify deletedList
        // verify modifiedList
        // verify oldContainer
        // verify oldContainmentProperty
        // verify originalElements
        // verify originalValueStores
        Map originalValueStores = ((SDOChangeSummary)cs).getOriginalValueStores();
        Map originalValueStoresCopy = ((SDOChangeSummary)cs2).getOriginalValueStores();

        // verify originally deleted items is referencing a copy and a copy of its valuestore
        // verify reverseDeletedMap
        // verify rootDataObject
        assertEquals(copy, cs2.getRootObject());
        // verify unsetPropsMap
        SDODataObject items2 = (SDODataObject)copy.get(PROPERTY_NAME_PO_ITEMS);

        // check new phone copy
        SDODataObject phone2c = (SDODataObject)copy.get(PROPERTY_NAME_PO_SHIPTO_PHONE2);
        assertNotNull(phone2);
        // get original new phone
        SDODataObject phone2o = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO_PHONE2);
        assertNotNull(phone2);
        assertFalse(phone2o == phone2c);
        assertFalse(phone2o._getCurrentValueStore() == phone2c._getCurrentValueStore());

        // check new phone copy (in oldSettings) is == to currentValueStore phone (both are the same deepcopies of the original)
        List createdListCopy = ((SDOChangeSummary)cs2).getCreated();
        assertNotNull(createdListCopy);
        assertEquals(1, createdListCopy.size());
        SDODataObject phone2cInCreatedList = (SDODataObject)createdListCopy.get(0);
        assertNotNull(phone2cInCreatedList);
        assertNotNull(phone2cInCreatedList);
        assertTrue(phone2c == phone2cInCreatedList); // test cs.createList iterator makes deep copies
        assertTrue(phone2c._getCurrentValueStore() == phone2cInCreatedList._getCurrentValueStore());

        // get an oldSetting in order to enable caching to fill the hash map in the cs
        //Object oldValueItems2 = cs2.getOldValue(copy, copy.getInstanceProperty("items"));
        // verify that we have oldSettings in the new copy
        //        assertNotNull(oldValueItems2);
        //        assertNotNull(((SDOSetting)oldValueItems2).getValue());
        //        assertNull(copy.get("items"));
        // deleted objects are 9
        // verify that we have transferred the logged changes during the copy (we dont have to worry about nested changesummaries)
        assertEquals(changedObjectsLength, cs2.getChangedDataObjects().size());
        preOrderList = preOrderTraversalDataObjectList(copy, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        // assume that for logging=true copies we should have oldContainer, oldContProperties
        assertEquals(6, numberOfDataObjectsInSubTree);// 16 - 10
        assertEquals(((SDOChangeSummary)cs).getOldContainer().size(),//
                     copy.getChangeSummary().getOldContainer().size());
        assertEquals(((SDOChangeSummary)cs).getOldContainmentProperty().size(),//
                     copy.getChangeSummary().getOldContainmentProperty().size());

        // no oldSetting for simple object

        // verify oc props that were deleted are in oldSettings
        Property oc2cProp = openRootPropertyToBeDeleted;//(Property)copy.getOpenContentPropertiesMap().get(OC_PROP2SimpleSingleNAME);
        assertNotNull(oc2cProp);
        Object oc2cSetting = cs2.getOldValue(copy, oc2cProp);
        assertNotNull(oc2cSetting);
        String oc2cValue = (String)((SDOSetting)oc2cSetting).getValue();
        assertNotNull(oc2cValue);
        assertEquals(OC_PROP2SimpleSingleVALUE, oc2cValue);

        // verify unsetOC map
        List<Property> ocUnsetList = ((SDOChangeSummary)cs2).getUnsetOCProperties(copy);
        assertNotNull(ocUnsetList);
        Property oc2cProp_ocUnsetMap = ocUnsetList.get(0);
        assertNotNull(oc2cProp_ocUnsetMap);
        // verify that we are pointing to the same global property
        assertEquals(oc2cProp_ocUnsetMap, openRootPropertyToBeDeleted);
        String oc2cValue_ocUnsetMap = oc2cProp_ocUnsetMap.getName();
        assertNotNull(oc2cValue_ocUnsetMap);
        assertSame(openRootPropertyToBeDeleted.getName(), oc2cValue_ocUnsetMap);

        // verify oldContainer <key, value> are both deep copies
        // we an old setting first
        //DataObject anOldContainerValue = cs2.getOldContainer(items2);
        //assertTrue(copy == anOldContainerValue);



        // perform an undo on the copy and compare to the undone original (not the undone copy)
        cs2.undoChanges();
        // verify that original was unaffected by undo on copy
        items = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_ITEMS);
        assertNull(items);
        // get back "items" that has been reset
        items2 = (SDODataObject)copy.get(PROPERTY_NAME_PO_ITEMS);
        assertNotNull(items2);

        assertEquals(0, cs2.getChangedDataObjects().size());
        preOrderList = preOrderTraversalDataObjectList(copy, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        // assume that for logging=true copies we should have oldContainer, oldContProperties
        assertEquals(14, numberOfDataObjectsInSubTree);

        // undo changes on original
        cs.undoChanges();
        assertEquals(0, cs.getChangedDataObjects().size());
        // the items:do in the original and copy should not be the same object (different valueStores)
        // verify that original was unaffected by undo on copy
        items = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_ITEMS);
        assertFalse(items == items2);
        assertFalse(items._getCurrentValueStore() == items2._getCurrentValueStore());

        assertEquals(0, cs2.getChangedDataObjects().size());
        preOrderList = preOrderTraversalDataObjectList(copy, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        // assume that for logging=true copies we should have oldContainer, oldContProperties
        assertEquals(14, numberOfDataObjectsInSubTree);// 16 - 10

        // verify deep objects item[*] are distince between original and copy
        SDODataObject item1o = (SDODataObject)items.get("item[1]");
        SDODataObject item1c = (SDODataObject)items2.get("item[1]");
        assertNotNull(item1o);
        assertNotNull(item1c);
        assertFalse(item1o == item1c);
        assertFalse(item1o._getCurrentValueStore() == item1c._getCurrentValueStore());

        // verify listwrappers hashes are the same between two equal objects in the cs
        // verify simple Many integrity
        ListWrapper origComments = (ListWrapper)rootObject.get("items/item[1]/comment");
        assertNotNull(origComments);
        assertEquals(2, origComments.size());

        ListWrapper copyComments = (ListWrapper)copy.get("items/item[1]/comment");
        assertNotNull(copyComments);
        assertEquals(2, copyComments.size());
        //writeXML(copy);
        // check shallow equality
        assertTrue(equalityHelper.equalShallow(rootObject, copy));

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copy));

        // verify equality and undo the copyOfCopy to ensure that the csCopyOfCopy has enough info to do an undo
        copyOfCopy.getChangeSummary().undoChanges();
        assertTrue(equalityHelper.equalShallow(rootObject, copyOfCopy));

        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copyOfCopy));
        assertTrue(equalityHelper.equal(copy, copyOfCopy));

        // Verify CS undo of oc props
        // verify oc props that are copied
        Object oc1cProp = copy.get(OC_PROP1SimpleSingleNAME);
        assertNotNull(oc1cProp);
        assertEquals(OC_PROP1SimpleSingleVALUE, oc1cProp);

        // verify that deleted oc props were returned being set after an undo - use saved Property object (outside of this object)
        Object oc2cPropUndo = rootObject.get(openRootPropertyToBeDeleted);
        assertNotNull (oc2cPropUndo);
        assertEquals(oc2cPropUndo, OC_PROP2SimpleSingleVALUE);


        // test undo for oc - not implemented yet see #5928954
        // verify that deleted oc props were returned being set after an undo - do not used saved Property object -use getPath
        oc2cPropUndo = rootObject.get(openRootPropertyToBeDeleted.getName());
        assertNotNull(oc2cPropUndo);
        assertEquals(oc2cPropUndo, OC_PROP2SimpleSingleVALUE);

        // verify oc Property is in valueStore
        String openRootPropertyToBeDeletedAfterUndo = (String)((SDODataObject)rootObject)._getCurrentValueStore()//
            .getOpenContentProperty(openRootPropertyToBeDeleted);
        assertNotNull(openRootPropertyToBeDeletedAfterUndo);
        assertEquals(openRootPropertyToBeDeletedAfterUndo, OC_PROP2SimpleSingleVALUE);

        // exercise printstring
        cs.toString();
    }


    public void testDefineOpenContentPropDynamicallySpecP34() {
        // Create a new Type and with an open content property set
        DataObject myDataType = dataFactory.create("commonj.sdo", "Type");
        myDataType.set("name", "MyType");
        // SDOTypeHelperDelegate.openContentProperties Map is still null at this point
        Property openContentProperty = typeHelper.getOpenContentProperty(
                "commonj.sdo", "someProperty");
        assertNull(openContentProperty);
        // NPE here
        //myDataType.set(openContentProperty, "test");
        // Define the Type
        Type definedType = typeHelper.define(myDataType);
        // Retrieve the open content property
        Object retrievedValue = definedType.get(openContentProperty);
    }

    public void testDefineOpenContentPropDynamicallyLoggingOff() {
        // turn on logging
        assertFalse(cs.isLogging());

        // verify oc property does not exist prior to dynamically creating it
        Property openRootProperty =  rootObject.getInstanceProperty(OC_PROP1SimpleSingleNAME);
        assertNull(openRootProperty);

        // create oc prop on the fly
        ((SDOType) rootObject.getType()).setOpen(true);
        rootObject.set(OC_PROP1SimpleSingleNAME, OC_PROP1SimpleSingleVALUE);
        // get generated open content property
        openRootProperty = rootObject.getInstanceProperty(OC_PROP1SimpleSingleNAME);
        // check SDOTypeHelperDelegate.openContentProperties Map is set with this property
        Property openRootPropertyFromTypeHelper = typeHelper.getOpenContentProperty(OPEN_CONTENT_NS_URI, OC_PROP1SimpleSingleNAME);
        //assertNotNull(openRootPropertyFromTypeHelper);
    assertNull(openRootPropertyFromTypeHelper);
        assertNotNull(openRootProperty);
        //assertTrue(openRootProperty == openRootPropertyFromTypeHelper);
    }

    public void testDeepCopySettingForDynanicOpenContentSetAfterLoggingOn() {
        // turn on logging
        cs.beginLogging();
        assertTrue(cs.isLogging());

        // verify oc property does not exist prior to dynamically creating it
        Property openRootProperty =  rootObject.getInstanceProperty(OC_PROP1SimpleSingleNAME);
        assertNull(openRootProperty);

        // create oc prop on the fly
        ((SDOType) rootObject.getType()).setOpen(true);
        rootObject.set(OC_PROP1SimpleSingleNAME, OC_PROP1SimpleSingleVALUE);
        // get generated open content property
        openRootProperty = rootObject.getInstanceProperty(OC_PROP1SimpleSingleNAME);
        // check SDOTypeHelperDelegate.openContentProperties Map is set with this property
        Property openRootPropertyFromTypeHelper = typeHelper.getOpenContentProperty(//
                OPEN_CONTENT_NS_URI, OC_PROP1SimpleSingleNAME);
        //assertNotNull(openRootPropertyFromTypeHelper);
    assertNull(openRootPropertyFromTypeHelper);
        assertNotNull(openRootProperty);
        //assertTrue(openRootProperty == openRootPropertyFromTypeHelper);

        // deep copy
        DataObject dcopy = copyHelper.copy(rootObject);
        assertTrue(equalityHelper.equal(rootObject, dcopy));

        // get original setting
        ChangeSummary.Setting origSetting = rootObject.getChangeSummary().getOldValue(rootObject, openRootProperty);
        assertNotNull(origSetting);
        assertFalse(origSetting.isSet());
        assertEquals(null, origSetting.getValue());

        // get copy of original setting
        ChangeSummary.Setting copySetting = dcopy.getChangeSummary().getOldValue(dcopy, openRootProperty);
        assertNotNull(copySetting);
        // verify that isSet=false open content old values in the originalValueStores map are not copied over in cs.copy
        assertFalse(copySetting.isSet());
        assertEquals(null, copySetting.getValue());
    }

    public void testDeepCopySettingForOpenContentSetAfterLoggingOn() {
        // turn on logging
        cs.beginLogging();
        assertTrue(cs.isLogging());

        SDOProperty openRootProperty = new SDOProperty(aHelperContext);
        openRootProperty.setName(OC_PROP1SimpleSingleNAME);
        openRootProperty.setType(SDOConstants.SDO_STRING);
        ((SDOType) rootObject.getType()).setOpen(true);
        rootObject.set(openRootProperty, OC_PROP1SimpleSingleVALUE);

        DataObject deepCopy = copyHelper.copy(rootObject);
        assertTrue(equalityHelper.equal(rootObject, deepCopy));

        commonj.sdo.ChangeSummary.Setting setting = rootObject.getChangeSummary().getOldValue(rootObject, openRootProperty);
        assertNotNull(setting);
        assertFalse(setting.isSet());
        assertEquals(null, setting.getValue());

        commonj.sdo.ChangeSummary.Setting deepCopySetting = deepCopy.getChangeSummary().getOldValue(deepCopy, openRootProperty);
        assertNotNull(deepCopySetting);
        // verify that isSet=false open content old values in the originalValueStores map are not copied over in cs.copy
        assertFalse(deepCopySetting.isSet());
        assertEquals(null, deepCopySetting.getValue());
    }


    /**
     * Exercise cs.removeUnsetOCProperty()
     */
    public void testResetOfUnsetOpenContentPropertyClearsUnsetOCPropMap() {
        List preOrderList = null;
        int numberOfDataObjectsInSubTree = 0;

        // unset isMany=true (to fill unsetPropsMap and createdList later when we (re)set it back)
        SDODataObject shipTo = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO);

        // use index 2 to avoid a swap later
        SDODataObject phone2 = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO_PHONE2);
        shipTo.unset("phone[2]");

        // save size of tree before CS was turned on
        preOrderList = preOrderTraversalDataObjectList((SDODataObject)rootObject, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        int numberOfNodesInRootBeforeCSon = 14;
        assertEquals(numberOfNodesInRootBeforeCSon, numberOfDataObjectsInSubTree);

        // set a simple-single Open Content property
        SDOProperty openRootProperty = new SDOProperty(aHelperContext);
        openRootProperty.setName(OC_PROP1SimpleSingleNAME);
        openRootProperty.setType(SDOConstants.SDO_STRING);
        //aRootTypeOC.setOpen(true);
        ((SDOType)rootObject.getType()).setOpen(true);
        rootObject.set(openRootProperty, OC_PROP1SimpleSingleVALUE);

        // set an Open Content property and delete it
        SDOProperty openRootPropertyToBeDeleted = new SDOProperty(aHelperContext);
        openRootPropertyToBeDeleted.setName(OC_PROP2SimpleSingleNAME);
        openRootPropertyToBeDeleted.setType(SDOConstants.SDO_STRING);
        //aRootTypeOC.setOpen(true);
        rootObject.set(openRootPropertyToBeDeleted, OC_PROP2SimpleSingleVALUE);

        // turn on logging
        cs.beginLogging();
        assertTrue(cs.isLogging());

        // delete an Open Content property
        rootObject.unset(openRootPropertyToBeDeleted);
        assertFalse(((SDOChangeSummary)cs).getUnsetOCPropertiesMap().isEmpty());
        // reset it
        rootObject.set(openRootPropertyToBeDeleted, OC_PROP2SimpleSingleVALUE);
        assertTrue(((SDOChangeSummary)cs).getUnsetOCPropertiesMap().isEmpty());
    }

    /**
     * This test exercises bug 5913485: deepcopy is placed into cs.originalElements during a getOldValue()
     * SDOCopyHelper.copyChangeSummary()
     *  536                             // if deleted list is not found look in the reverse deleted map - if getOldSettings was called
     *  537  0                          SDODataObject reverseDeletedDO = (SDODataObject)originalCS.getReverseDeletedMap().get(aListItem);
     */
    public void testReverseDeletedMapUsageDuringDeepCopyChangeSummary() {
        // unset isMany=true (to fill unsetPropsMap and createdList later when we (re)set it back)
        SDODataObject shipTo = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO);
        // use index 2 to avoid a swap later
        SDODataObject phone2 = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_SHIPTO_PHONE2);
        shipTo.unset("phone[2]");
        cs.beginLogging();
        assertTrue(cs.isLogging());
        SDODataObject items = (SDODataObject)rootObject.get(PROPERTY_NAME_PO_ITEMS);
        // detach isMany=false (to fill deletedList and modifiedList)
        items.delete();
        // (re)set isMany=true (to fill createdList, unsetPropsMap)
        List phones = (List)shipTo.get("phone");
        phones.add(phone2);
        // get an oldSetting in order to enable caching to fill the oldSettings hash map in the cs
        Object oldValueItems = cs.getOldValue(rootObject, rootObject.getInstanceProperty("items")).getValue();
        assertNotNull(oldValueItems);
        assertNull(rootObject.get("items"));
        // save fields lengths for later comparision
        List<DataObject> changedObjects = cs.getChangedDataObjects();
        int changedObjectsLength = changedObjects.size();



        // verify #5913485 will cause an undone copy to be !deep equal
        int itemsOldValuesSize = cs.getOldValues(items).size();// invoke usage of the reverseDeletedMap
        // take an object with CS on and deep copy it
        SDODataObject copy = (SDODataObject)copyHelper.copy(rootObject);



        // verify that logging is still on
        ChangeSummary cs2 = copy.getChangeSummary();
        // verify saved field lengths from above
        assertEquals(changedObjectsLength, cs2.getChangedDataObjects().size());
        // check shallow equality
        boolean isEqual = equalityHelper.equalShallow(rootObject, copy);
        assertTrue(isEqual);
        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copy));
        // verify rootDataObject
        assertEquals(copy, cs2.getRootObject());
        // perform an undo on the copy and compare to the undone original (not the undone copy)
        cs2.undoChanges();
        // undo changes on original
        cs.undoChanges();
        // check shallow equality
        assertTrue(equalityHelper.equalShallow(rootObject, copy));
        // check deep equal is unaffected (we should have a copy of the copy for List items
        //- ListWrapper.add(item) will remove the item from its original wrapper)
        assertTrue(equalityHelper.equal(rootObject, copy));
    }


    //private void verifyCopyDistinctionFromOriginal(SDODataObject topObject, SDODataObject...childObjects ) {
    //}
    //private void verifyInternalListsAreSameInstancesThroughoutChangeSummary(SDODataObject topObject, ListWrapper...lists) {
    //}
    // depends on #5878605 test
    public void testEqualityWithMixedCSLoggingStatesDoesNotAffectEquality() {
        //SDODataObject copy = verifyDeepCopyObjectWithCSLoggingOnDoesNotLogChangesInTheDeepCopy((SDODataObject)rootObject);
        // load a 2nd copy of the same data object
        DataObject rootObject2EQ = null;
        ChangeSummary cs2EQ = null;
        try {
            XMLDocument document = xmlHelper.load(new FileInputStream("org/eclipse/persistence/testing/sdo/helper/xmlhelper/PurchaseOrderDeepWithCS.xml"));
            rootObject2EQ = document.getRootObject();
            cs2EQ = rootObject2EQ.getChangeSummary();
        } catch (Exception e) {
            e.printStackTrace();
            fail("An error occurred loading the xml file");
        }
        assertNotNull(rootObject2EQ);
        assertNotNull(cs2EQ);

        // 1. turn logging off on both
        cs.endLogging();
        cs2EQ.endLogging();

        // check shallow equal
        boolean isEqual = aHelperContext.getEqualityHelper().equalShallow(rootObject, rootObject2EQ);
        assertTrue(isEqual);

        // check deep equal is unaffected
        isEqual = aHelperContext.getEqualityHelper().equal(rootObject, rootObject2EQ);
        assertTrue(isEqual);

        // 2. turn logging on on both
        cs.beginLogging();
        cs2EQ.beginLogging();
        // check shallow equal
        isEqual = aHelperContext.getEqualityHelper().equalShallow(rootObject, rootObject2EQ);
        assertTrue(isEqual);

        // check deep equal is unaffected
        isEqual = aHelperContext.getEqualityHelper().equal(rootObject, rootObject2EQ);
        assertTrue(isEqual);

        // 3. turn logging off on one
        cs.endLogging();
        // check shallow equal
        isEqual = aHelperContext.getEqualityHelper().equalShallow(rootObject, rootObject2EQ);
        assertTrue(isEqual);

        // check deep equal is unaffected
        isEqual = aHelperContext.getEqualityHelper().equal(rootObject, rootObject2EQ);
        assertTrue(isEqual);

        // 4. perform changes on one of the copies and put it back (without an undo)
        DataObject items = (DataObject)rootObject2EQ.get("items");
        ((DataObject)rootObject2EQ.get("items")).detach();
        // get an oldSetting in order to enable caching to fill the hash map in the cs
        Object oldValueItems = cs2EQ.getOldValue(rootObject2EQ, rootObject2EQ.getInstanceProperty("items")).getValue();
        assertNotNull(oldValueItems);
        assertNull(rootObject2EQ.get("items"));
        rootObject2EQ.set("items", items);

        // check shallow equal is unaffected by the entry in the oldSettings list
        isEqual = aHelperContext.getEqualityHelper().equalShallow(rootObject, rootObject2EQ);
        assertTrue(isEqual);

        // check deep equal is unaffected by the entry in the oldSettings list
        isEqual = aHelperContext.getEqualityHelper().equal(rootObject, rootObject2EQ);
        assertTrue(isEqual);

        // 5. perform changes on both of the copies (1 with the cs on)
        items = (DataObject)rootObject.get("items");
        ((DataObject)rootObject.get("items")).detach();
        // get an oldSetting in order to enable caching to fill the hash map in the cs
        assertNull(rootObject.get("items"));
        items = (DataObject)rootObject2EQ.get("items");
        ((DataObject)rootObject2EQ.get("items")).detach();
        // get an oldSetting in order to enable caching to fill the hash map in the cs
        oldValueItems = cs2EQ.getOldValue(rootObject2EQ, rootObject2EQ.getInstanceProperty("items")).getValue();
        assertNotNull(oldValueItems);
        assertNull(rootObject2EQ.get("items"));
        //rootObject2EQ.set("items", items);
        // check shallow equal is unaffected by the entry in the oldSettings list
        isEqual = aHelperContext.getEqualityHelper().equalShallow(rootObject, rootObject2EQ);
        assertTrue(isEqual);

        // check deep equal is unaffected by the entry in the oldSettings list
        isEqual = aHelperContext.getEqualityHelper().equal(rootObject, rootObject2EQ);
        assertTrue(isEqual);
    }

    private SDODataObject verifyDeepCopyObjectWithCSLoggingOnDoesNotLogChangesInTheDeepCopy(SDODataObject aRootObject) {
        List preOrderList = null;
        int numberOfDataObjectsInSubTree = 0;

        // verify logging is on
        // turn on logging
        cs.beginLogging();
        assertTrue(cs.isLogging());

        // take an object with CS on and deep copy it
        SDODataObject copy = (SDODataObject)copyHelper.copy(aRootObject);

        // verify that logging is still on
        assertNotNull(cs);
        assertTrue(cs.isLogging());
        ChangeSummary cs2 = copy.getChangeSummary();
        assertNotNull(cs2);
        assertTrue(cs2.isLogging());
        // verify that we have not logged changes during the copy (we dont have to worry about nested changesummaries)
        assertEquals(0, cs2.getChangedDataObjects().size());// we should not have 5 old settings after a copy
        preOrderList = preOrderTraversalDataObjectList(copy, false);
        numberOfDataObjectsInSubTree = preOrderList.size();
        // assume that for logging=true copies we should have oldContainer, oldContProperties
        assertEquals(15, numberOfDataObjectsInSubTree);
        assertEquals(((SDOChangeSummary)cs2).getOldContainer().size(),//
                     copy.getChangeSummary().getOldContainer().size());
        assertEquals(((SDOChangeSummary)cs2).getOldContainmentProperty().size(),//
                     copy.getChangeSummary().getOldContainmentProperty().size());
        return copy;

    }

    // see bug #5878605: SDO: COPYHELPER.COPY() LOGS CS CHANGES - SHOULD SUSPEND LOGGING DURING COPY
    // we dont want changes to occur during the embedded set() calls in copy()
    // this test should be in the following location but this suite has a deeper model in order to fully test the bug see SDOCopyHelperDeepCopyTest.testDeepCopyObjectWithCSLoggingOnDoesNotLogChangesInTheDeepCopy()
    public void testDeepCopyObjectWithCSLoggingOnDoesNotLogChangesInTheDeepCopy() {
        verifyDeepCopyObjectWithCSLoggingOnDoesNotLogChangesInTheDeepCopy((SDODataObject)rootObject);
    }

    // verify unset after unset - logging on in the middle
    public void testUnsetCommentsAfterLoggingOnAfterUnset() {
        //cs.beginLogging();
        rootObject.unset("comment");
        cs.beginLogging();
        rootObject.unset("comment");
        assertUnchanged(rootObject, cs);//
        assertEquals(0, cs.getChangedDataObjects().size());

        List oldValues = cs.getOldValues(rootObject);
        assertEquals(0, oldValues.size());
        //writeXML(rootObject);
    }

    public void testDeleteItems() {
        DataObject itemsDO = rootObject.getDataObject("items");
        DataObject item1DO = rootObject.getDataObject("items/item[1]");
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item1ProductDO = item1DO.getDataObject("product");
        DataObject item1ProductPrice1DO = item1ProductDO.getDataObject("price[1]");
        DataObject item1ProductPrice2DO = item1ProductDO.getDataObject("price[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();
        itemsDO.delete();

        assertNotNull(item1DO);
        assertNotNull(item2DO);

        assertModified(rootObject, cs);
        assertDeleted(itemsDO, cs);
        assertDeleted(item1DO, cs);
        assertDeleted(item2DO, cs);
        assertDeleted(item1ProductDO, cs);
        assertDeleted(item1ProductPrice1DO, cs);
        assertDeleted(item1ProductPrice2DO, cs);
        assertDeleted(item2ProductDO, cs);
        assertDeleted(item2ProductPrice1DO, cs);
        assertDeleted(item2ProductPrice2DO, cs);
        assertEquals(10, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());//  from 9

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());// from 9

        //writeXML(rootObject);// null objectValue in org.eclipse.persistence.internal.oxm.XMLAnyCollectionMappingNodeValue.marshal(XMLAnyCollectionMappingNodeValue.java:92)
    }

    public void testDeleteItemsAndUndo() {
        // save original root for later comparison after undo
        DataObject originalRootDO = copyHelper.copy(rootObject);
        assertTrue(equalityHelper.equal(rootObject, originalRootDO));

        DataObject itemsDO = rootObject.getDataObject("items");
        DataObject item1DO = rootObject.getDataObject("items/item[1]");
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item1ProductDO = item1DO.getDataObject("product");
        DataObject item1ProductPrice1DO = item1ProductDO.getDataObject("price[1]");
        DataObject item1ProductPrice2DO = item1ProductDO.getDataObject("price[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();
        // verify original VS is null and save a copy of current VS for object identity testing after undo
        ValueStore aCurrentValueStore = ((SDODataObject)rootObject)._getCurrentValueStore();
        assertNotNull(aCurrentValueStore);
        ValueStore anOriginalValueStore = (ValueStore)((SDOChangeSummary)cs).getOriginalValueStores().get(rootObject);
        assertNull(anOriginalValueStore);

        itemsDO.delete();

        // check valueStores
        assertNotNull(aCurrentValueStore);
        ValueStore anOriginalValueStoreAfterOperation = (ValueStore)((SDOChangeSummary)cs).getOriginalValueStores().get(rootObject);
        ValueStore aCurrentValueStoreAfterOperation = ((SDODataObject)rootObject)._getCurrentValueStore();
        assertNotNull(anOriginalValueStoreAfterOperation);
        assertNotNull(aCurrentValueStoreAfterOperation);
        assertTrue(anOriginalValueStoreAfterOperation == aCurrentValueStore);

        assertNotNull(item1DO);
        assertNotNull(item2DO);

        assertModified(rootObject, cs);
        assertDeleted(itemsDO, cs);
        assertDeleted(item1DO, cs);
        assertDeleted(item2DO, cs);
        assertDeleted(item1ProductDO, cs);
        assertDeleted(item1ProductPrice1DO, cs);
        assertDeleted(item1ProductPrice2DO, cs);
        assertDeleted(item2ProductDO, cs);
        assertDeleted(item2ProductPrice1DO, cs);
        assertDeleted(item2ProductPrice2DO, cs);
        assertEquals(10, cs.getChangedDataObjects().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());//  from 9
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());// from 9

        assertUndoChangesEqualToOriginal(cs, rootObject, originalRootDO);

        // verify that property is reset
        assertTrue(rootObject.isSet("items"));
        // get back items object
        DataObject itemsDOundone = rootObject.getDataObject("items");

        ValueStore anOriginalValueStoreAfterUndo = (ValueStore)((SDOChangeSummary)cs).getOriginalValueStores().get(rootObject);
        ValueStore aCurrentValueStoreAfterUndo = ((SDODataObject)rootObject)._getCurrentValueStore();
        assertNull(anOriginalValueStoreAfterUndo);
        assertNotNull(aCurrentValueStoreAfterUndo);
        // we return the original value store back to the current VS
        assertTrue(aCurrentValueStoreAfterUndo == aCurrentValueStore);
    }

    public void testDetachItems() {
        // save original root for later comparison after undo
        DataObject originalRootDO = copyHelper.copy(rootObject);
        assertTrue(equalityHelper.equal(rootObject, originalRootDO));

        DataObject itemsDO = rootObject.getDataObject("items");
        DataObject item1DO = rootObject.getDataObject("items/item[1]");
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item1ProductDO = item1DO.getDataObject("product");
        DataObject item1ProductPrice1DO = item1ProductDO.getDataObject("price[1]");
        DataObject item1ProductPrice2DO = item1ProductDO.getDataObject("price[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();
        itemsDO.detach();

        assertNotNull(item1DO);
        assertNotNull(item2DO);

        assertModified(rootObject, cs);
        assertDetached(itemsDO, cs);
        assertDetached(item1DO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item2DO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item1ProductDO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item1ProductPrice1DO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item1ProductPrice2DO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item2ProductDO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item2ProductPrice1DO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item2ProductPrice2DO, cs, false);// internal children of a detach have a non-null container
        assertEquals(10, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());//  from 9

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());// from 9

        assertUndoChangesEqualToOriginal(cs, rootObject, originalRootDO);
    }

    // test unset of single property containing an isMany=true set of DataObjects
    public void testCSonRootUnsetComplexSingleAtRootWithComplexManyChildren() {// testUnsetItems() { // NPE on save
        DataObject itemsDO = rootObject.getDataObject("items");
        DataObject item1DO = rootObject.getDataObject("items/item[1]");
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item1ProductDO = item1DO.getDataObject("product");
        DataObject item1ProductPrice1DO = item1ProductDO.getDataObject("price[1]");
        DataObject item1ProductPrice2DO = item1ProductDO.getDataObject("price[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");
        Property containmentProp = itemsDO.getContainmentProperty();

        cs.beginLogging();
        rootObject.unset(containmentProp);

        //        verifyShipToDetachedOrUnset(shipToDO, yardDO,//
        //                phoneList, phone1, phone2, containmentProp, oldStreet);
        assertNotNull(item1DO);
        assertNotNull(item2DO);

        assertModified(rootObject, cs);
        assertDetached(itemsDO, cs);
        assertDetached(item1DO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item2DO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item1ProductDO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item1ProductPrice1DO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item1ProductPrice2DO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item2ProductDO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item2ProductPrice1DO, cs, false);// internal children of a detach have a non-null container
        assertDetached(item2ProductPrice2DO, cs, false);// internal children of a detach have a non-null container
        assertEquals(10, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());//  from 9

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());// from 9

        //writeXML(rootObject);// null objectValue in org.eclipse.persistence.internal.oxm.XMLAnyCollectionMappingNodeValue.marshal(XMLAnyCollectionMappingNodeValue.java:92)
    }

    // Test Scenarios:
    // - many delete
    public void testDeleteItem2Price1() {
        // save original root for later comparison after undo
        DataObject originalRootDO = copyHelper.copy(rootObject);
        assertTrue(equalityHelper.equal(rootObject, originalRootDO));

        DataObject itemsDO = rootObject.getDataObject("items");
        DataObject item1DO = rootObject.getDataObject("items/item[1]");
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item1ProductDO = item1DO.getDataObject("product");
        DataObject item1ProductPrice1DO = item1ProductDO.getDataObject("price[1]");
        DataObject item1ProductPrice2DO = item1ProductDO.getDataObject("price[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();
        item2ProductPrice1DO.delete();

        assertModified(item2ProductDO, cs);
        assertDeleted(item2ProductPrice1DO, cs);

        assertEquals(2, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        ChangeSummary.Setting containmentSetting = (ChangeSummary.Setting)cs.getOldValues(item2ProductDO).get(0);
        assertEquals("price", containmentSetting.getProperty().getName());
        assertTrue(containmentSetting.getValue() instanceof List);
        assertEquals(2, ((List)containmentSetting.getValue()).size());
        assertEquals(true, containmentSetting.isSet());
        //writeXML(rootObject);
        // undo and verify equality
        assertUndoChangesEqualToOriginal(cs, rootObject, originalRootDO);

    }

    public void testDetachItem2Price1() {
        DataObject itemsDO = rootObject.getDataObject("items");
        DataObject item1DO = rootObject.getDataObject("items/item[1]");
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item1ProductDO = item1DO.getDataObject("product");
        DataObject item1ProductPrice1DO = item1ProductDO.getDataObject("price[1]");
        DataObject item1ProductPrice2DO = item1ProductDO.getDataObject("price[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();
        item2ProductPrice1DO.detach();

        assertModified(item2ProductDO, cs);
        assertDetached(item2ProductPrice1DO, cs);

        assertEquals(2, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        ChangeSummary.Setting containmentSetting = (ChangeSummary.Setting)cs.getOldValues(item2ProductDO).get(0);
        assertEquals("price", containmentSetting.getProperty().getName());
        assertTrue(containmentSetting.getValue() instanceof List);
        assertEquals(2, ((List)containmentSetting.getValue()).size());
        assertEquals(true, containmentSetting.isSet());
        //writeXML(rootObject);
    }

    // Note: unset of a single item in a list is different than a detach in that all the items under
    // property being unset are detached.
    public void testCSonRootUnsetComplexSingleBelowRootWithCompexManyChildren() {// testUnsetItem2Price() {
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        //DataObject item1ProductDO = item1DO.getDataObject("product");
        //DataObject item1ProductPrice1DO = item1ProductDO.getDataObject("price[1]");
        //DataObject item1ProductPrice2DO = item1ProductDO.getDataObject("price[2]");
        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");
        Property containmentProp = item2ProductPrice1DO.getContainmentProperty();

        cs.beginLogging();
        // test isMany section of unset() - all items including price1 and price2 are unset
        item2ProductDO.unset(containmentProp);

        assertModified(item2ProductDO, cs);
        assertDetached(item2ProductPrice1DO, cs);
        assertDetached(item2ProductPrice2DO, cs);

        assertEquals(3, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        List aSettingList = cs.getOldValues(item2ProductDO);
        assertTrue(aSettingList.size() > 0);
        ChangeSummary.Setting containmentSetting = (ChangeSummary.Setting)aSettingList.get(0);
        assertEquals("price", containmentSetting.getProperty().getName());
        assertTrue(containmentSetting.getValue() instanceof List);
        assertEquals(2, ((List)containmentSetting.getValue()).size());
        assertEquals(true, containmentSetting.isSet());
        //writeXML(rootObject);
    }

    // unset a single item in a list
    // TODO: this test will fail as of 20070111 until bug#5757236 is fixed
    public void testSetItem2Price3() {
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();
        int startListSize = item2ProductDO.getList("price").size();
        assertEquals(2, startListSize);
        DataObject newPrice = dataFactory.create(item2ProductPrice2DO.getType());
        item2ProductDO.set("price[3]", newPrice);

        int endListSize = item2ProductDO.getList("price").size();
        assertEquals(3, endListSize);

        assertCreated(newPrice, cs);// TODO: failure starts here
        assertModified(item2ProductDO, cs);
        assertUnchanged(item2ProductPrice1DO, cs);
        assertUnchanged(item2ProductPrice2DO, cs);// TODO: failure starts here

        assertEquals(2, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        List aSettingList = cs.getOldValues(item2ProductDO);
        assertTrue(aSettingList.size() > 0);
        ChangeSummary.Setting containmentSetting = (ChangeSummary.Setting)aSettingList.get(0);
        assertEquals("price", containmentSetting.getProperty().getName());
        assertTrue(containmentSetting.getValue() instanceof List);
        assertEquals(2, ((List)containmentSetting.getValue()).size());
        assertEquals(true, containmentSetting.isSet());
        //writeXML(rootObject);
    }

    public void testRemoveByObjectItem2Price2() {
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();

        int startListSize = item2ProductDO.getList("price").size();
        assertEquals(2, startListSize);

        item2ProductDO.getList("price").remove(item2ProductPrice2DO);

        int endListSize = item2ProductDO.getList("price").size();
        assertEquals(1, endListSize);

        assertModified(item2ProductDO, cs);
        assertUnchanged(item2ProductPrice1DO, cs);
        assertDetached(item2ProductPrice2DO, cs);// TODO: failure starts here

        assertEquals(2, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        List aSettingList = cs.getOldValues(item2ProductDO);
        assertTrue(aSettingList.size() > 0);
        ChangeSummary.Setting containmentSetting = (ChangeSummary.Setting)aSettingList.get(0);
        assertEquals("price", containmentSetting.getProperty().getName());
        assertTrue(containmentSetting.getValue() instanceof List);
        assertEquals(2, ((List)containmentSetting.getValue()).size());
        assertEquals(true, containmentSetting.isSet());
        //writeXML(rootObject);
    }

    public void testRemoveByIndexItem2Price2() {
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();
        int startListSize = item2ProductDO.getList("price").size();
        assertEquals(2, startListSize);

        int indexToRemove = item2ProductDO.getList("price").indexOf(item2ProductPrice2DO);
        item2ProductDO.getList("price").remove(indexToRemove);

        int endListSize = item2ProductDO.getList("price").size();
        assertEquals(1, endListSize);

        assertModified(item2ProductDO, cs);
        assertUnchanged(item2ProductPrice1DO, cs);
        assertDetached(item2ProductPrice2DO, cs);// TODO: failure starts here

        assertEquals(2, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        List aSettingList = cs.getOldValues(item2ProductDO);
        assertTrue(aSettingList.size() > 0);
        ChangeSummary.Setting containmentSetting = (ChangeSummary.Setting)aSettingList.get(0);
        assertEquals("price", containmentSetting.getProperty().getName());
        assertTrue(containmentSetting.getValue() instanceof List);
        assertEquals(2, ((List)containmentSetting.getValue()).size());
        assertEquals(true, containmentSetting.isSet());
        //writeXML(rootObject);
    }

    // unset a single item in a list
    // TODO: this test will fail as of 20070111 until bug#5757236 is fixed
    public void testUnsetItem2Price2() {
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();
        int startListSize = item2ProductDO.getList("price").size();
        assertEquals(2, startListSize);
        // test isMany section of unset() - all items including price1 and price2 are unset
        item2ProductDO.unset("price[2]");

        int endListSize = item2ProductDO.getList("price").size();
        assertEquals(1, endListSize);

        assertModified(item2ProductDO, cs);
        assertUnchanged(item2ProductPrice1DO, cs);
        assertDetached(item2ProductPrice2DO, cs);// TODO: failure starts here

        assertEquals(2, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        List aSettingList = cs.getOldValues(item2ProductDO);
        assertTrue(aSettingList.size() > 0);
        ChangeSummary.Setting containmentSetting = (ChangeSummary.Setting)aSettingList.get(0);
        assertEquals("price", containmentSetting.getProperty().getName());
        assertTrue(containmentSetting.getValue() instanceof List);
        assertEquals(2, ((List)containmentSetting.getValue()).size());
        assertEquals(true, containmentSetting.isSet());
        //writeXML(rootObject);
    }

    /**
     * The following two tests do the same thing in 2 different ways.
     * The results should be the same after both calls
     * detach/re(set) yard
     * detach/undo yard
     * see bug# 5882923
     */
    private List setupDetachForResetOrUndoOfYardToSamePlace(DataObject shipToDO, DataObject yardDO, Object length) {
        cs.beginLogging();
        yardDO.detach();

        List yardDOSettings = cs.getOldValues(yardDO);
        assertEquals(3, yardDOSettings.size());
        assertDetached(yardDO, cs);
        assertModified(shipToDO, cs);
        assertFalse(cs.isModified(yardDO));
        assertEquals(2, cs.getChangedDataObjects().size());
        return yardDOSettings;
    }

    // perform a manual undo (local undo)
    // See SDO-225 Feb-15 2007 issue (option A - nothing in the cs, option B - track unset/reset)
    public void testDetachAndResetYardToSamePlaceUsingManualUndoViaSet() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");

        //Property containmentProp = shipToDO.getInstanceProperty("yard");
        DataObject yardDO = shipToDO.getDataObject("yard");
        Object length = yardDO.get("length");
        List yardDOSettings = setupDetachForResetOrUndoOfYardToSamePlace(shipToDO, yardDO, length);

        // originalValueStore of shipTo will already be copied in the modifiy part of the detach of its child above
        // this set will trigger a 2nd copy of the ValueStore - we will ignore it.
        /**
        * Case: Move/Reset
        *  a detach of a child modifies its parent - trigering a copy of parent's ValueStore
        *  a set on the parent will trigger another copy - but we will skip this one as we already
        *  have a copy of the original.
        *  Issue: if we reset the child back the same place (in effect doing our own undo)
        *  do we optimize this and remove the copy - for now a real undoChanges() will do the same
        */
        shipToDO.set("yard", yardDO); // the entry in deletedMap will be removed and isModified == false
        assertFalse(cs.isDeleted(yardDO));

        yardDOSettings = cs.getOldValues(yardDO);  // will return an empty list since the oldValueStore entry was removed during set()
        List shipToSettings = cs.getOldValues(shipToDO);
        // see cs.getOldValue() does not return null when yardDO is !modified and !deleted (but !created as well) - (re)set
        ChangeSummary.Setting lengthSetting = cs.getOldValue(yardDO, yardDO.getInstanceProperty("length"));

        // TODO: FIX this ambiguity Jira 225 and 109/125 via a smart local undo
        // 20070501: this test is has been switched to assertTrue to pass until we fix 5882923
        if(1 < 0) {
            assertFalse(cs.isModified(shipToDO)); // this should be the correct assertion
            assertEquals(0, cs.getChangedDataObjects().size());//if we add new logic
            // see cs.getOldValues() does not return and empty List when yardDO is !modified and !deleted (but !created as well) - (re)set
            assertEquals(0, yardDOSettings.size());// was 3 before we implemented undoChanges()
            //assertNotNull(lengthSetting);
            assertNull(lengthSetting);
        } else {
            assertTrue(cs.isModified(shipToDO)); // see bug# 5882923 - we should clear the setting here
            assertEquals(1, cs.getChangedDataObjects().size());//if we add new logic
            // see cs.getOldValues() does not return and empty List when yardDO is !modified and !deleted (but !created as well) - (re)set
            assertEquals(0, yardDOSettings.size());// was 3 before we implemented undoChanges()
            assertNull(lengthSetting);
            //assertNull(lengthSetting);
        }



















        assertFalse(cs.isModified(yardDO));

        //assertEquals(1, cs.getChangedDataObjects().size());//just shipTo
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        assertEquals(0, shipToSettings.size());// 20070214: modified from 1

        //assertEquals(length, lengthSetting.getValue());
        //writeXML(rootObject);
    }

    // same as above but using a real undoChanges() instead of a re(set)
    // see bug# 5882923
    // See SDO-225 Feb-15 2007 issue (option A - nothing in the cs, option B - track unset/reset)
    public void testDetachAndResetYardToSamePlaceUsingFullCSUndoChangesFunction() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");

        //Property containmentProp = shipToDO.getInstanceProperty("yard");
        DataObject yardDO = shipToDO.getDataObject("yard");
        Object length = yardDO.get("length");
        List yardDOSettings = setupDetachForResetOrUndoOfYardToSamePlace(shipToDO, yardDO, length);

        // originalValueStore of shipTo will already be copied in the modifiy part of the detach of its child above
        // this set will trigger a 2nd copy of the ValueStore - we will ignore it.
        /**
        * Case: Move/Reset
        *  a detach of a child modifies its parent - trigering a copy of parent's ValueStore
        *  a set on the parent will trigger another copy - but we will skip this one as we already
        *  have a copy of the original.
        *  Issue: if we reset the child back the same place (in effect doing our own undo)
        *  do we optimize this and remove the copy - for now a real undoChanges() will do the same
        */
        //shipToDO.set("yard", yardDO);
        cs.undoChanges();

        assertFalse(cs.isDeleted(yardDO));
        assertFalse(cs.isModified(shipToDO));//if we add new logic
        //assertTrue(cs.isModified(shipToDO)); // see bug# 5882923 - we should clear the setting here
        assertFalse(cs.isModified(yardDO));

        assertEquals(0, cs.getChangedDataObjects().size());//if we add new logic
        //assertEquals(1, cs.getChangedDataObjects().size());//just shipTo
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        List shipToSettings = cs.getOldValues(shipToDO);
        assertEquals(0, shipToSettings.size());// 20070214: modified from 1

        yardDOSettings = cs.getOldValues(yardDO);
        // see cs.getOldValues() does not return and empty List when yardDO is !modified and !deleted (but !created as well) - (re)set
        assertEquals(0, yardDOSettings.size());// was 3 before we implemented undoChanges()

        // see cs.getOldValue() does not return null when yardDO is !modified and !deleted (but !created as well) - (re)set
        ChangeSummary.Setting lengthSetting = cs.getOldValue(yardDO, yardDO.getInstanceProperty("length"));

        //assertNotNull(lengthSetting);
        assertNull(lengthSetting);

        //assertEquals(length, lengthSetting.getValue());
        //writeXML(rootObject);
    }

    // Verify that an unset followed by a (re)set of the same subtree returns tree to original state
    // See SDO-225 Feb-15 2007 issue (option A - nothing in the cs, option B - track unset/reset)
    public void testDetachAndReSetPrice1BackToSameIndex() {
        DataObject itemsDO = rootObject.getDataObject("items");
        DataObject item1DO = rootObject.getDataObject("items/item[1]");
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item1ProductDO = item1DO.getDataObject("product");
        DataObject item1ProductPrice1DO = item1ProductDO.getDataObject("price[1]");
        DataObject item1ProductPrice2DO = item1ProductDO.getDataObject("price[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();
        item2ProductPrice1DO.detach();

        assertModified(item2ProductDO, cs);
        assertDetached(item2ProductPrice1DO, cs);

        assertEquals(2, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        List aSettingList = cs.getOldValues(item2ProductDO);
        assertTrue(aSettingList.size() > 0);
        ChangeSummary.Setting containmentSetting = (ChangeSummary.Setting)aSettingList.get(0);
        assertEquals("price", containmentSetting.getProperty().getName());
        assertTrue(containmentSetting.getValue() instanceof List);
        assertEquals(2, ((List)containmentSetting.getValue()).size());
        assertEquals(true, containmentSetting.isSet());

        // UNDO - reattach subtree
        ((ListWrapper)item2ProductDO.get("price")).add(0, item2ProductPrice1DO);

        assertFalse(cs.isDeleted(item2ProductPrice1DO));
        //assertUnchanged(cs.isModified(item2ProductDO)); //if we add new logic
        assertFalse(cs.isModified(item2ProductDO));

        assertFalse(cs.isModified(item2ProductPrice1DO));

        assertEquals(0, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());
        //writeXML(rootObject);
    }

    // Verify that an unset followed by a set (swap) at a different position does not return the tree to the original state
    // price[1] becomes price[2], and price[2] becomes price[1]
    public void testSwapUsingDetachAndSetPrice1ToLastIndex2() {
        DataObject itemsDO = rootObject.getDataObject("items");
        DataObject item1DO = rootObject.getDataObject("items/item[1]");
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item1ProductDO = item1DO.getDataObject("product");
        DataObject item1ProductPrice1DO = item1ProductDO.getDataObject("price[1]");
        DataObject item1ProductPrice2DO = item1ProductDO.getDataObject("price[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();
        item2ProductPrice1DO.detach();

        assertModified(item2ProductDO, cs);
        assertDetached(item2ProductPrice1DO, cs);

        assertEquals(2, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        List aSettingList = cs.getOldValues(item2ProductDO);
        assertTrue(aSettingList.size() > 0);
        ChangeSummary.Setting containmentSetting = (ChangeSummary.Setting)aSettingList.get(0);
        assertEquals("price", containmentSetting.getProperty().getName());
        assertTrue(containmentSetting.getValue() instanceof List);
        assertEquals(2, ((List)containmentSetting.getValue()).size());
        assertEquals(true, containmentSetting.isSet());

        // Swap/move - reattach subtree in new positon
        ((ListWrapper)item2ProductDO.get("price")).add(//
        1,//
        item2ProductPrice1DO);

        // verify that container does not reference itself
        assertNotSame(item2ProductPrice1DO, item2ProductPrice1DO.getContainer());
        assertModified(item2ProductDO, cs);
        // TODO: fails
        //assertModified(item2ProductPrice1DO, cs);// assertDeleted
        assertFalse(cs.isModified(item2ProductPrice1DO));

        //assertEquals(0, cs.getChangedDataObjects().size());  //if we add new logic
        assertEquals(1, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());
        //writeXML(rootObject);
    }

    // test deletion inside a list - see detach() isMany section
    // Test Scenarios:
    // - many delete
    public void testDeleteMultipleInList() {
        cs.endLogging();
        DataObject itemsDO = rootObject.getDataObject("items");
        DataObject item1DO = rootObject.getDataObject("items/item[1]");
        DataObject item3DO = dataFactory.create(item1DO.getType());
        DataObject item4DO = dataFactory.create(item1DO.getType());
        DataObject item5DO = dataFactory.create(item1DO.getType());
        DataObject item6DO = dataFactory.create(item1DO.getType());
        itemsDO.getList("item").add(item3DO);
        itemsDO.getList("item").add(item4DO);
        itemsDO.getList("item").add(item5DO);
        itemsDO.getList("item").add(item6DO);
        cs.beginLogging();
        item3DO.delete();
        item5DO.delete();
        assertDeleted(item3DO, cs);// 5/2
        assertDeleted(item5DO, cs);// 5/2
        assertModified(itemsDO, cs);

        assertEquals(3, cs.getChangedDataObjects().size());
        assertEquals(18, ((SDOChangeSummary)cs).getOldContainer().size());// 14 + 4 new objects
        assertEquals(18, ((SDOChangeSummary)cs).getOldContainmentProperty().size());// 14 + 4 new objects
        assertEquals(1, cs.getOldValues(itemsDO).size());// from 2 (only 1st change on items is recorded)
        assertEquals(5, cs.getOldValues(item3DO).size());// 1
        assertEquals(5, cs.getOldValues(item5DO).size());// 1
        List aSettingList = cs.getOldValues(itemsDO);
        assertTrue(aSettingList.size() > 0);
        ChangeSummary.Setting containmentSetting = (ChangeSummary.Setting)aSettingList.get(0);
        assertEquals("item", containmentSetting.getProperty().getName());
        assertTrue(containmentSetting.getValue() instanceof List);
        assertEquals(6, ((List)containmentSetting.getValue()).size());
        assertEquals(true, containmentSetting.isSet());// see detach(boolean)
        //writeXML(rootObject);
    }

    // test deletion inside a list - see detach() isMany section
    // Test Scenarios:
    // - many delete
    public void testCSonRootDeleteComplexManyBelowRoot() {//testDeleteItem2() {
        DataObject itemsDO = rootObject.getDataObject("items");
        DataObject item1DO = rootObject.getDataObject("items/item[1]");
        DataObject item2DO = rootObject.getDataObject("items/item[2]");

        DataObject item2ProductDO = item2DO.getDataObject("product");
        DataObject item2ProductPrice1DO = item2ProductDO.getDataObject("price[1]");
        DataObject item2ProductPrice2DO = item2ProductDO.getDataObject("price[2]");

        cs.beginLogging();
        item2DO.delete();

        assertModified(itemsDO, cs);
        assertDeleted(item2DO, cs);
        assertDeleted(item2ProductDO, cs);
        assertDeleted(item2ProductPrice1DO, cs);
        assertDeleted(item2ProductPrice2DO, cs);

        assertEquals(5, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        assertEquals(1, cs.getOldValues(itemsDO).size());
        ChangeSummary.Setting containmentSetting = (ChangeSummary.Setting)cs.getOldValues(itemsDO).get(0);
        assertEquals("item", containmentSetting.getProperty().getName());
        assertTrue(containmentSetting.getValue() instanceof List);
        assertEquals(2, ((List)containmentSetting.getValue()).size());
        assertEquals(true, containmentSetting.isSet());
        //writeXML(rootObject);
    }

    public void testMoveYardWithSet() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");
        Property containmentProp = shipToDO.getInstanceProperty("yard");

        DataObject billToDO = rootObject.getDataObject("billTo");
        DataObject yardDO = shipToDO.getDataObject("yard");
        cs.beginLogging();
        billToDO.set("yard", yardDO);

        assertModified(shipToDO, cs);
        assertModified(billToDO, cs);
        assertFalse(cs.isDeleted(yardDO));
        assertEquals(2, cs.getChangedDataObjects().size());

        assertEquals(billToDO.getChangeSummary(), yardDO.getChangeSummary());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());
        // test detach from updateContainment
        List shipToSettings = cs.getOldValues(shipToDO);
        List billToSettings = cs.getOldValues(billToDO);
        assertEquals(1, billToSettings.size());
        assertEquals(1, shipToSettings.size());

        ChangeSummary.Setting billToSetting = (ChangeSummary.Setting)billToSettings.get(0);
        assertEquals("yard", billToSetting.getProperty().getName());
        assertEquals(null, billToSetting.getValue());

        //TODO: comment out this line when null policy stuff is working
        //assertEquals(false, billToSetting.isSet());
        ChangeSummary.Setting shipToSetting = (ChangeSummary.Setting)shipToSettings.get(0);
        assertEquals("yard", shipToSetting.getProperty().getName());
        assertFalse(yardDO == shipToSetting.getValue());
        assertTrue(equalityHelper.equal(yardDO, (DataObject)shipToSetting.getValue()));
        assertEquals(true, shipToSetting.isSet());
        assertEquals(shipToDO, cs.getOldContainer(yardDO));
        assertEquals(containmentProp, cs.getOldContainmentProperty(yardDO));
        //writeXML(rootObject);
    }

    public void testMoveYardWithDetachAndSet() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");
        Property containmentProp = shipToDO.getInstanceProperty("yard");

        DataObject billToDO = rootObject.getDataObject("billTo");
        DataObject yardDO = shipToDO.getDataObject("yard");
        cs.beginLogging();
        yardDO.detach();
        assertTrue(cs.isDeleted(yardDO));
        billToDO.set("yard", yardDO);

        assertModified(shipToDO, cs);
        assertModified(billToDO, cs);
        assertFalse(cs.isDeleted(yardDO));
        assertEquals(2, cs.getChangedDataObjects().size());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());
        // TODO: VERIFY 2 -> 3
        List shipToSettings = cs.getOldValues(shipToDO);
        List billToSettings = cs.getOldValues(billToDO);
        assertEquals(1, billToSettings.size());
        assertEquals(1, shipToSettings.size());

        ChangeSummary.Setting billToSetting = (ChangeSummary.Setting)billToSettings.get(0);
        assertEquals("yard", billToSetting.getProperty().getName());
        assertEquals(null, billToSetting.getValue());

        //TODO: comment out this line when null policy stuff is working
        //assertEquals(false, billToSetting.isSet());
        ChangeSummary.Setting shipToSetting = (ChangeSummary.Setting)shipToSettings.get(0);
        assertEquals("yard", shipToSetting.getProperty().getName());
        assertFalse(yardDO == shipToSetting.getValue());
        assertTrue(equalityHelper.equal(yardDO, (DataObject)shipToSetting.getValue()));
        assertEquals(true, shipToSetting.isSet());
        assertEquals(shipToDO, cs.getOldContainer(yardDO));
        assertEquals(containmentProp, cs.getOldContainmentProperty(yardDO));
        //writeXML(rootObject);
    }

    public void testDeleteYard() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");
        DataObject yardDO = shipToDO.getDataObject("yard");
        cs.beginLogging();
        yardDO.delete();

        assertYardDeleted(shipToDO, yardDO, cs, true);
        assertModified(shipToDO, cs);

        assertEquals(2, cs.getChangedDataObjects().size());

        assertEquals(1, cs.getOldValues(shipToDO).size());
        ChangeSummary.Setting shipToSetting = (ChangeSummary.Setting)cs.getOldValues(shipToDO).get(0);
        assertEquals("yard", shipToSetting.getProperty().getName());
        assertEquals(true, shipToSetting.isSet());
        DataObject yardDeepCopy = (DataObject)((SDOChangeSummary)cs).getDeepCopies().get(yardDO);
        assertNotNull(yardDeepCopy);
        assertEquals(yardDeepCopy, shipToSetting.getValue());

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        assertEquals(shipToDO, cs.getOldContainer(yardDO));
        //writeXML(rootObject);
    }

    // test deletion inside a list - see detach() isMany section
    // Test Scenarios:
    // - many delete
    public void testDeletePhone2() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");
        DataObject phoneDO = shipToDO.getDataObject("phone[2]");

        cs.beginLogging();
        phoneDO.delete();

        assertDeleted(phoneDO, cs);
        assertModified(shipToDO, cs);

        assertEquals(2, cs.getChangedDataObjects().size());
        assertEquals(1, cs.getOldValues(phoneDO).size());
        assertEquals(1, cs.getOldValues(shipToDO).size());

        ChangeSummary.Setting phoneSetting = (ChangeSummary.Setting)cs.getOldValues(shipToDO).get(0);
        assertEquals("phone", phoneSetting.getProperty().getName());
        assertEquals(true, phoneSetting.isSet());
        assertTrue(phoneSetting.getValue() instanceof List);
        assertEquals(2, ((List)phoneSetting.getValue()).size());
        DataObject phoneDeepCopy = (DataObject)((SDOChangeSummary)cs).getDeepCopies().get(phoneDO);

        assertTrue(((List)phoneSetting.getValue()).contains(phoneDeepCopy));

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        assertEquals(shipToDO, cs.getOldContainer(phoneDO));
        //writeXML(rootObject);
    }

    public void testDetachShipToBySet() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");
        DataObject yardDO = shipToDO.getDataObject("yard");
        List phoneList = shipToDO.getList("phone");
        DataObject phone1 = (DataObject)phoneList.get(0);
        DataObject phone2 = (DataObject)phoneList.get(1);
        Property containmentProp = shipToDO.getContainmentProperty();

        Object oldStreet = shipToDO.get("street");

        cs.beginLogging();
        DataObject newShipAddress = dataFactory.create(shipToDO.getType());
        rootObject.set("shipTo", newShipAddress);

        assertNull(shipToDO.getChangeSummary());
        assertNull(yardDO.getChangeSummary());

        Property shipToProp = rootObject.getInstanceProperty("shipTo");
        ChangeSummary.Setting shipToSetting = cs.getOldValue(rootObject, shipToProp);
        assertTrue(shipToSetting.isSet());
        Object shipToDeepCopy = ((SDOChangeSummary)cs).getDeepCopies().get(shipToDO);
        assertNotNull(shipToDeepCopy);
        assertEquals(shipToDeepCopy, shipToSetting.getValue());

        verifyShipToDetachedOrUnsetBasic(shipToDO, yardDO,//
                                         phoneList, phone1, phone2, containmentProp, oldStreet);

        assertCreated(newShipAddress, cs);
        assertEquals(6, cs.getChangedDataObjects().size());
        assertEquals(1, cs.getOldValues(rootObject).size());

        //writeXML(rootObject);
    }

    public void testDeleteShipTo() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");
        DataObject yardDO = shipToDO.getDataObject("yard");
        List phoneList = shipToDO.getList("phone");
        DataObject phone1 = (DataObject)phoneList.get(0);
        DataObject phone2 = (DataObject)phoneList.get(1);
        Property containmentProp = shipToDO.getContainmentProperty();

        Object oldStreet = shipToDO.get("street");

        cs.beginLogging();
        shipToDO.delete();
        assertNull(shipToDO.getChangeSummary());
        assertNull(yardDO.getChangeSummary());
        verifyShipToDetachedOrUnset(shipToDO, yardDO,//
                                    phoneList, phone1, phone2, containmentProp, oldStreet, true);

        //writeXML(rootObject);
    }

    public void testDetachShipTo() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");
        DataObject yardDO = shipToDO.getDataObject("yard");
        List phoneList = shipToDO.getList("phone");
        DataObject phone1 = (DataObject)phoneList.get(0);
        DataObject phone2 = (DataObject)phoneList.get(1);
        Property containmentProp = shipToDO.getContainmentProperty();

        Object oldStreet = shipToDO.get("street");

        cs.beginLogging();
        shipToDO.detach();
        assertNull(shipToDO.getChangeSummary());
        assertNull(yardDO.getChangeSummary());
        verifyShipToDetachedOrUnset(shipToDO, yardDO,//
                                    phoneList, phone1, phone2, containmentProp, oldStreet);
        //writeXML(rootObject);// null objectValue in org.eclipse.persistence.internal.oxm.XMLAnyCollectionMappingNodeValue.marshal(XMLAnyCollectionMappingNodeValue.java:92)
    }

    public void testUnsetShipTo() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");
        DataObject yardDO = shipToDO.getDataObject("yard");
        List phoneList = shipToDO.getList("phone");
        DataObject phone1 = (DataObject)phoneList.get(0);
        DataObject phone2 = (DataObject)phoneList.get(1);
        Property containmentProp = shipToDO.getContainmentProperty();

        Object oldStreet = shipToDO.get("street");

        cs.beginLogging();
        rootObject.unset(containmentProp);

        verifyShipToDetachedOrUnset(shipToDO, yardDO,//
                                    phoneList, phone1, phone2, containmentProp, oldStreet);
        //writeXML(rootObject);
    }

    private void verifyShipToDetachedOrUnset(//
            DataObject shipToDO,//
            DataObject yardDO,//
            List phoneList,//
            DataObject phone1,//
            DataObject phone2,//
            Property containmentProp,//
            Object oldStreet) {
        verifyShipToDetachedOrUnset(//
                shipToDO,//
                yardDO,//
                phoneList,//
                phone1,//
                phone2,//
                containmentProp,//
                oldStreet, false);
    }

    private void verifyShipToDetachedOrUnset(//
    DataObject shipToDO,//
    DataObject yardDO,//
    List phoneList,//
    DataObject phone1,//
    DataObject phone2,//
    Property containmentProp,//
    Object oldStreet, boolean fromDelete) {
        verifyShipToDetachedOrUnsetBasic(shipToDO, yardDO, phoneList, phone1, phone2, containmentProp, oldStreet, fromDelete);
        assertEquals(5, cs.getChangedDataObjects().size());// 2
        assertEquals(1, cs.getOldValues(rootObject).size());
    }


    private void verifyShipToDetachedOrUnsetBasic(//
            DataObject shipToDO,//
            DataObject yardDO,//
            List phoneList,//
            DataObject phone1,//
            DataObject phone2,//
            Property containmentProp,//
            Object oldStreet) {
        verifyShipToDetachedOrUnsetBasic(//
                shipToDO,//
                yardDO,//
                phoneList,//
                phone1,//
                phone2,//
                containmentProp,//
                oldStreet, false);
    }

    private void verifyShipToDetachedOrUnsetBasic(//
    DataObject shipToDO,//
    DataObject yardDO,//
    List phoneList,//
    DataObject phone1,//
    DataObject phone2,//
    Property containmentProp, Object oldStreet, boolean fromDelete) {
        // verify containers are not unset for children (oldSetting is same object as original - inside List)
        //assertNotNull(((DataObject)shipToDO.getList("phone").get(0)).getContainer());
        //assertNotNull(phone1.getContainer());
        //assertEquals(phone1.getContainer(), shipToDO);
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        if(!fromDelete) {
            assertEquals("123 Maple Street", shipToDO.get("street"));
        } else {
            assertEquals(null, shipToDO.get("street"));
        }
        DataObject oldContainer = ((SDOChangeSummary)cs).getOldContainer(shipToDO);
        Property shipToProp = oldContainer.getInstanceProperty("shipTo");
        ChangeSummary.Setting oldSetting = cs.getOldValue(oldContainer, shipToProp);
        DataObject deepCopyShipTo = (DataObject)oldSetting.getValue();
        assertEquals("123 Maple Street", deepCopyShipTo.get("street"));

        assertModified(rootObject, cs);
        assertNotNull(cs.getOldContainmentProperty(shipToDO));
        assertNotNull(cs.getOldContainer(shipToDO));
        assertEquals(rootObject, cs.getOldContainer(shipToDO));
        assertEquals(containmentProp, cs.getOldContainmentProperty(shipToDO));
        assertDetached(shipToDO, cs);// 8/0
        assertYardDetached(shipToDO, yardDO, cs, false);//
        assertDetached(phone1, cs, false);
        assertDetached(phone2, cs, false);

        ChangeSummary.Setting setting = (ChangeSummary.Setting)cs.getOldValues(rootObject).get(0);
        assertEquals(containmentProp, setting.getProperty());
        Object shipToDeepCopy = ((SDOChangeSummary)cs).getDeepCopies().get(shipToDO);
        assertNotNull(shipToDeepCopy);
        assertEquals(shipToDeepCopy, setting.getValue());
        assertEquals(true, setting.isSet());
        assertEquals(8, cs.getOldValues(shipToDO).size());// 0

        Object newStreet = shipToDO.get("street");

        // verify that children of detached objects are not unset
        if(!fromDelete) {
            assertNotNull(newStreet);
            assertEquals(oldStreet, newStreet);
        } else {
            assertNull(newStreet);
        }

        assertEquals(1, cs.getOldValues(phone1).size());// 0
        assertEquals(1, cs.getOldValues(phone2).size());// 0
        ChangeSummary.Setting phone2setting = (ChangeSummary.Setting)cs.getOldValues(phone2).get(0);
        assertEquals("number", phone2setting.getProperty().getName());
        assertEquals("2345678", phone2setting.getValue());
        assertEquals(true, phone2setting.isSet());
    }

    public void testCSonRootDeleteComplexSingleAtRoot() {//testDeleteShipTo() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");
        DataObject yardDO = shipToDO.getDataObject("yard");
        List phoneList = shipToDO.getList("phone");
        DataObject phone1 = (DataObject)phoneList.get(0);
        DataObject phone2 = (DataObject)phoneList.get(1);
        Property containmentProp = shipToDO.getContainmentProperty();
        cs.beginLogging();
        shipToDO.delete();

        // for dataType verify copy of shipTo has a set child in deleted list and current value is unset
        assertNull(shipToDO.get("street"));
        DataObject oldContainer = ((SDOChangeSummary)cs).getOldContainer(shipToDO);
        Property shipToProp = oldContainer.getInstanceProperty("shipTo");
        ChangeSummary.Setting oldSetting = cs.getOldValue(oldContainer, shipToProp);
        DataObject deepCopyShipTo = (DataObject)oldSetting.getValue();
        assertEquals("123 Maple Street", deepCopyShipTo.get("street"));

        assertEquals(14, ((SDOChangeSummary)cs).getOldContainer().size());
        assertEquals(14, ((SDOChangeSummary)cs).getOldContainmentProperty().size());

        assertModified(rootObject, cs);
        assertNotNull(cs.getOldContainmentProperty(shipToDO));
        assertNotNull(cs.getOldContainer(shipToDO));
        assertEquals(rootObject, cs.getOldContainer(shipToDO));

        assertEquals(shipToDO, cs.getOldContainer(yardDO));
        assertEquals(shipToDO, cs.getOldContainer(phone1));
        assertEquals(shipToDO, cs.getOldContainer(phone2));

        assertEquals(containmentProp, cs.getOldContainmentProperty(shipToDO));
        assertDeleted(shipToDO, cs);
        //assertDeleted(yardDO, cs);
        assertYardDeleted(shipToDO, yardDO, cs, true);
        assertDeleted(phone1, cs);
        assertDeleted(phone2, cs);
        assertEquals(5, cs.getChangedDataObjects().size());
        assertEquals(1, cs.getOldValues(rootObject).size());
        ChangeSummary.Setting setting = (ChangeSummary.Setting)cs.getOldValues(rootObject).get(0);
        assertEquals(containmentProp, setting.getProperty());
        DataObject shipToDeepCopy = (DataObject)((SDOChangeSummary)cs).getDeepCopies().get(shipToDO);

        assertEquals(shipToDeepCopy, setting.getValue());
        assertEquals(true, setting.isSet());
        assertEquals(8, cs.getOldValues(shipToDO).size());

        assertEquals(1, cs.getOldValues(phone1).size());
        assertEquals(1, cs.getOldValues(phone2).size());
        ChangeSummary.Setting phone2setting = (ChangeSummary.Setting)cs.getOldValues(phone2).get(0);
        assertEquals("number", phone2setting.getProperty().getName());
        assertEquals("2345678", phone2setting.getValue());
        assertEquals(true, phone2setting.isSet());
        //writeXML(rootObject);
    }

    // same test as below
    public void testUnsetCommentsAfterSetNull() {
        rootObject.set("comment", null);
        cs.beginLogging();
        rootObject.unset("comment");

        assertUnchanged(rootObject, cs);
        assertEquals(0, cs.getChangedDataObjects().size());

        List oldValues = cs.getOldValues(rootObject);
        assertEquals(0, oldValues.size());
        //writeXML(rootObject);
    }

    public void testUnsetComments() {
        rootObject.set("comment", null);// set all "comment"s to null
        cs.beginLogging();
        rootObject.unset("comment");// unset all 3 comments?
        assertUnchanged(rootObject, cs);
        assertEquals(0, cs.getChangedDataObjects().size());

        List oldValues = cs.getOldValues(rootObject);
        assertEquals(0, oldValues.size());
        //writeXML(rootObject);
    }

    public void testUnsetSimpleIDSetToNullOnRoot() {
        SDOProperty idProperty = (SDOProperty) ((SDOType)rootObject.getType()).getDeclaredPropertiesMap().get("poId");
        idProperty.setNullable(true);

        rootObject.set("poId", null);
        cs.beginLogging();
        rootObject.unset("poId");

        assertModified(rootObject, cs);
        assertEquals(1, cs.getChangedDataObjects().size());

        List oldValues = cs.getOldValues(rootObject);
        assertEquals(1, oldValues.size());

        ChangeSummary.Setting theSetting = (ChangeSummary.Setting)oldValues.get(0);
        assertEquals("poId", theSetting.getProperty().getName());
        assertEquals(true, theSetting.isSet());
        assertEquals(null, theSetting.getValue());
        //writeXML(rootObject);
    }

    public void testUnsetSimpleIDSetToValueOnRoot() {
        rootObject.set("poId", "123");
        // copy our root for later comparison
        DataObject original = copyHelper.copy(rootObject);

        boolean equals = equalityHelper.equal(original, rootObject);
        assertTrue(equals);

        cs.beginLogging();
        rootObject.unset("poId");

        assertModified(rootObject, cs);
        assertEquals(1, cs.getChangedDataObjects().size());

        List oldValues = cs.getOldValues(rootObject);
        assertEquals(1, oldValues.size());

        ChangeSummary.Setting theSetting = (ChangeSummary.Setting)oldValues.get(0);
        assertEquals("poId", theSetting.getProperty().getName());
        assertEquals(true, theSetting.isSet());
        assertEquals("123", theSetting.getValue());
        //writeXML(rootObject);
    }

    public void testUnsetNameAfterLoggingOnAfterUnset() {
        rootObject.unset("poId");
        cs.beginLogging();
        rootObject.unset("poId");
        assertUnchanged(rootObject, cs);//
        assertEquals(0, cs.getChangedDataObjects().size());

        List oldValues = cs.getOldValues(rootObject);
        assertEquals(0, oldValues.size());
        //writeXML(rootObject);
    }

    // test that we do not loose containment in the oldSetting - by unwrapping the ListWrapper into a List
    public void testUnsetFilledSimpleListOnRootRetainsContainmentInOldSetting() {
        List<String> comments = new ArrayList<String>();
        comments.add("comment1");
        comments.add("comment2");
        rootObject.set("comment", comments);
        cs.beginLogging();
        rootObject.unset("comment");

        assertModified(rootObject, cs);
        assertEquals(1, cs.getChangedDataObjects().size());

        List oldValues = cs.getOldValues(rootObject);
        assertEquals(1, oldValues.size());

        ChangeSummary.Setting theSetting = (ChangeSummary.Setting)oldValues.get(0);
        assertEquals("comment", theSetting.getProperty().getName());
        assertEquals(true, theSetting.isSet());
        assertEquals(comments.size(), ((List)theSetting.getValue()).size());
        //writeXML(rootObject);
    }
    public void testModifySimpleCollection() {
        DataObject item = rootObject.createDataObject("items");
        DataObject lineItem = item.createDataObject("item");
        //lineItem.setList("comments", new ArrayList());
        cs.beginLogging();
//        DataObject item = (DataObject)rootObject.getList("items").get(0);

        assertUnchanged(lineItem, cs);

        lineItem.getList("comment").add("a comment");
        lineItem.getList("comment").add("another comment");

        assertModified(lineItem, cs);

        cs.endLogging();
        cs.beginLogging();

        assertUnchanged(lineItem, cs);

        lineItem.getList("comment").remove(1);

        assertModified(lineItem, cs);

        cs.endLogging();
        cs.beginLogging();

        assertUnchanged(lineItem, cs);

        ArrayList newComments = new ArrayList();
        newComments.add("new comment 1");
        newComments.add("new comment 2");
        lineItem.getList("comment").addAll(newComments);

        assertModified(lineItem, cs);

        cs.endLogging();
        cs.beginLogging();

        assertUnchanged(lineItem, cs);

        lineItem.getList("comment").removeAll(newComments);
        assertModified(lineItem, cs);
    }
    public void testSetCommentToSameValue() {
        rootObject.set("poId", "123");
        cs.beginLogging();
        rootObject.set("poId", "123");

        assertUnchanged(rootObject, cs);
        assertEquals(0, cs.getChangedDataObjects().size());

        List oldValues = cs.getOldValues(rootObject);
        assertEquals(0, oldValues.size());
        //writeXML(rootObject);
    }

    private void assertYardDeleted(DataObject shipToDO, DataObject yardDO, ChangeSummary cs, boolean nullContainer) {
        assertDeleted(yardDO, cs, nullContainer);
        assertEquals(3, cs.getOldValues(yardDO).size());
        Property sfProp = yardDO.getInstanceProperty("squarefootage");
        Property widthProp = yardDO.getInstanceProperty("width");
        Property lengthProp = yardDO.getInstanceProperty("length");
        ChangeSummary.Setting yardSFsetting = cs.getOldValue(yardDO, sfProp);
        assertEquals(yardSFsetting.getValue(), null);

        //TODO: uncomment this line.  Will fail unless Node Null policy stuff is fixed
        //assertEquals(false, yardSFsetting.isSet());
        ChangeSummary.Setting yardWidthsetting = cs.getOldValue(yardDO, widthProp);
        assertEquals("65", yardWidthsetting.getValue());
        assertEquals(true, yardWidthsetting.isSet());

        ChangeSummary.Setting yardLengththsetting =  cs.getOldValue(yardDO, lengthProp);
        assertEquals("45", yardLengththsetting.getValue());
        assertEquals(true, yardLengththsetting.isSet());

        // shipToDO was not deleted, only check yardDO
        assertChildrenUnset(yardDO);
    }

    private void assertYardDetached(DataObject shipToDO, DataObject yardDO, ChangeSummary cs, boolean nullContainer) {
        assertDetached(yardDO, cs, nullContainer);
        assertEquals(3, cs.getOldValues(yardDO).size());
        Property sfProp = yardDO.getInstanceProperty("squarefootage");
        Property widthProp = yardDO.getInstanceProperty("width");
        Property lengthProp = yardDO.getInstanceProperty("length");
        ChangeSummary.Setting yardSFsetting =  cs.getOldValue(yardDO, sfProp);
        assertEquals(yardSFsetting.getValue(), null);

        //TODO: uncomment this line.  Will fail unless Node Null policy stuff is fixed
        //assertEquals(false, yardSFsetting.isSet());
        ChangeSummary.Setting yardWidthsetting = cs.getOldValue(yardDO, widthProp);
        assertEquals("65", yardWidthsetting.getValue());
        assertEquals(true, yardWidthsetting.isSet());

        ChangeSummary.Setting yardLengththsetting = cs.getOldValue(yardDO, lengthProp);
        assertEquals("45", yardLengththsetting.getValue());
        assertEquals(true, yardLengththsetting.isSet());
    }
}
