/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:  
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "NamespaceResolver.hpp"



#include <vector>



#include <XalanDOM/XalanNode.hpp>
#include <XalanDOM/XalanNamedNodeMap.hpp>



#include <PlatformSupport/XalanUnicode.hpp>



#include "DOMServices.hpp"



NamespaceResolver::NamespaceResolver() :
	m_NSInfos()
{
}



NamespaceResolver::~NamespaceResolver()
{
}


void
NamespaceResolver::reset()
{
	m_NSInfos.clear();
}


// Manefest constants: Prebuilt NSInfo objects for standard combinations
static NSInfo	theNSInfoUnProcWithXMLNS(false, true);
static NSInfo	theNSInfoUnProcWithoutXMLNS(false, false);
static NSInfo	theNSInfoUnProcNoAncestorXMLNS(false, false, NSInfo::ANCESTORNOXMLNS);
static NSInfo	theNSInfoNullWithXMLNS(true, true);
static NSInfo	theNSInfoNullWithoutXMLNS(true, false);
static NSInfo	theNSInfoNullNoAncestorXMLNS(true, false, NSInfo::ANCESTORNOXMLNS);


// Set (or reset) the cached NSInfo associated with a Node
void
NamespaceResolver::updateNamespace(
			const XalanNode*	theNode,
			const NSInfo&		theNamespace) const
{
#if defined(XALAN_NO_MUTABLE)
#if defined(XALAN_OLD_STYLE_CASTS)
	((NamespaceResolver*)this)->m_NSInfos[theNode] = theNamespace;
#else
	const_cast<NamespaceResolver*>(this)->m_NSInfos[theNode] = theNamespace;
#endif
#else
	m_NSInfos[theNode] = theNamespace;
#endif
}


// Find the name of the namespace bound to the current node. This is done by searching
// upward through the model for a Namespace Declaration attribute. Once resolved, the
// namespace is cached in the m_NSInfos table for faster retrieval. 
//
// Note that DOM Level 2 binds this value at the time the node is built, which should
// be considerably more efficient.
const XalanDOMString&
NamespaceResolver::getNamespaceOfNode(const XalanNode&	theNode) const
{
#if !defined(XALAN_NO_NAMESPACES)
	using std::make_pair;
	using std::pair;
	using std::vector;
#endif

	const XalanNode*				theLocalNode = &theNode;

	bool							hasProcessedNS;
    
	NSInfo							nsInfo;

    const XalanNode::NodeType		ntype = theLocalNode->getNodeType();

	NSInfoMapType::const_iterator	theIterator = m_NSInfos.end();

	// Find the node in the map of cached nodes, if it's not an
	// attribute node.
	if(XalanNode::ATTRIBUTE_NODE != ntype)
	{
		theIterator = m_NSInfos.find(theLocalNode);

		if (theIterator == m_NSInfos.end())
		{
			// Not found.
			hasProcessedNS = false;
		}
		else
		{
			// Ahh, we found it.
			nsInfo = (*theIterator).second;
			hasProcessedNS = nsInfo.m_hasProcessedNS;
		}
    }
    else
    {
		hasProcessedNS = false;
    }

	const XalanDOMString*	namespaceOfPrefix = &DOMServices::s_emptyString;

	if(hasProcessedNS)
	{
		namespaceOfPrefix = &nsInfo.m_namespace;
	}
	else
	{
		const XalanDOMString&		nodeName = theLocalNode->getNodeName();

		XalanDOMString::size_type	indexOfNSSep = indexOf(nodeName, XalanUnicode::charColon);

		XalanDOMString			prefix;

		// JKESS CHANGE: Attributes which have no prefix have no namespace,
		// per standard Namespaces In XML behavior. They should not inherit from
		// their owning Element, nor use the default namespace.
		if(XalanNode::ATTRIBUTE_NODE == ntype && indexOfNSSep >= length(nodeName))
		{
			// Attibute nodes aren't handled by the nsInfos logic above.
			// And since this is the no-prefix case, it won't buy us anything for
			// explicit prefix lookups. Hence, I don't see any reason to register
			// this result via updateNamespace.

			// BIG UGLY RETURN HERE!!!!!!!
			return *namespaceOfPrefix;
		}

		prefix = (indexOfNSSep < length(nodeName))
				? substring(nodeName, 0, indexOfNSSep) 
				: XalanDOMString();

		bool	ancestorsHaveXMLNS = false;
		bool	nHasXMLNS = false;

		// The xml: prefix is hardcoded
		// (In the DOM, so is the xmlns: prefix... but that's DOM behavior,
		// not specified by the NS spec.)
		if(equals(prefix, DOMServices::s_XMLString) == true)
		{
			namespaceOfPrefix = &DOMServices::s_XMLNamespaceURI;
		}
		else
		{
			XalanNode::NodeType		parentType = XalanNode::UNKNOWN_NODE;
			const XalanNode*		parent = theLocalNode;

			typedef pair<const XalanNode*, NSInfo>			CandidateNoAncestorEntryType;
			typedef vector<CandidateNoAncestorEntryType>	CandidateNoAncestorVectorType;

			CandidateNoAncestorVectorType	candidateNoAncestorXMLNS;

			candidateNoAncestorXMLNS.reserve(eDefaultVectorSize);

			// Hunt upward until resolve namespace or fail to do so.
			while (0 != parent && length(*namespaceOfPrefix) == 0)
			{
				if(theIterator != m_NSInfos.end()
				   && nsInfo.m_ancestorHasXMLNSAttrs == nsInfo.ANCESTORNOXMLNS)
				{
					break;
				}

				parentType = parent->getNodeType();

				if(theIterator == m_NSInfos.end() ||
				   nsInfo.m_hasXMLNSAttrs == true)
				{
					bool	elementHasXMLNS = false;
					
					// Elements
					if (parentType == XalanNode::ELEMENT_NODE) 
					{
						// Scan the Element's Attr's, looking for namespace declarations
						const XalanNamedNodeMap* const	nnm =
							parent->getAttributes();
						assert(nnm != 0);

						const unsigned int	theLength = nnm->getLength();

						for (unsigned int i = 0;  i < theLength;  i ++) 
						{
							const XalanNode*		attr = nnm->item(i);

							const XalanDOMString&	aname = attr->getNodeName();

							// Quick test of first character, to reduce cost of startsWith.
							if(charAt(aname, 0) == charAt(DOMServices::s_XMLNamespaceWithSeparator, 0))
							{
								// "xmlns:"* prefix declaration?
								bool isPrefix = startsWith(aname, DOMServices::s_XMLNamespaceWithSeparator);
							  
								// or "xmlns" default declaration?
								// JKESS: Reversed order of test; more efficient.
								if (isPrefix == true || equals(aname, DOMServices::s_XMLNamespace) == true) 
								{
									// Is this element the original node?
									if(theLocalNode == parent)
									{
										nHasXMLNS = true; // local decls exist
									}

									elementHasXMLNS = true; // decls exist on current parent
									ancestorsHaveXMLNS = true; // decls exist somewhere

									// If xmlns:, what prefix is declared?
									const XalanDOMString	p = (isPrefix == true)
											? substring(aname, length(DOMServices::s_XMLNamespaceWithSeparator)) 
											: XalanDOMString();

									// If it's the one we're looking for, resolve to NS
									if (equals(p, prefix) == true) 
									{
										namespaceOfPrefix = &attr->getNodeValue();
										break;
									}
								}
							}
						}
					}

					// Fallthough for unresolved Elements, 
					// plus anything else except Attr's
					if((XalanNode::ATTRIBUTE_NODE != parentType) &&
						(theIterator == m_NSInfos.end()) &&
						(theLocalNode != parent))
					{
						// Record whether this node defines any namespaces
						// (_not_ whether it defines its own or what that is)
						nsInfo = elementHasXMLNS 
							? theNSInfoUnProcWithXMLNS 
							: theNSInfoUnProcWithoutXMLNS;
						updateNamespace(parent, nsInfo);
					}
				}

				// Attr nodes need to look to their owning Element for their NS
				// declaration (if any). Note that we're using the XPath data model,
				// getParentOfNode(); in DOM terms, that's Attr.getOwningElement().
				if(XalanNode::ATTRIBUTE_NODE == parentType)
				{
					parent = DOMServices::getParentOfNode(*parent);
				}

				// Any other node gets queued for annotation pass,
				// along with our current nsInfo context
				else
				{
					candidateNoAncestorXMLNS.push_back(make_pair(parent, nsInfo));

					parent = parent->getParentNode();
				}

				// If we haven't run out of ancestors
				if(0 != parent)
				{
					// Try to retrieve cached NS info for the newly selected parent
					// for use in next pass through loop.
					// If not found, continue using previous value
					theIterator = m_NSInfos.find(parent);

					if (theIterator != m_NSInfos.end())
					{
						nsInfo = (*theIterator).second;
					}
				}
			}

			// Anotation pass over the "any other node" queue
			const CandidateNoAncestorVectorType::size_type	nCandidates =
				candidateNoAncestorXMLNS.size();

			if(nCandidates > 0)
			{
				// If no inherited declarations (and we checked all the way to the root)
				// then record nodes with no local declarations in the nsInfo cache,
				// to avoid repeatedly searching this branch of the tree.
				// ????? This feels overcomplicated, somehow... 
				if(false == ancestorsHaveXMLNS && 0 == parent)
				{
					for(unsigned int i = 0; i < nCandidates; i++)
					{
						const NSInfo&	candidateInfo = candidateNoAncestorXMLNS[i].second;

						if(candidateInfo == theNSInfoUnProcWithoutXMLNS ||
						   candidateInfo == theNSInfoNullWithoutXMLNS)
						{
							updateNamespace(parent, candidateInfo);
						}
					}
				}

				candidateNoAncestorXMLNS.clear();
			}
		}

		// NOTE that attibute nodes aren't handled by the nsInfos logic,
		// so it's unclear that the updateNamespace buys us anything directly.
		// But I'm guessing it may be useful for getNamespaceForPrefix.
		//
		// ????? This seems like a lot of code for something which should be a set of
		// bit-masks...
		if(XalanNode::ATTRIBUTE_NODE != ntype)
		{
			assert(namespaceOfPrefix != 0);

			// If Attribute's prefix wasn't resolved
			if(0 == length(*namespaceOfPrefix))
			{
				// In context where other prefixes are defined
				if(ancestorsHaveXMLNS == true)
				{
					// Local definitions exist
					if(nHasXMLNS == true)
					{
						updateNamespace(theLocalNode, theNSInfoNullWithXMLNS);
					}
				
					// Only inherited definitions exist
					else
					{
						updateNamespace(theLocalNode, theNSInfoNullWithoutXMLNS);
					}
				}
			  
				// No definitions exist
				else 
				{
					updateNamespace(theLocalNode, theNSInfoNullNoAncestorXMLNS);
				}
			}
			else // Attribute's prefix was resolved, at least that one is declared
			{
				updateNamespace(theLocalNode, NSInfo(*namespaceOfPrefix, nHasXMLNS));
			}
		}
	}

	return *namespaceOfPrefix;
}
