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

import commonj.sdo.DataObject;
import commonj.sdo.helper.XMLDocument;

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

import javax.xml.parsers.DocumentBuilderFactory;

import org.eclipse.persistence.internal.localization.LoggingLocalization;
import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.helper.SDOHelperContext;
import org.eclipse.persistence.sdo.helper.SDODataHelper;
import org.eclipse.persistence.sdo.helper.SDOTypeHelper;
import org.eclipse.persistence.sdo.helper.SDOXMLHelper;
import org.eclipse.persistence.sdo.helper.SDOXSDHelper;

import org.eclipse.persistence.testing.sdo.SDOXMLComparer;

public class SDOResolvableTest extends SDOResolvableTestCases {
    public final String SERIALIZATION_FILE_NAME = tempFileDir + "/serialization.bin";
    public final String SERIALIZATION_INSECURE_FILE_NAME = tempFileDir + "/serializationInsecure.bin";

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

    @Override
    public void setUp() {
        try {
            xmlComparer = new SDOXMLComparer();
            aHelperContext = SDOHelperContext.getHelperContext();
            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();
            // load in the schema
            String xsdString = getXSDString("org/eclipse/persistence/testing/sdo/helper/xmlhelper/PurchaseOrderDeep.xsd");

            // Define Types so that processing attributes completes
            List types = xsdHelper.define(xsdString);

            // first we set up root data object
            FileInputStream inStream = new FileInputStream("org/eclipse/persistence/testing/sdo/helper/xmlhelper/PurchaseOrderNSDeep.xml");

            XMLDocument document = xmlHelper.load(inStream);
            root = document.getRootObject();
            inStream.close();

        } catch (Exception e) {
            e.printStackTrace();
            fail("SDOResolvableTestCases.setup() failed to load DataObject");
        }
    }

    /*    public SDOResolvableTest(String name, HelperContext aContext) {
            super(name, aContext);
        }
    */

    // UC44: SDOResolvable only uses getPath() for internal nodes
    // We need to verify root behavior returns [.]
    public void testGetPathForRootObject() {
        //log("SDOResolvable.testGetPathForRootObject() UC44");
        String aPath = ((SDODataObject)root)._getPath();
        assertNotNull(aPath);
        assertEquals(SDOConstants.SDO_XPATH_TO_ROOT, aPath);
    }

    // UC43: Write null DataObject
    // Serialization does not occur because anObject is not of type SDODataObject
    public void testWriteNullDataObject() {
        // invoke serialization
        DataObject anObject = null;

        // check that we received a DataObject
        assertNull(anObject);
        // log("SDOResolvable.testWriteNullDataObject() UC43");
        serialize(anObject, SERIALIZATION_FILE_NAME);
    }

    // UC10: Write root DataObject
    // UC30: Read root DataObject
    public void testWriteReadRootDataObject() {
        // invoke serialization
        //log("SDOResolvable.testWriteReadRootDataObject() UC10|30");
        // check that we received a DataObject
        assertNotNull(root);

        serialize(root, SERIALIZATION_FILE_NAME);
        // deserialize the binary file representation
        DataObject aDeserializedDataObject = deserialize(SERIALIZATION_FILE_NAME);

        // the original and deserialized objects should be the same
        assertTrue(equalityHelper.equal(root, aDeserializedDataObject));
    }

    // UC6: Write (containment internal) DataObject
    // UC26: Read (containment internal) DataObject
    public void testWriteReadInternalDataObject() {
        // invoke serialization
        //log("SDOResolvable.testWriteReadInternalDataObject() UC6|26");
        DataObject anObject = root.getDataObject("shipTo");

        // check that we received a DataObject
        assertNotNull(anObject);

        serialize(anObject, SERIALIZATION_FILE_NAME);
        // deserialize the binary file representation
        DataObject aDeserializedDataObject = deserialize(SERIALIZATION_FILE_NAME);

        // the original and deserialized objects should be the same
        assertTrue(equalityHelper.equal(anObject, aDeserializedDataObject));
    }

    // UC3: Write (containment internal) indexed list DataObject
    // UC23: Read (containment internal) indexed list DataObject
    public void testWriteReadInternalListDataObject() {
        // invoke serialization
        //log("SDOResolvable.testWriteReadInternalListDataObject() UC3|23");
        DataObject anObject = root.getDataObject("items/item[2]");

        // check that we received a DataObject
        assertNotNull(anObject);

        serialize(anObject, SERIALIZATION_FILE_NAME);
        // deserialize the binary file representation
        DataObject aDeserializedDataObject = deserialize(SERIALIZATION_FILE_NAME);

        // the original and deserialized objects should be the same
        assertTrue(equalityHelper.equal(anObject, aDeserializedDataObject));
    }

    public void testWriteReadInternalMultiListDataObject() {
        // invoke serialization
        //log("SDOResolvable.testWriteReadInternalMultListDataObject() UC3|23");
        DataObject anObject = root.getDataObject("items/item[2]/levels2/level2[2]");

        // check that we received a DataObject
        assertNotNull(anObject);

        serialize(anObject, SERIALIZATION_FILE_NAME);
        // deserialize the binary file representation
        DataObject aDeserializedDataObject = deserialize(SERIALIZATION_FILE_NAME);

        // the original and deserialized objects should be the same
        assertTrue(equalityHelper.equal(anObject, aDeserializedDataObject));
    }

    // UC2: Write (containment internal)indexed list with changeSequence DataObject
    // UC22: Read (containment internal) indexed list with changeSequence DataObject

    /*    public void testWriteReadInternalListChangeSequenceDataObject() {
            // invoke serialization
            log("SDOResolvable.testWriteReadInternalListChangeSequenceDataObject() UC2|22");
            SDODataObject anObject = (SDODataObject)root;

            serialize(anObject, SERIALIZATION_FILE_NAME);
            // deserialize the binary file representation
            SDODataObject aDeserializedDataObject = (SDODataObject)deserialize(SERIALIZATION_FILE_NAME);

            // the original and deserialized objects should be the same
            assertTrue(equalityHelper.equal(anObject, aDeserializedDataObject));
        }*/
    public void testWriteListWrapper() {
        // invoke serialization
        //log("SDOResolvable.testWriteListWrapper()");
        DataObject itemsDO = root.getDataObject("items");
        assertNotNull(itemsDO);

        List items = itemsDO.getList("item");

        serializeList(items, SERIALIZATION_FILE_NAME + 2);
        // deserialize the binary file representation
        List aDeserializedDataObject = deserializeList(SERIALIZATION_FILE_NAME + 2);

        assertEquals(items.size(), aDeserializedDataObject.size());

        // the original and deserialized objects should be the same
        //assertTrue(equalityHelper.equal(anObject, aDeserializedDataObject));
    }

    public void testWriteList() {
        //log("SDOResolvable.testWriteList()");
        DataObject itemsDO = root.getDataObject("items");
        assertNotNull(itemsDO);

        List items = itemsDO.getList("item");
        ArrayList theList = new ArrayList(items);

        // invoke serialization
        serializeList(theList, SERIALIZATION_FILE_NAME + 3);
        // deserialize the binary file representation
        List aDeserializedDataObject = deserializeList(SERIALIZATION_FILE_NAME + 3);

        assertEquals(items.size(), aDeserializedDataObject.size());

        // the original and deserialized objects should be the same
        //assertTrue(equalityHelper.equal(anObject, aDeserializedDataObject));
    }

    public void testWriteReadInsecureDataObject() throws Exception {
        DataObject anObject = new InsecureDataObject();
        DataObject aDeserializedInsecureDataObject = null;

        // check that we received a DataObject
        assertNotNull(anObject);

        serialize(anObject, SERIALIZATION_INSECURE_FILE_NAME);
        // deserialize the binary file representation
        try {
            aDeserializedInsecureDataObject = deserializeInsecure(SERIALIZATION_INSECURE_FILE_NAME);
        } catch (InvalidClassException e) {
            assertEquals(LoggingLocalization.buildMessage("sdo_error_deserialization", new Object[] {anObject.getClass().getName()}), e.getMessage());
            return;
        }

        // the deserialized object variable must be null
        assertNull(aDeserializedInsecureDataObject);
        fail("java.io.InvalidClassException was not occured.");
    }
}
