/*
 * 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.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Vector;

import org.eclipse.persistence.platform.xml.XMLNamespaceResolver;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * <p >It is common for an XML document to include one or more namespaces.
 * TopLink supports this using its NamespaceResolver. The namespace resolver maintains
 * pairs of namespace prefixes and URIs. TopLink uses these prefixes in conjunction with the
 * XPath statements you specify on EIS mappings to XML records and XML mappings.
 *
 * <p>Although TopLink captures namespace prefixes in the XPath statements for mappings (if applicable),
 * the input document is not required to use the same namespace prefixes. TopLink will use the namespace
 * prefixes specified in the mapping when creating new documents.
 *
 * <p><em>Code Sample</em><br>
 * <code>
 *  <b>NamespaceResolver resolver = new NamespaceResolver();<br>
 *  resolver.put(    "ns", "urn:namespace-example");<br><br></b>
 *
 *  XMLDescriptor descriptor = new XMLDescriptor();<br>
 *  descriptor.setJavaClass(Customer.class); <br>
 *  descriptor.setDefaultRootElement("<b>ns</b>:customer");<br>
 *  descriptor.setNamespaceResolver(resolver);<br><br>
 *
 *  XMLDirectMapping mapping = new XMLDirectMapping();<br>
 *  mapping.setAttributeName("id");<br>
 *  mapping.setXPath("<b>ns</b>:id/text()");<br>
 *  descriptor.addMapping(mapping);
 *  </code>
 *
 *  @see org.eclipse.persistence.oxm.XMLDescriptor
 *  @see org.eclipse.persistence.eis.EISDescriptor
 *
 */
public class NamespaceResolver implements XMLNamespaceResolver {
    private static final String BASE_PREFIX = "ns";
    private static final Vector<Namespace> EMPTY_VECTOR = VectorUtils.emptyVector();

    private String defaultNamespaceURI;
    private NamespaceResolverStorage prefixesToNamespaces;
    private int prefixCounter;
    private Node dom;

    /**
     * Default constructor, creates a new NamespaceResolver.
     */
    public NamespaceResolver() {
        super();
    }

    /**
     * Copy Constructor
     * @since EclipseLink 2.5.0
     */
    public NamespaceResolver(NamespaceResolver namespaceResolver) {
        this.defaultNamespaceURI = namespaceResolver.defaultNamespaceURI;
        setPrefixesToNamespaces(namespaceResolver.prefixesToNamespaces);

        this.prefixCounter = namespaceResolver.prefixCounter;
        this.dom = namespaceResolver.dom;
    }

    private void setPrefixesToNamespaces(Map<String, String> input) {
        if (input == null) {
            return;
        }
        prefixesToNamespaces = new NamespaceResolverStorage(input.size());
        prefixesToNamespaces.putAll(input);
    }

    public Map<String, String> getPrefixesToNamespaces() {
        if (null == prefixesToNamespaces) {
            prefixesToNamespaces = new NamespaceResolverStorage();
        }
        return prefixesToNamespaces;
    }

    public boolean hasPrefixesToNamespaces() {
        return null != prefixesToNamespaces;
    }

    /**
     * Indicates whether given {@code prefix} is assigned to a name-space.
     * @param prefix name-space prefix
     * @return {@code true} if {@code prefix} is present in prefix to name-space map
     * ({@link #getPrefixesToNamespaces()}
     */
    public boolean hasPrefix(String prefix) {
        return null != prefixesToNamespaces ? prefixesToNamespaces.containsKey(prefix) : false;
    }

    public void setDOM(Node dom) {
        this.dom = dom;
    }

    /**
     * Returns the namespace URI associated with a specified namespace prefix
     * @param prefix The prefix to lookup a namespace URI for
     * @return The namespace URI associated with the specified prefix
     */
    @Override
    public String resolveNamespacePrefix(String prefix) {
        if (null == prefix || prefix.length() == 0) {
            return defaultNamespaceURI;
        }
        String uri = null;
        if (null != prefixesToNamespaces) {
            uri = prefixesToNamespaces.get(prefix);
        }
        if (null != uri) {
            return uri;
        } else if (javax.xml.XMLConstants.XML_NS_PREFIX.equals(prefix)) {
            return javax.xml.XMLConstants.XML_NS_URI;
        } else if (javax.xml.XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) {
            return javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
        }
        if (dom != null) {
            return XMLPlatformFactory.getInstance().getXMLPlatform().resolveNamespacePrefix(dom, prefix);
        }
        return null;
    }

    /**
     * Return the namespace prefix associated with a namespace URI.
     * @param uri A namespace URI.
     * @return The prefix associated with the namespace URI.
     */
    public String resolveNamespaceURI(String uri) {
        if (null == uri) {
            return null;
        }
        if (null != prefixesToNamespaces) {
            for (Entry<String, String> entry : prefixesToNamespaces.entrySet()) {
                if (uri.equals(entry.getValue())) {
                    return entry.getKey();
                }
            }
        }
        if (uri.equalsIgnoreCase(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
            return javax.xml.XMLConstants.XMLNS_ATTRIBUTE;
        } else if (uri.equalsIgnoreCase(javax.xml.XMLConstants.XML_NS_URI)) {
            return javax.xml.XMLConstants.XML_NS_PREFIX;
        }
        return resolveNamespaceURI(dom, uri);
    }

    private String resolveNamespaceURI(Node node, String uri) {
        if (null == node) {
            return null;
        }

        // If the element is of the same namespace URI, then return the prefix.
        if (uri.equals(node.getNamespaceURI())) {
            return node.getPrefix();
        }

        // Check the namespace URI declarations.
        NamedNodeMap namedNodeMap = node.getAttributes();
        if (null != namedNodeMap) {
            int namedNodeMapSize = namedNodeMap.getLength();
            for (int x = 0; x < namedNodeMapSize; x++) {
                Node attr = namedNodeMap.item(x);
                if (javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attr.getNamespaceURI())) {
                    if (uri.equals(attr.getNodeValue())) {
                        if (attr.getLocalName() != null && (!(attr.getLocalName()
                            .equals(javax.xml.XMLConstants.XMLNS_ATTRIBUTE)))) {
                            return attr.getLocalName();
                        } else {
                            return "";
                        }
                    }
                }
            }
        }

        // Repeat the process on the parent node.
        return resolveNamespaceURI(node.getParentNode(), uri);
    }

    /**
     * Adds a namespace to the collection of namespaces on the NamespaceResolver
     * @param prefix The prefix for a namespace
     * @param namespaceURI The namespace URI associated with the specified prefix
     */
    public void put(String prefix, String namespaceURI) {
        if (null == prefix || 0 == prefix.length()) {
            defaultNamespaceURI = namespaceURI;
        } else {
            //Replace same namespace with given prefix and put them to the end of list.

            //If you have prefix xmlns:oxm="namespace1" defined on the schema root,
            //and you (programmatically via namespace resolver) inject prefix xmlns:myns="namespace1" on some element (more deeply)
            //in the schema, you want this element (in the xml instance) to be prefixed with this myns (because it was defined more closely to the given element).
            //This can probably be setup in different way (declaratively maybe with some JAXB spec support or MOXy external xml mechanism).
            //This behavior is preserved, but it is now working independently on the JDK (because we are using HashMap and we are changing the order
            //of items in the LinkedHashMap so the resolver always find the prefix which is more closely (in xml schema) to the given element.
            ///@see XMLRootComplexDifferentPrefixTestCases
            List<String> removedKeys = null;
            final String cachedJvmValue = namespaceURI.intern();
            if (getPrefixesToNamespaces().containsValue(cachedJvmValue)) {
                removedKeys = new ArrayList<>();
                for (Map.Entry<String, String> prefixEntry : prefixesToNamespaces.entrySet()) {
                    if (cachedJvmValue.equals(prefixEntry.getValue())) {
                        removedKeys.add(prefixEntry.getKey());
                    }
                }
            }
            if (null != removedKeys) {
                for (String key : removedKeys) {
                    prefixesToNamespaces.remove(key);
                }
            }
            prefixesToNamespaces.put(prefix, cachedJvmValue);
            if (null != removedKeys) {
                for (String key : removedKeys) {
                    prefixesToNamespaces.put(key, cachedJvmValue);
                }
            }
        }
    }

    /**
     * Returns the list of prefixes in the NamespaceResolver
     * @return An Enumeration containing the prefixes in the NamespaceResolver
     */
    public Enumeration<String> getPrefixes() {
        if (hasPrefixesToNamespaces()) {
            return new IteratorEnumeration<>(getPrefixesToNamespaces().keySet().iterator());
        } else {
            return new IteratorEnumeration<>(null);
        }
    }

    /**
     * INTERNAL:
     * Returns a Vector of of Namespace objects in the current Namespace Resolver
     * Used for deployment XML
     * @return A Vector containing the namespace URIs in the namespace resolver
     */
    public Vector<Namespace> getNamespaces() {
        if (!hasPrefixesToNamespaces()) {
            return EMPTY_VECTOR;
        }
        return prefixesToNamespaces.getNamespaces();
    }

    /**
     * INTERNAL:
     * Set the namespaces on the namespace resolver based on the specified Vector of Namespace objects
     * Used for deployment XML
     * @param names A Vector of namespace URIs
     */
    public void setNamespaces(Vector<Namespace> names) {
        prefixesToNamespaces = new NamespaceResolverStorage(names.size());
        prefixesToNamespaces.setNamespaces(names);
    }

    public String generatePrefix() {
        return generatePrefix(getNextPrefix());
    }

    private String getNextPrefix() {
        return BASE_PREFIX + prefixCounter++;
    }

    public String generatePrefix(String defaultPrefix) {
        String lookup = resolveNamespacePrefix(defaultPrefix);
        while (lookup != null) {
            defaultPrefix = getNextPrefix();
            lookup = resolveNamespacePrefix(defaultPrefix);
        }
        return defaultPrefix;
    }

    public void removeNamespace(String prefix) {
        if (null != prefixesToNamespaces) {
            prefixesToNamespaces.remove(prefix);
        }
    }

    public void setDefaultNamespaceURI(String namespaceUri) {
        if (namespaceUri == null) {
            defaultNamespaceURI = null;
        } else {
            defaultNamespaceURI = namespaceUri.intern();
        }
    }

    public String getDefaultNamespaceURI() {
        if (null != defaultNamespaceURI) {
            return defaultNamespaceURI;
        } else if (dom != null) {
            return XMLPlatformFactory.getInstance().getXMLPlatform().resolveNamespacePrefix(dom, null);
        }
        return null;
    }

    private static class IteratorEnumeration<E> implements Enumeration<E> {

        private final Iterator<E> iterator;

        public IteratorEnumeration(Iterator<E> iterator) {
            this.iterator = iterator;
        }

        @Override
        public boolean hasMoreElements() {
            if (null == iterator) {
                return false;
            }
            return iterator.hasNext();
        }

        @Override
        public E nextElement() {
            return iterator.next();
        }

    }
}