/*
 * Copyright (c) 1998, 2020 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.helper.xsdhelper.defineandgenerate;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

import junit.textui.TestRunner;
import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.helper.DefaultSchemaLocationResolver;
import org.eclipse.persistence.sdo.helper.SDOXSDHelper;
import org.eclipse.persistence.oxm.XMLConstants;

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

public class DefineAndGenerateBidirectionalTestCases extends XSDHelperDefineAndGenerateTestCases {

    public static final String URINAME = "http://www.example.org";
    public static final String COMPANY_TYPENAME = "Company";
    public static final String PO_TYPENAME = "PurchaseOrder";
    public static final String CUSTOMER_TYPENAME = "Customer";
    public static final String ADDRESS_TYPENAME = "USAddress";
    public static final String ITEM_TYPENAME = "Item";

    //public static final String XML_PATH = "org/eclipse/persistence/testing/sdo/helper/xsdhelper/CompanyWithBidirectionalNS.xml";
    public static final String XML_PATH = "org/eclipse/persistence/testing/sdo/helper/xsdhelper/CompanyWithBidirectional.xml";
    public static final String XSD_PATH = "org/eclipse/persistence/testing/sdo/schemas/CompanyWithBidirectional.xsd";

    protected DataObject root;
    protected ChangeSummary cs;
    protected Type stringType;
    protected Type dateType;
    protected Type yearMonthDayType;
    protected Type decimalType;
    protected Type idType;


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

    public void setUp() {
        super.setUp();
        stringType = typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.STRING);
        dateType = typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.DATE);
        yearMonthDayType = typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.YEARMONTHDAY);
        decimalType = SDOConstants.SDO_DECIMAL;
        idType = typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.ID);
    }
    public static void main(String[] args) {
        String[] arguments = { "-c", "org.eclipse.persistence.testing.sdo.helper.xsdhelper.defineandgenerate.DefineAndGenerateBidirectionalTestCases" };
        TestRunner.main(arguments);
    }

    protected String getControlRootURI() {
        return URINAME;
    }

    protected String getControlRootName() {
        return "company";
    }

    public String getSchemaToDefine() {
        return XSD_PATH;
    }

    public String getControlGeneratedFileName() {
        return XSD_PATH;
    }

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

    public static String getXSDString(String filename) {
        try {
            FileInputStream inStream = new FileInputStream(filename);
            byte[] bytes = new byte[inStream.available()];
            inStream.read(bytes);
            return new String(bytes);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * This function will define control types programmatically to compare to XSD definition
     * by using the standard spec SDODataObject generation method on page
     *
     * The existing getControlTypes() uses non-public Property constructors
     * @throws Exception
     */
    public void testDefineAndGenerateUsingSpecMethod() throws Exception {
        boolean useXSD = false;
        List types;
        DefaultSchemaLocationResolver resolver = new DefaultSchemaLocationResolver(getMap());

        if(useXSD) {
           // InputStream is = getSchemaInputStream(getSchemaToDefine());
            //List types = xsdHelper.define(is, getSchemaLocation());
            types = xsdHelper.define(getXSDString(XSD_PATH));
        //compareGeneratedTypes(getControlTypesViaSpecMethod(), types);
        } else {
            registerTypes();
            types = getTypesToGenerateFrom();
        }

        String generatedSchema = ((SDOXSDHelper)xsdHelper).generate(types, resolver);
        log(generatedSchema);

//        //String controlSchema = getSchema(getControlGeneratedFileName());
//        //log("EXPECTED: \n" + controlSchema);
//        log("ACTUAL: \n" + generatedSchema);

//        StringReader reader = new StringReader(generatedSchema);
//        InputSource inputSource = new InputSource(reader);
//        Document generatedSchemaDoc = parser.parse(inputSource);
//        reader.close();

        try {
            root = createRootObject(true, types);//false, types);
        } catch (Exception e) {
            // SDOTestCase will currently throw a fail()
            fail(e.getMessage());
        }

        int aRootsize = preOrderTraversalDataObjectList((SDODataObject)root).size();
        //assertEquals(4, aRootsize);

        // get opposite properties

        // check that opposite bidirectional links resolve
        //DataObject porderDO = (DataObject)root.get("porder[1]");
        assertTrue(writeXML(root, URINAME, COMPANY_TYPENAME, System.out));

        //assertXMLIdentical(getDocument(getControlGeneratedFileName()), generatedSchemaDoc);
    }

    public DataObject createRootObject(boolean viaXML, List types) {
        DataObject aRoot = null;
        if(viaXML) {
            aRoot = loadXML(XML_PATH, true);
        } else {
//            <ns0:company xsi:type="CompanyType" xmlns:sdo="commonj.sdo" xmlns:ns0="http://www.example.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
//               <ns0:porder orderDate="1999-10-20">
//                  <ns0:poID>10</ns0:poID>
//                  <ns0:shipTo name="Alice Smith" country="US"/>
//                  <ns0:billTo name="Robert Smith" country="US"/>
//                  <ns0:item>6</ns0:item-->
//               </ns0:porder>
//            </ns0:company>

            DataObject cust1 = dataFactory.create(typeHelper.getType(URINAME, CUSTOMER_TYPENAME));
            cust1.set("custID", 5);

            DataObject item1 = dataFactory.create(typeHelper.getType(URINAME, ITEM_TYPENAME));
            item1.set("itemID", 3);
            item1.set("name", "item1-DF");
            DataObject item2 = dataFactory.create(typeHelper.getType(URINAME, ITEM_TYPENAME));
            item2.set("itemID", 6);
            item2.set("name", "item2-DF");
            DataObject item3 = dataFactory.create(typeHelper.getType(URINAME, ITEM_TYPENAME));
            item3.set("itemID", 7);
            item3.set("name", "item3-DF");

            DataObject billTo = dataFactory.create(typeHelper.getType(URINAME, ADDRESS_TYPENAME));
            billTo.set("name", "bill");
            DataObject shipTo = dataFactory.create(typeHelper.getType(URINAME, ADDRESS_TYPENAME));
            shipTo.set("name", "ship");

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

            // references to company/item
            List itemsRef = new ArrayList();
            itemsRef.add(item2);//6);
            po1.set("item", itemsRef); // unwrapping exception

            aRoot = dataFactory.create(typeHelper.getType(URINAME, COMPANY_TYPENAME));
            List<DataObject> customers = new ArrayList<DataObject>();
            customers.add(cust1);
            aRoot.set("cust", customers);
            // add purchaseOrders
            List pos = new ArrayList();
            pos.add(po1);
            aRoot.set("porder", pos);

            // /company/porder/customer is bidirectional with /company/customer/purchaseOrder
            //po1.set("customer", cust1);
            // /company/customer/purchaseOrder is bidirectional with /company/porder/customer
            //cust1.set("purchaseOrder", po1);

            // add items (containment)
            List items = new ArrayList();
            items.add(item1);
            items.add(item2);
            items.add(item3);
            aRoot.set("item", items);

            aRoot.set("name", "mycomp-DF");
        }

        return aRoot;
    }

    // this function is overridden above
    public void testDefineAndGenerate() {
    }

    private Type defineAndPostProcessUnidirectional(String containingPropertyLocalName, DataObject typeToDefine, //
            String idPropertyName, String containingPropertyName) {
        setIDPropForReferenceProperties(typeToDefine, idPropertyName);
        // define the current type
        Type aType = null;
        try {
            aType = typeHelper.define(typeToDefine);
        } catch (Exception e) {
            fail(e.getMessage());
        }
//        Property containingProperty = aType.getProperty(containingPropertyName);
//        ((SDOProperty)containingProperty).setXsd(true);
//        ((SDOProperty)containingProperty).setXsdLocalName(containingProperty.getContainingType().getName());//containingPropertyLocalName);
//        ((SDOType)aType).setIDProp(aType.getProperty(idPropertyName));
        return aType;
    }
/*
    private Type defineAndPostProcessBidirectional(DataObject typeToDefine, String idPropertyName) {
        Type aType = typeHelper.define(typeToDefine);
        //SDOProperty itemProperty = (SDOProperty)aType.getProperty("item");
        //itemProperty.setXsd(true);
        ((SDOType)aType).setIDProp(aType.getProperty(idPropertyName));
        return aType;
    }
*/
    private Type registerAddressType() {
        DataObject addressType = dataFactory.create(SDOConstants.SDO_URL, SDOConstants.TYPE);
        SDOProperty prop = (SDOProperty)addressType.getType().getProperty("uri");
        addressType.set(prop, getControlRootURI());
        prop = (SDOProperty)addressType.getType().getProperty(SDOConstants.SDOXML_NAME);
        addressType.set(prop,  ADDRESS_TYPENAME);

        addProperty(addressType, "name", stringType);
        addProperty(addressType, "street", stringType);
        addProperty(addressType, "city", stringType);
        addProperty(addressType, "state", stringType);
        addProperty(addressType, "zip", decimalType);

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

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

        itemType.set(prop, typeName);
        // set unidirectional reference id
        // TODO: BIDIRECTIONAL SUPPORT
        setIDPropForReferenceProperties(itemType, "itemID");

        //TODO: anyuri type?
        //addProperty(itemType, "itemID", stringType);//idType);
        DataObject newProperty = itemType.createDataObject("property");
        SDOProperty aProp = (SDOProperty)newProperty.getType().getProperty(SDOConstants.SDOXML_NAME);
        newProperty.set(aProp, idPropName);
        aProp = (SDOProperty)newProperty.getType().getProperty("type");
        Type idType = typeHelper.getType(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI, "ID");
        newProperty.set(aProp, stringType);     // no ID type to set - use string type
        aProp.setXsd(true);

        addProperty(itemType, "name", stringType);

        Type aType = typeHelper.define(itemType);
        //SDOProperty itemProperty = (SDOProperty)aType.getProperty("item");
        //itemProperty.setXsd(true);
        // TODO: BIDIRECTIONAL SUPPORT
///        ((SDOType)aType).setIDProp(aType.getProperty(idPropName));
        return aType;
    }

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

        DataObject shipToProp = addProperty(purchaseOrderType, "shipTo", addressType);
        shipToProp.setBoolean("containment", true);

        DataObject billToProp = addProperty(purchaseOrderType, "billTo", addressType);
        billToProp.setBoolean("containment", true);

        // unidirectional IDREFS
        DataObject itemProp = addProperty(purchaseOrderType, "item", itemType);
        itemProp.setBoolean("containment", false);
        itemProp.setBoolean("many", true);
        //itemProp.set("opposite", null);
        //itemProp.setBoolean("xsd", true);

        DataObject poidProperty = addProperty(purchaseOrderType, idPropName, stringType);
//      bug: we need to change from attribute to element
        poidProperty.setBoolean("containment", true); // I know containment=false - this is to put poid in the sequence
        //poidProperty.set("xmlElement", true); // not an instance property
        //addProperty(purchaseOrderTypeType, "comment", stringType);
        addProperty(purchaseOrderType, "orderDate", yearMonthDayType);

        // Bidirectional Opposite IDREF (dont set opposite yet)
//        DataObject custProp = addProperty(purchaseOrderType, "customer", customerType);
        //custProp.set("opposite", customerPOProperty);
//        custProp.setBoolean("many", false);
//        custProp.setBoolean("containment", false);

        String containingPropertyName = "item";
        Type aType = defineAndPostProcessUnidirectional(typeName, purchaseOrderType, idPropName, containingPropertyName);

        //Type aType = typeHelper.define(purchaseOrderType);
        //SDOProperty itemProperty = (SDOProperty)aType.getProperty(containingPropertyName);
        //itemProperty.setXsd(true);
        //((SDOType)aType).setIDProp(aType.getProperty("poID"));

        return aType;
    }

    private Type registerCustomerType(Type purchaseOrderType) {
        DataObject customerType = dataFactory.create(SDOConstants.SDO_URL, SDOConstants.TYPE);
        SDOProperty prop = (SDOProperty)customerType.getType().getProperty("uri");
        customerType.set(prop, getControlRootURI());
        prop = (SDOProperty)customerType.getType().getProperty(SDOConstants.SDOXML_NAME);
        String typeName = CUSTOMER_TYPENAME;
        String idPropName = "custID";
        customerType.set(prop, typeName);
        // set unidirectional reference id
        //setIDPropForReferenceProperties(customerType, "custID");

        //addProperty(customerType, "custName", stringType);
        DataObject custidProperty = addProperty(customerType, idPropName, stringType);
        //custidProperty.setBoolean("containment", true); // bug: we need to change from attribute to element

        // Bidirectional Opposite IDREF (dont set opposite yet)
        DataObject poProp = addProperty(customerType, "purchaseOrder", purchaseOrderType);
        //poProp.set("opposite", poCustomerProperty);
        poProp.setBoolean("many", false);
        poProp.setBoolean("containment", false);

        // post define processing
        String containingPropertyName = "purchaseOrder";
        Type aType = defineAndPostProcessUnidirectional(typeName, customerType, idPropName, containingPropertyName);
        return aType;
    }

    private Type registerCompanyType(Type purchaseOrderType, Type customerType, Type itemType) {
        DataObject companyType = dataFactory.create(SDOConstants.SDO_URL, SDOConstants.TYPE);
        SDOProperty prop = (SDOProperty)companyType.getType().getProperty("uri");
        companyType.set(prop, getControlRootURI());
        prop = (SDOProperty)companyType.getType().getProperty(SDOConstants.SDOXML_NAME);
        companyType.set(prop,  COMPANY_TYPENAME);

        //TODO: anyuri type?
        DataObject name = addProperty(companyType, "name", stringType);
        //name.setInstanceProperty(SDOConstants.XMLELEMENT_PROPERTY, Boolean.TRUE);
        SDOProperty nameProp = (SDOProperty)companyType.getType().getProperty(SDOConstants.XMLELEMENT_PROPERTY_NAME);
        //name.set(SDOConstants.XMLELEMENT_PROPERTY_NAME, false);
        //nameProp.setInstanceProperty(SDOConstants.XMLELEMENT_PROPERTY, Boolean.FALSE);
        DataObject custProp =  addProperty(companyType, "cust", customerType);
        custProp.setBoolean("containment", true);
        custProp.setBoolean("many", true);
        DataObject poProp = addProperty(companyType, "porder", purchaseOrderType);
        poProp.setBoolean("containment", true);
        poProp.setBoolean("many",  true);
        DataObject itemProp = addProperty(companyType, "item", itemType);//registerItemType());
        itemProp.setBoolean("containment", true);
        itemProp.setBoolean("many",  true);

        return typeHelper.define(companyType);
    }


    /**
     * See section 3.8.4 p.41
     * We would like to create at least one test framework that uses the standard createDataObject spec
     * instead of creating Property objects - which uses a non-public public api
     */
    public void registerTypes() {
        Type addressType = registerAddressType();
        Type itemType = registerItemType();
        boolean createTogether = true;
        Type poType = null;
        Type customerType = null;
        if(!createTogether) {
            poType = registerPurchaseOrderType(addressType, itemType, customerType);
            customerType = registerCustomerType(poType);
        } else {
            List<Type> types = registerPurchaseOrderAndCustomerTypes(addressType, itemType);
            poType = types.get(0);
            customerType = types.get(1);
        }
        // move before
        //SDOProperty poProperty = (SDOProperty)poType.getType().getProperty(SDOConstants.SDOXML_NAME);
        //DataObject customerProp = addProperty(purchaseOrderTypeType, "customer", customerType);
        //customerProp.setBoolean("containment", false);
        //((SDOType)aType).setIDProp(aType.getProperty(idPropertyName));

        // set Bidirectional Opposite properties after definition (IDProp is set)
        // /company/porder/customer is bidirectional with /company/customer/purchaseOrder
        SDOProperty poCustomerBidirectionalProperty = (SDOProperty)poType.getProperty("customer");
        // /company/customer/purchaseOrder is bidirectional with /company/porder/customer
        SDOProperty customerPOBidirectionalProperty = (SDOProperty)customerType.getProperty("purchaseOrder");
//        poCustomerBidirectionalProperty.setOpposite(customerPOBidirectionalProperty);
//        customerPOBidirectionalProperty.setOpposite(poCustomerBidirectionalProperty);

        // bidirectional needs poType defined here
        Type companyType = registerCompanyType(poType, customerType, itemType);
        // make Company a global type
        //((SDOTypeHelper)aHelperContext.getTypeHelper()).s
    }

    private List<Type> registerPurchaseOrderAndCustomerTypes(Type addressType, Type itemType) {
        /**
         * instance properties available
         * aliasName, name, many, containment, default, readOnly, type, opposite, nullable
         *
         * Algorithm:
         *
         */
        List<Type> types = new ArrayList<Type>();
        DataObject purchaseOrderTypeDO = dataFactory.create(SDOConstants.SDO_URL, SDOConstants.TYPE);
        SDOProperty prop = (SDOProperty)purchaseOrderTypeDO.getType().getProperty("uri");
        purchaseOrderTypeDO.set(prop, getControlRootURI());
        prop = (SDOProperty)purchaseOrderTypeDO.getType().getProperty(SDOConstants.SDOXML_NAME);
        purchaseOrderTypeDO.set(prop, PO_TYPENAME);

        DataObject shipToProp = addProperty(purchaseOrderTypeDO, "shipTo", addressType, true);
        //shipToProp.setBoolean("containment", true);

        DataObject billToProp = addProperty(purchaseOrderTypeDO, "billTo", addressType, true);
        //billToProp.setBoolean("containment", true);

        // unidirectional IDREFS
        DataObject itemProp = addProperty(purchaseOrderTypeDO, "item", itemType, false, true);
        itemProp.setBoolean("many", true);
        //itemProp.set("opposite", null);

        DataObject poidProperty = addProperty(purchaseOrderTypeDO, "poID", stringType, false);
//      bug: we need to change from attribute to element
        //poidProperty.setBoolean("containment", true); // I know containment=false - this is to put poid in the sequence
        //poidProperty.set("xmlElement", true); // not an instance property
        //addProperty(purchaseOrderTypeType, "comment", stringType);
        addProperty(purchaseOrderTypeDO, "orderDate", yearMonthDayType);

        // Bidirectional Opposite IDREF to customer/po
        // set Bidirectional Opposite properties after definition (IDProp is set)
        // /company/porder/customer is bidirectional with /company/customer/purchaseOrder
        // /company/customer/purchaseOrder is bidirectional with /company/porder/customer
        Type customerType = null;
        Type purchaseOrderType = typeHelper.define(purchaseOrderTypeDO);
        types.add(purchaseOrderType);

        // define customer
        DataObject customerTypeDO = dataFactory.create(SDOConstants.SDO_URL, SDOConstants.TYPE);
        SDOProperty customerProp = (SDOProperty)customerTypeDO.getType().getProperty("uri");
        customerTypeDO.set(customerProp, getControlRootURI());
        customerProp = (SDOProperty)customerTypeDO.getType().getProperty(SDOConstants.SDOXML_NAME);
        customerTypeDO.set(customerProp, CUSTOMER_TYPENAME);
        DataObject custProp = addProperty(purchaseOrderTypeDO, "customer", customerType);
        custProp.setBoolean("many", false);
        custProp.setBoolean("containment", false);

        //addProperty(customerType, "custName", stringType);
        DataObject custidProperty = addProperty(customerTypeDO, "custID", stringType);

        // Bidirectional Opposite IDREF to po/customer
//        DataObject poProp = addProperty(customerTypeDO, "purchaseOrder", types.get(0));
//        SDOProperty poCustomerProperty =  (SDOProperty)purchaseOrderType.getProperty("customer");
//        poProp.setBoolean("many", false);
//        poProp.setBoolean("containment", false);

        types.add(typeHelper.define(customerTypeDO));

        // set opposites after definition
        //poProp.set("opposite", poCustomerProperty);
        //custProp.set("opposite", customerPOProperty);

        // /company/porder/customer is bidirectional with /company/customer/purchaseOrder
//        SDOProperty poCustomerBidirectionalProperty = (SDOProperty)purchaseOrderType.getProperty("customer");
        // /company/customer/purchaseOrder is bidirectional with /company/porder/customer
//        SDOProperty customerPOBidirectionalProperty = (SDOProperty)customerType.getProperty("purchaseOrder");

        return types;
    }

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

    /*
    // use XSD to define and XML to load - working
    public void testDefineViaXSDandLoadViaXML() throws Exception {
        DefaultSchemaLocationResolver resolver = new DefaultSchemaLocationResolver(getMap());
           List<Type> types = xsdHelper.define(getXSDString(XSD_PATH));

        String generatedSchema = ((SDOXSDHelper)xsdHelper).generate(types, resolver);
        log(generatedSchema);
        root = createRootObject(true, types);
        int aRootsize = preOrderTraversalDataObjectList((SDODataObject)root).size();
        System.out.println("UC1: via XSD/XML: size: " + aRootsize);
        //assertEquals(4, aRootsize);
        // get opposite properties

        // check that opposite bidirectional links resolve
        //DataObject porderDO = (DataObject)root.get("porder[1]");
        System.out.println(root);
        assertTrue(writeXML(root, URINAME, COMPANY_TYPENAME, System.out));
        //assertXMLIdentical(getDocument(getControlGeneratedFileName()), generatedSchemaDoc);
    }

    // use XSD to define and programmatic DataFactory to load -  not working
    public void testDefineViaXSDandLoadViaDataFactory() throws Exception {
        DefaultSchemaLocationResolver resolver = new DefaultSchemaLocationResolver(getMap());
           List<Type> types = xsdHelper.define(getXSDString(XSD_PATH));
        String generatedSchema = ((SDOXSDHelper)xsdHelper).generate(types, resolver);
        log(generatedSchema);
        root = createRootObject(false, types);
        int aRootsize = preOrderTraversalDataObjectList((SDODataObject)root).size();
        System.out.println("UC2: via XSD/DF: size: " + aRootsize);
        //assertEquals(4, aRootsize);
        // get opposite properties

        // check that opposite bidirectional links resolve
        //DataObject porderDO = (DataObject)root.get("porder[1]");
        System.out.println(root);
        assertTrue(writeXML(root, URINAME, COMPANY_TYPENAME, System.out));
        //assertXMLIdentical(getDocument(getControlGeneratedFileName()), generatedSchemaDoc);
    }

    // use programmatic define(DataObject) to define and XML to load - not working
    public void testDefineViaDataObjectandLoadViaXML() throws Exception {
        DefaultSchemaLocationResolver resolver = new DefaultSchemaLocationResolver(getMap());
        registerTypes();
        List<Type> types = getTypesToGenerateFrom();
        String generatedSchema = ((SDOXSDHelper)xsdHelper).generate(types, resolver);
        log(generatedSchema);
        root = createRootObject(true, types);
        int aRootsize = preOrderTraversalDataObjectList((SDODataObject)root).size();
        System.out.println("UC3: via DO/XML: size: " + aRootsize);
        //assertEquals(4, aRootsize);
        // get opposite properties

        // check that opposite bidirectional links resolve
        //DataObject porderDO = (DataObject)root.get("porder[1]");
        System.out.println(root);
        assertTrue(writeXML(root, URINAME, COMPANY_TYPENAME, System.out));
        //assertXMLIdentical(getDocument(getControlGeneratedFileName()), generatedSchemaDoc);
    }

    // use programmatic define(DataObject) and programmatic DataFactory to load - not working
    public void testDefineViaDataObjectandLoadViaDataFactory() throws Exception {
        DefaultSchemaLocationResolver resolver = new DefaultSchemaLocationResolver(getMap());
        registerTypes();
        List<Type> types = getTypesToGenerateFrom();

        String generatedSchema = ((SDOXSDHelper)xsdHelper).generate(types, resolver);
        log(generatedSchema);
        root = createRootObject(false, types);
        int aRootsize = preOrderTraversalDataObjectList((SDODataObject)root).size();
        System.out.println("UC4: via DO/DF: size: " + aRootsize);
        //assertEquals(4, aRootsize);
        // get opposite properties

        // check that opposite bidirectional links resolve
        //DataObject porderDO = (DataObject)root.get("porder[1]");
        System.out.println(root);
        assertTrue(writeXML(root, URINAME, COMPANY_TYPENAME, System.out));
        //assertXMLIdentical(getDocument(getControlGeneratedFileName()), generatedSchemaDoc);
    }
  */

}
