/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id$
 */
package org.apache.xml.serializer;

import java.util.Enumeration;
import java.util.Hashtable;

import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;

/**
 * This class keeps track of the currently defined namespaces. Conceptually the
 * prefix/uri/depth triplets are pushed on a stack pushed on a stack. The depth
 * indicates the nesting depth of the element for which the mapping was made.
 * 
 * <p>For example:
 * <pre>
 * <chapter xmlns:p1="def">
 *   <paragraph xmlns:p2="ghi">
 *      <sentance xmlns:p3="jkl">
 *      </sentance>
 *    </paragraph>
 *    <paragraph xlmns:p4="mno">
 *    </paragraph>
 * </chapter>
 * </pre>
 * 
 * When the <chapter> element is encounted the prefix "p1" associated with uri
 * "def" is pushed on the stack with depth 1.
 * When the first <paragraph> is encountered "p2" and "ghi" are pushed with
 * depth 2.
 * When the <sentance> is encountered "p3" and "jkl" are pushed with depth 3.
 * When </sentance> occurs the popNamespaces(3) will pop "p3"/"jkl" off the
 * stack.  Of course popNamespaces(2) would pop anything with depth 2 or
 * greater.
 * 
 * So prefix/uri pairs are pushed and poped off the stack as elements are
 * processed.  At any given moment of processing the currently visible prefixes
 * are on the stack and a prefix can be found given a uri, or a uri can be found
 * given a prefix.
 *
 * This class is intended for internal use only.  However, it is made public because
 * other packages require it. 
 * @xsl.usage internal
 */
public class NamespaceMappings
{
    /**
     * This member is continually incremented when new prefixes need to be
     * generated. ("ns0"  "ns1" ...)
     */
    private int count = 0;

    /**
     * Each entry (prefix) in this hashtable points to a Stack of URIs
     * This table maps a prefix (String) to a Stack of NamespaceNodes.
     * All Namespace nodes in that retrieved stack have the same prefix,
     * though possibly different URI's or depths. Such a stack must have
     * mappings at deeper depths push later on such a stack.  Mappings pushed
     * earlier on the stack will have smaller values for MappingRecord.m_declarationDepth.
     */
    private Hashtable m_namespaces = new Hashtable();

    /** 
     * This stack is used as a convenience.
     * It contains the pushed NamespaceNodes (shallowest
     * to deepest) and is used to delete NamespaceNodes 
     * when leaving the current element depth 
     * to returning to the parent. The mappings of the deepest
     * depth can be popped of the top and the same node
     * can be removed from the appropriate prefix stack.
     * 
     * All prefixes pushed at the current depth can be 
     * removed at the same time by using this stack to
     * ensure prefix/uri map scopes are closed correctly.
     */
    private Stack m_nodeStack = new Stack();

    private static final String EMPTYSTRING = "";
    private static final String XML_PREFIX = "xml"; // was "xmlns"

    /**
     * Default constructor
     * @see java.lang.Object#Object()
     */
    public NamespaceMappings()
    {
        initNamespaces();
    }

    /**
     * This method initializes the namespace object with appropriate stacks
     * and predefines a few prefix/uri pairs which always exist.
     */
    private void initNamespaces()
    {
        // The initial prefix mappings will never be deleted because they are at element depth -1 
        // (a kludge)
        
        // Define the default namespace (initially maps to "" uri)
        Stack stack;
        MappingRecord nn;
        nn = new MappingRecord(EMPTYSTRING, EMPTYSTRING, -1);
        stack = createPrefixStack(EMPTYSTRING);
        stack.push(nn);

        // define "xml" namespace
        nn = new MappingRecord(XML_PREFIX, "http://www.w3.org/XML/1998/namespace", -1);
        stack = createPrefixStack(XML_PREFIX);
        stack.push(nn);
    }

    /**
     * Use a namespace prefix to lookup a namespace URI.
     * 
     * @param prefix String the prefix of the namespace
     * @return the URI corresponding to the prefix, returns ""
     * if there is no visible mapping.
     */
    public String lookupNamespace(String prefix)
    {
        String uri = null;
        final Stack stack = getPrefixStack(prefix);
        if (stack != null && !stack.isEmpty()) {
            uri = ((MappingRecord) stack.peek()).m_uri;
        }
        if (uri == null)
            uri = EMPTYSTRING;
        return uri;
    }
  
    
    MappingRecord getMappingFromPrefix(String prefix) {
        final Stack stack = (Stack) m_namespaces.get(prefix);
        return stack != null && !stack.isEmpty() ? 
            ((MappingRecord) stack.peek()) : null;
    }

    /**
     * Given a namespace uri, and the namespaces mappings for the 
     * current element, return the current prefix for that uri.
     * 
     * @param uri the namespace URI to be search for
     * @return an existing prefix that maps to the given URI, null if no prefix
     * maps to the given namespace URI.
     */
    public String lookupPrefix(String uri)
    {
        String foundPrefix = null;
        Enumeration prefixes = m_namespaces.keys();
        while (prefixes.hasMoreElements())
        {
            String prefix = (String) prefixes.nextElement();
            String uri2 = lookupNamespace(prefix);
            if (uri2 != null && uri2.equals(uri))
            {
                foundPrefix = prefix;
                break;
            }
        }
        return foundPrefix;
    }
    
    MappingRecord getMappingFromURI(String uri)
    {
        MappingRecord foundMap = null;
        Enumeration prefixes = m_namespaces.keys();
        while (prefixes.hasMoreElements())
        {
            String prefix = (String) prefixes.nextElement();
            MappingRecord map2 = getMappingFromPrefix(prefix);
            if (map2 != null && (map2.m_uri).equals(uri))
            {
                foundMap = map2;
                break;
            }
        }
        return foundMap;
    }

    /**
     * Undeclare the namespace that is currently pointed to by a given prefix
     */
    boolean popNamespace(String prefix)
    {
        // Prefixes "xml" and "xmlns" cannot be redefined
        if (prefix.startsWith(XML_PREFIX))
        {
            return false;
        }

        Stack stack;
        if ((stack = getPrefixStack(prefix)) != null)
        {
            stack.pop();
            return true;
        }
        return false;
    }

    /**
     * Declare a mapping of a prefix to namespace URI at the given element depth.
     * @param prefix a String with the prefix for a qualified name
     * @param uri a String with the uri to which the prefix is to map
     * @param elemDepth the depth of current declaration
     */
    public boolean pushNamespace(String prefix, String uri, int elemDepth)
    {
        boolean pushed;
        // Prefixes "xml" and "xmlns" cannot be redefined
        if (!prefix.startsWith(XML_PREFIX))
        {

            Stack stack;
            // Get the stack that contains URIs for the specified prefix
            if ((stack = getPrefixStack(prefix)) == null)
                stack = createPrefixStack(prefix);

            switch (stack.top)
            {
                case -1 :
                    pushed = true;  // stack is empty, so push the new one on the stack
                    break;
                case 0 :
                    {
                        // only one thing on the stack, if the new one is the
                        // same prefix/uri mapping as the old one don't push, 
                        // but if the uri's differ push it on the stack.
                        MappingRecord pm = (MappingRecord) stack.peek();
                        if (uri.equals(pm.m_uri))
                            pushed = false;
                        else
                            pushed = true;
                    }
                    break;
                default : // 2 or more things on the stack
                    {
                        MappingRecord pm = (MappingRecord) stack.peek();
                        if (null == pm.m_uri
                            && !uri.equals(EMPTYSTRING)
                            && pm.m_declarationDepth == elemDepth)
                        {
                            // The top of the stack masks shallower mappings and
                            // the new mapping is at the same depth as the masking
                            // and the masked mapping is the same as the new one
                            
                            MappingRecord pm2 =
                                (MappingRecord) stack.peek(stack.top - 1);
                            if (uri.equals(pm2.m_uri))
                            {
                                // The masked mapping is the same as the new one
                                // so don't push this mapping, but delete the masking
                                // one by popping it off the top
                                // This is an optimization to re-use the ancestors mapping.
                                pushed = false;
                                stack.pop();
                            }
                            else
                                pushed = true;
                            // the ancestors mapping differs, so push it
                        }
                        else
                        {
                            // The mapping at the top of the stack is not a masking
                            // or is shallower than the new one or the new mapping is
                            // itself not a masking
                            if (uri.equals(pm.m_uri))
                            {
                                pushed = false;
                                // old and new URI's are the same, don't push
                                // this is an optimization to re-use the ancestors mapping
                            }
                            else
                                pushed = true;
                                // old and new URI's differ, so push                      
                        }
                    }
                break;
            }
            if (pushed)
            {

                MappingRecord namespaceNode =
                    new MappingRecord(prefix, uri, elemDepth);
                stack.push(namespaceNode);
                //        m_nodeStack.push(new Integer(elemDepth));
                m_nodeStack.push(namespaceNode);
            }

        }
        else
            pushed = false;

        return pushed;
    }

    /**
     * Pop, or undeclare all namespace definitions that are currently
     * declared at the given element depth, or deepter.
     * @param elemDepth the element depth for which mappings declared at this
     * depth or deeper will no longer be valid
     * @param saxHandler The ContentHandler to notify of any endPrefixMapping()
     * calls.  This parameter can be null.
     */
    void popNamespaces(int elemDepth, ContentHandler saxHandler)
    {
        while (true)
        {
            if (m_nodeStack.isEmpty())
                return;
            MappingRecord map = (MappingRecord) (m_nodeStack.peek());
            int depth = map.m_declarationDepth;
            if (elemDepth < 1 || map.m_declarationDepth < elemDepth)
                break;
            /* the depth of the declared mapping is elemDepth or deeper
             * so get rid of it
             */

            MappingRecord nm1 = (MappingRecord) m_nodeStack.pop();
            // pop the node from the stack
            String prefix = map.m_prefix;

            Stack prefixStack = getPrefixStack(prefix);
            MappingRecord nm2 = (MappingRecord) prefixStack.peek();
            if (nm1 == nm2)
            {
                // It would be nice to always pop() but we
                // need to check that the prefix stack still has
                // the node we want to get rid of. This is because
                // the optimization of essentially this situation:
                // <a xmlns:x="abc"><b xmlns:x="" xmlns:x="abc" /></a>
                // will remove both mappings in <b> because the
                // new mapping is the same as the masked one and we get
                // <a xmlns:x="abc"><b/></a>
                // So we are only removing xmlns:x="" or
                // xmlns:x="abc" from the depth of element <b>
                // when going back to <a> if in fact they have
                // not been optimized away.
                // 
                prefixStack.pop();
                if (saxHandler != null)
                {
                    try
                    {
                        saxHandler.endPrefixMapping(prefix);
                    }
                    catch (SAXException e)
                    {
                        // not much we can do if they aren't willing to listen
                    }
                }
            }

        }
    }

    /**
     * Generate a new namespace prefix ( ns0, ns1 ...) not used before
     * @return String a new namespace prefix ( ns0, ns1, ns2 ...)
     */
    public String generateNextPrefix()
    {
        return "ns" + (count++);
    }

 
    /**
     * This method makes a clone of this object.
     *
     */
    public Object clone() throws CloneNotSupportedException {
        NamespaceMappings clone = new NamespaceMappings();
        clone.m_nodeStack = (NamespaceMappings.Stack) m_nodeStack.clone();        
        clone.count = this.count;
        clone.m_namespaces = (Hashtable) m_namespaces.clone();
        
        clone.count = count;
        return clone;
        
    }
    
    final void reset()
    {
        this.count = 0;
        this.m_namespaces.clear();
        this.m_nodeStack.clear();        
        
        initNamespaces();
    }
    
    /**
     * Just a little class that ties the 3 fields together
     * into one object, and this simplifies the pushing
     * and popping of namespaces to one push or one pop on
     * one stack rather than on 3 separate stacks.
     */
    class MappingRecord {
        final String m_prefix;  // the prefix
        final String m_uri;     // the uri, possibly "" but never null
        // the depth of the element where declartion was made
        final int m_declarationDepth;
        MappingRecord(String prefix, String uri, int depth) {
            m_prefix = prefix;
            m_uri = (uri==null)? EMPTYSTRING : uri;
            m_declarationDepth = depth;
        }
    }    
    
    /**
     * Rather than using java.util.Stack, this private class
     * provides a minimal subset of methods and is faster
     * because it is not thread-safe.
     */
    private class Stack {
        private int top = -1;
        private int max = 20;
        Object[] m_stack = new Object[max];
        
        public Object clone() throws CloneNotSupportedException {
            NamespaceMappings.Stack clone = new NamespaceMappings.Stack();  
            clone.max = this.max;
            clone.top = this.top;
            clone.m_stack = new Object[clone.max];
            for (int i=0; i <= top; i++) {
            	// We are just copying references to immutable MappingRecord objects here
            	// so it is OK if the clone has references to these.
            	clone.m_stack[i] = this.m_stack[i];
            }
            return clone;            
        }
        
        public Stack()
        {
        }
        
        public Object push(Object o) {
            top++;
            if (max <= top) {
                int newMax = 2*max + 1;
                Object[] newArray = new Object[newMax];
                System.arraycopy(m_stack,0, newArray, 0, max);
                max = newMax;
                m_stack = newArray;
            }
            m_stack[top] = o;
            return o;
        }
        
        public Object pop() {
            Object o;
            if (0 <= top) {
                o = m_stack[top];
                // m_stack[top] = null;  do we really care?
                top--;
            }
            else
                o = null;
            return o;
        }
        
        public Object peek() {
            Object o;
            if (0 <= top) {
                o = m_stack[top];
            }
            else
                o = null;
            return o;
        }
        
        public Object peek(int idx) {
            return m_stack[idx];
        }
        
        public boolean isEmpty() {
            return (top < 0);
        }
        public boolean empty() {
            return (top < 0);
        }
        
        public void clear() {
            for (int i=0; i<= top; i++)
                m_stack[i] = null;
            top = -1;
        }  
        
        public Object getElement(int index) {
            return m_stack[index];      
        }
    }
    /**
     * A more type-safe way to get a stack of prefix mappings
     * from the Hashtable m_namespaces
     * (this is the only method that does the type cast).
     */

    private Stack getPrefixStack(String prefix) {
        Stack fs = (Stack) m_namespaces.get(prefix);
        return fs;
    }
    
    /**
     * A more type-safe way of saving stacks under the
     * m_namespaces Hashtable.
     */
    private Stack createPrefixStack(String prefix)
    {
        Stack fs = new Stack();
        m_namespaces.put(prefix, fs);
        return fs;
    }
    
    /**
     * Given a namespace uri, get all prefixes bound to the Namespace URI in the current scope. 
     * 
     * @param uri the namespace URI to be search for
     * @return An array of Strings which are
     * all prefixes bound to the namespace URI in the current scope.
     * An array of zero elements is returned if no prefixes map to the given
     * namespace URI.
     */
    public String[] lookupAllPrefixes(String uri)
    {
        java.util.ArrayList foundPrefixes = new java.util.ArrayList();
        Enumeration prefixes = m_namespaces.keys();
        while (prefixes.hasMoreElements())
        {
            String prefix = (String) prefixes.nextElement();
            String uri2 = lookupNamespace(prefix);
            if (uri2 != null && uri2.equals(uri))
            {
                foundPrefixes.add(prefix);
            }
        }
        String[] prefixArray = new String[foundPrefixes.size()];
        foundPrefixes.toArray(prefixArray);
        return prefixArray;
    }
}
