/*******************************************************************************
 * Copyright (c) 1998, 2008 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the 
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
 ******************************************************************************/  
package org.eclipse.persistence.testing.sdo.model.sequence;

import commonj.sdo.ChangeSummary;
import commonj.sdo.DataObject;
import commonj.sdo.Property;
import commonj.sdo.Sequence;
import commonj.sdo.Type;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Iterator;
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.helper.DefaultSchemaLocationResolver;
import org.eclipse.persistence.sdo.helper.ListWrapper;
import org.eclipse.persistence.sdo.helper.SDOXSDHelper;
import org.eclipse.persistence.exceptions.SDOException;
import org.eclipse.persistence.oxm.XMLConstants;

public class SDOSequenceTestCS extends SDOSequenceTestCases {

    public static final String URINAME = "http://www.example.org";
    public static final String COMPANY_TYPENAME = "Company";
    public static final String PO_TYPENAME = "PurchaseOrder";
    public static final String PO_SEQUENCE_PATH = "porder[1]";
    public static final int PO_SEQUENCE_SIZE = 7;
    public static final int PO_SEQUENCE_TREE_SIZE = 7;
    public static final int PO_COMMENT_LIST_SIZE = 2;
    public static final int PO_TREE_SIZE = 5;
    public static final String PO_PATH = "porder";
    public static final String CUSTOMER_PATH = "cust";
    public static final String ITEM_PATH = "item";
    public static final String CUSTOMER_TYPENAME = "Customer";
    public static final String ADDRESS_TYPENAME = "USAddress";
    public static final String ITEM_TYPENAME = "Item";
    public static final String PO_COMMENT_VALUE1 = "comment 1";
    
    public static final String XML_PATH = "org/eclipse/persistence/testing/sdo/model/sequence/CompanyWithSequenceCS.xml";
    public static final String XSD_PATH = "org/eclipse/persistence/testing/sdo/schemas/CompanyWithSequenceCS.xsd";    
	
	public static final int NO_MATCH_INDEX = -1;
    
    protected DataObject root;
    protected ChangeSummary cs;
    protected Type stringType;
    protected Type dateType;
    protected Type yearMonthDayType;
    protected Type decimalType;
    protected Type idType;
    
    
    public SDOSequenceTestCS(String name) {
        super(name);
    }

    public void setUp() {
        super.setUp();
        stringType = typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.STRING);
        dateType = typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.DATE);
        yearMonthDayType = typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.YEARMONTHDAY);
        decimalType = SDOConstants.SDO_DECIMAL;
        idType = typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.ID);     
    }
    
    public static void main(String[] args) {
        String[] arguments = { "-c", "org.eclipse.persistence.testing.sdo.model.sequence.SDOSequenceTestCS" };
        TestRunner.main(arguments);
    }
    
    protected String getControlRootURI() {
        return URINAME;
    }
    
    protected String getControlRootName() {
        return "company";
    }
    
    public String getSchemaToDefine() {
        return XSD_PATH;
    }

    public String getControlGeneratedFileName() {
        return XSD_PATH;
    }

    protected List<Type> getTypesToGenerateFrom() {
        return getControlTypes();
    }

	public static String getXSDString(String filename) {
		try {
			FileInputStream inStream = new FileInputStream(filename);
			byte[] bytes = new byte[inStream.available()];
			inStream.read(bytes);
			return new String(bytes);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
    
    /**
     * This function will define control types programmatically to compare to XSD definition
     * by using the standard spec SDODataObject generation method on page
     * 
     * The existing getControlTypes() uses non-public Property constructors
     * @throws Exception
     */
    public DataObject createRootObject(boolean viaXML, List types) {
    	DataObject aRoot = null;
    	if(viaXML) {
    		aRoot = loadXML(XML_PATH, false);
    	} else {
    		DataObject cust1 = dataFactory.create(typeHelper.getType(URINAME, CUSTOMER_TYPENAME));
    		cust1.set("custID", 5);
    		List emails = new ArrayList();
    		emails.add("email1-DF@myCompany.com");
    		emails.add("email2-DF@myCompany.com");
    		cust1.set("email", emails);
    		List phones = new ArrayList();
    		phones.add("6135550001");
    		cust1.set("phone", phones);
    		
    		DataObject item1 = dataFactory.create(typeHelper.getType(URINAME, ITEM_TYPENAME));
    		item1.set("itemID", 3);
    		item1.set("name", "item1-DF");    		
    		DataObject item2 = dataFactory.create(typeHelper.getType(URINAME, ITEM_TYPENAME));
    		item2.set("itemID", 6);
    		item2.set("name", "item2-DF");    		
    		DataObject item3 = dataFactory.create(typeHelper.getType(URINAME, ITEM_TYPENAME));
    		item3.set("itemID", 7);
    		item3.set("name", "item3-DF");    		
    		
    		DataObject billTo = dataFactory.create(typeHelper.getType(URINAME, ADDRESS_TYPENAME));
    		billTo.set("name", "bill");
    		DataObject shipTo = dataFactory.create(typeHelper.getType(URINAME, ADDRESS_TYPENAME));
    		shipTo.set("name", "ship");

    		DataObject po1 = dataFactory.create(typeHelper.getType(URINAME, PO_TYPENAME));
    		po1.set("poID", 10);
    		po1.set("shipTo", shipTo);
    		po1.set("billTo", billTo);

    		// set comments list
    		List<String> comments = new ArrayList<String>();
    		comments.add(PO_COMMENT_VALUE1);
    		comments.add("comment 2");
            po1.set("comment", comments);
    		
    		po1.set("orderDate", "1999-10-20");
    		
    		// references to company/item
    		List<DataObject> itemsRef = new ArrayList<DataObject>();
    		itemsRef.add(item2);//6);
    		itemsRef.add(item3);//7);
    		po1.set("item", itemsRef); // unwrapping exception
    		
            aRoot = dataFactory.create(typeHelper.getType(URINAME, COMPANY_TYPENAME));
            aRoot.set(CUSTOMER_PATH, cust1);
            //aRoot.set(propertyIndex, value)
            // add purchaseOrders
    		List<DataObject> pos = new ArrayList<DataObject>();
    		pos.add(po1);
            aRoot.set(PO_PATH, pos);

            // add items (containment)
    		List<DataObject> items = new ArrayList<DataObject>();
    		items.add(item1);
    		items.add(item2);
    		items.add(item3);
    		aRoot.set(ITEM_PATH, items);
    		
            aRoot.set("name", "mycomp-DF");
            
            SDOChangeSummary aChangeSummary = new SDOChangeSummary();
            // add changeSummary
            aRoot.set("myChangeSummary", aChangeSummary);
    	}
    	return aRoot;
    }

    
    private Type defineAndPostProcessUnidirectional(String containingPropertyLocalName, DataObject typeToDefine, //
    		String idPropertyName, String containingPropertyName) {
    	// define the current type
        Type aType = typeHelper.define(typeToDefine);
        // get the 
        Property containingProperty = aType.getProperty(containingPropertyName);
        ((SDOProperty)containingProperty).setXsd(true);
        ((SDOProperty)containingProperty).setXsdLocalName(containingProperty.getContainingType().getName());//containingPropertyLocalName);
//        ((SDOType)aType).setIDProp(aType.getProperty(idPropertyName));
        // set unidirection reference id
        setIDPropForReferenceProperties(typeToDefine, containingPropertyLocalName);

        return aType;
    }

    private Type defineAndPostProcessBidirectional(DataObject typeToDefine, String idPropertyName) {
        Type aType = typeHelper.define(typeToDefine);
        //SDOProperty itemProperty = (SDOProperty)aType.getProperty("item");
        //itemProperty.setXsd(true);
        //((SDOType)aType).setIDProp(aType.getProperty(idPropertyName));
        return aType;
    }
    
    private Type registerAddressType(boolean sequencedFlag) {
        DataObject addressType = dataFactory.create(SDOConstants.SDO_URL, SDOConstants.TYPE);
        SDOProperty prop = (SDOProperty)addressType.getType().getProperty("uri");
        addressType.set(prop, getControlRootURI());
        prop = (SDOProperty)addressType.getType().getProperty(SDOConstants.SDOXML_NAME);
        addressType.set(prop,  ADDRESS_TYPENAME);
        
        addProperty(addressType, "name", stringType);
        addProperty(addressType, "street", stringType);
        addProperty(addressType, "city", stringType);
        addProperty(addressType, "state", stringType);
        addProperty(addressType, "zip", decimalType);

        DataObject newProperty = addProperty(addressType, "country", stringType);
        prop = (SDOProperty)newProperty.getType().getProperty("default");
        newProperty.set(prop, "US");
        return typeHelper.define(addressType);
    }

    private Type registerItemType(boolean sequencedFlag) {
        DataObject itemType = dataFactory.create(SDOConstants.SDO_URL, SDOConstants.TYPE);
        SDOProperty prop = (SDOProperty)itemType.getType().getProperty("uri");
        itemType.set(prop, getControlRootURI());
        prop = (SDOProperty)itemType.getType().getProperty(SDOConstants.SDOXML_NAME);
        String typeName = ITEM_TYPENAME;
        String idPropName = "itemID";
        // set unidirection reference id
        setIDPropForReferenceProperties(itemType, "itemID");

        itemType.set(prop, typeName);

        DataObject newProperty = itemType.createDataObject("property");
        SDOProperty aProp = (SDOProperty)newProperty.getType().getProperty(SDOConstants.SDOXML_NAME);
        newProperty.set(aProp, idPropName);
        aProp = (SDOProperty)newProperty.getType().getProperty("type");
        Type idType = typeHelper.getType(XMLConstants.SCHEMA_URL, "ID");
        newProperty.set(aProp, stringType);     // no ID type to set - use string type
        aProp.setXsd(true);

        addProperty(itemType, "name", stringType);

        Type aType = typeHelper.define(itemType);
        //itemProperty.setXsd(true);
//        ((SDOType)aType).setIDProp(aType.getProperty(idPropName));
        return aType;
    }

    // sequenced
    private Type registerPurchaseOrderType(boolean sequencedFlag, Type addressType, Type itemType, Type customerType) {
    	 // instance properties available
    	 // aliasName, name, many, containment, default, readOnly, type, opposite, nullable
        DataObject purchaseOrderTypeDO = dataFactory.create(SDOConstants.SDO_URL, SDOConstants.TYPE);
        SDOProperty prop = (SDOProperty)purchaseOrderTypeDO.getType().getProperty("uri");
        purchaseOrderTypeDO.set(prop, getControlRootURI());
        purchaseOrderTypeDO.set("sequenced", sequencedFlag); 
        prop = (SDOProperty)purchaseOrderTypeDO.getType().getProperty(SDOConstants.SDOXML_NAME);
        String typeName = PO_TYPENAME;
        String idPropName = "poID";
        purchaseOrderTypeDO.set(prop, typeName);
        // set unidirection reference id
        setIDPropForReferenceProperties(purchaseOrderTypeDO, "poID");

        // add properties in sequence
        DataObject shipToProp = addProperty(purchaseOrderTypeDO, "shipTo", addressType, true);
        DataObject billToProp = addProperty(purchaseOrderTypeDO, "billTo", addressType, true);
        DataObject commentProp = addProperty(purchaseOrderTypeDO, "comment", stringType, false, true);

        // unidirectional IDREFS
        DataObject itemProp = addProperty(purchaseOrderTypeDO, "item", itemType, false, true);

        DataObject poidProperty = addProperty(purchaseOrderTypeDO, idPropName, stringType, false);
        // !many, !containment and !nullable - we must set one of these so poID can be an element and exist in the sequence
        poidProperty.set("nullable", true); // this statement goes along with the false containment flag above
        addProperty(purchaseOrderTypeDO, "orderDate", yearMonthDayType);

        String containingPropertyName = ITEM_PATH;
        Type aType = defineAndPostProcessUnidirectional(typeName, purchaseOrderTypeDO, idPropName, containingPropertyName);        
        return aType;
    }

    // not sequenced
    private Type registerCompanyType(boolean sequencedFlag, Type purchaseOrderType, Type customerType, Type itemType, Type csType) {
        SDOType changeSummaryType = (SDOType) typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.CHANGESUMMARY);

        DataObject companyType = dataFactory.create(SDOConstants.SDO_URL, SDOConstants.TYPE);
        SDOProperty prop = (SDOProperty)companyType.getType().getProperty("uri");
        companyType.set(prop, getControlRootURI());
        companyType.set("sequenced", true);//false);//sequencedFlag); // sequenced is false by default
        //companyType.set("sequenced", true);         
        prop = (SDOProperty)companyType.getType().getProperty(SDOConstants.SDOXML_NAME);
        companyType.set(prop,  COMPANY_TYPENAME);

        DataObject name = addProperty(companyType, "name", stringType);
        //name.setInstanceProperty(SDOConstants.XMLELEMENT_PROPERTY, Boolean.TRUE);
        SDOProperty nameProp = (SDOProperty)companyType.getType().getProperty(SDOConstants.XMLELEMENT_PROPERTY_NAME);
        //name.set(SDOConstants.XMLELEMENT_PROPERTY_NAME, false);
        //nameProp.setInstanceProperty(SDOConstants.XMLELEMENT_PROPERTY, Boolean.FALSE);        
        DataObject custProp =  addProperty(companyType, CUSTOMER_PATH, customerType, true, false);
        DataObject poProp = addProperty(companyType, PO_PATH, purchaseOrderType, true, true);
        DataObject itemProp = addProperty(companyType, ITEM_PATH, itemType, true, true);

        // changeSummary property
        DataObject changeSumPropertyDO = addProperty(companyType, "myChangeSummary", changeSummaryType);
        changeSumPropertyDO.set("containment", false);
        
        Type aType = typeHelper.define(companyType);
        return aType;
    }

    protected DataObject addProperty(DataObject parentType, String name, Type propType) {
        DataObject newProperty = parentType.createDataObject("property");
        SDOProperty prop = (SDOProperty)newProperty.getType().getProperty("name");
        newProperty.set(prop, name);
        prop = (SDOProperty)newProperty.getType().getProperty("type");
        newProperty.set(prop, propType);
        return newProperty;        
    }    
    
    private Type registerChangeSummary() {
        DataObject csTypeDO = dataFactory.create(SDOConstants.SDO_URL, SDOConstants.TYPE);
        SDOProperty csProp = (SDOProperty)csTypeDO.getType().getProperty("uri");
        //SDOProperty csProperty = new SDOProperty(aHelperContext);
        //csProperty.setName(name);
        csTypeDO.set(csProp, getControlRootURI());
        //csTypeDO.set("name", "myChangeSummary");
        SDOProperty prop = (SDOProperty)csTypeDO.getType().getProperty(SDOConstants.SDOXML_NAME);
        csTypeDO.set(prop, "myChangeSummary");
        //csTypeDO.set("containment", false);
        SDOProperty typeProp = (SDOProperty)csTypeDO.getType().getProperty("type");//SDOConstants.SDOXML_PROPERTYTYPE);
        Type aType = typeHelper.define(csTypeDO);
        return aType;
    }
    
    private Type registerCustomerType(boolean sequencedFlag, Type purchaseOrderType) {
        DataObject customerType = dataFactory.create(SDOConstants.SDO_URL, SDOConstants.TYPE);
        SDOProperty prop = (SDOProperty)customerType.getType().getProperty("uri");
        customerType.set("sequenced", true);//sequencedFlag); // sequenced is true by default
        customerType.set(prop, getControlRootURI());
        prop = (SDOProperty)customerType.getType().getProperty(SDOConstants.SDOXML_NAME);
        String typeName = CUSTOMER_TYPENAME;
        String idPropName = "custID";
        String emailPropName = "email";
        String phonePropName = "phone";
        customerType.set(prop, typeName);
        setIDPropForReferenceProperties(customerType, "custID");

        DataObject custEmailProperty = addProperty(customerType, emailPropName, stringType);
        DataObject custPhoneProperty = addProperty(customerType, phonePropName, stringType);
        
        DataObject custidProperty = addProperty(customerType, idPropName, stringType);
//        DataObject poProp = addProperty(customerType, "purchaseOrder", purchaseOrderType, false, false);
        // post define processing
        String containingPropertyName = "purchaseOrder";
        //Type aType = defineAndPostProcessUnidirectional(typeName, customerType, idPropName, containingPropertyName);
        Type aType = typeHelper.define(customerType);        
        return aType;
    }
    

     // See section 3.8.4 p.41
     // We would like to create at least one test framework that uses the standard createDataObject spec
     // instead of creating Property objects - which uses a non-public public api
    public void registerTypes(boolean sequencedFlag) {
    	// pass the sequenced flag to the typeHelper.define() calls so we can create without a sequence
        Type addressType = registerAddressType(sequencedFlag);
        Type itemType = registerItemType(sequencedFlag);
        Type customerType = null;
        Type poType = registerPurchaseOrderType(sequencedFlag, addressType, itemType, customerType);
        customerType = registerCustomerType(sequencedFlag, poType);
        Type csType = registerChangeSummary();
        Type companyType = registerCompanyType(sequencedFlag, poType, customerType, itemType, csType);        
    }    

    public void registerTypes() {
    	registerTypes(true);
    }
    public List<Type> getControlTypes() {
        List<Type> types = new ArrayList<Type>();
        if(typeHelper.getType(URINAME, COMPANY_TYPENAME) != null) {
        	types.add(typeHelper.getType(URINAME, COMPANY_TYPENAME));
        }
        if(typeHelper.getType(URINAME, PO_TYPENAME) != null) {
        	types.add(typeHelper.getType(URINAME, PO_TYPENAME));
        }
        if(typeHelper.getType(URINAME, CUSTOMER_TYPENAME) != null) {
        	types.add(typeHelper.getType(URINAME, CUSTOMER_TYPENAME));
        }
        if(typeHelper.getType(URINAME, ADDRESS_TYPENAME) != null) {
        	types.add(typeHelper.getType(URINAME, ADDRESS_TYPENAME));
        }
        if(typeHelper.getType(URINAME, ITEM_TYPENAME) != null) {
        	types.add(typeHelper.getType(URINAME, ITEM_TYPENAME));
        }
    	return types;
    }

    public void setTypeSequenced(String typeName, boolean sequenced) {
    	SDOType aType = (SDOType)typeHelper.getType(URINAME, typeName);
    	aType.setSequenced(sequenced);
    }
    
    // use XSD to define and XML to load - sequenced Flag has affect only when defining via typeHelper
    public void defineAndLoadRoot(boolean defineViaXSD, boolean loadViaXML, boolean sequencedFlag) {
        	DefaultSchemaLocationResolver resolver = new DefaultSchemaLocationResolver(getMap());
        	List<Type> types = null;
        	if(defineViaXSD) {
        		types = xsdHelper.define(getXSDString(XSD_PATH));
        	} else {
        		registerTypes(sequencedFlag);
        		types = getControlTypes();
        	}
           
            String generatedSchema = ((SDOXSDHelper)xsdHelper).generate(types, resolver);
            //log(generatedSchema);
            root = createRootObject(loadViaXML, types);
        	int aRootsize = preOrderTraversalDataObjectList((SDODataObject)root).size();
//        	if(!loadViaXML)  {
//        		assertTrue(writeXML(root, URINAME, COMPANY_TYPENAME, System.out));
//        	}
        	assertEquals(10, aRootsize);
        }

    public void defineAndLoadRoot(boolean defineViaXSD, boolean loadViaXML) {
    	defineAndLoadRoot(defineViaXSD, loadViaXML, true);
    }
    public void defineAndLoadRoot() {
    	defineAndLoadRoot(true, true);
    }
    
    
    private SDOSequence getSequence(DataObject aRoot, String sequencePath, int sequenceSize) {
    	// get sequence DO
    	DataObject dataObject = (DataObject)aRoot.get(sequencePath);
    	assertNotNull(dataObject);
        assertTrue(dataObject.getType().isSequenced());
        // get sequence
        SDOSequence aSequence = (SDOSequence)dataObject.getSequence();
        // check sequence
        assertNotNull(aSequence);
        //assertEquals(sequenceSize, aSequence.size());
        return aSequence;    	
    }
    
    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;
    }

    /**
     * Invoke a get() call to finish the lazy initialization of this map
     * @param aCS
     */
    public Map verifyOldSequences(SDOChangeSummary aCS) {
    	return aCS.getOldSequences();    
    }

    /**
     * Invoke a get() call to finish the lazy initialization of this map
     * @param aCS
     */
    public Map verifyOriginalSequences(SDOChangeSummary aCS) {
    	return aCS.getOriginalSequences();    
    }
    
    /**
     * ChangeSummary tests
     */

    
    public void turnCSon(SDOChangeSummary aCS) {
        assertNotNull(aCS);
        aCS.endLogging();
        aCS.beginLogging();
    }
    
    public void testAddTextUndoChanges() {
    	// make a source object
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        int sequenceSize = aSequence.size();
        DataObject poDO = (DataObject)root.get(PO_SEQUENCE_PATH);
        assertNotNull(poDO);
        DataObject shipToDO = (DataObject)poDO.get("shipTo");
        assertNotNull(shipToDO);
        List items = (List)poDO.get("item");
        assertNotNull(poDO);
        int listSize = items.size();
        assertEquals(2, listSize);

        // turn on change summary
        SDOChangeSummary aCS = (SDOChangeSummary)root.getChangeSummary();
        turnCSon(aCS);
        
        // change a sequence that is not tracked by the cs
        aSequence.addText("random text2");        
        
        // verify change
       int newSequenceSize = aSequence.size();
       assertEquals(sequenceSize + 1, newSequenceSize);
       
        // verify changeSummary not changed
       Map oldSequences = aCS.getOldSequences();
       Map originalSequences = aCS.getOriginalSequences();
       assertEquals(0, oldSequences.size());
       assertEquals(1, originalSequences.size());
        
        // undo change (nop for untracked items)
       aCS.undoChanges();
        
        // verify unchange (nop for untracked items)
       assertEquals(sequenceSize + 1, newSequenceSize);
        
        // verify unChangeSummary (still no changes)
       assertEquals(0, oldSequences.size());
       assertEquals(0, originalSequences.size());        
    }
    
    /**
     * Purpose:
     * Test that the sequence on a move is updated on both the source and target objects
     */
    public void testMoveToCopyAlsoRemovesSequenceSettingOnOriginal() {
    	// make a source object
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        DataObject poDO = (DataObject)root.get(PO_SEQUENCE_PATH);
        assertNotNull(poDO);
        DataObject shipToDO = (DataObject)poDO.get("shipTo");
        assertNotNull(shipToDO);

        // make a copy so that we can move between trees
    	DataObject rootCopy = copyHelper.copy(root);    	
    	// check sequence was copied
        SDOSequence aPOSequenceCopy = getSequence(rootCopy, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        assertNotNull(aPOSequenceCopy);
        int sequenceCopySizeBeforeDelete = aPOSequenceCopy.size();
        
        // delete shipTo on target
        DataObject poDOCopy = (DataObject)rootCopy.get(PO_SEQUENCE_PATH);
        assertNotNull(poDO);
        SDODataObject shipToCopy = (SDODataObject)poDOCopy.get("shipTo");
        assertNotNull(shipToCopy);
        shipToCopy.delete();
        
        // verify that the sequence on the copy has been adjusted
        int sequenceCopySizeAfterDelete = aPOSequenceCopy.size();
        assertEquals(sequenceCopySizeBeforeDelete - 1, sequenceCopySizeAfterDelete);
        // verify that the object was deleted on the copy in prep for a move from the root to this copy
        assertNull(rootCopy.get(PO_SEQUENCE_PATH + "/shipTo"));
        
    	// get shipTo sequence
    	int shipToSequenceIndex = getNthSequenceIndexFor(aSequence, "shipTo");
    	assertTrue(shipToSequenceIndex > -1);
    	DataObject shipToObjectFromSetting = (DataObject)aSequence.getValue(shipToSequenceIndex);
    	assertNotNull(shipToObjectFromSetting);
    	assertTrue(shipToObjectFromSetting == shipToDO);

        // turn on change summary
        SDOChangeSummary aCSroot = (SDOChangeSummary)root.getChangeSummary();
        turnCSon(aCSroot);
        SDOChangeSummary aCScopy = (SDOChangeSummary)rootCopy.getChangeSummary();
        turnCSon(aCScopy);
    	
    	// move shipTo from root to copyRoot
        int sequenceSizeBeforeMove = aSequence.size();
        int sequenceCopySizeBeforeMove = aPOSequenceCopy.size();
    	poDOCopy.set("shipTo", shipToDO);

        // verify that the sequence on the copy has been increased and on the original has been decreased
        int sequenceCopySizeAfterMove = aPOSequenceCopy.size();
        int sequenceSizeAfterMove = aSequence.size();
        assertEquals(sequenceCopySizeBeforeMove + 1, sequenceCopySizeAfterMove);
        assertEquals(sequenceSizeBeforeMove - 1, sequenceSizeAfterMove);
        // verify that the object was deleted on the copy in prep for a move from the root to this copy
        assertNull(root.get(PO_SEQUENCE_PATH + "/shipTo"));
        
        // undoChanges
       // aCS.undoChanges();
        
        // verify unchange
        // shipTo has moved back to the root from copyRoot
        //assertNull()
        
        // verify unChangeSummary
        
    }
    
    public void testRemoveAllEmptyComplexManyReferenceViaListWrapper() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        int sequenceSizeBefore = aSequence.size();
        DataObject itemDO1 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
        // after removal the items list indexes on the dataObject will shift down, get item[2] for later comparison
        DataObject itemDO2 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[2]");
        assertNotNull(itemDO1);
        assertNotNull(itemDO2);
        assertFalse(itemDO1 == itemDO2);
    	
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
        
    	// get item from sequence
    	int item2SequenceIndex = getNthSequenceIndexFor(aSequence, "item", 2);
    	assertTrue(item2SequenceIndex > -1);
    	DataObject itemObjectFromSetting = (DataObject)aSequence.getValue(item2SequenceIndex);
    	assertNotNull(itemObjectFromSetting);
    	assertTrue(itemObjectFromSetting == itemDO2);
    	
    	// create a list of items to remove
    	List<DataObject> listToRemove = new ArrayList<DataObject>();
    	//for(Iterator<DataObject> i = existingList.iterator(); i.hasNext();) {
    		//listToRemove.add(i.next());	
    	//}
    	
    	int sizeListToRemove = listToRemove.size();

    	// remove entire list
    	existingList.removeAll(listToRemove);
    	assertEquals(sequenceSizeBefore - sizeListToRemove, aSequence.size());
    	assertEquals(listSizeBefore - sizeListToRemove, existingList.size());
    	
    	// are we removed on the DataObject?
    	//DataObject item1ObjectFromAfterRemove = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
    	// TODO: verify delete or dont delete after a sequence.remove
    	//assertTrue(item1ObjectFromAfterRemove == itemDO1);   
    	//assertFalse(item1ObjectFromAfterRemove == itemDO2);   
    }
    
    public void verifyAddAllAtIndexComplexManyByListWrapperAddPropertyOnExistingList(int addIndex) {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[1]");
    	assertNotNull(item3);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add list of items to existing list
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	aListToAdd.add(item3);
    	// add to the end of the list
    	existingList.addAll(addIndex,aListToAdd);

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);

    	// verify that the sequence size has increased
    	assertEquals(indexToPlaceAtEnd + aListToAdd.size(), aSequence.size());
    	
    	// get back new Setting value
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd + aListToAdd.size() - 1);
    	assertNotNull(item2Value);
    	assertEquals(item2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + aListToAdd.size(), aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + aListToAdd.size(), treeSizeAfterAdd);
    }
    
    public void testAddAllAtIndex0ComplexManyByListWrapperAddPropertyOnExistingList() {
    	verifyAddAllAtIndexComplexManyByListWrapperAddPropertyOnExistingList(0);
    }

    public void testAddAllAtIndex1ComplexManyByListWrapperAddPropertyOnExistingList() {
    	verifyAddAllAtIndexComplexManyByListWrapperAddPropertyOnExistingList(1);
    }
    /*
    public void testRemoveSimpleManyBySequence() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("comment");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(PO_COMMENT_LIST_SIZE, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	
    	Property aProperty = po.getInstanceProperty("comment");
    	
    	// add list of items to existing list
    	//List<String> aListToAdd = new ArrayList<String>();
    	//aListToAdd.add("comment 2");
    	//aListToAdd.add("comment 3");    	
    	
    	// remove entire list of comments
    	for(int i=0; i<listSizeBefore; i++) {
    		//int indexOfSetting = aSequence.getIndex(aProperty, existingList.get(i));
    		int indexOfSetting = getNthSequenceIndexFor(aSequence, aProperty.getName());
        	// get original setting
        	SDOSetting aSetting = (SDOSetting)aSequence.getSettings().get(indexOfSetting);

        	aSequence.remove(indexOfSetting);
        	
        	assertFalse(aSetting == aSequence.getSettings().get(indexOfSetting));
    	}

    	// verify that the list has decreased on the do
    	int listSizeAfter = ((ListWrapper)po.get("comment")).size();
    	assertEquals(0, listSizeAfter);

    	// verify that the sequence size has decreased
    	assertEquals(indexToPlaceAtEnd - listSizeBefore, aSequence.size());
    	
    	// verify that the sequence hash corresponding to the index to be removed is gone
    	// check decreased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE - listSizeBefore, aSequence.size());
    	
    	// verify that DataObject has not changed for simple types
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd, treeSizeAfterAdd);
    }
    */
    public void testClearSimpleManyByListWrapper() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("comment");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(PO_COMMENT_LIST_SIZE, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	
    	Property itemProperty = po.getInstanceProperty("comment");
    	
    	// add list of items to existing list
    	List<String> aListToAdd = new ArrayList<String>();
    	aListToAdd.add("comment 2");
    	aListToAdd.add("comment 3");
    	
    	existingList.clear();

    	// verify that the list has decreased on the do
    	int listSizeAfter = ((ListWrapper)po.get("comment")).size();
    	assertEquals(0, listSizeAfter);

    	// verify that the sequence size has decreased
    	assertEquals(indexToPlaceAtEnd - listSizeBefore, aSequence.size());
    	
    	// check decreased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE - listSizeBefore, aSequence.size());
    	
    	// verify that DataObject has not changed for simple types
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd, treeSizeAfterAdd);
    }
    
    public void testClearComplexManyReferenceByListWrapper() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[1]");
    	assertNotNull(item3);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add list of items to existing list
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	aListToAdd.add(item3);
    	aListToAdd.add(item3);
    	
    	existingList.clear();

    	// verify that the list has decreased on the do
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore - aListToAdd.size(), listSizeAfter);

    	// verify that the sequence size has decreased
    	assertEquals(indexToPlaceAtEnd - aListToAdd.size(), aSequence.size());
    	
    	// check decreased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE - aListToAdd.size(), aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd - aListToAdd.size(), treeSizeAfterAdd);
    }
    
    // SDOSequence and SDODataObject bidirectional testing
    public void testDeleteAlsoRemovesSequenceSetting() {
    	defineAndLoadRoot(false, false);
    	// get sequence po
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        DataObject shipToDO = (DataObject)po.get("shipTo");
        assertNotNull(shipToDO);
        SDOSequence aSequence = (SDOSequence)po.getSequence();
    	assertNotNull(aSequence);
    	// 4 instead of 5 because the one attribute property cannot be sequenced
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());
    	
    	// get shipTo sequence
    	int shipToSequenceIndex = getNthSequenceIndexFor(aSequence, "shipTo");
    	assertTrue(shipToSequenceIndex > -1);
    	DataObject shipToObjectFromSetting = (DataObject)aSequence.getValue(shipToSequenceIndex);
    	assertNotNull(shipToObjectFromSetting);
    	assertTrue(shipToObjectFromSetting == shipToDO);
    	
    	// delete po[1]/shipTo
    	shipToDO.delete();
    	
    	// are we removed on the sequence?
    	int shipToSequenceIndexAfterDelete = getNthSequenceIndexFor(aSequence, "shipTo");
    	assertEquals(NO_MATCH_INDEX, shipToSequenceIndexAfterDelete);
    	//DataObject shipToObjectFromSettingAfterDelete = (DataObject)aSequence.getValue(getSequenceIndexFor(aSequence, "shipTo"));
    	//assertNull(shipToObjectFromSettingAfterDelete);    	
    }

    public void testUnsetAlsoRemovesSequenceSetting() {
    	defineAndLoadRoot(false, false);
    	// get sequence po
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        DataObject shipToDO = (DataObject)po.get("shipTo");
        assertNotNull(shipToDO);
        SDOSequence aSequence = (SDOSequence)po.getSequence();
    	assertNotNull(aSequence);
    	// 4 instead of 5 because the one attribute property cannot be sequenced
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());
    	
    	// get shipTo sequence
    	int shipToSequenceIndex = getNthSequenceIndexFor(aSequence, "shipTo");
    	assertTrue(shipToSequenceIndex > -1);
    	DataObject shipToObjectFromSetting = (DataObject)aSequence.getValue(shipToSequenceIndex);
    	assertNotNull(shipToObjectFromSetting);
    	assertTrue(shipToObjectFromSetting == shipToDO);
    	
    	// delete po[1]/shipTo
    	po.unset("shipTo");
    	
    	// are we removed on the sequence?
    	int shipToSequenceIndexAfterDelete = getNthSequenceIndexFor(aSequence, "shipTo");
    	assertEquals(NO_MATCH_INDEX, shipToSequenceIndexAfterDelete);
    }

    public void testDetachAlsoRemovesSequenceSetting() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        DataObject shipToDO = (DataObject)root.get(PO_SEQUENCE_PATH + "/shipTo");
        assertNotNull(shipToDO);
    	
    	// get shipTo sequence
    	int shipToSequenceIndex = getNthSequenceIndexFor(aSequence, "shipTo");
    	assertTrue(shipToSequenceIndex > -1);
    	DataObject shipToObjectFromSetting = (DataObject)aSequence.getValue(shipToSequenceIndex);
    	assertNotNull(shipToObjectFromSetting);
    	assertTrue(shipToObjectFromSetting == shipToDO);
    	
    	// delete po[1]/shipTo
    	shipToDO.detach();
    	
    	// are we removed on the sequence?
    	int shipToSequenceIndexAfterDelete = getNthSequenceIndexFor(aSequence, "shipTo");
    	assertEquals(NO_MATCH_INDEX, shipToSequenceIndexAfterDelete);
    }

    public void testSetNullAlsoSetsSequenceSetting() {
    	
    }

    // TODO: Issue resolution 20070403-1: is remove local to Sequence - no
    public void testRemoveDoesDeleteDataObjectPropertyValue() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        DataObject shipToDO = (DataObject)root.get(PO_SEQUENCE_PATH + "/shipTo");
        assertNotNull(shipToDO);
    	
    	// get shipTo sequence
    	int shipToSequenceIndex = getNthSequenceIndexFor(aSequence, "shipTo");
    	assertTrue(shipToSequenceIndex > -1);
    	DataObject shipToObjectFromSetting = (DataObject)aSequence.getValue(shipToSequenceIndex);
    	assertNotNull(shipToObjectFromSetting);
    	assertTrue(shipToObjectFromSetting == shipToDO);
    	
    	// delete po[1]/shipTo from setting
    	aSequence.remove(shipToSequenceIndex);
    	
    	// are we removed on the DataObject?
    	DataObject shipToObjectFromAfterRemove = (DataObject)root.get(PO_SEQUENCE_PATH + "/shipTo");
    	assertNull(shipToObjectFromAfterRemove);   
    }
/*
    // TODO: tltest cannot pickup now SDOSequence function defs
    public void testRemoveIndexDoesDeleteDataObjectPropertyValue() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        DataObject shipToDO = (DataObject)root.get(PO_SEQUENCE_PATH + "/shipTo");
        assertNotNull(shipToDO);
    	
    	// get shipTo sequence
    	int shipToSequenceIndex = getNthSequenceIndexFor(aSequence, "shipTo");
    	assertTrue(shipToSequenceIndex > -1);
    	DataObject shipToObjectFromSetting = (DataObject)aSequence.getValue(shipToSequenceIndex);
    	assertNotNull(shipToObjectFromSetting);
    	assertTrue(shipToObjectFromSetting == shipToDO);
    	
    	// delete po[0] from setting
    	aSequence.remove(aSequence.getProperty(0).getName(), aSequence.getProperty(0).getType().getURI(),  true);
    	
    	// are we removed on the DataObject?
    	Object shipToObjectFromAfterRemove = root.get(PO_SEQUENCE_PATH + "/poID");
    	// TODO: verify delete or dont delete after a sequence.remove
    	assertNull(shipToObjectFromAfterRemove);   
    }
    */
    
    public void testRemoveIndex0ContainingSimpleSingleType() {
    	
    }
    public void testRemoveIndex0ContainingComplexSingleType() {
    	
    }
    public void testRemoveIndex0ContainingComplexManyType() {
    	
    }
    public void testRemoveIndex0ContainingMultipleComplexManyType() {
    	
    }
    public void testRemoveIndex0ContainingSimpleManyType() {
    	
    }
    /**
     * SDOSequence specific unit tests
     */

    public void testSequenceConstructorWithNullDataObjectThrowsException() {
		// create a non-standard sequence - a null DataObject is invalid    	
    	boolean exceptionThrown = false;
    	SDOSequence aSequence = null;
        int errorCode = -1;
    	try {
    		aSequence = new SDOSequence(null);
    	} catch (SDOException e) {
    		exceptionThrown = true;
        	errorCode = e.getErrorCode();
    	} finally {
        	assertTrue(exceptionThrown);
    		assertNull(aSequence);
            assertEquals(45021, errorCode);
    	}
    }
    
    /**
     * Returns the <code>Sequence</code> for this DataObject.
     * When getType().isSequencedType() == true,
     * the Sequence of a DataObject corresponds to the
     * XML elements representing the values of its Properties.
     * Updates through DataObject and the Lists or Sequences returned
     * from DataObject operate on the same data.
     * When getType().isSequencedType() == false, null is returned.
     * @return the <code>Sequence</code> or null.
     */
    public void testSequenceReturnFrom_SDODataObject_getSequence() {
    	defineAndLoadRoot(false, false);
        getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    }
    
    /**
     * Returns the value of a <code>Sequence</code> property identified by the specified path.
     * @param path the path to a valid object and property.
     * @return the <code>Sequence</code> value of the specified property.
     * @see #get(String)
     * @deprecated in 2.1.0.
     */
    public void test_SequenceReturnFrom_SDODataObject_getSequence_StringFails() {
    	defineAndLoadRoot(false, false);
    	assertNotNull(root);
    	boolean exceptionThrown = false;
    	SDOSequence aSequence = null;
        int errorCode = -1;
    	try {
    		aSequence = (SDOSequence)root.getSequence(PO_PATH);
    	} catch (SDOException e) {
    		exceptionThrown = true;
        	errorCode = e.getErrorCode();
    	} finally {
        	assertTrue(exceptionThrown);
    		assertNull(aSequence);
            assertEquals(45020, errorCode);
    	}
    }
    
    public void test_SequenceReturnFrom_SDODataObject_getSequence_StringPasses() {
    	defineAndLoadRoot(false, false);
    	assertNotNull(root);
        SDOSequence aSequence = (SDOSequence)root.getSequence(PO_SEQUENCE_PATH);
        // check sequence
        assertNotNull(aSequence);
        assertEquals(PO_SEQUENCE_SIZE, aSequence.size());
    }
    
    /**
     * Returns the value of a <code>Sequence</code> property identified by the specified property index.
     * @param propertyIndex the index of the property.
     * @return the <code>Sequence</code> value of the specified property.
     * @see #get(int)
     * @deprecated in 2.1.0.
     */
    public void test_SequenceReturnFrom_SDODataObject_getSequence_index_type_complex_many() {
    	defineAndLoadRoot(false, false);
    	assertNotNull(root);
    	// get property index of porder
    	int propertyIndex = ((SDOProperty)root.getInstanceProperty(PO_PATH)).getIndexInType();
    	// Expect a failure for a complex many property
    	boolean exceptionThrown = false;
        int errorCode = -1;
    	SDOSequence aSequence = null;
    	try {
    		aSequence = (SDOSequence)root.getSequence(propertyIndex);
    	} catch (SDOException e) {
    		exceptionThrown = true;
        	errorCode = e.getErrorCode();
    	} finally {
        	assertTrue(exceptionThrown);
    		assertNull(aSequence);
            assertEquals(45022, errorCode);
    	}
    }

    public void test_SequenceReturnFrom_SDODataObject_getSequence_index_type_simple_many() {
    	defineAndLoadRoot(false, false);
    	assertNotNull(root);
    	// get property index of porder
    	int propertyIndex = ((SDOProperty)root.getInstanceProperty(PO_PATH)).getIndexInType();
    	assertEquals(2, propertyIndex);
    	// Expect a failure for a many property
    	boolean exceptionThrown = false;
    	SDOSequence aSequence = null;
        int errorCode = -1;
    	try {
    		aSequence = (SDOSequence)root.getSequence(propertyIndex);
    	} catch (SDOException e) {
    		exceptionThrown = true;
        	errorCode = e.getErrorCode();
    	} finally {
        	assertTrue(exceptionThrown);
    		assertNull(aSequence);
            assertEquals(45022, errorCode);
    	}
    	//verifySequenceIntegrity(aSequence, root.getInstanceProperty(PO_PATH));
    }

    public void test_SequenceReturnFrom_SDODataObject_getSequence_index_type_simple_single() {
    	defineAndLoadRoot(false, false);
    	assertNotNull(root);
    	// get property index of porder
    	int propertyIndex = ((SDOProperty)root.getInstanceProperty(PO_PATH)).getIndexInType();
    	// Expect a failure for a many property
    	boolean exceptionThrown = false;
    	SDOSequence aSequence = null;
        int errorCode = -1;
    	try {
    		aSequence = (SDOSequence)root.getSequence(propertyIndex);
    	} catch (SDOException e) {
    		exceptionThrown = true;
        	errorCode = e.getErrorCode();
    	} finally {
        	assertTrue(exceptionThrown);
    		assertNull(aSequence);
            assertEquals(45022, errorCode);
    	}
    	//verifySequenceIntegrity(aSequence, root.getInstanceProperty(PO_PATH));
    }

    // TODO: NEED SINGLE COMPLEX WITH COMPLEX CHILDREN
    public void test_SequenceReturnFrom_SDODataObject_getSequence_index_type_complex_single() {
    	defineAndLoadRoot(false, false);
    	assertNotNull(root);
    	// get property index of porder
    	int propertyIndex = ((SDOProperty)root.getInstanceProperty(CUSTOMER_PATH)).getIndexInType();
        SDOSequence aSequence = (SDOSequence)root.getSequence(propertyIndex);
//    	verifySequenceIntegrity(aSequence, root.getInstanceProperty(CUSTOMER_PATH));
    }

    /**
     * Returns the value of the specified <code>Sequence</code> property.
     * @param property the property to get.
     * @return the <code>Sequence</code> value of the specified property.
     * @see #get(Property)
     * @deprecated in 2.1.0.
     */
    public void test_SequenceReturnFrom_SDODataObject_getSequence_Property_type_single_many() { 
    	defineAndLoadRoot(false, false);
    	assertNotNull(root);
    	// get property index of porder
    	Property aPOProperty = root.getInstanceProperty(PO_PATH);
    	// Expect a failure for a single many property
    	SDOSequence aSequence = null;
    	boolean exceptionThrown = false;
        int errorCode = -1;
    	try {
        	aSequence = (SDOSequence)root.getSequence(aPOProperty);
    	} catch (SDOException e) {
    		exceptionThrown = true;
        	errorCode = e.getErrorCode();
    	} finally {
        	assertTrue(exceptionThrown);
    		assertNull(aSequence);
            assertEquals(45022, errorCode);
    	}
    }

    public void test_SequenceReturnFrom_SDODataObject_getSequence_Property_type_complex_many() { 
    	defineAndLoadRoot(false, false);
    	assertNotNull(root);
    	// get property index of porder
    	Property aPOProperty = root.getInstanceProperty(PO_PATH);
    	// Expect a failure for a complex many property
    	SDOSequence aSequence = null;
    	boolean exceptionThrown = false;
        int errorCode = -1;
    	try {
        	aSequence = (SDOSequence)root.getSequence(aPOProperty);
    	} catch (SDOException e) {
    		exceptionThrown = true;
        	errorCode = e.getErrorCode();
    	} finally {
        	assertTrue(exceptionThrown);
    		assertNull(aSequence);
            assertEquals(45022, errorCode);
    	}
    }

    public void test_SequenceReturnFrom_SDODataObject_getSequence_Property_type_simple_single() { 
    	defineAndLoadRoot(false, false);
    	assertNotNull(root);
    	// get property index of porder
    	Property aPOProperty = root.getInstanceProperty(PO_PATH);
    	// Expect a failure for a simple single property
    	SDOSequence aSequence = null;
    	boolean exceptionThrown = false;
        int errorCode = -1;
    	try {
        	aSequence = (SDOSequence)root.getSequence(aPOProperty);
    	} catch (SDOException e) {
    		exceptionThrown = true;
        	errorCode = e.getErrorCode();
    	} finally {
        	assertTrue(exceptionThrown);
    		assertNull(aSequence);
            assertEquals(45022, errorCode);
    	}
    }

    public void test_SequenceReturnFrom_SDODataObject_getSequence_Property_type_complex_single() { 
    	defineAndLoadRoot(false, false);
    	//setTypeSequenced(CUSTOMER_TYPENAME, true);
    	assertNotNull(root);
    	// get property index of porder
    	Property aCustomerProperty = root.getInstanceProperty(CUSTOMER_PATH);
    	// Expect no failure for a complex single property
    	SDOSequence aSequence = null;
    	boolean exceptionThrown = false;
        int errorCode = -1;
    	try {
        	aSequence = (SDOSequence)root.getSequence(aCustomerProperty);
    	} catch (SDOException e) {
    		exceptionThrown = true;
        	errorCode = e.getErrorCode();
    	} finally {
        	assertFalse(exceptionThrown);
    		assertNotNull(aSequence);
            //assertEquals(45022, errorCode);
    	}
   	}
    
    private boolean verifySequenceIntegrity(SDOSequence aSequence, Property aProperty) {
    	assertNotNull(aSequence);
    	// verify that the # element properties (not attributes) are the same as in aProperty
    	
    	List<Property> sequencedProperties = new ArrayList<Property>();//InProperty;//aProperty.getInstanceProperties()
    	for(Iterator i = aProperty.getInstanceProperties().iterator(); i.hasNext();) {
    		Property currentProperty = (Property)i.next();
    		if(currentProperty.getType().isSequenced()) {
    			sequencedProperties.add(currentProperty);
    		}    		
    	}
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());
    	return true;
    }
   
    public void testSDOSequence_constructor() {
    	// DataObject aDataObject) {
    	// get po
    	defineAndLoadRoot(false, false);
    	// get sequence po
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
    	
    	SDOSequence aSequence = new SDOSequence((SDODataObject)po);
    	// verify size
    	assertEquals(0, aSequence.size());
    }

    /**
     * Returns the number of entries in the sequence.
     * @return the number of entries.
     */
    public void test_intReturnFrom_size() {
    }

    // create an open content property
    public void test_booleanReturnFrom_add_String_Object_createOpenContentProperty() {
    }
    
    /**
     * Adds a new entry with the specified property name and value
     * to the end of the entries.
     * @param propertyName the name of the entry's property.
     * @param value the value for the entry.
     */
    public void test_booleanReturnFrom_add_String_Object() {
    	// String propertyName, Object value) {
    }
    
    /**
     * Adds a new entry with the specified property index and value
     * to the end of the entries.
     * @param propertyIndex the index of the entry's property.
     * @param value the value for the entry.
     */
    public void test_booleanReturnFrom_add_int_Object() {
    	// int propertyIndex, Object value) {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item2 = (DataObject)root.get("item[2]");
    	assertNotNull(item2);
    	
    	// get "item" property index
    	int propIndex = 0;
    	for(Iterator i=po.getInstanceProperties().iterator(); i.hasNext();) {
    		Property aProperty = (Property)i.next();
    		if(aProperty != null && aProperty.getName().equals("item")) {
    			break;
    		} else {
    			propIndex++;
    		}
    	}
    	// add to sequence
    	aSequence.add(propIndex, item2);
    	// get back new Setting value
    	//ListWrapper item2Value = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd);    	
    	assertNotNull(item2Value);
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_SIZE + 1, aSequence.size());
    	
    	// verify that the list has increased
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + 1, listSizeAfter);
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + 1, treeSizeAfterAdd);
    }

    public void testAddListToSequence() {
    	// a do.set(List) should populate the sequence
    	
    }
    
    /**
     * Adds a new entry with the specified property and value
     * to the end of the entries.
     * @param property the property of the entry.
     * @param value the value for the entry.
     */
    public void test_booleanReturnFrom_add_Property_Object() {
    	// Property property, Object value) {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item2 = (DataObject)root.get("item[2]");
    	assertNotNull(item2);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add to sequence
    	aSequence.add(itemProperty, item2);
    	// get back new Setting value
    	//ListWrapper item2Value = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(item2Value);
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());
    	
    	// verify that the list has increased
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + 1, listSizeAfter);
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + 1, treeSizeAfterAdd);
    }

    /**
     * Test setting a many property using a single item of a list instead of passing a
     * ListWrapper as usual.
     * The existing list will need to be null (not an empty ListWrapper)
     */
    public void test_booleanReturnFrom_add_Property_Object_WhereValuePassedIsSingleItemInEmptyList() {
    	// Property property, Object value) {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item2 = (DataObject)root.get("item[2]");
    	assertNotNull(item2);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add to sequence
    	aSequence.add(itemProperty, item2);   	
    	
    	
    	
    	
    	// get back new Setting value
    	//ListWrapper item2Value = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(item2Value);
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());
    	
    	// verify that the list has increased
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + 1, listSizeAfter);
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + 1, treeSizeAfterAdd);
    }
    
    public void testAddMultipleValuesIntoSequence() {
    }
/*    
    public List<SDOSetting> reflectiveGetList(Object receiver, String fieldName) {
    	List<SDOSetting> instanceField = null;
        try {
            Class cls = receiver.getClass();
            //Field field = cls.getField(fieldName);
            Field field = cls.getDeclaredField(fieldName);            
            // override default security settings for private field access from another class
            field.setAccessible(true); 
            instanceField = (List<SDOSetting>)field.get(receiver);
          } catch (Throwable e) {
             System.err.println(e);
          }
          return instanceField;
    }

    public DataObject reflectiveGetDataObject(Object receiver, String fieldName) {
    	DataObject instanceField = null;
        try {
            Class cls = receiver.getClass();
            //Field field = cls.getField(fieldName);
            Field field = cls.getDeclaredField(fieldName);            
            // override default security settings for private field access from another class
            field.setAccessible(true); 
            instanceField = (DataObject)field.get(receiver);
          } catch (Throwable e) {
             System.err.println(e);
          }
          return instanceField;
    }
*/    
/*    public boolean compareSequences(SDOSequence aSequence, SDOSequence aSequenceCopy, int size, boolean isDeep) {
        // the sequence may be a new object but may be the same if we compare a sequence to itself
        int sequenceSize = aSequence.size();
        assertEquals(size, sequenceSize);
        assertEquals(aSequence.size(), aSequenceCopy.size());
        // the settings inside the sequence must be new objects
        SDOSetting originalSetting = null;
        SDOSetting copySetting = null;
        List<SDOSetting> originalSettingsList = aSequence.getSettings();
        assertNotNull(originalSettingsList);
        assertEquals(sequenceSize, originalSettingsList.size());
        List copySettingsList = aSequenceCopy.getSettings();
        assertNotNull(copySettingsList);
        assertEquals(sequenceSize, copySettingsList.size());

        Property originalProperty = null;
        Property copyProperty = null;

        for(int index = 0, size2 = aSequence.size(); index <  size2; index++) {
        	originalSetting = originalSettingsList.get(index);
        	copySetting = (SDOSetting)copySettingsList.get(index);

            // dataObject back pointer may be distinct
//            DataObject originalDO = reflectiveGetDataObject(aSequence, "dataObject");
//            DataObject copyDO = reflectiveGetDataObject(aSequenceCopy, "dataObject");
        	
        	// each setting may be a new object
        	//assertFalse(originalSetting == copySetting);
            // the property field on the setting must point to the same property instance as the original
        	// check names before instances
            originalProperty = originalSetting.getProperty();
            copyProperty = copySetting.getProperty();
            
            // we must handle null properties that represent unstructured text
            // both null = unstructured
            // one null = invalid state (return not equal)
            // both !null = valid state (check equality)
           	if((null == originalProperty && null != copyProperty) || (null != originalProperty && null == copyProperty)) {
           		assertTrue(false);
            }
           	
           	if(null != originalProperty) {
           		assertEquals(originalProperty.getName(), copyProperty.getName());
           		assertEquals(originalProperty.hashCode(), copyProperty.hashCode());
           		// the value field on the setting must point the the deep copy value instance        	
           		// the property field on the setting must point to the same property instance as the original
           		if(originalProperty != copyProperty) {
           			assertTrue(false);
           		}
           	}
        	// for unstructuredText (null property) and simple dataTypes we check equality directly
/*        	if(null != originalProperty && originalProperty.getType().isDataType()) {        		
        		if(!originalSetting.getValue().equals(copySetting.getValue())) { // we can also use !.equals()
        			assertTrue(false);
        		}
        	} else {
        		// For complex types
            	// we do not need to check deep equality on dataObjects twice here, just check instances
        		// because the dataObject compare will iterate all the properties of each dataObject
        		// only compare DataObjects when in a  deep equal
                if (isDeep) {
                	// there are no lists in settings
                	Object originalValue = originalSetting.getValue();
                	Object copyValue = copySetting.getValue();                	
                	
                	if(null != originalValue && null != copyValue) {
                		if(originalProperty.isMany()) {
                			List aList = (List)originalValue;
                			List aListCopy = (List)copyValue;
                			for(int i = 0, lsize = aList.size(); i< lsize; i++) {                				
                				if(!equal((DataObject)aList.get(i), (DataObject)aListCopy.get(i))) {
                					return false;
                				}
                			}
                		} else {
                			if(!equal((DataObject)originalValue, (DataObject)copyValue)) {
                				return false;
                			}
                		}
                	}
                }
        	}
*//*        }
        return true;
    }
*/    
    public void testCopyDeepWithNoSequence() {
    	
    }
    
    public void testCopyShallowWithNoSequence() {
    }

    public void testCopyShallowWithDiffSequenceSimpleValue() {
    }
    
    public void testCopyDeepComplexManySequence() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	// copy po
    	DataObject rootCopy = (DataObject)copyHelper.copy(root);    	
    	// check sequence was copied
        SDOSequence aSequenceCopy = getSequence(rootCopy, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        assertNotNull(aSequenceCopy);
        assertEquals(aSequence.size(), aSequenceCopy.size());
        //compareSequences(aSequence, aSequenceCopy, PO_SEQUENCE_SIZE, true);
    }

    public void testCopyDeepComplexSingleSequence() {
    	
    }

    public void testCopyDeepSimpleManySequence() {
    	
    }

    public void testCopyDeepSimpleSingleSequence() {
    	
    }

    public void testEqualShallowSimpleSingleSequence() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        //aSequence.setValue(0, 5);        
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	// copy po
    	DataObject poCopy = copyHelper.copyShallow(po);    	
    	// check sequence was copied
        SDOSequence aSequenceCopy = (SDOSequence)poCopy.getSequence();
        assertNotNull(aSequenceCopy);
        //compareSequences(aSequence, aSequenceCopy, PO_SEQUENCE_SIZE, false);
        
        // test equalityHelper
    	//DataObject poCopy = (DataObject)rootCopy.get(PO_SEQUENCE_PATH);
        boolean bEqual = equalityHelper.equalShallow(po, poCopy);
        assertTrue(bEqual);
    }

    public void testEqualShallowSimpleSingleSequenceDifferentValue() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        //aSequence.setValue(0, 5);        
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	// copy po
    	DataObject poCopy = copyHelper.copyShallow(po);    	
    	// check sequence was copied
        SDOSequence aSequenceCopy = (SDOSequence)poCopy.getSequence();
        assertNotNull(aSequenceCopy);
        //compareSequences(aSequence, aSequenceCopy, PO_SEQUENCE_SIZE, false);

        boolean bEqual = equalityHelper.equalShallow(po, poCopy);
        assertTrue(bEqual);

        // modify copy sequence
        aSequenceCopy.setValue(0, 5);

        // test equalityHelper
    	//DataObject poCopy = (DataObject)rootCopy.get(PO_SEQUENCE_PATH);
        bEqual = equalityHelper.equalShallow(po, poCopy);
        assertFalse(bEqual);
    }
    
    public void testEqualShallowFailsSimpleSingleSequenceDifferentValueViaXSD() {
    	//defineAndLoadRoot(true, false);
    	defineAndLoadRoot(false, false);    	
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        //aSequence.setValue(0, 5);        
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	// copy po
    	DataObject poCopy = copyHelper.copyShallow(po);    	
    	// check sequence was copied
        SDOSequence aSequenceCopy = (SDOSequence)poCopy.getSequence();
        assertNotNull(aSequenceCopy);
        //compareSequences(aSequence, aSequenceCopy, PO_SEQUENCE_SIZE, false);
        
        // modify copy sequence
        aSequenceCopy.setValue(0, 5);
        // test equalityHelper
    	//DataObject poCopy = (DataObject)rootCopy.get(PO_SEQUENCE_PATH);
        boolean bEqual = equalityHelper.equalShallow(po, poCopy);
        assertFalse(bEqual);
    }

    public void testEqualShallowSimpleSingleSequenceDifferentUnstructuredTextValue() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        aSequence.addText("text1");        
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	// copy po
    	DataObject poCopy = copyHelper.copyShallow(po);    	
    	// check sequence was copied
        SDOSequence aSequenceCopy = (SDOSequence)poCopy.getSequence();
        assertNotNull(aSequenceCopy);
        //compareSequences(aSequence, aSequenceCopy, PO_TREE_SIZE + 1, false);
        
        // modify copy sequence
        aSequenceCopy.setValue(aSequenceCopy.size() -1, "text2");
        // test equalityHelper
    	//DataObject poCopy = (DataObject)rootCopy.get(PO_SEQUENCE_PATH);
        boolean bEqual = equalityHelper.equalShallow(po, poCopy);
        assertFalse(bEqual);
    }

    
    public void testDeepEqualWithNoSequence() {
    	
    }

    public void testEqualShallowWithNoSequence() {
    	
    }
    
    public void testEqualDeepComplexManySequence() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	// copy po
    	DataObject rootCopy = (DataObject)copyHelper.copy(root);    	
    	// check sequence was copied
        SDOSequence aSequenceCopy = getSequence(rootCopy, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        assertNotNull(aSequenceCopy);
        //compareSequences(aSequence, aSequenceCopy, PO_SEQUENCE_SIZE, true);
        
        // test equalityHelper
    	DataObject poCopy = (DataObject)rootCopy.get(PO_SEQUENCE_PATH);
        boolean bEqual = equalityHelper.equal(po, poCopy);
        assertTrue(bEqual);
    }

    public void testEqualDeepComplexManySequenceWithDifferentSequence2() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	// copy po
    	DataObject rootCopy = (DataObject)copyHelper.copy(root);    	
    	// check sequence was copied
        SDOSequence aSequenceCopy = getSequence(rootCopy, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        assertNotNull(aSequenceCopy);
        //compareSequences(aSequence, aSequenceCopy, PO_SEQUENCE_SIZE, true);
        
        // modify copy sequence
        aSequenceCopy.setValue(0, null);
        // test equalityHelper
    	DataObject poCopy = (DataObject)rootCopy.get(PO_SEQUENCE_PATH);
        boolean bEqual = equalityHelper.equal(po, poCopy);
        assertFalse(bEqual);
    }
    
    /*
//  variant test cases that should cause equality failure
    testSequenceOnCopyHasDifferentOrder
    testSequenceOnCopyIsEmpty
    testSequenceOnCopyIsLarger
    testSequenceOnCopyIsSmaller
    testSequenceOnCopyHasDifferentPropertyAtIndex
    testSequenceOnCopyHasDifferentValueAtIndex
    testSequenceOnOriginalHasDifferentOrder
    testSequenceOnOriginalIsEmpty
    testSequenceOnOriginalIsLarger
    testSequenceOnOriginalIsSmaller
    testSequenceOnOriginalHasDifferentPropertyAtIndex
    testSequenceOnOriginalHasDifferentValueAtIndex
*/
    
    public void testEqualDeepTrueAfterIsSequencedSetToFalseAfterDefineViaNonSpecMethod() {
    	defineAndLoadRoot(false, false);
        Sequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	// copy po
    	DataObject rootCopy = (DataObject)copyHelper.copy(root);    	
    	// check sequence was copied
        Sequence aSequenceCopy = getSequence(rootCopy, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        assertNotNull(aSequenceCopy);
        //compareSequences((SDOSequence)aSequence, (SDOSequence)aSequenceCopy, PO_SEQUENCE_SIZE, true);
        
        // test equalityHelper
    	DataObject poCopy = (DataObject)rootCopy.get(PO_SEQUENCE_PATH);
        boolean bEqual = equalityHelper.equal(po, poCopy);
        assertTrue(bEqual);

        // modify copy sequence state - non public method - both po and poCopy will have their state changed because they share an SDOType
        assertTrue(po.getType().isSequenced());
        assertTrue(poCopy.getType().isSequenced());
        // WARNING: Users should not be doing this - however it is supported
        ((SDOType)poCopy.getType()).setSequenced(false);
        assertFalse(po.getType().isSequenced());
        assertFalse(poCopy.getType().isSequenced());        
        bEqual = equalityHelper.equal(po, poCopy);
        // sequences will not be compared
        assertTrue(bEqual);
    }

    public void testSequencesStillNullAfterIsSequencedSetToTrueOutOfSpec() {
    	// create a dataObject with no sequence - the root
    	defineAndLoadRoot(false, false);
        Sequence aSequence = root.getSequence();
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	// copy po
    	DataObject rootCopy = copyHelper.copy(root);
    	// verify we are using the same context
    	//assertEquals(helperContext, ((SDOCopyHelper)copyHelper).getHelperContext())
    	// check sequence was copied
        SDOSequence aSequenceCopy = getSequence(rootCopy, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        assertNotNull(aSequenceCopy);
        //compareSequences(aSequence, aSequenceCopy, PO_SEQUENCE_SIZE, true);
        
        // test equalityHelper
    	DataObject poCopy = (DataObject)rootCopy.get(PO_SEQUENCE_PATH);
        boolean bEqual = equalityHelper.equal(po, poCopy);
        assertTrue(bEqual);

        // modify copy sequence state - non public method - both po and poCopy will have their state changed because they share an SDOType
        assertTrue(po.getType().isSequenced());
        assertTrue(poCopy.getType().isSequenced());
        // WARNING: Users should not be doing this - however it is supported
        ((SDOType)poCopy.getType()).setSequenced(false);
        assertFalse(po.getType().isSequenced());
        assertFalse(poCopy.getType().isSequenced());        
        bEqual = equalityHelper.equal(po, poCopy);
        // sequences will not be compared
        assertTrue(bEqual);
    	
    	// turn on isSequenced - not available via spec interface - do not use
    	// copy
    	
    	// check equality
    	
    }
    
    public void testEqualDeepComplexSingleSequence() {
    	
    }

    public void testEqualDeepSimpleManySequence() {
    	
    }

    public void testEqualDeepSimpleSingleSequence() {
    	
    }

    
//  remove via sequence
    public void testRemoveSimpleSingleByIndex() {
    	
    }
    public void testRemoveSimpleManyByIndex() {
    	
    }
    public void testRemoveComplexSingleByIndex() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        DataObject shipToDO = (DataObject)root.get(PO_SEQUENCE_PATH + "/shipTo");
        assertNotNull(shipToDO);
    	
    	// get shipTo sequence
    	int shipToSequenceIndex = getNthSequenceIndexFor(aSequence, "shipTo");
    	assertTrue(shipToSequenceIndex > -1);
    	DataObject shipToObjectFromSetting = (DataObject)aSequence.getValue(shipToSequenceIndex);
    	assertNotNull(shipToObjectFromSetting);
    	assertTrue(shipToObjectFromSetting == shipToDO);
    	
    	// delete po[1]/shipTo from setting
    	aSequence.remove(shipToSequenceIndex);
    	
    	// are we removed on the DataObject?
    	DataObject shipToObjectFromAfterRemove = (DataObject)root.get(PO_SEQUENCE_PATH + "/shipTo");
    	// TODO: verify delete or dont delete after a sequence.remove
    	assertNull(shipToObjectFromAfterRemove);   
    }
    
    public void testRemoveComplexManyByIndex() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        int sequenceSizeBefore = aSequence.size();
        DataObject itemDO1 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
        // after removal the items list indexes on the dataObject will shift down, get item[2] for later comparison
        DataObject itemDO2 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[2]");
        assertNotNull(itemDO1);
        assertNotNull(itemDO2);
        assertFalse(itemDO1 == itemDO2);
    	
    	// get item from sequence
    	int item2SequenceIndex = getNthSequenceIndexFor(aSequence, "item", 2);
    	assertTrue(item2SequenceIndex > -1);
    	DataObject itemObjectFromSetting = (DataObject)aSequence.getValue(item2SequenceIndex);
    	assertNotNull(itemObjectFromSetting);
    	assertTrue(itemObjectFromSetting == itemDO2);
    	
    	// delete po[1]/item[2] from setting
    	aSequence.remove(item2SequenceIndex);
    	assertEquals(sequenceSizeBefore - 1, aSequence.size());
    	
    	// are we removed on the DataObject?
    	DataObject item1ObjectFromAfterRemove = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
    	// TODO: verify delete or dont delete after a sequence.remove
    	assertTrue(item1ObjectFromAfterRemove == itemDO1);   
    	assertFalse(item1ObjectFromAfterRemove == itemDO2);   
    }

    public void testRemoveIndexComplexManyReferenceViaListWrapper() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        int sequenceSizeBefore = aSequence.size();
        DataObject itemDO1 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
        // after removal the items list indexes on the dataObject will shift down, get item[2] for later comparison
        DataObject itemDO2 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[2]");
        assertNotNull(itemDO1);
        assertNotNull(itemDO2);
        assertFalse(itemDO1 == itemDO2);
    	
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
        
    	// get item from sequence
    	int item2SequenceIndex = getNthSequenceIndexFor(aSequence, "item", 2);
    	assertTrue(item2SequenceIndex > -1);
    	DataObject itemObjectFromSetting = (DataObject)aSequence.getValue(item2SequenceIndex);
    	assertNotNull(itemObjectFromSetting);
    	assertTrue(itemObjectFromSetting == itemDO2);
    	
    	// create a list of items to remove
    	List<DataObject> listToRemove = new ArrayList<DataObject>();
    	for(Iterator<DataObject> i = existingList.iterator(); i.hasNext();) {
    		listToRemove.add(i.next());	
    	}
    	
    	int sizeListToRemove = listToRemove.size();

    	// remove entire list
    	for(int i=0; i<listSizeBefore; i++) {
    		existingList.remove(0);
    	}
    	assertEquals(sequenceSizeBefore - sizeListToRemove, aSequence.size());
    	assertEquals(listSizeBefore - sizeListToRemove, existingList.size());
    	
    	// are we removed on the DataObject?
    	//DataObject item1ObjectFromAfterRemove = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
    	// TODO: verify delete or dont delete after a sequence.remove
    	//assertTrue(item1ObjectFromAfterRemove == itemDO1);   
    	//assertFalse(item1ObjectFromAfterRemove == itemDO2);   
    }

    public void testRemoveIndexFirstDuplicateComplexManyReferenceViaListWrapper() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        int sequenceSizeBefore = aSequence.size();
        DataObject itemDO1 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
        // after removal the items list indexes on the dataObject will shift down, get item[2] for later comparison
        DataObject itemDO2 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[2]");
        assertNotNull(itemDO1);
        assertNotNull(itemDO2);
        assertFalse(itemDO1 == itemDO2);
    	
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
        
    	// get item from sequence
    	int item2SequenceIndex = getNthSequenceIndexFor(aSequence, "item", 2);
    	assertTrue(item2SequenceIndex > -1);
    	DataObject itemObjectFromSetting = (DataObject)aSequence.getValue(item2SequenceIndex);
    	assertNotNull(itemObjectFromSetting);
    	assertTrue(itemObjectFromSetting == itemDO2);
    	
    	// create a list of items to remove
    	List<DataObject> listToRemove = new ArrayList<DataObject>();
    	for(Iterator<DataObject> i = existingList.iterator(); i.hasNext();) {
    		listToRemove.add(i.next());	
    	}
    	
    	int sizeListToRemove = listToRemove.size();

    	// remove entire list
    	for(int i=0; i<listSizeBefore; i++) {
    		existingList.remove(0);
    	}
    	assertEquals(sequenceSizeBefore - sizeListToRemove, aSequence.size());
    	assertEquals(listSizeBefore - sizeListToRemove, existingList.size());
    	
    	// are we removed on the DataObject?
    	//DataObject item1ObjectFromAfterRemove = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
    	// TODO: verify delete or dont delete after a sequence.remove
    	//assertTrue(item1ObjectFromAfterRemove == itemDO1);   
    	//assertFalse(item1ObjectFromAfterRemove == itemDO2);   
    }

    /**
     * Unable to test removal of an index of a duplicated list because the updateContainment code now does not allow duplicate
     * containment dataobjects
     */
    public void testRemoveIndexFirstDuplicateComplexManyReferenceViaSequence() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        int sequenceSizeBefore = aSequence.size();
        DataObject itemDO1 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
        // after removal the items list indexes on the dataObject will shift down, get item[2] for later comparison
        DataObject itemDO2 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[2]");
        assertNotNull(itemDO1);
        assertNotNull(itemDO2);
        assertFalse(itemDO1 == itemDO2);
    	
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
        
    	// get item from sequence
    	int item2SequenceIndex = getNthSequenceIndexFor(aSequence, "item", 2);
    	assertTrue(item2SequenceIndex > -1);
    	DataObject itemObjectFromSetting = (DataObject)aSequence.getValue(item2SequenceIndex);
    	assertNotNull(itemObjectFromSetting);
    	assertTrue(itemObjectFromSetting == itemDO2);
    	
    	// create a list of items to remove
    	List<DataObject> listToRemove = new ArrayList<DataObject>();
    	for(Iterator<DataObject> i = existingList.iterator(); i.hasNext();) {
    		listToRemove.add(i.next());	
    	}
    	
    	int sizeListToRemove = listToRemove.size();

    	// q2: remove(itemDO@123 = index 2) from seq(itemDO@123, shipToDO@234, itemDO@123, itemDO@123) = seq(itemDO@123, shipToDO@234, itemDO@123) - 3rd item removed
    	// invalid state - cannot reproduce
    	
    	// remove entire list
    	for(int i=0; i<listSizeBefore; i++) {
    		aSequence.remove(5);
    	}
    	assertEquals(sequenceSizeBefore - sizeListToRemove, aSequence.size());
    	assertEquals(listSizeBefore - sizeListToRemove, existingList.size());
    	
    	// are we removed on the DataObject?
    	//DataObject item1ObjectFromAfterRemove = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
    	// TODO: verify delete or dont delete after a sequence.remove
    	//assertTrue(item1ObjectFromAfterRemove == itemDO1);   
    	//assertFalse(item1ObjectFromAfterRemove == itemDO2);   
    }
    
    public void testRemoveAllComplexManyReferenceViaListWrapper() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        int sequenceSizeBefore = aSequence.size();
        DataObject itemDO1 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
        // after removal the items list indexes on the dataObject will shift down, get item[2] for later comparison
        DataObject itemDO2 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[2]");
        assertNotNull(itemDO1);
        assertNotNull(itemDO2);
        assertFalse(itemDO1 == itemDO2);
    	
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
        
    	// get item from sequence
    	int item2SequenceIndex = getNthSequenceIndexFor(aSequence, "item", 2);
    	assertTrue(item2SequenceIndex > -1);
    	DataObject itemObjectFromSetting = (DataObject)aSequence.getValue(item2SequenceIndex);
    	assertNotNull(itemObjectFromSetting);
    	assertTrue(itemObjectFromSetting == itemDO2);
    	
    	// create a list of items to remove
    	List<DataObject> listToRemove = new ArrayList<DataObject>();
    	for(Iterator<DataObject> i = existingList.iterator(); i.hasNext();) {
    		listToRemove.add(i.next());	
    	}
    	
    	int sizeListToRemove = listToRemove.size();

    	// remove entire list
    	existingList.removeAll(listToRemove);
    	assertEquals(sequenceSizeBefore - sizeListToRemove, aSequence.size());
    	assertEquals(listSizeBefore - sizeListToRemove, existingList.size());
    	
    	// are we removed on the DataObject?
    	//DataObject item1ObjectFromAfterRemove = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
    	// TODO: verify delete or dont delete after a sequence.remove
    	//assertTrue(item1ObjectFromAfterRemove == itemDO1);   
    	//assertFalse(item1ObjectFromAfterRemove == itemDO2);   
    }

    public void testRemoveAllComplexManyViaListWrapper() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, "/", 5);
        int sequenceSizeBefore = aSequence.size();
        DataObject itemDO1 = (DataObject)root.get("item[1]");
        // after removal the items list indexes on the dataObject will shift down, get item[2] for later comparison
        DataObject itemDO2 = (DataObject)root.get("item[2]");
        assertNotNull(itemDO1);
        assertNotNull(itemDO2);
        assertFalse(itemDO1 == itemDO2);
    	
    	//DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	ListWrapper existingList = (ListWrapper)root.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(3, listSizeBefore);
        
    	// get item from sequence
    	int item2SequenceIndex = getNthSequenceIndexFor(aSequence, "item", 2);
    	assertTrue(item2SequenceIndex > -1);
    	DataObject itemObjectFromSetting = (DataObject)aSequence.getValue(item2SequenceIndex);
    	assertNotNull(itemObjectFromSetting);
    	assertTrue(itemObjectFromSetting == itemDO2);
    	
    	// create a list of items to remove
    	List<DataObject> listToRemove = new ArrayList<DataObject>();
    	for(Iterator<DataObject> i = existingList.iterator(); i.hasNext();) {
    		listToRemove.add(i.next());	
    	}
    	
    	int sizeListToRemove = listToRemove.size();

    	// remove entire list
    	existingList.removeAll(listToRemove);
    	assertEquals(sequenceSizeBefore - sizeListToRemove, aSequence.size());
    	assertEquals(listSizeBefore - sizeListToRemove, existingList.size());
    	
    	// are we removed on the DataObject?
    	//DataObject item1ObjectFromAfterRemove = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
    	// TODO: verify delete or dont delete after a sequence.remove
    	//assertTrue(item1ObjectFromAfterRemove == itemDO1);   
    	//assertFalse(item1ObjectFromAfterRemove == itemDO2);
    	assertEquals(0, existingList.size());
    }
    
    public void testRemoveComplexManyReferenceViaListWrapperIndex() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        int sequenceSizeBefore = aSequence.size();
        DataObject itemDO1 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
        // after removal the items list indexes on the dataObject will shift down, get item[2] for later comparison
        DataObject itemDO2 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[2]");
        assertNotNull(itemDO1);
        assertNotNull(itemDO2);
        assertFalse(itemDO1 == itemDO2);
    	
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
        
    	// get item from sequence
    	int item2SequenceIndex = getNthSequenceIndexFor(aSequence, "item", 2);
    	assertTrue(item2SequenceIndex > -1);
    	DataObject itemObjectFromSetting = (DataObject)aSequence.getValue(item2SequenceIndex);
    	assertNotNull(itemObjectFromSetting);
    	assertTrue(itemObjectFromSetting == itemDO2);
    	
    	// delete po[1]/item[2] from setting
    	existingList.remove(1);
    	assertEquals(sequenceSizeBefore - 1, aSequence.size());
    	
    	// are we removed on the DataObject?
    	DataObject item1ObjectFromAfterRemove = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
    	// TODO: verify delete or dont delete after a sequence.remove
    	assertTrue(item1ObjectFromAfterRemove == itemDO1);   
    	assertFalse(item1ObjectFromAfterRemove == itemDO2);   
    }

    public void testRemoveComplexManyReferenceViaListWrapperReference() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        int sequenceSizeBefore = aSequence.size();
        DataObject itemDO1 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
        // after removal the items list indexes on the dataObject will shift down, get item[2] for later comparison
        DataObject itemDO2 = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[2]");
        assertNotNull(itemDO1);
        assertNotNull(itemDO2);
        assertFalse(itemDO1 == itemDO2);
    	
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
        
    	// get item from sequence
    	int item2SequenceIndex = getNthSequenceIndexFor(aSequence, "item", 2);
    	assertTrue(item2SequenceIndex > -1);
    	DataObject itemObjectFromSetting = (DataObject)aSequence.getValue(item2SequenceIndex);
    	assertNotNull(itemObjectFromSetting);
    	assertTrue(itemObjectFromSetting == itemDO2);
    	
    	// delete po[1]/item[2] from setting
    	existingList.remove(itemDO2);
    	assertEquals(sequenceSizeBefore - 1, aSequence.size());
    	
    	// are we removed on the DataObject?
    	DataObject item1ObjectFromAfterRemove = (DataObject)root.get(PO_SEQUENCE_PATH + "/item[1]");
    	// TODO: verify delete or dont delete after a sequence.remove
    	assertTrue(item1ObjectFromAfterRemove == itemDO1);   
    	assertFalse(item1ObjectFromAfterRemove == itemDO2);   
    }

    public void testRemoveComplexManyViaListWrapperReference() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, "/", 5);
        int sequenceSizeBefore = aSequence.size();
        DataObject itemDO1 = (DataObject)root.get("item[1]");
        // after removal the items list indexes on the dataObject will shift down, get item[2] for later comparison
        DataObject itemDO2 = (DataObject)root.get("item[2]");
        assertNotNull(itemDO1);
        assertNotNull(itemDO2);
        assertFalse(itemDO1 == itemDO2);
    	
    	ListWrapper existingList = (ListWrapper)root.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(3, listSizeBefore);
        
    	// get item from sequence
    	int item2SequenceIndex = getNthSequenceIndexFor(aSequence, "item", 2);
    	assertTrue(item2SequenceIndex > -1);
    	DataObject itemObjectFromSetting = (DataObject)aSequence.getValue(item2SequenceIndex);
    	assertNotNull(itemObjectFromSetting);
    	assertTrue(itemObjectFromSetting == itemDO2);
    	
    	// delete po[1]/item[2] from setting
    	existingList.remove(itemDO2);
    	assertEquals(sequenceSizeBefore - 1, aSequence.size());
    	
    	// are we removed on the DataObject?
    	DataObject item1ObjectFromAfterRemove = (DataObject)root.get("item[1]");
    	// TODO: verify delete or dont delete after a sequence.remove
    	assertTrue(item1ObjectFromAfterRemove == itemDO1);   
    	assertFalse(item1ObjectFromAfterRemove == itemDO2);   
    }

    
    /**
     * Test operations involving deep complex types that contain complex children
     *
     */
    public void testRemoveNullComplexManyWithComplexChildrenViaListWrapperReference() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, "/", 5);
        int sequenceSizeBefore = aSequence.size();
    	ListWrapper existingList = (ListWrapper)root.get("porder");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(1, listSizeBefore);
    	existingList.remove(null);
    	assertEquals(sequenceSizeBefore, aSequence.size());
    }

    public void testRemoveComplexManyWithComplexChildreViaListWrapperReference() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, "/", 5);
        int sequenceSizeBefore = aSequence.size();
        DataObject po1 = (DataObject)root.get("porder[1]");        
        assertNotNull(po1);
    	
    	ListWrapper existingList = (ListWrapper)root.get("porder");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(1, listSizeBefore);

    	existingList.remove(po1);
    	assertEquals(sequenceSizeBefore - 1, aSequence.size());
    	
    	// are we removed on the DataObject?
    	ListWrapper existingList2 = (ListWrapper)root.get("porder");  // same instance of existingList
    	int listSizeAfter = existingList2.size();
    	assertEquals(0, listSizeAfter);
    }
    
//     remove via dataobject (same as detach)
    public void testUnsetSimpleSingleByIndex() {
    	
    }
    public void testUnsetSimpleManyByIndex() {
    	
    }
    public void testUnsetComplexSingleByIndex() {
    	
    }
    public void testUnsetComplexManyByIndex() {
    	
    }

    public void testDeleteSimpleSingleByProperty() {
    	
    }
    public void testDeleteSimpleManyByProperty() {
    	
    }
    public void testDeleteComplexSingleByProperty() {
    	
    }
    public void testDeleteComplexManyByProperty() {
    	
    }

    public void testDetachSimpleSingleByProperty() {
    	
    }
    public void testDetachSimpleManyByProperty() {
    	
    }
    public void testDetachComplexSingleByProperty() {
    	
    }
    public void testDetachComplexManyByProperty() {
    	
    }

//     add via sequence

//     add via dataobject
    public void testAddSimpleSingleByDataObjectSetProperty() {
    	
    }
    public void testAddSimpleManyByDataObjectSetPropertyWithListOnEmptyList() {
    	
    }
    public void testAddSimpleManyByDataObjectSetPropertyWithListOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("comment")).size();
    	assertEquals(PO_COMMENT_LIST_SIZE, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	
    	Property commentProperty = po.getInstanceProperty("comment");
    	
    	// add list of items to sequence
    	List<String> aListToAdd = new ArrayList<String>();
    	aListToAdd.add("comment 2");
    	aListToAdd.add("comment 3");
    	aSequence.add(indexToPlaceAtEnd, commentProperty, aListToAdd);

    	// get back new Setting value
    	String comment2Value = (String)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(comment2Value);
    	assertEquals(comment2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence for simple type
    	assertEquals(PO_SEQUENCE_TREE_SIZE + aListToAdd.size(), aSequence.size());
    	
    	// verify that the list has increased
    	int listSizeAfter = ((ListWrapper)po.get("comment")).size();
    	assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);
    	
    	// verify that DataObject has changed but not the # of dataObjects
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + 0, treeSizeAfterAdd);
    }

    public void testAddComplexSingleByDataObjectSetProperty() {
    }
    public void testAddComplexManyByDataObjectSetPropertyWithListOnEmptyList() {
    	
    }
    
    public void testAddComplexManyByDataObjectSetPropertyWithListOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[1]");
    	assertNotNull(item3);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add list of items to sequence
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	aListToAdd.add(item3);
    	aSequence.add(indexToPlaceAtEnd, itemProperty, aListToAdd);

    	// get back new Setting value
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(item2Value);
    	assertEquals(item2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());
    	
    	// verify that the list has increased
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + 1, treeSizeAfterAdd);
    }
    
    public void testAddComplexManyByDataObjectSetPropertyWithSingleItemOnEmptyList() {
    }
    
    public void testAddComplexManyByDataObjectSetPropertyWithSingleItemOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[3]");
    	assertNotNull(item3);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add to sequence
    	aSequence.add(indexToPlaceAtEnd, itemProperty, item3);
    	// get back new Setting value
    	//ListWrapper item2Value = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(item2Value);
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());
    	
    	// verify that the list has increased
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + 1, listSizeAfter);
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + 1, treeSizeAfterAdd);
    }

//  add via ListWrapper
    public void testAddSimpleSingleByListWrapperAddProperty() {
    	
    }
    public void testAddSimpleManyByListWrapperAddProperty() {
    	
    }
    public void testAddComplexSingleByListWrapperAddProperty() {
    	
    }
    public void testAddComplexManyByListWrapperAddPropertyOnEmptyList() {
    	
    }

    public void testAddComplexManyByListWrapperAddPropertyOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[1]");
    	assertNotNull(item3);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add list of items to existing list
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	aListToAdd.add(item3);
    	aListToAdd.add(item3);
    	for(Iterator i = aListToAdd.iterator(); i.hasNext();) {
    		// add to the end of the list
    		existingList.add(i.next());
    	}

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);

    	// verify that the sequence size has increased
    	assertEquals(indexToPlaceAtEnd + aListToAdd.size(), aSequence.size());
    	
    	// get back new Setting value
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd + aListToAdd.size() - 1);
    	assertNotNull(item2Value);
    	assertEquals(item2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + aListToAdd.size(), aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + aListToAdd.size(), treeSizeAfterAdd);
    }

    public void testAddComplexManyByListWrapperAddAllPropertyOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[1]");
    	assertNotNull(item3);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add list of items to existing list
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	aListToAdd.add(item3);
    	aListToAdd.add(item3);
    	// add to the end of the list
    	existingList.addAll(aListToAdd);

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);

    	// verify that the sequence size has increased
    	assertEquals(indexToPlaceAtEnd + aListToAdd.size(), aSequence.size());
    	
    	// get back new Setting value
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd + aListToAdd.size() - 1);
    	assertNotNull(item2Value);
    	assertEquals(item2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + aListToAdd.size(), aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + aListToAdd.size(), treeSizeAfterAdd);
    }
    
    public void testAddAllComplexManyNonContainmentByListWrapperAddAllPropertyOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[3]");
    	assertNotNull(item3);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add list of items to existing list
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	aListToAdd.add(item3);
    	// add to the end of the list
    	existingList.addAll(aListToAdd);

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);

    	// verify that the sequence size has increased
    	assertEquals(indexToPlaceAtEnd + aListToAdd.size(), aSequence.size());
    	
    	// get back new Setting value
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd + aListToAdd.size() - 1);
    	assertNotNull(item2Value);
    	assertEquals(item2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + aListToAdd.size(), aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + aListToAdd.size(), treeSizeAfterAdd);
    }
/*
    public void testRemove1StOccurrenceComplexManyNonContainmentByListWrapperAddAllPropertyOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[3]");
    	assertNotNull(item3);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add list of items to existing list
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	aListToAdd.add(item3);
    	// add to the end of the list
    	existingList.addAll(aListToAdd);

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);

    	// verify that the sequence size has increased
    	assertEquals(indexToPlaceAtEnd + aListToAdd.size(), aSequence.size());
    	
    	// get back new Setting value
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd + aListToAdd.size() - 1);
    	assertNotNull(item2Value);
    	assertEquals(item2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + aListToAdd.size(), aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + aListToAdd.size(), treeSizeAfterAdd);
    	
    	// get sequence object that will be removed
    	SDOSetting aSetting5 = (SDOSetting)aSequence.getSettings().get(5);
    	SDOSetting aSetting6 = (SDOSetting)aSequence.getSettings().get(6);
    	// remove the first occurrence of the duplicated items in the sequence 
    	existingList.remove(1);
    	
    	// check size
    	assertEquals(indexToPlaceAtEnd, aSequence.size());
    	
    	// verify that the correct index in the sequence was removed based on the listWrapper index
    	//assertEquals(aSetting6, aSequence.getSettings().get(5)); // 6 shifted into 5's place
    	//assertFalse(aSetting5 == aSequence.getSettings().get(5)); // 5 is gone
    	assertTrue(aSetting5 == aSequence.getSettings().get(5)); // 5 is still there    	
    }

    public void testRemove2ndOccurrenceComplexManyNonContainmentByListWrapperAddAllPropertyOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[3]");
    	assertNotNull(item3);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add list of items to existing list
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	aListToAdd.add(item3);
    	// add to the end of the list
    	existingList.addAll(aListToAdd);

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);

    	// verify that the sequence size has increased
    	assertEquals(indexToPlaceAtEnd + aListToAdd.size(), aSequence.size());
    	
    	// get back new Setting value
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd + aListToAdd.size() - 1);
    	assertNotNull(item2Value);
    	assertEquals(item2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + aListToAdd.size(), aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + aListToAdd.size(), treeSizeAfterAdd);
    	
    	// get sequence object that will be removed
    	SDOSetting aSetting5 = (SDOSetting)aSequence.getSettings().get(5);
    	SDOSetting aSetting6 = (SDOSetting)aSequence.getSettings().get(6);
    	// remove the first occurrence of the duplicated items in the sequence 
    	existingList.remove(2);
    	
    	// check size
    	assertEquals(indexToPlaceAtEnd, aSequence.size());
    	
    	// verify that the correct index in the sequence was removed based on the listWrapper index
    	assertEquals(aSetting5, aSequence.getSettings().get(5)); // 6 shifted into 5's place
    	assertFalse(aSetting6 == aSequence.getSettings().get(5)); // 5 is gone
    }*/

    // TODO: Verify that existing duplicates will be removed before the new list is added - addAll same as set
    public void testAddAllDuplicatesComplexManyByListWrapperAddAllPropertyOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, "/", 5);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(root).size();
    	assertEquals(10, treeSizeBeforeAdd);
    	assertEquals(5, aSequence.size());

    	ListWrapper existingList = (ListWrapper)root.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(3, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[3]");
    	assertNotNull(item3);
    	
    	Property itemProperty = root.getInstanceProperty("item");
    	
    	// add list of items to existing list
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	aListToAdd.add(item3);
    	aListToAdd.add(item3);
    	aListToAdd.add(item3);
    	// add to the end of the list
    	existingList.addAll(aListToAdd);

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)root.get("item")).size();

    	
    	// TODO: We should not be removing the existing item?
    	int newItems = aListToAdd.size() - 3;
    	//assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);
    	assertEquals(listSizeBefore + newItems, listSizeAfter);

    	// verify that the sequence size has increased
    	assertEquals(indexToPlaceAtEnd + newItems, aSequence.size());
    	
    	// get back new Setting value
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd + newItems - 1);
    	assertNotNull(item2Value);
    	assertEquals(item2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd - 1));
    	// check increased size of sequence
    	assertEquals(indexToPlaceAtEnd + newItems, aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(root).size();
    	assertEquals(treeSizeBeforeAdd + newItems, treeSizeAfterAdd);
  	
    }
/*
    // TODO: Verify that existing duplicates will be removed before the new list is added - addAll same as set
    public void testRemove2ndOccurrenceSimpleManyByListWrapperAddAllPropertyOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("comment");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(PO_COMMENT_LIST_SIZE, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	Property commentProperty = po.getInstanceProperty("comment");
    	
    	// add list of items to existing list
    	List<String> aListToAdd = new ArrayList<String>();
    	aListToAdd.add(PO_COMMENT_VALUE1);
    	aListToAdd.add(PO_COMMENT_VALUE1);
    	aListToAdd.add(PO_COMMENT_VALUE1);
    	// add to the end of the list
    	existingList.addAll(aListToAdd);

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)po.get("comment")).size();
    	
    	// TODO: We should not be removing the existing item?
    	int newItems = aListToAdd.size();
    	//assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);
    	assertEquals(listSizeBefore + newItems, listSizeAfter);

    	// verify that the sequence size has increased
    	assertEquals(indexToPlaceAtEnd + newItems, aSequence.size());
    	
    	// get back new Setting value
    	String comment2Value = (String)aSequence.getValue(indexToPlaceAtEnd + newItems - 1);
    	assertNotNull(comment2Value);
    	assertEquals(comment2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd - 1));
    	// check increased size of sequence
    	assertEquals(indexToPlaceAtEnd + newItems, aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	// but dataObject node list is the same
    	assertEquals(treeSizeBeforeAdd, treeSizeAfterAdd);
    	
    	// get sequence object that will be removed
    	SDOSetting aSetting7 = (SDOSetting)aSequence.getSettings().get(7);
    	SDOSetting aSetting8 = (SDOSetting)aSequence.getSettings().get(8);
    	SDOSetting aSetting9 = (SDOSetting)aSequence.getSettings().get(9);
    	// remove the first occurrence of the duplicated items in the sequence 
    	int aSequenceSizeBeforeRemove = aSequence.size();
    	existingList.remove(2);
    	
    	// check size
    	assertEquals(aSequenceSizeBeforeRemove - 1, aSequence.size());
    	
    	// verify that the correct index in the sequence was removed based on the listWrapper index
    	assertEquals(aSetting8, aSequence.getSettings().get(7)); // 6 shifted into 5's place
    	assertEquals(aSetting9, aSequence.getSettings().get(8)); // 6 shifted into 5's place
    	assertFalse(aSetting7 == aSequence.getSettings().get(7)); // 5 is gone
    	assertFalse(aSetting7 == aSequence.getSettings().get(8)); // 5 is gone
    	//assertFalse(aSetting7 == aSequence.getSettings().get(9)); // 5 is gone
    }
        */
    // TODO: Verify that existing duplicates will be removed before the new list is added - addAll same as set
    public void testRemoveLastOccurrenceComplexManyByListWrapperAddAllPropertyOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, "/", 5);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(root).size();
    	assertEquals(10, treeSizeBeforeAdd);
    	assertEquals(5, aSequence.size());

    	ListWrapper existingList = (ListWrapper)root.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(3, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[3]");
    	assertNotNull(item3);
    	
    	Property itemProperty = root.getInstanceProperty("item");
    	
    	// add list of items to existing list
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	aListToAdd.add(item3);
    	aListToAdd.add(item3);
    	aListToAdd.add(item3);
    	// add to the end of the list
    	existingList.addAll(aListToAdd);

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)root.get("item")).size();

    	
    	// TODO: We should not be removing the existing item
    	int newItems = aListToAdd.size() - 3;
    	//assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);
    	assertEquals(listSizeBefore + newItems, listSizeAfter);

    	// verify that the sequence size has increased by 1
    	assertEquals(indexToPlaceAtEnd + newItems, aSequence.size());
    	
    	// get back new Setting value
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd + newItems - 1);
    	assertNotNull(item2Value);
    	assertEquals(item2Value, aListToAdd.get(0));
    	// the following is no longer valid after we refactored addAll(do list) to not add duplicates
/*    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(indexToPlaceAtEnd + newItems, aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(root).size();
    	assertEquals(treeSizeBeforeAdd + newItems, treeSizeAfterAdd);
    	
    	// get sequence object that will be removed
    	SDOSetting aSetting4 = (SDOSetting)aSequence.getSettings().get(4);
    	SDOSetting aSetting5 = (SDOSetting)aSequence.getSettings().get(5);
    	SDOSetting aSetting6 = (SDOSetting)aSequence.getSettings().get(6);
    	// remove the first occurrence of the duplicated items in the sequence 
    	int aSequenceSizeBeforeRemove = aSequence.size();
    	existingList.remove(existingList.size() - 1);
    	
    	// check size
    	assertEquals(aSequenceSizeBeforeRemove -1, aSequence.size());
    	
    	// verify that the correct index in the sequence was removed based on the listWrapper index
    	assertEquals(aSetting4, aSequence.getSettings().get(4)); 
    	assertEquals(aSetting5, aSequence.getSettings().get(5)); 
    	assertFalse(aSetting6 == aSequence.getSettings().get(5)); 
*/    }

    // Purpose is to verify that a remove(item) for duplicates removes the first occurrence of that item.
    /*
    public void testRemove1stOccurrenceSimpleManyByListWrapperAddAllPropertyOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("comment");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(PO_COMMENT_LIST_SIZE, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	Property commentProperty = po.getInstanceProperty("comment");
    	
    	// add list of items to existing list
    	List<String> aListToAdd = new ArrayList<String>();
    	aListToAdd.add(PO_COMMENT_VALUE1);
    	aListToAdd.add(PO_COMMENT_VALUE1);
    	aListToAdd.add(PO_COMMENT_VALUE1);
    	// add to the end of the list
    	existingList.addAll(aListToAdd);

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)po.get("comment")).size();
    	
    	// TODO: We should not be removing the existing item?
    	int newItems = aListToAdd.size();
    	//assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);
    	assertEquals(listSizeBefore + newItems, listSizeAfter);

    	// verify that the sequence size has increased
    	assertEquals(indexToPlaceAtEnd + newItems, aSequence.size());
    	
    	// get back new Setting value
    	String comment2Value = (String)aSequence.getValue(indexToPlaceAtEnd + newItems - 1);
    	assertNotNull(comment2Value);
    	assertEquals(comment2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd - 1));
    	// check increased size of sequence
    	assertEquals(indexToPlaceAtEnd + newItems, aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	// but dataObject node list is the same
    	assertEquals(treeSizeBeforeAdd, treeSizeAfterAdd);
    	
    	// get sequence object that will be removed
    	SDOSetting aSetting7 = (SDOSetting)aSequence.getSettings().get(7);
    	SDOSetting aSetting8 = (SDOSetting)aSequence.getSettings().get(8);
    	SDOSetting aSetting9 = (SDOSetting)aSequence.getSettings().get(9);
    	// remove the first occurrence of the duplicated items in the sequence 
    	int aSequenceSizeBeforeRemove = aSequence.size();
    	existingList.remove("comment 1");
    	
    	// check size
    	assertEquals(aSequenceSizeBeforeRemove - 1, aSequence.size());
    	
    	// verify that the correct index in the sequence was removed based on the listWrapper index
    	assertEquals(aSetting8, aSequence.getSettings().get(7)); // 6 shifted into 5's place
    	assertEquals(aSetting9, aSequence.getSettings().get(8)); // 6 shifted into 5's place
    	assertFalse(aSetting7 == aSequence.getSettings().get(7)); // 5 is gone
    	assertFalse(aSetting7 == aSequence.getSettings().get(8)); // 5 is gone
    	//assertFalse(aSetting7 == aSequence.getSettings().get(9)); // 5 is gone
    }
    */
    public void testAddAllComplexManyByListWrapperAddAllPropertyOnExistingList() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, "/", 5);
    	//DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(root).size();
    	assertEquals(10, treeSizeBeforeAdd);
    	assertEquals(5, aSequence.size());

    	ListWrapper existingList = (ListWrapper)root.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(3, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[1]");
    	assertNotNull(item3);
    	
    	Property itemProperty = root.getInstanceProperty("item");
    	
    	// add list of items to existing list
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	
		DataObject item4 = dataFactory.create(typeHelper.getType(URINAME, ITEM_TYPENAME));
		item4.set("itemID", 4);
		item4.set("name", "item4-DF");    		
		DataObject item5 = dataFactory.create(typeHelper.getType(URINAME, ITEM_TYPENAME));
		item5.set("itemID", 5);
		item5.set("name", "item5-DF");    		
    	aListToAdd.add(item4);
    	aListToAdd.add(item5);
    	// add to the end of the list
    	existingList.addAll(aListToAdd);

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)root.get("item")).size();
    	assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);

    	// verify that the sequence size has increased
    	assertEquals(indexToPlaceAtEnd + aListToAdd.size(), aSequence.size());
    	
    	// get back new Setting value
    	for(int i=0; i< aListToAdd.size(); i++) {
    		SDODataObject itemValue = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd + i);    		
    		assertNotNull(itemValue);
    		assertEquals(itemValue, aListToAdd.get(i));
    		assertNotNull(aSequence.getProperty(indexToPlaceAtEnd + i));
    	}
    	// check increased size of sequence
    	assertEquals(5 + aListToAdd.size(), aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(root).size();
    	assertEquals(treeSizeBeforeAdd + aListToAdd.size(), treeSizeAfterAdd);
    }
    
    /**
     * Adds a new entry with the specified property name and value
     * at the specified entry index.
     * @param index the index at which to add the entry.
     * @param propertyName the name of the entry's property.
     * @param value the value for the entry.
     * TODO: single and many versions required
     */
    public void test_voidReturnFrom_add_int_String_Object() {
    	// int index, String propertyName, Object value) {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item2 = (DataObject)root.get("item[2]");
    	assertNotNull(item2);
    	// add to sequence
    	aSequence.add(indexToPlaceAtEnd, "item", item2);
    	// get back new Setting value
    	//ListWrapper item2Value = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd);    	
    	assertNotNull(item2Value);
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());
    	
    	// verify that the list has increased
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + 1, listSizeAfter);
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + 1, treeSizeAfterAdd);
    }

    /**
     * Adds a new entry with the specified property index and value
     * at the specified entry index.
     * @param index the index at which to add the entry.
     * @param propertyIndex the index of the entry's property.
     * @param value the value for the entry.
     * TODO: single and many versions required
     */
    public void test_voidReturnFrom_add_int_int_Object() {
    	// int index, int propertyIndex, Object value) {
    	// int index, String propertyName, Object value) {
    	defineAndLoadRoot(false, false);
    	// detach shipTo
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item2 = (DataObject)root.get("item[2]");
    	assertNotNull(item2);
    	
    	// get "item" property index
    	int propIndex = 0;
    	for(Iterator i=po.getInstanceProperties().iterator(); i.hasNext();) {
    		Property aProperty = (Property)i.next();
    		if(aProperty != null && aProperty.getName().equals("item")) {
    			break;
    		} else {
    			propIndex++;
    		}
    	}
    	// add to sequence
    	aSequence.add(indexToPlaceAtEnd, propIndex, item2);
    	// get back new Setting value
    	//ListWrapper item2Value = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(item2Value);
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());
    	
    	// verify that the list has increased
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + 1, listSizeAfter);
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + 1, treeSizeAfterAdd);
    }

    /**
     * Adds a new entry with the specified property and value
     * at the specified entry index.
     * @param index the index at which to add the entry.
     * @param property the property of the entry.
     * @param value the value for the entry.
     */
    public void test_voidReturnFrom_add_int_Property_Object() {
    	// int index, Property property, Object value) {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item2 = (DataObject)root.get("item[2]");
    	assertNotNull(item2);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add to sequence
    	aSequence.add(indexToPlaceAtEnd, itemProperty, item2);
    	// get back new Setting value
    	//ListWrapper item2Value = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(item2Value);
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());
    	
    	// verify that the list has increased
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + 1, listSizeAfter);
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + 1, treeSizeAfterAdd);
    }

    public void test_voidReturnFrom_add_int_Property_Object_outofbounds() {
    	// int index, Property property, Object value) {
    	defineAndLoadRoot(false, false);
    	// detach shipTo
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item2 = (DataObject)root.get("item[2]");
    	assertNotNull(item2);
    	
    	Property itemProperty = po.getInstanceProperty("item");
    	
    	// add to sequence
    	try {
    		aSequence.add(-1, itemProperty, item2);
    	} catch (Exception e) {
    		
    	}
    	
      boolean exceptionThrown =false;
    	// get back new Setting value
    	ListWrapper item2Value = null;    	
    	try {
    		item2Value = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	} catch (SDOException e) {
    		assertEquals(SDOException.INVALID_INDEX ,e.getErrorCode());
        exceptionThrown = true;
    	}
    	assertNull(item2Value);    	
      assertTrue(exceptionThrown);
    	
/*    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence didnt happen
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());
    	
    	// verify that the list has not increased
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore, listSizeAfter);
    	
    	// verify that DataObject has not changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd, treeSizeAfterAdd);
*/    }

    public void test_voidReturnFrom_add_int_Property_Object_propertyIsAttribute() {
    	// int index, Property property, Object value) {
    	defineAndLoadRoot(false, false);
    	// detach shipTo
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size();
    	// object to add
    	DataObject item2 = (DataObject)root.get("item[2]");
    	assertNotNull(item2);
    	
    	Property orderDateProperty = po.getInstanceProperty("orderDate");
    	
    	// add to sequence
    	try {
    		aSequence.add(indexToPlaceAtEnd, orderDateProperty, "1999-10-19");
    	} catch (Exception e) {
    		
    	}
    	
    	// get back new Setting value
    	ListWrapper item2Value = null;
    	
    	try {
    		item2Value = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	} catch (SDOException e) {
    		assertEquals(SDOException.INVALID_INDEX ,e.getErrorCode());
    	}
    	assertNull(item2Value);    	
   }
    
    
    /**
     * Removes the entry at the given entry index.
     * @param index the index of the entry.
     */
    public void test_voidReturnFrom_remove_int() {
    	// int index) {
    }

    /**
     * Moves the entry at <code>fromIndex</code> to <code>toIndex</code>.
     * @param toIndex the index of the entry destination.
     * @param fromIndex the index of the entry to move.
     */
    public void test_voidReturnFrom_move_int_int() {
    	// int toIndex, int fromIndex) {
    }

    /**
    * @deprecated replaced by {@link #addText(String)} in 2.1.0
    */
    public void test_voidReturnFrom_add_String() {
    	// String text) {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	int textIndexToPlaceAtEnd = aSequence.size();

    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	
    	aSequence.add("random text");
    	Object addText = aSequence.getValue(textIndexToPlaceAtEnd);
    	assertNotNull(addText);
    	assertNull(aSequence.getProperty(textIndexToPlaceAtEnd));
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());

    	// verify that DataObject has not changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd, treeSizeAfterAdd);
    }

    /**
     * @deprecated replaced by {@link #addText(int, String)} in 2.1.0
     */
    public void test_voidReturnFrom_add_int_String() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	int textIndexToPlaceAtEnd = aSequence.size();
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	
    	aSequence.add(textIndexToPlaceAtEnd, "random text");
    	Object addText = aSequence.getValue(textIndexToPlaceAtEnd);
    	assertNotNull(addText);
    	assertNull(aSequence.getProperty(textIndexToPlaceAtEnd));
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());
    	
    	// verify that DataObject has not changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd, treeSizeAfterAdd);
    }

    /**
     * Adds a new text entry to the end of the Sequence.
     * @param text value of the entry.
     */
    public void test_voidReturnFrom_addText_String() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	int textIndexToPlaceAtEnd = aSequence.size();
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	
    	aSequence.addText("random text");
    	Object addText = aSequence.getValue(textIndexToPlaceAtEnd);
    	assertNotNull(addText);
    	assertNull(aSequence.getProperty(textIndexToPlaceAtEnd));
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());

    	// verify that DataObject has not changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd, treeSizeAfterAdd);
    }

    /**
     * Adds a new text entry at the given index.
     * @param index the index at which to add the entry.
     * @param text value of the entry.
     */
    public void test_voidReturnFromAddText_int_String() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	int textIndexToPlaceAtEnd = aSequence.size();
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	
    	aSequence.addText(textIndexToPlaceAtEnd, "random text");
    	Object addText = aSequence.getValue(textIndexToPlaceAtEnd);
    	assertNotNull(addText);
    	assertNull(aSequence.getProperty(textIndexToPlaceAtEnd));
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());
    	
    	// verify that DataObject has not changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd, treeSizeAfterAdd);
    }

    /**
     * Sets the entry at a specified index to the new value.
     * @param index the index of the entry.
     * @param value the new value for the entry.
     */
    public void test_addAll_complexMany() {
    	// int index, Object value) {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	ListWrapper existingList = (ListWrapper)po.get("item");    	
    	int listSizeBefore = existingList.size();
    	assertEquals(2, listSizeBefore);
    	
    	int sequenceSizeBefore = aSequence.size();
    	int indexToPlaceAtEnd = aSequence.size() - 1;
    	// object to replace
    	DataObject item2 = (DataObject)root.get("item[2]");
    	assertNotNull(item2);
    	
    	// object to add
    	DataObject item3 = (DataObject)root.get("item[1]");
    	assertNotNull(item3);
   	
    	// add to sequence
    	
    	// TODO: TEST setting a many property using an item instead of a List of items
    	    	
    	// add the item to the current list
    	// add list of items to existing list
    	List<DataObject> aListToAdd = new ArrayList<DataObject>();
    	aListToAdd.add(item3);
    	// add to the end of the list
    	existingList.addAll(aListToAdd);

    	// verify that the list has increased on the do
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + aListToAdd.size(), listSizeAfter);

    	// verify that the sequence size has increased
    	assertEquals(sequenceSizeBefore + aListToAdd.size(), aSequence.size());
    	
    	// get back new Setting value
    	SDODataObject item2Value = (SDODataObject)aSequence.getValue(aSequence.size() -1);
    	assertNotNull(item2Value);
    	assertEquals(item2Value, aListToAdd.get(0));
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check increased size of sequence
    	assertEquals(PO_SEQUENCE_TREE_SIZE + 1, aSequence.size());
    	
    	// verify that DataObject has changed
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + 1, treeSizeAfterAdd);
    }

    public void test_setValue_singleComplex() {
    	
    }
    public void test_setValue_manySimple() {
    	
    }
    public void test_setValue_manyComplex() {
    	
    }

    public void test_setValue_manyComplex_toNull_ThrowsUnsupportedOperationException() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	int indexToPlaceAtEnd = aSequence.size() - 1;
        boolean exceptionOccurred = false;
        // null value on non-nillable many property will throw exception
        try {
            aSequence.setValue(indexToPlaceAtEnd, null);
        } catch (UnsupportedOperationException iex) {
            exceptionOccurred = true;
        }
        assertTrue("An UnsupportedOperationException did not occur as expected", exceptionOccurred);
    }

    public void test_setValue_manyComplex_invalidIndexThrowsException() {
    	// int index, String propertyName, Object value) {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size() - 1;
    	// object to replace
    	DataObject item2 = (DataObject)root.get("item[2]");
    	
    	assertNotNull(item2);
/*   	
    	// add the item to the current list
    	ListWrapper existingList = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(existingList);
    	existingList.add(item2);

    	boolean exceptionThrown = false;
    	try {
    		aSequence.setValue(indexToPlaceAtEnd + 1, existingList);
    	} catch (IndexOutOfBoundsException e) {
    		exceptionThrown = true;
    	} finally {
        	assertTrue(exceptionThrown);
    	}
    	
    	// get back modified Setting value
    	ListWrapper item2Value = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(item2Value);
    	assertNotNull(aSequence.getProperty(indexToPlaceAtEnd));
    	// check no increase in size of sequence
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());
    	
    	// verify that the list has increased
    	int listSizeAfter = ((ListWrapper)po.get("item")).size();
    	assertEquals(listSizeBefore + 1, listSizeAfter);
    	
    	// verify that DataObject has changed in size
    	int treeSizeAfterAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(treeSizeBeforeAdd + 1, treeSizeAfterAdd);
*/    }
    
    public void test_getValue_whereSettingIsNull() {
    	registerCustomerType(true, null);
		DataObject cust1 = (DataObject)dataFactory.create(typeHelper.getType(URINAME, CUSTOMER_TYPENAME));
		cust1.set("custID", 5);
		List emails = new ArrayList();
		emails.add("email1-DF@myCompany.com");
		emails.add("email2-DF@myCompany.com");
		cust1.set("email", emails);
		List phones = new ArrayList();
		phones.add("6135550001");
		cust1.set("phone", phones);

		// create a non-standard sequence
    	SDOSequence aSequence = new SDOSequence((SDODataObject)cust1);
    	// TODO: there is no way to get a null setting from a sequence
    }

    public void test_getValue_whereIndexIsOutOfBounds() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size() - 1;
    	// object to replace
    	DataObject item2 = (DataObject)root.get("item[2]");
    	
    	assertNotNull(item2);
/*   	
    	// add the item to the current list
    	ListWrapper existingList = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(existingList);
    	existingList.add(item2);

    	boolean exceptionThrown = false;
    	try {
    		aSequence.getValue(-1);
    	} catch (IndexOutOfBoundsException e) {
    		exceptionThrown = true;
    	} finally {
        	assertTrue(exceptionThrown);
    	}
*/    }

    /**
     * Returns the property for the given entry index.
     * Returns <code>null</code> for mixed text entries.
     * @param index the index of the entry.
     * @return the property or <code>null</code> for the given entry index.
     */
    public void test_PropertyReturnFrom_getProperty() {
    	// int index) {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size() - 1;
    	// object to replace
    	DataObject item2 = (DataObject)root.get("item[2]");
    	
    	assertNotNull(item2);
   	
/*    	// add the item to the current list
    	ListWrapper existingList = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(existingList);
    	existingList.add(item2);

    	boolean exceptionThrown = false;
    	Property property1 = po.getInstanceProperty("item"); 
    	Object property1Return = null;
    	try {
    		property1Return = aSequence.getProperty(indexToPlaceAtEnd);
    	} catch (IndexOutOfBoundsException e) {
    		exceptionThrown = true;
    	} finally {
        	assertFalse(exceptionThrown);
    	}
    	
    	// verify property
    	assertNotNull(property1Return);
    	assertEquals(property1, property1Return);
*/    }

    /**
     * Returns the property value for the given entry index.
     * @param index the index of the entry.
     * @return the value for the given entry index.
     */
    public void test_ObjectReturnFrom_getValue() {
    	// int index) {
    }
    
    public void test_getProperty_whereIndexIsOutOfBounds() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	
    	int treeSizeBeforeAdd = preOrderTraversalDataObjectList(po).size();
    	assertEquals(PO_TREE_SIZE, treeSizeBeforeAdd);
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());

    	int listSizeBefore = ((ListWrapper)po.get("item")).size();
    	assertEquals(2, listSizeBefore);
    	
    	int indexToPlaceAtEnd = aSequence.size() - 1;
    	// object to replace
    	DataObject item2 = (DataObject)root.get("item[2]");
    	
    	assertNotNull(item2);
   	
/*    	// add the item to the current list
    	ListWrapper existingList = (ListWrapper)aSequence.getValue(indexToPlaceAtEnd);
    	assertNotNull(existingList);
    	existingList.add(item2);

    	boolean exceptionThrown = false;
    	try {
    		aSequence.getProperty(-1);
    	} catch (IndexOutOfBoundsException e) {
    		exceptionThrown = true;
    	} finally {
        	assertTrue(exceptionThrown);
    	}
*/    }
    
    // get id
    public void test_getSequenceViaPropertyIndexFromSingleSimpleType() {
    	
    }

    // get comment[1]
    public void test_getSequenceViaPropertyIndexFromManySimpleType() {
    	
    }

    // get 
    public void test_getSequenceViaPropertyIndexFromSingleComplexType() {
    	
    }

    // get porder[1]
    public void test_getSequenceViaPropertyIndexFromManyComplexType() {
    	
    }

    public void testMoveSameIndex() {
    	defineAndLoadRoot(false, false);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        SDOSequence aSequence = (SDOSequence)po.getSequence();

        // move 2 sequenced objects
        Property beforeMoveProp1 = aSequence.getProperty(1);
        assertNotNull(beforeMoveProp1);
        
        aSequence.move(1, 1);
        
        Property afterMoveProp1 = aSequence.getProperty(1);
        assertTrue(beforeMoveProp1 == afterMoveProp1);
    }

  
    public void testMoveSameIndexOutOfBoundsHigh() {
    	defineAndLoadRoot(false, false);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        SDOSequence aSequence = (SDOSequence)po.getSequence();

        // move 2 sequenced objects
        Property beforeMoveProp1 = aSequence.getProperty(1);
        assertNotNull(beforeMoveProp1);
    	
        	aSequence.move(99, 99);
        
        Property afterMoveProp1 = aSequence.getProperty(1);
        // verify the move did not take place
        assertTrue(beforeMoveProp1 == afterMoveProp1);
    	
    }

    public void testMoveIndexFromOutOfBoundsHigh() {
    	defineAndLoadRoot(false, false);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        SDOSequence aSequence = (SDOSequence)po.getSequence();

        // move 2 sequenced objects
        Property beforeMoveProp1 = aSequence.getProperty(1);
        assertNotNull(beforeMoveProp1);
    	boolean exceptionThrown = false;
        try {
        	aSequence.move(99, 1);
        } catch (SDOException e) {
        assertEquals(SDOException.INVALID_INDEX ,e.getErrorCode());

        	// catch error
          exceptionThrown = true;
        }
        
        Property afterMoveProp1 = aSequence.getProperty(1);
        // verify the move did not take place
        assertTrue(beforeMoveProp1 == afterMoveProp1);
    	assertTrue(exceptionThrown);
    }
    
    public void testMoveIndexToOutOfBoundsHigh() {
    	defineAndLoadRoot(false, false);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        SDOSequence aSequence = (SDOSequence)po.getSequence();

        // move 2 sequenced objects
        Property beforeMoveProp1 = aSequence.getProperty(1);
        assertNotNull(beforeMoveProp1);
    	boolean exceptionThrown = false;
        try {
        	aSequence.move(1, 99);
        } catch (SDOException e) {
        	// catch error
          assertEquals(SDOException.INVALID_INDEX ,e.getErrorCode());
          exceptionThrown = true;
        }
        
        Property afterMoveProp1 = aSequence.getProperty(1);
        // verify the move did not take place
        assertTrue(beforeMoveProp1 == afterMoveProp1);
        assertTrue(exceptionThrown);
    }

    public void testMoveIndexBothOutOfBoundsHigh() {
    	defineAndLoadRoot(false, false);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        SDOSequence aSequence = (SDOSequence)po.getSequence();

        // move 2 sequenced objects
        Property beforeMoveProp1 = aSequence.getProperty(1);
        assertNotNull(beforeMoveProp1);
    	boolean exceptionThrown = false;
        try {
        	aSequence.move(101, 99);
        } catch (SDOException e) {
        	// catch error
          assertEquals(SDOException.INVALID_INDEX ,e.getErrorCode());
    		exceptionThrown = true;
        
        }
        
        Property afterMoveProp1 = aSequence.getProperty(1);
        // verify the move did not take place
        assertTrue(beforeMoveProp1 == afterMoveProp1);
    	assertTrue(exceptionThrown);
    }

    public void testMoveSameIndexOutOfBoundsLow() {
    	defineAndLoadRoot(false, false);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        SDOSequence aSequence = (SDOSequence)po.getSequence();

        // move 2 sequenced objects
        Property beforeMoveProp1 = aSequence.getProperty(1);
        assertNotNull(beforeMoveProp1);
        	aSequence.move(-1, -1);
        
        Property afterMoveProp1 = aSequence.getProperty(1);
        // verify the move did not take place
        assertTrue(beforeMoveProp1 == afterMoveProp1);
    	
    }

    public void testMoveIndexFromOutOfBoundsLow() {
    	defineAndLoadRoot(false, false);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        SDOSequence aSequence = (SDOSequence)po.getSequence();

        // move 2 sequenced objects
        Property beforeMoveProp1 = aSequence.getProperty(1);
        assertNotNull(beforeMoveProp1);
    	boolean exceptionThrown = false;
        try {
        	aSequence.move(-1, 1);
        } catch (SDOException e) {
        	assertEquals(SDOException.INVALID_INDEX ,e.getErrorCode());
          // catch error
    		exceptionThrown = true;
        }
        
        Property afterMoveProp1 = aSequence.getProperty(1);
        // verify the move did not take place
        assertTrue(beforeMoveProp1 == afterMoveProp1);
    	assertTrue(exceptionThrown);
    }
    
    public void testMoveIndexToOutOfBoundsLow() {
    	defineAndLoadRoot(false, false);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        SDOSequence aSequence = (SDOSequence)po.getSequence();

        // move 2 sequenced objects
        Property beforeMoveProp1 = aSequence.getProperty(1);
        assertNotNull(beforeMoveProp1);
    	boolean exceptionThrown = false;
        try {
        	aSequence.move(1, -1);
        } catch (SDOException e) {
        	// catch error
    		exceptionThrown = true;
        assertEquals(SDOException.INVALID_INDEX ,e.getErrorCode());
        }
        
        Property afterMoveProp1 = aSequence.getProperty(1);
        // verify the move did not take place
        assertTrue(beforeMoveProp1 == afterMoveProp1);
    	assertTrue(exceptionThrown);
    }

    public void testMoveIndexBothOutOfBoundsLow() {
    	defineAndLoadRoot(false, false);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        SDOSequence aSequence = (SDOSequence)po.getSequence();

        // move 2 sequenced objects
        Property beforeMoveProp1 = aSequence.getProperty(1);
        assertNotNull(beforeMoveProp1);
    	boolean exceptionThrown = false;
        try {
        	aSequence.move(-1, -2);
        } catch (SDOException e) {
        	// catch error
          assertEquals(SDOException.INVALID_INDEX ,e.getErrorCode());
          exceptionThrown = true;
        }
        
        Property afterMoveProp1 = aSequence.getProperty(1);
        // verify the move did not take place
        assertTrue(beforeMoveProp1 == afterMoveProp1);
    	assertTrue(exceptionThrown);
    }
    
    public void testMoveIndex0toEnd() {
    	defineAndLoadRoot(false, false);
    	//SDOSequence aSequence = getSequence();
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        SDOSequence aSequence = (SDOSequence)po.getSequence();

        // move 2 sequenced objects
        Property beforeMoveProp0 = aSequence.getProperty(0);
        Property beforeMoveProp1 = aSequence.getProperty(1);
        Property beforeMoveProp3 = aSequence.getProperty(3);
        assertNotNull(beforeMoveProp0);
        assertNotNull(beforeMoveProp1);
        assertNotNull(beforeMoveProp3);
        
        // 0,1,2,3 -> 1,2,3,0
        aSequence.move(3, 0);
        
        Property afterMoveProp0 = aSequence.getProperty(0);
        //Property afterMoveProp0 = aSequence.getProperty(0);
        Property afterMoveProp3 = aSequence.getProperty(3);
        assertTrue(beforeMoveProp1 == afterMoveProp0);
        assertTrue(beforeMoveProp0 == afterMoveProp3);
    }
    
    public void testMoveIndexEndto0() {
    	
    }
    public void testMoveIndexAdjacent1to2() {
    	
    }
    public void testMoveIndexAdjacent2to1() {
    	
    }

    public void testToString() {
    	// exercise the toString() method for code coverage
    	defineAndLoadRoot(false, false);
    	// get sequence po
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        SDOSequence aSequence = (SDOSequence)po.getSequence();
    	assertNotNull(aSequence);
    	// 4 instead of 5 because the one attribute property cannot be sequenced
    	assertEquals(PO_SEQUENCE_SIZE, aSequence.size());
    	String aString = aSequence.toString();
    	assertNotNull(aString);
    	// we could do some minimal string comparison
    	
    }
    
    public void testEqualDeepSameSequence() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        //compareSequences(aSequence, aSequence, PO_SEQUENCE_SIZE, true);
    	// get sequence po
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        
        // test equalityHelper
        boolean bEqual = equalityHelper.equal(po, po);
        assertTrue(bEqual);
    }

    public void testEqualShallowSameSequence() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        //compareSequences(aSequence, aSequence, PO_SEQUENCE_SIZE, true);
    	// get sequence po
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        
        // test equalityHelper
        boolean bEqual = equalityHelper.equalShallow(po, po);
        assertTrue(bEqual);
    }

    // Via a non-interface method the user is able to set sequenced=true after type definition - not supported
    public void testEqualShallowSameSequenceFlagTrueButSequenceIsNull() {
    	defineAndLoadRoot(false, false);
        SDOSequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        //compareSequences(aSequence, aSequence, PO_SEQUENCE_SIZE, true);
    	// get sequence po
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	assertNotNull(po);
        assertTrue(po.getType().isSequenced());
        
        // test equalityHelper
        boolean bEqual = equalityHelper.equalShallow(po, po);
        assertTrue(bEqual);
        
/*        
    	defineAndLoadRoot(false, false);
        Sequence aSequence = getSequence(root, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
    	DataObject po = (DataObject)root.get(PO_SEQUENCE_PATH);
    	// copy po
    	DataObject rootCopy = (DataObject)copyHelper.copy(root);    	
    	// check sequence was copied
        Sequence aSequenceCopy = getSequence(rootCopy, PO_SEQUENCE_PATH, PO_SEQUENCE_SIZE);
        assertNotNull(aSequenceCopy);
        //compareSequences((SDOSequence)aSequence, (SDOSequence)aSequenceCopy, PO_SEQUENCE_SIZE, true);
        
        // test equalityHelper
    	DataObject poCopy = (DataObject)rootCopy.get(PO_SEQUENCE_PATH);
        boolean bEqual = equalityHelper.equal(po, poCopy);
        assertTrue(bEqual);

        // modify copy sequence state - non public method - both po and poCopy will have their state changed because they share an SDOType
        assertTrue(po.getType().isSequenced());
        assertTrue(poCopy.getType().isSequenced());
        // WARNING: Users should not be doing this - however it is supported
        ((SDOType)poCopy.getType()).setSequenced(false);
        assertFalse(po.getType().isSequenced());
        assertFalse(poCopy.getType().isSequenced());        
        bEqual = equalityHelper.equal(po, poCopy);
        // sequences will not be compared
        assertTrue(bEqual);
*/    }
    
    
/*    
    // use XSD to define and XML to load - working
    public void testDefineViaXSDandLoadViaXML() throws Exception {
    	DefaultSchemaLocationResolver resolver = new DefaultSchemaLocationResolver(getMap());
       	List<Type> types = xsdHelper.define(getXSDString(XSD_PATH));
       
        String generatedSchema = ((SDOXSDHelper)xsdHelper).generate(types, resolver);
        log(generatedSchema);
        root = createRootObject(true, types);
    	int aRootsize = preOrderTraversalDataObjectList((SDODataObject)root).size();
        assertTrue(writeXML(root, URINAME, COMPANY_TYPENAME, System.out));
        //assertXMLIdentical(getDocument(getControlGeneratedFileName()), generatedSchemaDoc);    	
    }
 
    
    // use XSD to define and programmatic DataFactory to load -  not working
    public void testDefineViaXSDandLoadViaDataFactory() throws Exception {
    	DefaultSchemaLocationResolver resolver = new DefaultSchemaLocationResolver(getMap());
       	List<Type> types = xsdHelper.define(getXSDString(XSD_PATH));
        String generatedSchema = ((SDOXSDHelper)xsdHelper).generate(types, resolver);
        log(generatedSchema);
        root = createRootObject(false, types);
    	int aRootsize = preOrderTraversalDataObjectList((SDODataObject)root).size();
    	assertEquals(9, aRootsize);
        assertTrue(writeXML(root, URINAME, COMPANY_TYPENAME, System.out));
    }
*/
/*    
    // use programmatic define(DataObject) to define and XML to load - not working
    public void testDefineViaDataObjectandLoadViaXML() throws Exception {
    	DefaultSchemaLocationResolver resolver = new DefaultSchemaLocationResolver(getMap());
    	registerTypes();
    	List<Type> types = getTypesToGenerateFrom();
        String generatedSchema = ((SDOXSDHelper)xsdHelper).generate(types, resolver);
        log(generatedSchema);
        root = createRootObject(true, types);
    	int aRootsize = preOrderTraversalDataObjectList((SDODataObject)root).size();
        assertTrue(writeXML(root, URINAME, COMPANY_TYPENAME, System.out));
    }
*/
/*    
    // use programmatic define(DataObject) and programmatic DataFactory to load
    public void testDefineViaDataObjectandLoadViaDataFactory() throws Exception {
    	DefaultSchemaLocationResolver resolver = new DefaultSchemaLocationResolver(getMap());
    	registerTypes();
    	List<Type> types = getTypesToGenerateFrom();
       
        String generatedSchema = ((SDOXSDHelper)xsdHelper).generate(types, resolver);
        log(generatedSchema);
        root = createRootObject(false, types);
    	int aRootsize = preOrderTraversalDataObjectList((SDODataObject)root).size();
    	assertEquals(9, aRootsize);
        assertTrue(writeXML(root, URINAME, COMPANY_TYPENAME, System.out));
    }
*/
}
