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

import java.util.ArrayList;
import java.util.List;

import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.oxm.mappings.nullpolicy.AbstractNullPolicy;
import org.eclipse.persistence.oxm.mappings.nullpolicy.XMLNullRepresentationType;
import org.eclipse.persistence.oxm.record.XMLEntry;
import org.eclipse.persistence.oxm.record.XMLRecord;
import org.eclipse.persistence.platform.xml.XMLNamespaceResolver;
import org.eclipse.persistence.platform.xml.XMLNodeList;
import org.eclipse.persistence.platform.xml.XMLPlatform;
import org.eclipse.persistence.platform.xml.XMLPlatformException;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * INTERNAL:
 * <p><b>Purpose</b>: Utility class for finding XML nodes using XPath
 * expressions.</p>
 * @since Oracle TopLink 10.1.3
 */

public class UnmarshalXPathEngine <
     XML_FIELD extends Field
     > {

    private static UnmarshalXPathEngine instance = null;
    private XMLPlatform xmlPlatform;

    /**
     * The default constructor creates a platform instance
     */
    public UnmarshalXPathEngine() {
        xmlPlatform = XMLPlatformFactory.getInstance().getXMLPlatform();
    }

    /**
     * Return the <code>XPathEngine</code> singleton.
     */
    public static UnmarshalXPathEngine getInstance() {
        if (instance == null) {
            instance = new UnmarshalXPathEngine();
        }
        return instance;
    }

    /**
     * Execute the XPath statement relative to the context node.
     *
     * @param contextNode the node relative to which the XPath statement will be executed
     * @param xmlField the field containing the XPath statement to be executed
     * @param xmlNamespaceResolver used to resolve namespace prefixes to the corresponding namespace URI
     * @return the first node located matching the XPath statement
     */
    public Object selectSingleNode(Node contextNode, XML_FIELD xmlField, XMLNamespaceResolver xmlNamespaceResolver, boolean checkForXsiNil) throws XMLMarshalException {
        try {
            if (contextNode == null) {
                return null;
            }

            XPathFragment xPathFragment = xmlField.getXPathFragment();

            // allow the platform to handle the advanced case
            if (xPathFragment.shouldExecuteSelectNodes()) {
                return xmlPlatform.selectSingleNodeAdvanced(contextNode, xmlField.getXPath(), xmlNamespaceResolver);
            }
            Object result = selectSingleNode(contextNode, xPathFragment, xmlNamespaceResolver, checkForXsiNil);
            if(result == XMLRecord.noEntry) {
                if(xmlField.getLastXPathFragment().nameIsText() || xmlField.getLastXPathFragment().isAttribute()) {
                    return result;
                } else {
                    return null;
                }
            }
            return result;
        } catch (Exception x) {
            throw XMLMarshalException.invalidXPathString(xmlField.getXPath(), x);
        }
    }

    public Object selectSingleNode(Node contextNode, XML_FIELD xmlField, XMLNamespaceResolver xmlNamespaceResolver) throws XMLMarshalException {
        return this.selectSingleNode(contextNode, xmlField, xmlNamespaceResolver, false);
    }

    private Object selectSingleNode(Node contextNode, XPathFragment xPathFragment, XMLNamespaceResolver xmlNamespaceResolver, boolean checkForXsiNil) {
        Node resultNode = getSingleNode(contextNode, xPathFragment, xmlNamespaceResolver);
        if (checkForXsiNil) {
            // Check for presence of xsi:nil="true"
            String nil = ((Element) contextNode).getAttributeNS(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_NIL_ATTRIBUTE);

            if (nil.equals(Constants.BOOLEAN_STRING_TRUE)) {
                return XMLRecord.NIL;
            }
        }
        if (resultNode == null) {



            if(!xPathFragment.nameIsText()) {
                return XMLRecord.noEntry;
            }
            return null;
        }
        if(xPathFragment.getNextFragment() == null) {
            return resultNode;
        }

        return selectSingleNode(resultNode, xPathFragment.getNextFragment(), xmlNamespaceResolver, checkForXsiNil);
    }

    /**
     * Execute the XPath statement relative to the context node.
     *
     * @param contextNode the node relative to which the XPath statement will be executed
     * @param xmlField the field containing the XPath statement to be executed
     * @param xmlNamespaceResolver used to resolve namespace prefixes to the corresponding namespace URI
     * @return a list of nodes matching the XPath statement
     */
    public NodeList selectNodes(Node contextNode, XML_FIELD xmlField, XMLNamespaceResolver xmlNamespaceResolver) throws XMLMarshalException {
        return this.selectNodes(contextNode, xmlField, xmlNamespaceResolver, null);
    }

    public NodeList selectNodes(Node contextNode, XML_FIELD xmlField, XMLNamespaceResolver xmlNamespaceResolver, AbstractNullPolicy nullPolicy) throws XMLMarshalException {
        return selectNodes(contextNode, xmlField, xmlNamespaceResolver, nullPolicy, false);
    }

    public NodeList selectNodes(Node contextNode, XML_FIELD xmlField, XMLNamespaceResolver xmlNamespaceResolver, AbstractNullPolicy nullPolicy, boolean omitText) throws XMLMarshalException {
        return selectNodes(contextNode, xmlField, xmlNamespaceResolver, nullPolicy, omitText, true);
    }

    public NodeList selectNodes(Node contextNode, XML_FIELD xmlField, XMLNamespaceResolver xmlNamespaceResolver, AbstractNullPolicy nullPolicy, boolean omitText, boolean concatinateTextNodes) {
        try {
            if (contextNode == null) {
                return null;
            }

            XPathFragment xPathFragment = xmlField.getXPathFragment();

            // allow the platform to handle the advanced case
            if (xPathFragment.shouldExecuteSelectNodes()) {
                return xmlPlatform.selectNodesAdvanced(contextNode, xmlField.getXPath(), xmlNamespaceResolver);
            }
            return selectNodes(contextNode, xPathFragment, xmlNamespaceResolver, nullPolicy, omitText, concatinateTextNodes);
        } catch (Exception x) {
            throw XMLMarshalException.invalidXPathString(xmlField.getXPath(), x);
        }
    }

    public List<XMLEntry> selectNodes(Node contextNode, List<XML_FIELD> xmlFields, XMLNamespaceResolver xmlNamespaceResolver) throws XMLMarshalException {
        List<XMLEntry> nodes = new ArrayList<>();
        List<XPathFragment> firstFragments = new ArrayList<>(xmlFields.size());
        for(XML_FIELD nextField:xmlFields) {
            firstFragments.add(nextField.getXPathFragment());
        }
        selectNodes(contextNode, firstFragments, xmlNamespaceResolver, nodes);
        return nodes;
    }

    private void selectNodes(Node contextNode, List<XPathFragment> xpathFragments, XMLNamespaceResolver xmlNamespaceResolver, List<XMLEntry> entries) {
        NodeList childNodes = contextNode.getChildNodes();
        for(int i = 0, size = childNodes.getLength(); i < size; i++) {
            Node nextChild = childNodes.item(i);
            List<XPathFragment> matchingFragments = new ArrayList<>();
            for(XPathFragment<XML_FIELD> nextFragment:xpathFragments) {
                if((nextChild.getNodeType() == Node.TEXT_NODE || nextChild.getNodeType() == Node.CDATA_SECTION_NODE) && nextFragment.nameIsText()) {
                    addXMLEntry(nextChild, nextFragment.getXMLField(), entries);
                } else if(nextChild.getNodeType() == Node.ATTRIBUTE_NODE && nextFragment.isAttribute()) {
                    String attributeNamespaceURI = null;
                    if (nextFragment.hasNamespace()) {
                        attributeNamespaceURI = xmlNamespaceResolver.resolveNamespacePrefix(nextFragment.getPrefix());
                    }
                    if(sameName(nextChild, nextFragment.getLocalName()) && sameNamespaceURI(nextChild, attributeNamespaceURI)) {
                        addXMLEntry(nextChild, nextFragment.getXMLField(), entries);
                    }
                } else if(nextChild.getNodeType() == Node.ELEMENT_NODE) {
                    String elementNamespaceURI = null;
                    if(nextFragment.hasNamespace()) {
                        elementNamespaceURI = xmlNamespaceResolver.resolveNamespacePrefix(nextFragment.getPrefix());
                    }
                    if(sameName(nextChild, nextFragment.getLocalName()) && sameNamespaceURI(nextChild, elementNamespaceURI)) {
                        if(nextFragment.getNextFragment() == null) {
                            addXMLEntry(nextChild, nextFragment.getXMLField(), entries);
                        } else {
                            matchingFragments.add(nextFragment.getNextFragment());
                        }
                    }
                }
            }
            if(matchingFragments.size() > 0) {
                selectNodes(nextChild, matchingFragments, xmlNamespaceResolver, entries);
            }
        }
    }

    private void addXMLEntry(Node entryNode, XML_FIELD xmlField, List<XMLEntry> entries) {
        XMLEntry entry = new XMLEntry();
        entry.setValue(entryNode);
        entry.setXMLField(xmlField);
        entries.add(entry);
    }

    private NodeList selectNodes(Node contextNode, XPathFragment xPathFragment, XMLNamespaceResolver xmlNamespaceResolver, AbstractNullPolicy nullPolicy, boolean omitText, boolean concatText) {
        NodeList resultNodes = getNodes(contextNode, xPathFragment, xmlNamespaceResolver, nullPolicy, concatText);

        if (xPathFragment.getNextFragment() != null && !(omitText && xPathFragment.getNextFragment().nameIsText())) {
            Node resultNode;
            XMLNodeList result = new XMLNodeList();
            int numberOfResultNodes = resultNodes.getLength();
            for (int x = 0; x < numberOfResultNodes; x++) {
                resultNode = resultNodes.item(x);
                result.addAll(selectNodes(resultNode, xPathFragment.getNextFragment(), xmlNamespaceResolver, nullPolicy, omitText, concatText));
            }
            return result;
        }

        return resultNodes;
    }

    private Node getSingleNode(Node contextNode, XPathFragment xPathFragment, XMLNamespaceResolver xmlNamespaceResolver) {
        if (xPathFragment.isAttribute()) {
            return selectSingleAttribute(contextNode, xPathFragment, xmlNamespaceResolver);
        } else if (xPathFragment.nameIsText()) {
            return selectSingleText(contextNode);
        } else if (xPathFragment.isSelfFragment()) {
            return contextNode;
        }

        if (xPathFragment.containsIndex()) {
            return selectSingleElement(contextNode, xPathFragment, xmlNamespaceResolver, xPathFragment.getIndexValue());
        }
        return selectSingleElement(contextNode, xPathFragment, xmlNamespaceResolver);
    }

    private NodeList getNodes(Node contextNode, XPathFragment xPathFragment, XMLNamespaceResolver xmlNamespaceResolver, AbstractNullPolicy nullPolicy, boolean concatText) {
        if (xPathFragment.isAttribute()) {
            return selectAttributeNodes(contextNode, xPathFragment, xmlNamespaceResolver);
        } else if (xPathFragment.nameIsText()) {
            return selectTextNodes(contextNode, nullPolicy, concatText);
        } else if (xPathFragment.isSelfFragment()) {
            XMLNodeList xmlNodeList = new XMLNodeList(1);
            xmlNodeList.add(contextNode);
            return xmlNodeList;
        }

        if (xPathFragment.containsIndex()) {
            return selectElementNodes(contextNode, xPathFragment, xmlNamespaceResolver, xPathFragment.getIndexValue());
        }
        return selectElementNodes(contextNode, xPathFragment, xmlNamespaceResolver);
    }

    private Node selectSingleAttribute(Node contextNode, XPathFragment xPathFragment, XMLNamespaceResolver xmlNamespaceResolver) {
        if (xPathFragment.hasNamespace()) {
            if(Node.ELEMENT_NODE == contextNode.getNodeType()) {
                String attributeNamespaceURI = xmlNamespaceResolver.resolveNamespacePrefix(xPathFragment.getPrefix());
                return contextNode.getAttributes().getNamedItemNS(attributeNamespaceURI, xPathFragment.getLocalName());
            } else {
                return null;
            }
        } else {
            if(Node.ELEMENT_NODE == contextNode.getNodeType()) {
                return contextNode.getAttributes().getNamedItem(xPathFragment.getShortName());
            } else {
                return null;
            }
        }
    }

    private NodeList selectAttributeNodes(Node contextNode, XPathFragment xPathFragment, XMLNamespaceResolver xmlNamespaceResolver) {
        XMLNodeList xmlNodeList = new XMLNodeList();

        Node child = selectSingleAttribute(contextNode, xPathFragment, xmlNamespaceResolver);
        if (null != child) {
            xmlNodeList.add(child);
        }
        return xmlNodeList;
    }

    private Node selectSingleElement(Node contextNode, XPathFragment xPathFragment, XMLNamespaceResolver xmlNamespaceResolver) {
        Node child = contextNode.getFirstChild();
        while (null != child) {
            String elementNamespaceURI = null;
            if(xmlNamespaceResolver != null) {
                elementNamespaceURI = xmlNamespaceResolver.resolveNamespacePrefix(xPathFragment.getPrefix());
            }
            if ((child.getNodeType() == Node.ELEMENT_NODE) && sameName(child, xPathFragment.getLocalName()) && sameNamespaceURI(child, elementNamespaceURI)) {
                return child;
            }
            child = child.getNextSibling();
        }
        return null;
    }

    public NodeList selectElementNodes(Node contextNode, XPathFragment xPathFragment, XMLNamespaceResolver xmlNamespaceResolver) {
        XMLNodeList xmlNodeList = new XMLNodeList();
        Node child = contextNode.getFirstChild();

        while (null != child) {
            String elementNamespaceURI = null;
            if(xmlNamespaceResolver != null) {
                elementNamespaceURI = xmlNamespaceResolver.resolveNamespacePrefix(xPathFragment.getPrefix());
            }
            if ((child.getNodeType() == Node.ELEMENT_NODE) && sameName(child, xPathFragment.getLocalName()) && sameNamespaceURI(child, elementNamespaceURI)) {
                XPathPredicate predicate = xPathFragment.getPredicate();
                if(predicate != null) {
                    XPathFragment predicateFragment = predicate.getXPathFragment();
                    if(predicateFragment.isAttribute() && child.getAttributes() != null) {
                        Attr attr = (Attr)child.getAttributes().getNamedItemNS(predicateFragment.getNamespaceURI(), predicateFragment.getLocalName());
                        if(attr != null) {
                            String attribute = attr.getValue();
                            if(xPathFragment.getPredicate().getValue().equals(attribute)) {
                                xmlNodeList.add(child);
                            }
                        }
                    }
                } else {
                    xmlNodeList.add(child);
                }
            }
            child = child.getNextSibling();
        }
        return xmlNodeList;
    }

    private Node selectSingleElement(Node contextNode, XPathFragment xPathFragment, XMLNamespaceResolver xmlNamespaceResolver, int position) {
        Node child = contextNode.getFirstChild();

        while (null != child) {
            String elementNamespaceURI = null;
            if(xmlNamespaceResolver != null) {
                elementNamespaceURI = xmlNamespaceResolver.resolveNamespacePrefix(xPathFragment.getPrefix());
            }
            if ((child.getNodeType() == Node.ELEMENT_NODE) && sameName(child, xPathFragment.getShortName()) && sameNamespaceURI(child, elementNamespaceURI)) {
                if (0 == --position) {
                    return child;
                }
            }
            child = child.getNextSibling();
        }

        return null;
    }

    private NodeList selectElementNodes(Node contextNode, XPathFragment xPathFragment, XMLNamespaceResolver xmlNamespaceResolver, int position) {
        XMLNodeList xmlNodeList = new XMLNodeList();
        Node child = selectSingleElement(contextNode, xPathFragment, xmlNamespaceResolver, position);
        if (null != child) {
            xmlNodeList.add(child);
        }
        return xmlNodeList;
    }

    private Node selectSingleText(Node contextNode) {
        NodeList childrenNodes = contextNode.getChildNodes();
        int numberOfNodes = childrenNodes.getLength();

        if (numberOfNodes == 0) {
            return null;
        }

        if (numberOfNodes == 1) {
            Node child = childrenNodes.item(0);
            if (child.getNodeType() == Node.TEXT_NODE || child.getNodeType() == Node.CDATA_SECTION_NODE) {
                return child;
            }
            return null;
        }

        String returnVal = null;
        for (int i = 0; i < numberOfNodes; i++) {
            Node next = childrenNodes.item(i);
            if (next.getNodeType() == Node.TEXT_NODE || next.getNodeType() == Node.CDATA_SECTION_NODE) {

                String val = next.getNodeValue();
                if (val != null) {
                    if (returnVal == null) {
                        returnVal = "";
                    }
                    if(next.getNodeType() == Node.CDATA_SECTION_NODE) {
                        val = val.trim();
                    }
                    returnVal += val;
                }
            }
        }

        //bug#4515249 a new text node was being created when null should have been returned
        //case where contextNode had several children but no Text children
       if (returnVal != null) {
            return contextNode.getOwnerDocument().createTextNode(returnVal);
       }
        return null;
    }

    private NodeList selectTextNodes(Node contextNode, AbstractNullPolicy nullPolicy, boolean concatText) {
        if(!concatText) {
            return selectAllText(contextNode);
        }

        Node n = selectSingleText(contextNode);

        XMLNodeList xmlNodeList = new XMLNodeList();

        if (n == null && nullPolicy != null) {
            if (nullPolicy.valueIsNull((Element) contextNode)) {
                if (nullPolicy.getMarshalNullRepresentation() != XMLNullRepresentationType.ABSENT_NODE) {
                    xmlNodeList.add(null);
                }
            } else {
                xmlNodeList.add(contextNode.getOwnerDocument().createTextNode(Constants.EMPTY_STRING));
            }
        } else {
            if (nullPolicy != null && nullPolicy.isNullRepresentedByXsiNil() && nullPolicy.valueIsNull((Element) contextNode))  {
                xmlNodeList.add(null);
            }else if (n != null) {
                xmlNodeList.add(n);
            }
        }

        return xmlNodeList;
    }

    private NodeList selectAllText(Node contextNode) {
       XMLNodeList nodes = new XMLNodeList();
       NodeList children = contextNode.getChildNodes();

       for(int i = 0; i < children.getLength(); i++) {
           Node next = children.item(i);
           if (next.getNodeType() == Node.TEXT_NODE || next.getNodeType() == Node.CDATA_SECTION_NODE) {
               nodes.add(next);
           }
       }
       return nodes;
    }

    private boolean sameNamespaceURI(Node node, String namespaceURI) {
        // HANDLE THE NULL CASE
        String nodeNamespaceURI = node.getNamespaceURI();
        if (nodeNamespaceURI == namespaceURI) {
            return true;
        }

        if ((nodeNamespaceURI == null) && namespaceURI.length() == 0) {
            return true;
        }

        if ((namespaceURI == null) && nodeNamespaceURI.length() == 0) {
            return true;
        }

        // HANDLE THE NON-NULL CASE
        return (null != nodeNamespaceURI) && nodeNamespaceURI.equals(namespaceURI);
    }

    private boolean sameName(Node node, String name) {
        return name.equals(node.getLocalName()) || name.equals(node.getNodeName());
    }

}
