/*
 * Copyright (c) 2011, 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:
//     rbarkhouse - 2010-03-04 12:22:11 - initial implementation
package org.eclipse.persistence.testing.jaxb.dynamic;

import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.internal.dynamic.DynamicEntityImpl;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.testing.jaxb.JAXBTestCases;
import org.w3c.dom.*;

public class DynamicJAXBFromSessionsXMLTestCases extends JAXBTestCases {

    private static final String SESSION_NAMES =
        "org.eclipse.persistence.testing.jaxb.dynamic:org.eclipse.persistence.testing.jaxb.dynamic.secondproject";
    private static final String XML_RESOURCE =
        "org/eclipse/persistence/testing/jaxb/dynamic/root-instance.xml";

    private static final String DOCWRAPPER_CLASS_NAME =
        "org.persistence.testing.jaxb.dynamic.xxx.DocWrapper";
    private static final String ROOT_CLASS_NAME =
        "org.persistence.testing.jaxb.dynamic.xxx.Root";
    private static final String COMPOBJ_CLASS_NAME =
        "org.persistence.testing.jaxb.dynamic.xxx.CompositeObjectTarget";
    private static final String COMPCOLL_CLASS_NAME =
        "org.persistence.testing.jaxb.dynamic.xxx.CompositeCollectionTarget";
    private static final String ANYOBJ_CLASS_NAME =
        "org.persistence.testing.jaxb.dynamic.xxx.AnyObjectTarget";
    private static final String ANYCOLL_CLASS_NAME =
        "org.persistence.testing.jaxb.dynamic.xxx.AnyCollectionTarget";
    private static final String ANYATT_CLASS_NAME =
        "org.persistence.testing.jaxb.dynamic.xxx.AnyAttributeTarget";
    private static final String OBJREFSUB_CLASS_NAME =
        "org.persistence.testing.jaxb.dynamic.xxx.ObjectReferenceSubclassTarget";
    private static final String COLLREF_CLASS_NAME =
        "org.persistence.testing.jaxb.dynamic.xxx.CollectionReferenceTarget";

    private static final String EMP_CLASS_NAME =
        "org.persistence.testing.jaxb.dynamic.zzz.Employee";

    protected ArrayList objectsAlreadyCheckedForEquality;

    public DynamicJAXBFromSessionsXMLTestCases(String name) throws Exception {
        super(name);

        setControlDocument(XML_RESOURCE);

        // Calling newInstance will end up eventually end up in DynamicJAXBContextFactory.createContext
        jaxbContext = DynamicJAXBContext.newInstance(SESSION_NAMES);
        jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbUnmarshaller = jaxbContext.createUnmarshaller();

        xmlContext = ((DynamicJAXBContext) jaxbContext).getXMLContext();
    }

    @Override
    protected Object getControlObject() {
        DynamicEntity docWrapper = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(DOCWRAPPER_CLASS_NAME);

        DynamicEntity root = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(ROOT_CLASS_NAME);

        DynamicEntity compObj = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(COMPOBJ_CLASS_NAME);
        compObj.set("value", null);
        Vector anyColl = new Vector(2);
        DynamicEntity anyItem1 = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(ANYCOLL_CLASS_NAME);
        anyItem1.set("value", "aNyOne");
        anyColl.add(anyItem1);
        DynamicEntity anyItem2 = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(ANYCOLL_CLASS_NAME);
        anyItem2.set("value", "aNyTwo");
        anyColl.add(anyItem2);
        compObj.set("anyColl", anyColl);
        root.set("compObj", compObj);

        ArrayList compColl = new ArrayList();
        DynamicEntity item1 = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(COMPCOLL_CLASS_NAME);
        item1.set("value", "123");
        DynamicEntity item2 = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(COMPCOLL_CLASS_NAME);
        item2.set("value", "456");
        item1.set("invRef", root);
        item2.set("invRef", root);
        compColl.add(item1);
        compColl.add(item2);
        root.set("compColl", compColl);

        Vector comDirColl = new Vector(2);
        comDirColl.add("qWe");
        comDirColl.add("rTy");
        root.set("compDirColl", comDirColl);

        root.set("binData", new byte[] { 'a', 'b', 'c', 'd', 'e' });

        Vector binDataColl = new Vector();
        binDataColl.add(new byte[] { '1', '2', '3' });
        binDataColl.add(new byte[] { '4', '5', '6' });
        root.set("binDataColl", binDataColl);

        DynamicEntity anyObj = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(ANYOBJ_CLASS_NAME);
        anyObj.set("value", "aNy");
        root.set("anyObj", anyObj);

        DynamicEntity anyAtt = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(ANYATT_CLASS_NAME);
        Properties anyAttProps = new Properties();
        anyAttProps.put(new QName("", "anyAtt1"), "aNyaTT1");
        anyAttProps.put(new QName("", "anyAtt2"), "aNyAttTWO");
        anyAtt.set("value", anyAttProps);
        root.set("anyAtt", anyAtt);

        String[] transform = new String[2];
        transform[0] = "transformValue1";
        transform[1] = "transformValue2";
        root.set("transform", transform);

        Document doc;
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            doc = db.newDocument();
        } catch(ParserConfigurationException e) {
            throw new RuntimeException(e);
        }

        Element elem = doc.createElementNS("", "frag");
        Text text = doc.createTextNode("XML Fragment Text Content");
        elem.appendChild(text);
        root.set("frag", elem);

        Vector fragColl = new Vector(2);
        Element elem1 = doc.createElementNS("", "frag-coll");
        Text text1 = doc.createTextNode("XML Fragment Collection One");
        elem1.appendChild(text1);
        Element elem2 = doc.createElementNS("", "frag-coll");
        Text text2 = doc.createTextNode("XML Fragment Collection Two");
        elem2.appendChild(text2);
        fragColl.add(elem1);
        fragColl.add(elem2);
        root.set("fragColl", fragColl);

        DynamicEntity objRef = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(OBJREFSUB_CLASS_NAME);
        objRef.set("id", "13579");
        objRef.set("superclassValue", "SUPER");
        objRef.set("subclassValue", "SUB");
        root.set("objRef", objRef);

        Vector collRef = new Vector(2);
        DynamicEntity collRef1 = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(COLLREF_CLASS_NAME);
        collRef1.set("id", "112233");
        collRef1.set("value", "collRefVal1");
        DynamicEntity collRef2 = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(COLLREF_CLASS_NAME);
        collRef2.set("id", "445566");
        collRef2.set("value", "collRefVal2");
        collRef.add(collRef1);
        collRef.add(collRef2);
        root.set("collRef", collRef);

        root.set("choice", 2112);

        Vector choiceColl = new Vector(3);
        choiceColl.add(3.14159);
        choiceColl.add("Pi");
        choiceColl.add(Boolean.TRUE);
        root.set("choiceColl", choiceColl);

        docWrapper.set("root", root);
        docWrapper.set("objRefTarget", objRef);
        docWrapper.set("collRefTarget", collRef);

        return docWrapper;
    }

    public void testSecondProject() throws Exception {
        // Ensure that the second project's descriptor is also available from this context

        DynamicEntity emp = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(EMP_CLASS_NAME);
        assertNotNull("Could not instantiate Descriptor from second project.", emp);
    }

    public void testGetSetByXPath() throws Exception {
        NamespaceResolver nsResolver = new NamespaceResolver();
        nsResolver.put("ns0", "myNamespace");
        nsResolver.put("xsi", javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);

        URL url = ClassLoader.getSystemResource(resourceName);
        DynamicEntity docWrapper = (DynamicEntity) jaxbUnmarshaller.unmarshal(url);

        DynamicEntity root = ((DynamicJAXBContext) jaxbContext).getValueByXPath(docWrapper, "ns0:root", nsResolver, DynamicEntity.class);
        assertNotNull(root);

        DynamicEntity anyAtt = root.get("anyAtt");
        DynamicEntity anyAttFromXPath = ((DynamicJAXBContext) jaxbContext).getValueByXPath(root, "any-att", nsResolver, DynamicEntity.class);
        assertEquals(anyAtt, anyAttFromXPath);

        DynamicEntity newAnyAtt = ((DynamicJAXBContext) jaxbContext).newDynamicEntity(ANYATT_CLASS_NAME);
        Properties anyAttProps = new Properties();
        anyAttProps.put(new QName("", "anyAtt1"), "333");
        anyAttProps.put(new QName("", "anyAtt2"), "fourfourfour");
        newAnyAtt.set("value", anyAttProps);

        ((DynamicJAXBContext) jaxbContext).setValueByXPath(root, "any-att", nsResolver, newAnyAtt);

        DynamicEntity newAnyAttFromXPath = ((DynamicJAXBContext) jaxbContext).getValueByXPath(root, "any-att", nsResolver, DynamicEntity.class);
        assertEquals(newAnyAtt, newAnyAttFromXPath);

        Object compColl = root.get("compColl");
        Object compCollFromXPath = ((DynamicJAXBContext) jaxbContext).getValueByXPath(root, "comp-coll/item", nsResolver, ArrayList.class);
        assertEquals(compColl, compCollFromXPath);
    }

    protected void compareObjects(Object controlObject, Object testObject) throws Exception {
        if (objectsAlreadyCheckedForEquality.contains(testObject)) {
            // To handle cyclic relationships, only check each pair of DynamicEntities once
            return;
        }

        if (controlObject == null && testObject == null) {
            // Nothing to check
            return;
        }

        if (controlObject == null && testObject != null) {
            fail("testObject was [" + testObject + "] but controlObject was [" + controlObject + "].");
        }

        if (controlObject != null && testObject == null) {
            fail("testObject was [" + testObject + "] but controlObject was [" + controlObject + "].");
        }

        if (testObject instanceof Element && controlObject instanceof Element) {
            Element testElement = (Element) testObject;
            Element controlElement = (Element) controlObject;

            boolean equal = true;
            try {
                if (testElement.getNodeType() == Node.ATTRIBUTE_NODE && controlElement.getNodeType() == Node.ATTRIBUTE_NODE) {
                    Attr att1 = (Attr) testElement;
                    Attr att2 = (Attr) controlElement;
                    equal = equal && att1.getNodeValue().equals(att2.getNodeValue());
                } else if (testElement.getNodeType() == Node.TEXT_NODE && controlElement.getNodeType() == Node.TEXT_NODE) {
                    Text text1 = (Text) testElement;
                    Text text2 = (Text) controlElement;
                    equal = equal && text1.getNodeValue().equals(text2.getNodeValue());
                } else if (testElement.getNodeType() == Node.ELEMENT_NODE && controlElement.getNodeType() == Node.ELEMENT_NODE) {
                    Element elem1 = testElement;
                    Element elem2 = controlElement;
                    equal = equal && elem1.getNodeName().equals(elem2.getNodeName());
                    equal = equal && (elem1.getChildNodes().getLength() == elem2.getChildNodes().getLength());
                    compareObjects(elem1.getFirstChild().getNodeValue(), elem2.getFirstChild().getNodeValue());
                }
                if (!equal) {
                    fail("testElement was [" + testElement + "] but controlElement was [" + controlElement + "].");
                }
            } catch (Exception e) {
                fail("Element comparison failed: " + e.getLocalizedMessage());
            }
            return;
        }

        if (testObject instanceof List && controlObject instanceof List) {
            if ((((List) testObject).size()) != (((List) controlObject).size())) {
                fail("testObject had [" + ((List) testObject).size() + "] elements but controlObject had [" + ((List) controlObject).size() + "].");
            }
            for (int i = 0; i < ((List) controlObject).size(); i++) {
                compareObjects(((List) controlObject).get(i), ((List) testObject).get(i));
            }
            // We've now checked all the elements so return
            return;
        }

        if (testObject.getClass().isArray() && controlObject.getClass().isArray()) {
            if (!Helper.comparePotentialArrays(testObject, controlObject)) {
                fail("controlObject [" + controlObject + "] is not equal to testObject [" + testObject + "].");
            }
            // We've now checked all the elements so return
            return;
        }

        if (controlObject instanceof DynamicEntityImpl && testObject instanceof DynamicEntityImpl) {
            DynamicEntityImpl dynamicControl = (DynamicEntityImpl) controlObject;
            DynamicEntityImpl dynamicTest = (DynamicEntityImpl) testObject;

            String controlClass = dynamicControl.getType().getClassName();
            String testClass = dynamicTest.getType().getClassName();
            if (!controlClass.equals(testClass)) {
                fail("testObject [" + testClass + "] and controlObject [" + controlClass + "] are not the same class.");
            }

            objectsAlreadyCheckedForEquality.add(testObject);

            if (dynamicControl.getType().getNumberOfProperties() != dynamicTest.getType().getNumberOfProperties()) {
                fail("testObject and controlObject did not have the same number of properties.");
            }

            List<String> propNames = dynamicControl.getType().getPropertiesNames();
            Iterator<String> it = propNames.iterator();
            while (it.hasNext()) {
                String propName = it.next();

                Object controlValue = dynamicControl.get(propName);
                Object testValue = dynamicTest.get(propName);

                compareObjects(controlValue, testValue);
            }
        } else {
            if (!testObject.equals(controlObject)) {
                fail("testObject was [" + testObject + "] but controlObject was [" + controlObject + "].");
            }
        }
    }

    @Override
    public void xmlToObjectTest(Object testObject) throws Exception {
        log("\n**xmlToObjectTest**");
        log("Expected:");
        Object controlObject = getReadControlObject();
        if (null == controlObject) {
            log((String) null);
        } else {
            log(controlObject.toString());
        }
        log("Actual:");
        if (null == testObject) {
            log((String) null);
        } else {
            log(testObject.toString());
        }

        if ((controlObject instanceof XMLRoot) && (testObject instanceof XMLRoot)) {
            XMLRoot controlRoot = (XMLRoot) controlObject;
            XMLRoot testRoot = (XMLRoot) testObject;
            compareXMLRootObjects(controlRoot, testRoot);
        } else {
            objectsAlreadyCheckedForEquality = new ArrayList();
            compareObjects(controlObject, testObject);
        }
    }

}
