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

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.SDOSequence;
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 org.eclipse.persistence.testing.sdo.model.changesummary.ChangeSummaryOnRootTestCases;
import commonj.sdo.ChangeSummary;
import commonj.sdo.DataObject;
import commonj.sdo.Property;
import commonj.sdo.Sequence;
import commonj.sdo.Type;
import commonj.sdo.helper.XMLDocument;

/**
 *    02/14/07 - cs.undoChanges is the same as a detach/reset
 *                        testDetachAndResetYardToSamePlace() mod assertEquals(0, shipToSettings.size()); from 1
 *    05/01/07 - copy from ChangeSummaryXSDTestCases - extend with child sequence on Address
 *
 */
public class ChangeSummaryXSDwSeqTestCases 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 ChangeSummaryXSDwSeqTestCases(String name) {
        super(name);
    }

    public static void main(String[] args) {
        String[] arguments = { "-c", "org.eclipse.persistence.testing.sdo.model.changesummary.sequence.ChangeSummaryXSDwSeqTestCases" };
        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/schemas/PurchaseOrderDeepWithCSandSequences.xsd");
            xsdHelper.define(is, null);
            XMLDocument document = xmlHelper.load(new FileInputStream("org/eclipse/persistence/testing/sdo/model/sequence/PurchaseOrderDeepWithCSandSequences.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;
    }

    public int getNthSequenceIndexFor(SDOSequence aSequence, String propertyName) {
        return getNthSequenceIndexFor(aSequence, propertyName, 1);
    }

    public int getNthSequenceIndexFor(SDOSequence aSequence, String propertyName, int matchNumber) {
        // search for the indexed position in the sequence that corresponds to propertyName
        int matchIndex = -1;
        int numberMatches = matchNumber;
        Property aProperty = null;
        // TODO: linear performance hit
        for(int i = 0, size = aSequence.size(); i < size; i++) {
            aProperty = aSequence.getProperty(i);
            // TODO: handle null property for unstructured text
            if(aProperty != null && aProperty.getName().equals(propertyName)) {
                // breakout of loop with this property
                matchIndex = i;
                if(--numberMatches < 1) {
                    i = aSequence.size();
                }
            }
        }
        return matchIndex;
    }

    // see #6026714: for fix for null complex type retains last sequence value during copy of a copy
    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);

        // see #6026714: for fix for null complex type retains last sequence value during copy of a copy

        // 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)
        boolean copyEqualToOriginal = equalityHelper.equal(rootObject, copy);
        assertTrue(copyEqualToOriginal);
        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();
    }

    // verify order of sequence matches what is in the XML (not the XSD) document - to verify unmarshal
    // Note: order should be the same except for special cases such as nulls or non-containment references
    // see xmlhelper tests for full suite tests
    public void testUnmarshalSequenceOrderCorrect() {
        // this test should fail until unmarshall is fully implemented
        DataObject shipToDO = rootObject.getDataObject("shipTo");

        //Property containmentProp = shipToDO.getInstanceProperty("yard");
        DataObject yardDO = shipToDO.getDataObject("yard");
        Object length = yardDO.get("length");
        cs.beginLogging();

        Sequence aSequence = shipToDO.getSequence();

        //<ns0:purchaseOrder orderDate="1999-10-20" xmlns:sdo="commonj.sdo" xmlns:ns0="http://www.example.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        //<ns0:myChangeSummary logging="true">
       //<ns0:shipTo country="US">
//              <ns0:name>Alice Smith</ns0:name>
//                <ns0:street>123 Maple Street</ns0:street>
//                <ns0:city>Mill Valley</ns0:city>
//                 <ns0:state>CA</ns0:state>
//                <ns0:zip>90952</ns0:zip>
//                <ns0:yard>
//                <ns0:phone>
//                  <ns0:phone>
       //<ns0:billTo country="US">
       //<ns0:comment>Hurry, my lawn is going wild!</ns0:comment>
       //<ns0:items>
       //   <ns0:item partNum="872-AA">
       //     <ns0:product>
        //        <ns0:price>
        //        <ns0:price>
        //     <ns0:comment>Confirm this is electric2</ns0:comment>
        //  <ns0:item partNum="926-AA">
        //     <ns0:product>
        //        <ns0:price>
        //        <ns0:price>

        assertEquals(8, aSequence.size());
        assertEquals(aSequence.getValue(0), shipToDO.get("name"));
        assertEquals(aSequence.getValue(1), shipToDO.get("street"));
        assertEquals(aSequence.getValue(2), shipToDO.get("city"));
        assertEquals(aSequence.getValue(3), shipToDO.get("state"));
        assertEquals(aSequence.getValue(4), shipToDO.get("zip"));
        assertEquals(aSequence.getValue(5), shipToDO.get("yard"));
        assertEquals(aSequence.getValue(6), shipToDO.get("phone[1]"));
        assertEquals(aSequence.getValue(7), shipToDO.get("phone[2]"));
    }

     //* Purpose: See JIRA-242
     //* http://bug.us.oracle.com/pls/bug/webbug_edit.edit_info_top?rptno=6031657
     //* http://www.xcalia.com/support/browse/SDO-242
     //* We need to clarify move behavior
     //* If we do a set(property) on an existing non-many (simple or complex)
     //* property what is the expected behavior?
     //* 1) We modify the existing sequence (by setValue or creating a new setting in the existing index)
     //* 2) We continue to add the new setting at the end of the sequence and remove
     //* the previously existing sequence (shifting subsequence settings down)
     //* 20070505: we are doing (1) when called from DataObject and (2) when called from Sequence (but without the remove)
    public void testModifySimpleSingleViaDataObjectSet() {

    }
    public void testModifySimpleSingleViaDataObjectSetNull() {

    }
    public void testModifySimpleSingleViaSequenceSetValue() {

    }
    public void testModifySimpleSingleViaSequenceSetValueNull() {

    }
    public void testDontModifySimpleSingleViaSequenceAdd() {

    }
    public void testDontModifySimpleSingleViaSequenceAddNull() {

    }

    public void testModifyComplexSingleViaDataObjectSet() {

    }
    public void testModifyComplexSingleViaDataObjectSetNull() {

    }
    public void testModifyComplexSingleViaSequenceSetValue() {

    }
    public void testModifyComplexSingleViaSequenceSetValueNull() {

    }
    public void testDontModifyComplexSingleViaSequenceAdd() {

    }
    public void testDontModifyComplexSingleViaSequenceAddNull() {

    }

    // modify sequence without modifying container and undo
    public void testAddUnstructuredTextAffectsChangeSummaryUndo() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");

        //Property containmentProp = shipToDO.getInstanceProperty("yard");
        DataObject yardDO = shipToDO.getDataObject("yard");
        //Object length = yardDO.get("length");
        cs.beginLogging();

        Sequence aSequence = shipToDO.getSequence();

        // modify sequence without modifying container dataObject
        //int yardIndex = getNthSequenceIndexFor((SDOSequence)aSequence, "yard");
        //aSequence.remove(yardIndex);
        //yardDO.detach();

        aSequence.addText("Unstructured1");

        List yardDOSettings = cs.getOldValues(yardDO);

        // no change to container when unstructured text is added
        // TODO: is this the case? adding unstructured text
        // should cause the data object to be considered 'modified'

        assertEquals(0, yardDOSettings.size());

        assertTrue(cs.isModified(shipToDO));

        //assertDetached(yardDO, cs);
        //assertModified(shipToDO, cs);
        assertFalse(cs.isModified(yardDO));

        // TODO: since "addText()" now sets modified on the dataObject, we will
        // have a changed dataObject.  Verify this...
        //assertEquals(0, cs.getChangedDataObjects().size());
        assertEquals(1, cs.getChangedDataObjects().size());

        //return yardDOSettings;

        // check oldSequence before undo
        Sequence shipToSeqBefore = cs.getOldSequence(shipToDO);
        assertNotNull(shipToSeqBefore);

        cs.undoChanges();

        // check oldSequence after undo
        Sequence shipToSeqAfter = cs.getOldSequence(shipToDO);
        assertNotNull(shipToSeqAfter);
        // verify that object references in settings are the same ones on the valueStore


        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);
    }

    public void testDetachYardDOViaSequenceRemoveAndUndo() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");

        //Property containmentProp = shipToDO.getInstanceProperty("yard");
        DataObject yardDO = shipToDO.getDataObject("yard");
        Object length = yardDO.get("length");
        cs.beginLogging();

        Sequence aSequence = shipToDO.getSequence();

        // remove/detach yardDO by index in its sequence instead of via property on shipToDO
        //aSequence.addText("Unstructured1");
        int yardIndex = getNthSequenceIndexFor((SDOSequence)aSequence, "yard");
        aSequence.remove(yardIndex);
        //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;

        // check oldSequence before undo
        Sequence shipToSeqBefore = cs.getOldSequence(shipToDO);
        assertNotNull(shipToSeqBefore);

        cs.undoChanges();

        // check oldSequence after undo
        Sequence shipToSeqAfter = cs.getOldSequence(shipToDO);
        assertNotNull(shipToSeqAfter);
        // verify that object references in settings are the same ones on the valueStore


        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);
    }

    public void testDetachYardDOViaContainerAndUndo() {
        DataObject shipToDO = rootObject.getDataObject("shipTo");

        //Property containmentProp = shipToDO.getInstanceProperty("yard");
        DataObject yardDO = shipToDO.getDataObject("yard");
        Object length = yardDO.get("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;

        // check oldSequence before undo
        Sequence shipToSeqBefore = cs.getOldSequence(shipToDO);
        assertNotNull(shipToSeqBefore);

        cs.undoChanges();

        // check oldSequence after undo
        Sequence shipToSeqAfter = cs.getOldSequence(shipToDO);
        assertNotNull(shipToSeqAfter);
        // different sequences in originalSequences
        assertFalse(shipToSeqBefore == shipToSeqAfter);
        // different settings in originalSequences
        assertFalse(((SDOSequence)shipToSeqBefore).getSettings().get(0) == ((SDOSequence)shipToSeqAfter).getSettings().get(0));
        // verify that object references in settings are the same ones on the valueStore


        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);
    }


    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 but the modifedList entry will remain
        assertFalse(cs.isDeleted(yardDO));

        yardDOSettings = cs.getOldValues(yardDO);
        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);
        }



















        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 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());
    }
}
