/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.sdo;

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
    }

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

    @Override
    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));
    }
    @Override
    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 = removeCopyrightFromString(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);
                    } else if (aType.equals(SDO_FLOAT)) {
                        assertEquals(0, (Float) aPropertyValue);
                    } 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(changeSummary.isDeleted(dataObject));
            if (dataObject.getSequence() != null) {
                assertNotNull(changeSummary.getOldSequence(dataObject));
            } else {
                assertNull(changeSummary.getOldSequence(dataObject));
            }
        } else {
            assertFalse(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(changeSummary.isDeleted(dataobject));
        } else {
            assertFalse(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
     */
    /**
     *
     */
    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);
                    }
                }
            }
        }
    }

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

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

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

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

    /**
     *
     */
    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 = ((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
     *
     */
    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 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;
    }

    /**
     *
     */
    protected DataObject addProperty(DataObject parentType, String name, Type propType, boolean isContainment) {
        DataObject newProperty = addProperty(parentType, name, propType);
        newProperty.setBoolean(CONTAINMENT, isContainment);
        return newProperty;
    }

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

    /**
     *
     */
    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) {
        InputStream inputStream = null;
        try{
          inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(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);
            }
        }
    }

    public static void removeCopyrightNode(Node node) {
        NodeList nodeList = node.getChildNodes();
        Node childNode;
        for (int x = 0; x < nodeList.getLength(); x++) {
            childNode = nodeList.item(x);
            if (childNode.getNodeType() == Node.COMMENT_NODE) {
                if (childNode.getNodeValue().trim().contains("Copyright")) {
                    node.removeChild(childNode);
                    break;
                }
            }
        }
    }

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

    public static String removeCopyrightFromString(String s) {
        return s.replaceAll("<!--.*Copyright.*?-->", "").replaceAll("(?s)/\\*.*Copyright.*?\\*/", "");
    }

    /**
     * Write to the output stream and return a success flag if no exceptions
     * thrown
     *
     * @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;
    }

}
