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

import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import junit.framework.TestCase;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.oxm.XPathEngine;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.platform.xml.XMLPlatformException;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.eclipse.persistence.platform.xml.XMLTransformer;
import org.eclipse.persistence.sessions.factories.SessionManager;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

public class XPathEngineCreateTestCases extends org.eclipse.persistence.testing.oxm.XMLTestCase {

    private Document controlDocument;
    private Element searchNode;
    private AbstractSession session;

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

    @Override
    public void setUp() throws Exception {
        InputStream inputStream = ClassLoader.getSystemResourceAsStream("org/eclipse/persistence/testing/oxm/xpathengine/AddressBook.xml");

        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        builderFactory.setIgnoringElementContentWhitespace(true);
        DocumentBuilder parser = builderFactory.newDocumentBuilder();
        controlDocument = parser.parse(inputStream);

        searchNode = controlDocument.getDocumentElement();

        XMLContext ctx = new XMLContext(new org.eclipse.persistence.testing.oxm.xmlmarshaller.XMLMarshallerTestProject());
        session = (AbstractSession) ctx.getSession(0);
    }

    // ==========================================================================================

    public void testCreateElement() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        String fieldName = "newElement";
        XMLField field = new XMLField(fieldName);
        XPathEngine.getInstance().create(field, searchNode, session);
        XPathEngine.getInstance().create(field, searchNode, session);

        NodeList verifyNodes = searchNode.getElementsByTagName(fieldName);

        assertTrue("XPath failed to create the element.", verifyNodes.getLength() > 0);

        assertTrue("XPath failed to create the correct number of elements.", verifyNodes.getLength() == 2);

        searchNode = backupNode;
    }

    // ==========================================================================================

    public void testCreateElementWithValue() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        String newElementValue = "newValue";

        String fieldName = "newElement";
        XMLField field = new XMLField(fieldName);
        Node createdNode = XPathEngine.getInstance().create(field, searchNode, newElementValue, session);

        NodeList verifyNodes = searchNode.getElementsByTagName(fieldName);

        assertTrue("XPath failed to create the element.", verifyNodes != null);
        assertTrue("XPath failed to create the element.", verifyNodes.getLength() == 1);

        assertEquals("New element's value was not created.", verifyNodes.item(0).getFirstChild().getNodeValue(), newElementValue);

        searchNode = backupNode;
    }

    // ==========================================================================================
    public void testCreateElementWithNullValue() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);
        ArrayList value = new ArrayList();

        String fieldName = "newElement";
        XMLField field = new XMLField(fieldName);
        Node createdNode = XPathEngine.getInstance().create(field, searchNode, value, session);

        NodeList verifyNodes = searchNode.getElementsByTagName(fieldName);

        assertTrue("XPath created the element and should not have.", createdNode == null);
        assertTrue("XPath created the element and should not have.", verifyNodes.getLength() == 0);

        searchNode = backupNode;
    }

    // ==========================================================================================
    public void testCreateElementWithChildElements() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        String fieldName = "newElement/newChild";
        XMLField field = new XMLField(fieldName);
        XPathEngine.getInstance().create(field, searchNode, session);
        XPathEngine.getInstance().create(field, searchNode, session);

        NodeList verifyNodes = searchNode.getElementsByTagName("newChild");

        assertTrue("XPath failed to create the correct number of child elements.", verifyNodes.getLength() == 2);

        searchNode = backupNode;
    }

    // ==========================================================================================

    public void testCreateElementWithElementValue() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        Document document = builderFactory.newDocumentBuilder().newDocument();

        Element elementValue = document.createElement("newChildWithElementValue");
        Element elementValueChild = document.createElement("newChildElementValue");

        Text textNode = document.createTextNode("theValue");
        elementValueChild.appendChild(textNode);
        elementValue.appendChild(elementValueChild);

        String fieldName = "newElement/newChildWithElementValue";
        XMLField field = new XMLField(fieldName);

        Node created = XPathEngine.getInstance().create(field, searchNode, elementValue, session);
        NodeList verifyNodes = searchNode.getElementsByTagName("newChildWithElementValue");

        assertTrue("XPath failed to create the child elements.", verifyNodes != null);
        assertTrue("XPath failed to create the correct number of child elements.", verifyNodes.getLength() == 1);

        StringWriter stringWriter1 = new StringWriter();
        PrintWriter writer1 = new PrintWriter(stringWriter1);
        try {
            XMLTransformer xmlTransformer = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLTransformer();
            xmlTransformer.transform(elementValue, writer1);
        } catch (XMLPlatformException exception) {
            fail("An XMLPlatformException was thrown");
            return;
        }

        StringWriter stringWriter2 = new StringWriter();
        PrintWriter writer2 = new PrintWriter(stringWriter2);
        try {
            XMLTransformer xmlTransformer = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLTransformer();
            xmlTransformer.transform(verifyNodes.item(0), writer2);
        } catch (XMLPlatformException exception) {
            fail("An XMLPlatformException was thrown");
            return;
        }

        assertTrue(stringWriter1.toString().equals(stringWriter2.toString()));
        searchNode = backupNode;
    }

    // ==========================================================================================

    public void testCreateIndexedElement() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        String fieldName = "newIndexedElement[10]";
        XMLField field = new XMLField(fieldName);
        XPathEngine.getInstance().create(field, searchNode, session);

        NodeList verifyNodes = searchNode.getElementsByTagName("newIndexedElement");

        searchNode = backupNode;
    }

    // ==========================================================================================

    public void testCreateIndexedElementWithValue() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        String fieldName = "newIndexedElement[10]";
        XMLField field = new XMLField(fieldName);

        String newElementValue = "newValue";

        Node createdNode = XPathEngine.getInstance().create(field, searchNode, newElementValue, session);

        NodeList verifyNodes = searchNode.getElementsByTagName("newIndexedElement");

        assertTrue("XPath failed to create the element.", verifyNodes != null);
        assertTrue("XPath failed to create the correct number of elements.", verifyNodes.getLength() == 10);
        Node verifyNode = verifyNodes.item(9);
        assertEquals("New element's value was not created.", verifyNode.getFirstChild().getNodeValue(), newElementValue);

        searchNode = backupNode;
    }

    // ==========================================================================================

    public void testCreateIndexedElementWithValueAlreadyExists() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        String newElementValue = "newValue";

        String fieldName = "newIndexedElement[10]";
        XMLField field = new XMLField(fieldName);

        Node createdNodeExisting = XPathEngine.getInstance().create(field, searchNode, newElementValue, session);
        Node createdNode = XPathEngine.getInstance().create(field, searchNode, newElementValue, session);

        NodeList verifyNodes = searchNode.getElementsByTagName("newIndexedElement");

        assertTrue("XPath failed to create the element.", verifyNodes != null);
        assertTrue("XPath failed to create the correct number of elements.", verifyNodes.getLength() == 10);

        Node verifyNode = verifyNodes.item(9);
        assertEquals("New element's value was not created.", verifyNode.getFirstChild().getNodeValue(), newElementValue);

        searchNode = backupNode;
    }

    // ==========================================================================================

    public void testCreateIndexedElementWithChildElements() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        String fieldName = "newIndexedElement[1]/newChild";
        XMLField field = new XMLField(fieldName);
        XPathEngine.getInstance().create(field, searchNode, session);
        XPathEngine.getInstance().create(field, searchNode, session);

        NodeList parentNodes = searchNode.getElementsByTagName("newIndexedElement");
        Element indexedElement = (Element) parentNodes.item(0);

        NodeList verifyNodes = indexedElement.getElementsByTagName("newChild");

        assertTrue("XPath failed to create the correct number of child elements.", verifyNodes.getLength() == 2);

        searchNode = backupNode;
    }

    // ==========================================================================================

    public void testCreateAttribute() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        String fieldName = "address/@newAttribute";
        XMLField field = new XMLField(fieldName);
        XPathEngine.getInstance().create(field, searchNode, session);

        NodeList verifyNodes = searchNode.getElementsByTagName("address");
        Element verifyNode = (Element) verifyNodes.item(0);
        verifyNode.getAttributeNode("newAttribute");

        assertTrue("XPath failed to create the attribute.", verifyNode != null);

        searchNode = backupNode;
    }

    // ==========================================================================================

    public void testCreateAttributeWithValue() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        String newAttributeValue = "newValue";

        String fieldName = "address/@newAttribute";
        XMLField field = new XMLField(fieldName);

        XPathEngine.getInstance().create(field, searchNode, newAttributeValue, session);

        NodeList verifyNodes = searchNode.getElementsByTagName("address");
        int length = verifyNodes.getLength();
        Element verifyElement = (Element) verifyNodes.item(1);

        Node verifyNode = verifyElement.getAttributeNode("newAttribute");

        assertTrue("XPath failed to create the attribute.", verifyNode != null);

        assertEquals("New attribute's value was not created.", newAttributeValue, verifyElement.getAttribute("newAttribute"));

        searchNode = backupNode;
    }

    // ==========================================================================================

    public void testCreateAttributeOnIndexedElement() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        String fieldName = "newIndexedElement[5]/@newAttribute";
        XMLField field = new XMLField(fieldName);
        XPathEngine.getInstance().create(field, searchNode, session);

        NodeList verifyNodes = searchNode.getElementsByTagName("newIndexedElement");
        Element verifyElement = (Element) verifyNodes.item(4);
        Node verifyNode = verifyElement.getAttributeNode("newAttribute");

        assertTrue("XPath failed to create the attribute.", verifyNodes.getLength() != 0);
        assertTrue("XPath failed to create the indexed elements.", verifyNodes.getLength() == 5);
        assertTrue("XPath failed to create the attribute.", verifyNode != null);

        searchNode = backupNode;
    }

    // ==========================================================================================

    public void testCreateElementAndMultipleAttributes() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        String fieldName = "newElement/@firstAttribute";
        XMLField field = new XMLField(fieldName);
        XPathEngine.getInstance().create(field, searchNode, session);

        String fieldName2 = "newElement/@secondAttribute";
        XMLField field2 = new XMLField(fieldName2);
        XPathEngine.getInstance().create(field2, searchNode, session);

        NodeList verifyNodes = searchNode.getElementsByTagName("newElement");

        assertTrue("XPath failed to create the attribute.", verifyNodes.getLength() != 0);
        assertTrue("XPath created too many attributes, should only have created one.", verifyNodes.getLength() == 1);

        Element element = (Element) verifyNodes.item(0);

        assertTrue("XPath did not create both attributes.", element.getAttributes().getLength() == 2);

        searchNode = backupNode;
    }

    // ==========================================================================================
    public void testCreateInvalidIndexedElement() throws Exception {
        Element backupNode = (Element) searchNode.cloneNode(true);

        try {
            String fieldName = "newIndexedElement[10.0]";
            XMLField field = new XMLField(fieldName);
            XPathEngine.getInstance().create(field, searchNode, session);
        } catch (XMLMarshalException validationException) {
            assertTrue("An unexpected XMLMarshalException was caught. " + validationException.getMessage(), validationException.getErrorCode() == XMLMarshalException.INVALID_XPATH_INDEX_STRING);
            return;
        } catch (Exception e) {
            fail("An unexpected Exception was caught. " + e.getMessage());
            return;
        }
        searchNode = backupNode;
        assertTrue(false);
    }
}
