/*******************************************************************************
 * Copyright (c) 1998, 2013 Oracle and/or its affiliates. All rights reserved.
 * This program and the accompanying materials are made available under the 
 * terms of the Eclipse Public License 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;

import commonj.sdo.ChangeSummary;
import commonj.sdo.DataObject;
import commonj.sdo.Property;
import commonj.sdo.Sequence;
import commonj.sdo.helper.CopyHelper;
import commonj.sdo.helper.DataFactory;
import commonj.sdo.helper.EqualityHelper;
import commonj.sdo.helper.HelperContext;
import commonj.sdo.helper.TypeHelper;
import commonj.sdo.helper.XMLDocument;
import commonj.sdo.helper.XMLHelper;
import commonj.sdo.helper.XSDHelper;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.persistence.sdo.SDOChangeSummary;
import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOSequence;
import org.eclipse.persistence.sdo.SDOSetting;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.sdo.ValueStore;
import org.eclipse.persistence.sdo.helper.SDOClassLoader;
import org.eclipse.persistence.sdo.helper.SDODataHelper;
import org.eclipse.persistence.sdo.helper.SDOHelperContext;
import org.eclipse.persistence.sdo.helper.SDOTypeHelper;
import org.eclipse.persistence.sdo.helper.SDOXMLHelper;
import org.eclipse.persistence.sdo.helper.SDOXSDHelper;
import commonj.sdo.Type;
import commonj.sdo.impl.HelperProvider;
import org.eclipse.persistence.Version;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.platform.xml.XMLComparer;

import static org.eclipse.persistence.sdo.SDOConstants.*;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class SDOTestCase extends junit.framework.TestCase {

    static {
        System.setProperty("user.timezone", "Canada/Eastern");
    }

    public boolean useLogging = false;
    public boolean ignoreCRLF = false;
    public boolean customContext = false;
    public boolean loggingLevelFinest = false;
    public HelperContext aHelperContext;
    public TypeHelper typeHelper;
    public XMLHelper xmlHelper;
    public XSDHelper xsdHelper;
    public EqualityHelper equalityHelper;
    public CopyHelper copyHelper;
    public DataFactory dataFactory;
    public SDODataHelper dataHelper;
    public DocumentBuilder parser;
    public String classgenCompilePath; 
    public String tempFileDir;
    public SDOXMLComparer xmlComparer;

    protected static final String USER_DIR = System.getProperty("user.dir").replace('\\', '/');
    protected static final String FILE_PROTOCOL = USER_DIR.startsWith("/")? "file:" : "file:/";    
    protected static final String HTTP_PROTOCOL = "http://";
    protected static final String NON_DEFAULT_JAVA_PACKAGE_DIR = "org/example";  
    protected static final String NON_DEFAULT_JAVA_PACKAGE_NAME = "org.example";
    protected static final String NON_DEFAULT_URI = "http://www.example.org";
    
    public SDOTestCase(String name) {
        super(name);
        useLogging = Boolean.getBoolean("useLogging");
        ignoreCRLF = Boolean.getBoolean("ignoreCRLF");
        customContext = Boolean.getBoolean("customContext");
        loggingLevelFinest = Boolean.getBoolean("loggingLevelFinest");
		classgenCompilePath = System.getProperty("sdo.classgen.compile.path");
		tempFileDir = System.getProperty("tempFileDir");
        if(null == tempFileDir || tempFileDir.length() < 1) {
			tempFileDir = ".";
		}
	
        if (loggingLevelFinest && AbstractSessionLog.getLog().getLevel() != AbstractSessionLog.FINEST) {
            // override default INFO logging level for static logs
            AbstractSessionLog.getLog().setLevel(AbstractSessionLog.FINEST);
            AbstractSessionLog.getLog().log(AbstractSessionLog.FINEST, "{0} {1}", //
                    new Object[] {Version.getProduct(), Version.getVersionString()}, false);
        }

        // reverse the flags so that a false(from the flag not found) will not
        // default to a static context
    }
    
    public void setUp() {
        xmlComparer = new SDOXMLComparer();
        if (customContext) {
            // default to instance of a HelperContext
            aHelperContext = new SDOHelperContext();
        } else {
            // default to static context (Global)
            aHelperContext = HelperProvider.getDefaultContext();
        }
        typeHelper = aHelperContext.getTypeHelper();
        xmlHelper = aHelperContext.getXMLHelper();
        xsdHelper = aHelperContext.getXSDHelper();
        equalityHelper = aHelperContext.getEqualityHelper();
        copyHelper = aHelperContext.getCopyHelper();
        dataFactory = aHelperContext.getDataFactory();
        // TODO: we should be using the DataHelper interface
        dataHelper = (SDODataHelper)aHelperContext.getDataHelper();

        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        builderFactory.setNamespaceAware(true);
        builderFactory.setIgnoringElementContentWhitespace(true);
        try {
            parser = builderFactory.newDocumentBuilder();
        } catch (Exception e) {
            fail("Could not create parser.");
            e.printStackTrace();
        }
        
        ((SDOTypeHelper) typeHelper).reset();
        ((SDOXMLHelper) xmlHelper).reset();
        ((SDOXSDHelper) xsdHelper).reset();
    }
    
    public void tearDown() throws Exception {
        
        ((SDOTypeHelper) typeHelper).reset();
        ((SDOXMLHelper) xmlHelper).reset();
        ((SDOXSDHelper) xsdHelper).reset();
        
        typeHelper = null;
        xmlHelper = null;
        xsdHelper = null;
        equalityHelper = null;
        copyHelper = null;
        dataFactory = null;
        parser = null;
        aHelperContext = null;
        
        
    }
        
    public void assertXMLIdentical(Document control, Document test) {
        boolean isEqual = xmlComparer.isNodeEqual(control, test);
        String controlString = "";
        String testString = "";
        
        if (!isEqual) {
            org.eclipse.persistence.platform.xml.XMLTransformer t = 
                org.eclipse.persistence.platform.xml.XMLPlatformFactory.getInstance().getXMLPlatform().newXMLTransformer();
            java.io.StringWriter controlWriter = new java.io.StringWriter();
            t.transform(control, controlWriter);
            
            t = org.eclipse.persistence.platform.xml.XMLPlatformFactory.getInstance().getXMLPlatform().newXMLTransformer();
            java.io.StringWriter testWriter = new java.io.StringWriter();
            t.transform(test, testWriter);

            controlString = controlWriter.toString();
            testString = testWriter.toString();
        }
        
        assertTrue("Documents are not equal.\nCONTROL:\n" + controlString + "\nTEST:\n" + testString, isEqual);
    }
    
    public void assertSchemaIdentical(Document control, Document test) {
        assertTrue("Node " + control + " is not equal to node " + test, xmlComparer.isSchemaEqual(control, test));
    }
    public String getName() {
        String longClassName = getClass().getName();
        String shortClassName = longClassName.substring(longClassName.lastIndexOf(".") + 1, longClassName.length() - 1);
        return shortClassName + SDO_XPATH_NS_SEPARATOR_FRAGMENT + super.getName();
    }

    protected void log(String string) {
        if (useLogging) {
            System.out.println(string);
        }
    }

    protected void log(List items) {
        if (useLogging) {
            for (int i = 0; i < items.size(); i++) {
                log(items.get(i));
            }
        }
    }

    protected void log(Object object) {
        if (useLogging) {
            if (object instanceof Type) {
                log((Type) object);
            } else {
                System.out.println(object.toString());
            }
        }
    }

    protected void log(Type type) {
        if (useLogging) {
            System.out.println(type.getURI());
            System.out.println(type.getName());
        }
    }

    public String getSchema(String fileName) {
        String xsdSchema = EMPTY_STRING;
        FileInputStream is = null;
        try {
            is = new FileInputStream(fileName);           
            return getSchema(is, fileName);
        } catch (Exception e) {
            log(getClass().toString() + ": Reading error for : " + fileName + " message: " + e.getClass() + " " + e.getMessage());
        } finally {
            try {
                if (null != is) {
                    is.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return xsdSchema;
    }

 public String getSchema(InputStream is, String fileName) {
        String xsdSchema = EMPTY_STRING;        
        try {            
            byte[] bytes = new byte[is.available()];
            is.read(bytes);
            xsdSchema = new String(bytes);
            log(xsdSchema);
            return xsdSchema;
        } catch (Exception e) {
            log(getClass().toString() + ": Reading error for : " + fileName + " message: " + e.getClass() + " " + e.getMessage());
        } finally {
            try {
                if (null != is) {
                    is.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return xsdSchema;
    }

    /* Tree specific algorithms to aide in testing */
    /**
     * Return the depth of this dataObject from it's root
     * 
     * @return int
     */
    public int depth(DataObject aChild) {
        if (null == aChild.getContainer()) {
            // base case
            return 0;
        } else {
            // recursive case
            return 1 + depth(aChild.getContainer());
        }
    }

    // diff function required

    /**
     * Return an ArrayList of all the DataObjects in the tree in a preOrder
     * fashion
     */
    public List<DataObject> preOrderTraversalDataObjectList(SDODataObject currentDO) {
        return preOrderTraversalDataObjectList(currentDO, new ArrayList<DataObject>(), false, true);
    }

    public List<DataObject> preOrderTraversalDataObjectList(DataObject currentDO) {
        return preOrderTraversalDataObjectList((SDODataObject) currentDO, new ArrayList<DataObject>(), false, true);
    }

    /**
     * Return an ArrayList of all the DataObjects (including unset ones) in the
     * tree in a preOrder fashion
     */
    public List<DataObject> preOrderTraversalDataObjectList(SDODataObject currentDO, boolean countNullObjects) {
        return preOrderTraversalDataObjectList(currentDO, new ArrayList<DataObject>(), countNullObjects, true);
    }

    private List<DataObject> preOrderTraversalDataObjectList(SDODataObject currentDO, ArrayList<DataObject> currentList, boolean countNullObjects, boolean recurse) {
        if (currentDO != null) {
            // add yourself
            currentList.add(currentDO);
            // check DO's recursively
            List instanceProperties = currentDO.getInstanceProperties();
            SDOProperty nextProperty = null;
            Object value = null;
            if (recurse) {
                for (int i = 0; i < instanceProperties.size(); i++) {
                    nextProperty = (SDOProperty) instanceProperties.get(i);
                    value = currentDO.get(nextProperty);
                    boolean recurseHopefullyNotToInfinityPlease = true;
                    if (!nextProperty.getType().isChangeSummaryType() && !nextProperty.getType().isDataType()) {
                        // don't traverse into opposite properties to avoid an
                        // infinite loop
                        if (null != nextProperty.getOpposite()) {
                            recurseHopefullyNotToInfinityPlease = false;
                        }

                        if (nextProperty.isMany()) {
                            // iterate list
                            Object manyItem;

                            // use of delete while using an iterator will
                            // generate a ConcurrentModificationException
                            for (int index = 0; index < ((List) value).size(); index++) {
                                manyItem = ((List) value).get(index);
                                if (manyItem != null && manyItem instanceof SDODataObject) {
                                    preOrderTraversalDataObjectList((SDODataObject) manyItem, currentList, countNullObjects, recurseHopefullyNotToInfinityPlease);
                                }
                            }
                        } else {
                            if (value != null) {
                                preOrderTraversalDataObjectList((SDODataObject) value, currentList, countNullObjects, recurseHopefullyNotToInfinityPlease);
                            }
                        }
                    }
                }
            }
        } else {
            if (countNullObjects) {
                currentList.add(currentDO);
            }
        }
        return currentList;
    }

    protected void assertCreated(DataObject dataObject, ChangeSummary changeSummary) {
        assertTrue(changeSummary.isCreated(dataObject));
        assertFalse(changeSummary.isModified(dataObject));
        assertFalse(changeSummary.isDeleted(dataObject));
        // if we are at the root then there is no parent to track
        if (null != dataObject.getContainer()) {
            // check that parent (if not the root) sequence has been saved in
            // originalSequences (if dataObject is not an attribute - which it
            // is not)
            if (dataObject.getContainer().getSequence() != null) {
                assertNotNull(changeSummary.getOldSequence(dataObject.getContainer()));
            } else {
                assertNull(changeSummary.getOldSequence(dataObject.getContainer()));
            }
        }
        assertEquals(0, changeSummary.getOldValues(dataObject).size());
    }

    protected void assertModified(DataObject dataObject, ChangeSummary changeSummary) {
        assertFalse(changeSummary.isCreated(dataObject));
        assertTrue(changeSummary.isModified(dataObject));
        assertFalse(changeSummary.isDeleted(dataObject));
    }

    protected void assertChildrenUnset(DataObject dataobject) {
        // verify all properties are unset and all many properties are size 0
        Iterator anIterator = dataobject.getType().getProperties().iterator();
        while (anIterator.hasNext()) {
            Property aProperty = (Property) anIterator.next();
            Object aPropertyValue = dataobject.get(aProperty);
            assertFalse(dataobject.isSet(aProperty));
            // all properties must be unset
            if (aProperty.isMany()) {
                assertSame(((List) aPropertyValue).size(), 0);
            } else {
            	if(!aProperty.getType().isDataType()) {
            		assertEquals(aProperty.getDefault(),aPropertyValue);
            		// assertSame(aProperty.getDefault(), dataobject.get(aProperty));
            	} else {
            		// JIRA-253: we return a wrapped numeric primitive when it has no default
            		Type aType = aProperty.getType();
                	if (aType.equals(SDO_BOOLEAN)) {
                		assertEquals(false, ((Boolean)aPropertyValue).booleanValue());
                	} else if (aType.equals(SDO_BYTE)) {
                		assertEquals(0, ((Byte)aPropertyValue).byteValue());
                	} else if (aType.equals(SDO_CHARACTER)) {
                		assertEquals(0, ((Character)aPropertyValue).charValue());
                	} else if (aType.equals(SDO_DOUBLE)) {
                		assertEquals(0, ((Double)aPropertyValue).doubleValue());
                	} else if (aType.equals(SDO_FLOAT)) {
                		assertEquals(0, ((Float)aPropertyValue).floatValue());
                	} else if (aType.equals(SDO_INT)) {
                		assertEquals(0, ((Integer)aPropertyValue).intValue());
                	} else if (aType.equals(SDO_SHORT)) {
                		assertEquals(0, ((Short)aPropertyValue).shortValue());
                	} else if (aType.equals(SDO_LONG)) {
                		assertEquals(0, ((Long)aPropertyValue).longValue());
                	}
            	}                                
            }
        }
    }

    protected void assertDeleted(DataObject dataobject, ChangeSummary changeSummary) {
        assertDeleted(dataobject, changeSummary, true, false, false);
    }

    protected void assertDeleted(DataObject dataobject, ChangeSummary changeSummary, boolean nullContainer) {
        assertDeleted(dataobject, changeSummary, nullContainer, false, false);
    }

    // for objects that were detached and then (re)set - their container and cs
    // will not be null but they will have oldSettings/deletedList items
    protected void assertDeleted(DataObject dataObject, ChangeSummary changeSummary, boolean nullContainer, boolean testLoadSave) {
        assertDeleted(dataObject, changeSummary, nullContainer, false, testLoadSave);
        assertChildrenUnset(dataObject);
    }

    protected void assertDeleted(DataObject dataObject, ChangeSummary changeSummary, boolean nullContainer, boolean isReAttached, boolean testLoadSave) {
        assertFalse(changeSummary.isCreated(dataObject));
        assertFalse(changeSummary.isModified(dataObject));
        if (!isReAttached) {
            assertTrue(((SDOChangeSummary) changeSummary).isDeleted(dataObject));
            if (dataObject.getSequence() != null) {
                assertNotNull(changeSummary.getOldSequence(dataObject));
            } else {
                assertNull(changeSummary.getOldSequence(dataObject));
            }
        } else {
            assertFalse(((SDOChangeSummary) changeSummary).isDeleted(dataObject));
        }

        int propertySize = dataObject.getType().getProperties().size();
        int oldValuesSize = changeSummary.getOldValues(dataObject).size();

        assertEquals(propertySize, oldValuesSize);

        // for objects that were detached and then (re)set - their container and
        // cs will not be null but they will have oldSettings/deletedList items
        if (nullContainer) {
            assertNull(dataObject.getContainer());
            // verify that the cs is not set on deleted/detached objects
            assertNull(dataObject.getChangeSummary());
        }

        assertChildrenUnset(dataObject);
    }

    // detached objects' properties are intact and not unset
    protected void assertDetached(DataObject dataobject, ChangeSummary changeSummary) {
        assertDetached(dataobject, changeSummary, true, false, false);
    }

    // we delete/detach and then (Re)set - deletedSet is cleared but oldSettings
    // remain (for now until we have smart undo code)
    protected void assertDetachedAndReset(DataObject dataobject, ChangeSummary changeSummary, boolean nullContainment) {
        assertDetached(dataobject, changeSummary, nullContainment, true, false);
    }

    protected void assertDetached(DataObject dataobject, ChangeSummary changeSummary, boolean nullContainment) {
        assertDetached(dataobject, changeSummary, nullContainment, false, false);
    }

    protected void assertDetached(DataObject dataobject, ChangeSummary changeSummary, boolean nullContainment, boolean isReAttached) {
        assertDetached(dataobject, changeSummary, nullContainment, isReAttached, false);
    }

    // isReAttached means that the property was detached and then (re)set - no
    // deletedSet entry but oldSettings remain
    protected void assertDetached(DataObject dataobject, ChangeSummary changeSummary, boolean nullContainment, boolean isReAttached, boolean testLoadSave) {
        assertFalse(changeSummary.isCreated(dataobject));
        assertFalse(changeSummary.isModified(dataobject));
        if (!isReAttached) {
            assertTrue(((SDOChangeSummary) changeSummary).isDeleted(dataobject));
        } else {
            assertFalse(((SDOChangeSummary) changeSummary).isDeleted(dataobject));
        }

        int propertySize = dataobject.getType().getProperties().size();
        int oldValuesSize = changeSummary.getOldValues(dataobject).size();

        assertEquals(propertySize, oldValuesSize);

        // for objects that were detached and then (re)set - their container and
        // cs will not be null but they will have oldSettings/deletedList items
        if (nullContainment) {
            assertNull(dataobject.getContainer());
            // verify that the cs is not set on deleted/detached objects
            assertNull(dataobject.getChangeSummary());
        }
    }

    protected void assertUnchanged(DataObject dataobject, ChangeSummary changeSummary) {
        assertFalse(changeSummary.isCreated(dataobject));
        assertFalse(changeSummary.isModified(dataobject));
        assertFalse(changeSummary.isDeleted(dataobject));

        assertEquals(0, changeSummary.getOldValues(dataobject).size());
    }

    // inOrderNodeList, preOrderNodeList, postOrderNodeList
    // function to monitor actual values inside the oldSetting HashMap
    protected void checkOldSettingsValues(String values, SDOChangeSummary aCS, List dataObjectList) {
        SDODataObject aDataObject = null;
        for (int i = 0; i < dataObjectList.size(); i++) {
            aDataObject = (SDODataObject) dataObjectList.get(i);
            assertEquals(Integer.parseInt(values.substring(i, i + 1)), aCS.getOldValues(aDataObject).size());
        }
    }

    protected void checkOldContainers(SDOChangeSummary aCS,//
    List dataObjectChildList, List dataObjectContainerList) {// we need
                                                                // generics here
        SDODataObject aChildDataObject = null;
        SDODataObject aContainerDataObject = null;
        for (int i = 0; i < dataObjectChildList.size(); i++) {
            aChildDataObject = (SDODataObject) dataObjectChildList.get(i);
            aContainerDataObject = (SDODataObject) dataObjectContainerList.get(i);
            assertEquals(aChildDataObject, aCS.getOldContainer(aContainerDataObject));
        }
    }

    /*
     * ChangeSummary specific functions for undoChanges
     */
    /**
     * 
     * @param currentDO
     * @param isCSonAncestor
     */
    public void assertChangeSummaryStatusIfClearedIfCSIsAncestor(DataObject currentDO, boolean isCSonAncestor) {
        if (currentDO != null) {
            // check current DO
            if (isCSonAncestor) {
                assertNull(((SDODataObject) currentDO).getChangeSummary());
            } else {
                assertNotNull(((SDODataObject) currentDO).getChangeSummary());
            }
            // check DO's recursively
            List instanceProperties = currentDO.getInstanceProperties();
            for (int i = 0; i < instanceProperties.size(); i++) {
                SDOProperty nextProperty = (SDOProperty) instanceProperties.get(i);
                Object value = currentDO.get(nextProperty);

                if (!nextProperty.getType().isChangeSummaryType() && !nextProperty.getType().isDataType() && value != null) {
                    if (nextProperty.isMany()) {
                        // iterate list
                        Object manyItem;

                        // use of delete while using an iterator will generate a
                        // ConcurrentModificationException
                        for (int index = 0; index < ((List) value).size(); index++) {
                            manyItem = ((List) value).get(index);
                            if (manyItem != null) {
                                assertChangeSummaryStatusIfClearedIfCSIsAncestor((SDODataObject) manyItem, isCSonAncestor);
                            }
                        }
                    } else {
                        assertChangeSummaryStatusIfClearedIfCSIsAncestor((SDODataObject) value, isCSonAncestor);
                    }
                }
            }
        }
    }

    /**
     * 
     * @param aChangeSummary
     * @param undoneDO
     * @param originalDO
     */
    protected void assertUndoChangesEqualToOriginal(ChangeSummary aChangeSummary,//
    DataObject undoneDO, DataObject originalDO) {
        // get logging flag before
        boolean loggingStateBefore = aChangeSummary.isLogging();
        aChangeSummary.undoChanges();
        assertTrue(loggingStateBefore == aChangeSummary.isLogging());

        // verify that the model has been returned to its original base state
        assertTrue(equalityHelper.equal(undoneDO, originalDO));
        // the objects are deep copies of each other but not the actual same
        // purchase order
        assertFalse(undoneDO == originalDO);
        // verify that CS is cleared but logging is unchanged
        assertTrue(aChangeSummary.getChangedDataObjects().size() == 0);
        assertTrue(aChangeSummary.getOldValues(undoneDO).size() == 0);
        assertTrue(aChangeSummary.getOldValues(originalDO).size() == 0);
    }

    /**
     * 
     * @param aRootObject
     */
    // test undo when logging is off (with previous changes)
    protected void assertValueStoresInitializedAfterLoggingOn(DataObject aRootObject) {
        // verify logging is on
        assertTrue(aRootObject.getChangeSummary().isLogging());
        // verify original VS is null and save a copy of current VS for object
        // identity testing after undo
        ValueStore aCurrentValueStore = ((SDODataObject) aRootObject)._getCurrentValueStore();
        assertNotNull(aCurrentValueStore);
        ValueStore anOriginalValueStore = (ValueStore) ((SDOChangeSummary) aRootObject.getChangeSummary()).getOriginalValueStores().get(aRootObject);
        assertNull(anOriginalValueStore);
    }

    /**
     * 
     * @param aRootObject
     * @param aCurrentValueStoreAfterLoggingFirstOnParam
     */
    protected void assertValueStoresCopiedAndSwappedAfterFirstModifyOperation(DataObject aRootObject, ValueStore aCurrentValueStoreAfterLoggingFirstOnParam) {
        // verify logging is on
        assertTrue(aRootObject.getChangeSummary().isLogging());
        assertNotNull(aCurrentValueStoreAfterLoggingFirstOnParam);
        ValueStore anOriginalValueStoreAfterOperation = (ValueStore) ((SDOChangeSummary) aRootObject.getChangeSummary()).getOriginalValueStores().get(aRootObject);
        ValueStore aCurrentValueStoreAfterOperation = ((SDODataObject) aRootObject)._getCurrentValueStore();
        assertNotNull(anOriginalValueStoreAfterOperation);
        assertNotNull(aCurrentValueStoreAfterOperation);
        assertTrue(anOriginalValueStoreAfterOperation == aCurrentValueStoreAfterLoggingFirstOnParam);
    }

    protected void assertSequencesCopiedAndSwappedAfterFirstModifyOperation(DataObject aRootObject, Sequence aCurrentSequenceAfterLoggingFirstOnParam) {
        // verify logging is on
        assertTrue(aRootObject.getChangeSummary().isLogging());
        assertNotNull(aCurrentSequenceAfterLoggingFirstOnParam);
        Sequence anOriginalSequenceAfterOperation = (Sequence) ((SDOChangeSummary) aRootObject.getChangeSummary()).getOriginalSequences().get(aRootObject);
        Sequence aCurrentSequenceAfterOperation = ((SDODataObject) aRootObject).getSequence();
        assertNotNull(anOriginalSequenceAfterOperation);
        assertNotNull(aCurrentSequenceAfterOperation);
        assertTrue(anOriginalSequenceAfterOperation == aCurrentSequenceAfterLoggingFirstOnParam);
    }

    /**
     * 
     * @param aRootObject
     * @param aCurrentValueStoreAfterLoggingFirstOnParam
     */
    protected void assertValueStoresReturnedToStartStateAfterUndoChanges(DataObject aRootObject, ValueStore aCurrentValueStoreAfterLoggingFirstOnParam) {
        // verify logging is on
        assertTrue(aRootObject.getChangeSummary().isLogging());
        ValueStore anOriginalValueStoreAfterUndo = (ValueStore) ((SDOChangeSummary) aRootObject.getChangeSummary()).getOriginalValueStores().get(aRootObject);
        ValueStore aCurrentValueStoreAfterUndo = ((SDODataObject) aRootObject)._getCurrentValueStore();
        assertNull(anOriginalValueStoreAfterUndo);
        assertNotNull(aCurrentValueStoreAfterUndo);
        // we return the original value store back to the current VS
        assertTrue(aCurrentValueStoreAfterUndo == aCurrentValueStoreAfterLoggingFirstOnParam);
    }

    /**
     * 
     * @param aRootObject
     * @param aCurrentSequenceAfterLoggingFirstOnParam
     */
    protected void assertSequencesReturnedToStartStateAfterUndoChanges(DataObject aRootObject, Sequence aCurrentSequenceAfterLoggingFirstOnParam) {
        // verify logging is on
        assertTrue(aRootObject.getChangeSummary().isLogging());
        SDOSequence anOriginalSequenceAfterUndo = (SDOSequence) ((SDOChangeSummary) aRootObject.getChangeSummary()).getOriginalSequences().get(aRootObject);
        SDOSequence aCurrentSequenceAfterUndo = (SDOSequence) ((SDODataObject) aRootObject).getSequence();
        assertNull(anOriginalSequenceAfterUndo);
        assertNotNull(aCurrentSequenceAfterUndo);
        // we return the sequence back to the current VS
        assertEquals(aCurrentSequenceAfterUndo.size(), aCurrentSequenceAfterLoggingFirstOnParam.size());
        assertTrue(compareSequences(aCurrentSequenceAfterUndo, (SDOSequence) aCurrentSequenceAfterLoggingFirstOnParam, true));
    }

    /**
     * INTERNAL: Return whether the 2 sequences are equal. Element properties
     * and unstructured text will be compared - attributes are out of scope.
     * <p>
     * For shallow equal - only dataType=true objects are compared, DataObject
     * values are ignored but should be defaults. Note: A setting object should
     * handle its own isEqual() behavior
     * 
     * @param aSequence
     * @param aSequenceCopy
     * @param isDeep
     * @return
     */
    public boolean compareSequences(SDOSequence aSequence, SDOSequence aSequenceCopy, boolean isDeep) {
        // corner case: isSequenced set to true after type definition had not
        // sequence
        if (null == aSequence && null == aSequenceCopy) {
            return true;
        }
        // both sequences must be null
        if (null == aSequence || null == aSequenceCopy) {
            return false;
        }
        // for shallow equal - match whether we skipped creating settings or set
        // value=null for shallow copies
        if (aSequence.size() != aSequenceCopy.size()) {
            return false;
        }

        // the settings inside the sequence must be new objects
        SDOSetting originalSetting = null;
        SDOSetting copySetting = null;
        List originalSettingsList = aSequence.getSettings();
        List copySettingsList = aSequenceCopy.getSettings();
        if (null == originalSettingsList || null == copySettingsList) {
            return false;
        }

        Property originalProperty = null;
        Property copyProperty = null;
        /**
         * For shallow equal when dataType is false we do not check this
         * setting, the value will be unset (default value) in the shallow copy.
         * orig v1=String v2=DataObject v3=String shallowcopy v1=String
         * v2=null(default) v3=String deepcopy v1=String v2=DataObject v3=String
         */
        for (int index = 0, size = aSequence.size(); index < size; index++) {
            originalSetting = (SDOSetting) originalSettingsList.get(index);
            copySetting = (SDOSetting) copySettingsList.get(index);

            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)) {
                return false;
            }

            // the property field on the setting must point to the same property
            // instance as the original
            // handle both properties == null
            if (originalProperty != copyProperty) { 
                return false;
            }

            Object originalValue = originalSetting.getValue();
            Object copyValue = copySetting.getValue();

            // for unstructuredText (null property) and simple dataTypes we
            // check equality directly
            if (null == originalProperty || originalProperty.getType().isDataType()) {
                // if one of the values is null return false
                if (((null == originalValue) && (null != copyValue)) || //
                ((null != originalValue) && (null == copyValue))) {
                    return false;
                }
                // if both values are null - they are equal
                // we can also use !.equals
                if ((null != originalValue) && !originalValue.equals(copyValue)) {
                    return 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) {
                    if (null != originalValue && null != copyValue) {
                        // setting.isSet is ignored for sequences
                        // perform a deep equal on the single item
                        // the values may not match their types - return false
                        // instead of a CCE
                        if (originalValue instanceof DataObject && copyValue instanceof DataObject) {
                            if (!equalityHelper.equal((DataObject) originalValue, (DataObject) copyValue)) {
                                return false;
                            }
                        } else {
                            return false;
                        }
                    } else {
                        // both values must be null to be equal
                        if ((null == originalValue && null != copyValue) || (null == copyValue && null != originalValue)) {
                            return false;
                        }
                    }
                } else {
                    /**
                     * For DataObjects in general anything that is deep equal is
                     * also shallow equal - but not the reverse. In the case of
                     * shallow equal on sequences. We can ignore the state of
                     * the 2 complex objects. UC1: if aSequenceCopy setting was
                     * from a shallowCopy then it will be unset. UC2: if
                     * aSequenceCopy setting was from a deepCopy or a reversed
                     * argument shallowCopy then it may be unset or set. We will
                     * not check for a default value on either sequence setting.
                     */
                }
            }
        }
        return true;
    }

    /**
     * Remove CR\LF=13\10 from source and target strings so that we can run the
     * suite on windows without assertEquals() failing. Use the system property
     * -DignoreCRLF=true
     * 
     * @param control
     * @param test
     * @param removeCRLF
     *            void
     * 
     */
    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;
    }

    /**
     * 
     * @param parentType
     * @param name
     * @param propType
     * @param isContainment
     * @return
     */
    protected DataObject addProperty(DataObject parentType, String name, Type propType, boolean isContainment) {
        DataObject newProperty = addProperty(parentType, name, propType);
        newProperty.setBoolean(CONTAINMENT, isContainment);
        return newProperty;
    }

    /**
     * 
     * @param parentType
     * @param name
     * @param propType
     * @param isContainment
     * @param isMany
     * @return
     */
    protected DataObject addProperty(DataObject parentType, String name, Type propType, boolean isContainment, boolean isMany) {
        DataObject newProperty = addProperty(parentType, name, propType, isContainment);
        newProperty.setBoolean(SDOXML_MANY, isMany);
        return newProperty;
    }

    protected DataObject addProperty(DataObject parentType, String name, Type propType, boolean isContainment, boolean isMany, boolean isElement) {
        DataObject newProperty = addProperty(parentType, name, propType, isContainment, isMany);
        if (isElement) {
            newProperty.set(XMLELEMENT_PROPERTY, true);

        }
        return newProperty;
    }
    
    protected DataObject addProperty(DataObject parentType, String name, DataObject propTypeDO, boolean isContainment, boolean isMany, boolean isElement) {
        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, propTypeDO);
        
        newProperty.setBoolean(CONTAINMENT, isContainment);
        if (isElement) {
            newProperty.set(XMLELEMENT_PROPERTY, true);

        }
        return newProperty;
    }

    /**
     * Set the oc prop containing the idProp property - for unidirectional/bidirectional relationships
     */ 
    public void setIDPropForReferenceProperties(DataObject doType, Object idProp) {
    	// get the global property referencing the idProp property
        doType.set(ID_PROPERTY, idProp);
    }

    /**
     * INTERNAL:
     * Get the reference ID open content Property if it exists for this Type.
     * @return id Property or null
     */
    public SDOProperty getIDProp(Type aType) {
   		return (SDOProperty)aType.getProperty((String)aType.get(SDOConstants.ID_PROPERTY));
    }
    
    /**
     * 
     * @param uri
     * @param name
     * @return
     */
    protected DataObject defineType(String uri, String name) {
        DataObject newType = aHelperContext.getDataFactory().create(SDO_URL, TYPE);
        newType.set("uri", uri);
        newType.set("name", name);
        return newType;
    }

    public HelperContext getHelperContext() {
        return aHelperContext;
    }

    public void setHelperContext(HelperContext helperContext) {
        aHelperContext = helperContext;
    }

    protected void assertEqualsBytes(byte[] controlBytes, byte[] bytes) {
        if (controlBytes.length != bytes.length) {
            fail("Expected:" + log(controlBytes) + " but was:" + log(bytes));
        }

        for (int i = 0; i < controlBytes.length; i++) {
            if (controlBytes[i] != bytes[i]) {
                fail("Expected:" + log(controlBytes) + " but was:" + log(bytes));
            }
        }
    }

    protected String log(byte[] bytes) {
        String s = new String();
        for (int i = 0; i < bytes.length; i++) {
            s += bytes[i];
        }
        return s;
    }

    protected Document getDocument(String fileName) {
        FileInputStream inputStream = null;
        try{
          inputStream = new FileInputStream(fileName);
          return getDocument(inputStream);
          } catch (Exception e) {
            e.printStackTrace();
            fail("An error occurred loading the control document:" + fileName);
            return null;
        } finally {
            try {
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }

    }
    
     protected Document getDocument(InputStream inputStream) {        
        try {
            
            Document document = parser.parse(inputStream);
            inputStream.close();
            return document;
        } catch (Exception e) {
            e.printStackTrace();
            fail("An error occurred loading the control document:"); // + inputStream.);
            return null;
        } finally {
            try {
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }

    public void assertStringsEqual(String controlString, String generatedString) {
        String controlString2 = removeCRLFfromString(controlString);
        String generatedString2 = removeCRLFfromString(generatedString);
        // Allow Windows generated java code to pass comparison as well as Linux generated ones
//        if (ignoreCRLF) {
            assertEquals(controlString2, generatedString2);
//        } else {
//            assertEquals(controlString, generatedString);
//        }
    }

    protected void removeEmptyTextNodes(Node node) {
        NodeList nodeList = node.getChildNodes();
        Node childNode;
        for (int x = nodeList.getLength() - 1; x >= 0; x--) {
            childNode = nodeList.item(x);
            if (childNode.getNodeType() == Node.TEXT_NODE) {
                if (childNode.getNodeValue().trim().equals("")) {
                    node.removeChild(childNode);
                }
            } else if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                removeEmptyTextNodes(childNode);
            }
        }
    }

    protected String removeWhiteSpaceFromString(String s) {
        String returnString = s.replaceAll(" ", "");
        returnString = returnString.replaceAll("\n", "");
        returnString = returnString.replaceAll("\t", "");
        returnString = returnString.replaceAll("\r", "");

        return returnString;
    }

    protected String removeCRLFfromString(String s) {
        String returnString = s.replaceAll("\n", "");
        returnString = returnString.replaceAll("\t", "");
        returnString = returnString.replaceAll("\r", "");
        return returnString;
    }

    /**
     * Write to the output stream and return a success flag if no exceptions
     * thrown
     * 
     * @param anObject
     * @param uri
     * @param typename
     * @param aStream
     * @return success flag
     */
    public boolean writeXML(DataObject anObject, String uri, String typename, OutputStream aStream) {
        boolean success = true;
        // verify save
        if (useLogging) {
            try {
                xmlHelper.save(anObject, uri, typename, aStream);
            } catch (Exception e) {
                System.out.println("Exception: " + e.getMessage());
                e.printStackTrace();
                success = false;
            }
        }
        return success;
    }

    public DataObject loadXML(String filename, boolean resetChangeSummary) {
        DataObject anObject = null;
        try {
            XMLDocument document = xmlHelper.load(new FileInputStream(filename));
            anObject = document.getRootObject();
            // leave the cs alone?
            if (resetChangeSummary) {
                ChangeSummary aCS = anObject.getChangeSummary();
                if (aCS != null) {
                    aCS.endLogging();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            fail("_Error: SDOTestSuite.loadXML(): An error occurred loading the xml file " + filename);
        }
        return anObject;
    }
    
     protected void emptyAndDeleteDirectory(File f) {
        if (f.isDirectory()) {
            File[] files = f.listFiles();
            for (int i = 0; i < files.length; i++) {
                File next = files[i];
                if (next.isDirectory()) {
                    emptyAndDeleteDirectory(next);
                } else {
                    next.delete();
                }
            }
            f.delete();
        }
    }
    
     protected void deleteDirsOnExit(File f) {
        if (f.isDirectory()) {
            File[] files = f.listFiles();
            for (int i = 0; i < files.length; i++) {
                File next = files[i];
                if (next.isDirectory()) {
                    deleteDirsOnExit(next);
                } else {
                    next.deleteOnExit();
                }
            }
            f.deleteOnExit();
        }
    }
    
    protected String getClassPathForCompile(){
        return classgenCompilePath;
    }
 
}
