/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed 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.
 */

#include "Stylesheet.hpp"



#include <algorithm>



#include <xercesc/sax/AttributeList.hpp>
#include <xercesc/util/PlatformUtils.hpp>



#include <xalanc/Include/STLHelper.hpp>



#include <xalanc/XalanDOM/XalanDOMException.hpp>



#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>



#include <xalanc/DOMSupport/DOMServices.hpp>



#include <xalanc/XMLSupport/XMLParserLiaison.hpp>



#include <xalanc/XPath/XObject.hpp>
#include <xalanc/XPath/XPath.hpp>
#include <xalanc/XPath/XalanQNameByReference.hpp>



#include "Constants.hpp"
#include "ElemAttributeSet.hpp"
#include "ElemDecimalFormat.hpp"
#include "ElemTemplate.hpp"
#include "ElemTemplateElement.hpp"
#include "ElemVariable.hpp"
#include "ExtensionNSHandler.hpp"
#include "KeyTable.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetExecutionContext.hpp"
#include "XalanMatchPatternData.hpp"



XALAN_CPP_NAMESPACE_BEGIN



const XalanDOMString			Stylesheet::s_emptyString;

const XalanQNameByReference		Stylesheet::s_emptyQName;



Stylesheet::Stylesheet(
		StylesheetRoot& 				root,
		const XalanDOMString&			baseIdentifier,
		StylesheetConstructionContext&	constructionContext) :
	PrefixResolver(),
	m_stylesheetRoot(root),
	m_baseIdent(baseIdentifier),
	m_keyDeclarations(),
	m_whitespaceElements(),
	m_XSLTNamespaceURI(constructionContext.getXSLTNamespaceURI()),
	m_imports(),
	m_importsSize(0),
	m_namespaces(),
	m_namespaceDecls(),
	m_isWrapperless(false),
	m_extensionNamespaces(),
	m_firstTemplate(0),
	m_includeStack(),
	m_namedTemplates(),
	m_topLevelVariables(),
	m_XSLTVerDeclared(1.0L),
	m_elementPatternTable(),
	m_elementPatternTableEnd(m_elementPatternTable.end()),
	m_elementAnyPatternList(),
	m_attributePatternTable(),
	m_attributePatternTableEnd(m_attributePatternTable.end()),
	m_attributeAnyPatternList(),
	m_textPatternList(),
	m_commentPatternList(),
	m_rootPatternList(),
	m_piPatternList(),
	m_nodePatternList(),
	m_patternCount(0),
	m_elemDecimalFormats(),
	m_namespacesHandler()
{
	if (length(m_baseIdent) == 0)
	{
		m_includeStack.push_back(m_baseIdent);
	}
	else
	{
		try
		{
			const XalanDOMString urlString = constructionContext.getURLStringFromString(m_baseIdent);

			if (length(urlString) != 0)
			{
				m_includeStack.push_back(urlString);

				m_baseIdent = urlString;
			}
		}
		catch(const XERCES_CPP_NAMESPACE_QUALIFIER XMLPlatformUtilsException&)
		{
			// Assume that any exception here relates to get the urlString from
			// m_baseIdent.  We'll assume that it's just a fake base identifier
			// since the parser will throw the real error if the base identifier
			// can't be resolved.
			m_includeStack.push_back(baseIdentifier);
		}
	}
}



Stylesheet::~Stylesheet()
{
#if !defined(XALAN_NO_STD_NAMESPACE)
	using std::for_each;
#endif

	// Clean up all entries in the imports vector.
	for_each(m_imports.begin(),
			 m_imports.end(),
			 DeleteFunctor<Stylesheet>());

	// Clean up the decimal formats vector
	for_each(m_elemDecimalFormats.begin(),
			 m_elemDecimalFormats.end(),
			 DeleteFunctor<ElemDecimalFormat>());

	// Clean up the extension namespaces vector
	for_each(m_extensionNamespaces.begin(),
			 m_extensionNamespaces.end(),
			 MapValueDeleteFunctor<ExtensionNamespacesMapType>());
}



ElemTemplateElement*
Stylesheet::initWrapperless(
			StylesheetConstructionContext&	constructionContext,
			const LocatorType*				locator)
{
	if (m_isWrapperless == true)
	{
		constructionContext.error(
			XalanMessageLoader::getMessage(XalanMessages::StylesheetHasWrapperlessTemplate),
			0,
			locator);
	}

	assert(m_firstTemplate == 0);

	m_isWrapperless = true;


	AttributeListImpl	templateAttrs;

	templateAttrs.addAttribute(c_wstr(Constants::ATTRNAME_NAME),
							   c_wstr(Constants::ATTRTYPE_CDATA),
							   c_wstr(Constants::ATTRVAL_SIMPLE));

	ElemTemplateElement* const	theNewTemplate =
		constructionContext.createElement(
			StylesheetConstructionContext::ELEMNAME_TEMPLATE,
			*this,
			templateAttrs,
			locator);

	theNewTemplate->addToStylesheet(constructionContext, *this);

	assert(m_firstTemplate == theNewTemplate);

	return theNewTemplate;
}



void
Stylesheet::processKeyElement(
			const PrefixResolver&			nsContext,
			const AttributeListType&		atts,
			const LocatorType*				locator,
			StylesheetConstructionContext&	constructionContext)
{
	const XalanQName*		theQName = 0;
	XPath*					matchAttr = 0;
	XPath*					useAttr = 0;
 
	const unsigned int	nAttrs = atts.getLength();

	for(unsigned int i = 0; i < nAttrs; i++)
	{
		const XalanDOMChar* const	aname = atts.getName(i);

		if (equals(aname, Constants::ATTRNAME_NAME))
		{
			theQName = constructionContext.createXalanQName(atts.getValue(i), m_namespaces, locator);

			if (theQName->isValid() == false)
			{
				constructionContext.error(
						XalanMessageLoader::getMessage(
							XalanMessages::AttributeValueNotValidQName_2Param,
							Constants::ATTRNAME_NAME.c_str(),
							atts.getValue(i)),
						0,
						locator);
			}
		}
		else if(equals(aname, Constants::ATTRNAME_MATCH))
		{
			matchAttr =
					constructionContext.createMatchPattern(
						0,
						XalanDOMString(atts.getValue(i)),
						nsContext);
		}
		else if(equals(aname, Constants::ATTRNAME_USE))
		{
			useAttr =
					constructionContext.createXPath(
						0,
						atts.getValue(i),
						nsContext);
		}
		else if (isAttrOK(aname, atts, i, constructionContext) == false)
		{
			constructionContext.error(
				XalanMessageLoader::getMessage(
					XalanMessages::TemplateHasIllegalAttribute_2Param,
					Constants::ELEMNAME_KEY_WITH_PREFIX_STRING.c_str(),
					aname),
				0,
				locator);
		}
	}

	if(0 == theQName)
	{
		constructionContext.error(
			XalanMessageLoader::getMessage(
				XalanMessages::ElementRequiresAttribute_2Param,
				Constants::ELEMNAME_KEY_WITH_PREFIX_STRING,
				Constants::ATTRNAME_NAME),
			0,
			locator);
	}

	if(0 == matchAttr)
	{
		constructionContext.error(
			XalanMessageLoader::getMessage(
				XalanMessages::ElementRequiresAttribute_2Param,
				Constants::ELEMNAME_KEY_WITH_PREFIX_STRING,
				Constants::ATTRNAME_MATCH),
			0,
			locator);
	}

	if(0 == useAttr)
	{
		constructionContext.error(
			XalanMessageLoader::getMessage(
				XalanMessages::ElementRequiresAttribute_2Param,
				Constants::ELEMNAME_KEY_WITH_PREFIX_STRING,
				Constants::ATTRNAME_USE),
			0,
			locator);
	}

	m_keyDeclarations.push_back(
		KeyDeclaration(
			*theQName,
			*matchAttr,
			*useAttr,
			m_baseIdent,
			XalanLocator::getLineNumber(locator),
			XalanLocator::getColumnNumber(locator)));
}



void
Stylesheet::pushNamespaces(const AttributeListType&		atts)
{
	const unsigned int		nAttrs = atts.getLength();

	NamespaceVectorType 	namespaces;

	XalanDOMString			prefix;

	for(unsigned int i = 0; i < nAttrs; i++)
	{
		const XalanDOMChar* const	aname = atts.getName(i);
		const XalanDOMChar* const	value = atts.getValue(i);

		const bool	isPrefix = startsWith(aname, DOMServices::s_XMLNamespaceWithSeparator);

		if (equals(aname, DOMServices::s_XMLNamespace) || isPrefix) 
		{
			if (isPrefix == false)
			{
				prefix.clear();
			}
			else
			{
				substring(aname, prefix, DOMServices::s_XMLNamespaceWithSeparatorLength);
			}

			namespaces.push_back(NameSpace(prefix, XalanDOMString(value)));
		}
	}

	m_namespaces.push_back(namespaces);
}



class attrSetCompare
{
public:

	attrSetCompare(const ElemAttributeSet&	theAttrSet) :
		m_attrSet(theAttrSet)
	{
	}

	bool
	operator()(const ElemAttributeSet*	theRHS) const
	{
		assert(theRHS != 0);

		return m_attrSet == *theRHS;
	}

private:

	const ElemAttributeSet&		m_attrSet;
};



static void
addToList(
			Stylesheet::PatternTableVectorType&		theList,
			const XalanMatchPatternData*		    thePattern)
{
	typedef Stylesheet::size_type	size_type;
	assert(thePattern != 0);

	const double		thePatternPriority = thePattern->getPriorityOrDefault();
	const size_type		thePatternPosition = thePattern->getPosition();

	typedef Stylesheet::PatternTableVectorType	PatternTableListType;
	typedef PatternTableListType::iterator		iterator;

	iterator		theCurrent = theList.begin();

	const iterator	theEnd = theList.end();

	while(theCurrent != theEnd)
	{
		const double	theCurrentPriority = (*theCurrent)->getPriorityOrDefault();

		if (thePatternPriority > theCurrentPriority)
		{
			break;
		}
		else if (thePatternPriority == theCurrentPriority &&
				 thePatternPosition > (*theCurrent)->getPosition())
		{
			break;
		}

		++theCurrent;
	}

	theList.insert(theCurrent, thePattern);
}



static void
addToTable(
		   Stylesheet::PatternTableMapType&				theTable,
		   const Stylesheet::PatternTableVectorType&	theList)
{
	typedef Stylesheet::PatternTableMapType		PatternTableMapType;
	typedef Stylesheet::PatternTableVectorType	PatternTableListType;

	PatternTableMapType::iterator				theCurrentTable = theTable.begin();
	const PatternTableMapType::iterator			theTableEnd = theTable.end();
	const PatternTableListType::const_iterator	theListEnd = theList.end();

	while(theCurrentTable != theTableEnd)
	{
		PatternTableListType::const_iterator	theCurrent = theList.begin();

		while(theCurrent != theListEnd)
		{
			addToList((*theCurrentTable).second, *theCurrent);

			++theCurrent;
		}

		++theCurrentTable;
	}
}



void
Stylesheet::addWhitespaceElement(const XalanSpaceNodeTester&	theTester)
{
	typedef WhitespaceElementsVectorType::iterator	iterator;

	const XPath::eMatchScore	theMatchScore = theTester.getMatchScore();

	iterator	i = m_whitespaceElements.begin();

	while(i != m_whitespaceElements.end())
	{
		if (theMatchScore >= (*i).getMatchScore())
		{
			break;
		}
		else
		{
			++i;
		}
	}

	m_whitespaceElements.insert(i, theTester);
}



void
Stylesheet::postConstruction(StylesheetConstructionContext&		constructionContext)
{
	KeyDeclarationVectorType::size_type			theKeyDeclarationsCount = 0;
	WhitespaceElementsVectorType::size_type		theWhitespaceElementsCount = 0;

	{
		m_importsSize = m_imports.size();

		// Call postConstruction() on any imported stylesheets, in reverse order,
		// so namespace aliases are processed properly. Also, get any key
		// declarations and preserve/strip space information.
		const StylesheetVectorType::reverse_iterator	theEnd = m_imports.rend();
		StylesheetVectorType::reverse_iterator			i = m_imports.rbegin();

		while(i != theEnd)
		{
			(*i)->postConstruction(constructionContext);

			m_namespacesHandler.copyNamespaceAliases((*i)->getNamespacesHandler());

			theKeyDeclarationsCount += (*i)->m_keyDeclarations.size();
			theWhitespaceElementsCount += (*i)->m_whitespaceElements.size();

			++i;
		}
	}

	{
		// Call postConstruction() on any imported stylesheets, in import order,
		// and process preserve/strip space information.
		const StylesheetVectorType::iterator	theEnd = m_imports.end();
		StylesheetVectorType::iterator			i = m_imports.begin();

		m_keyDeclarations.reserve(
			m_keyDeclarations.size() + theKeyDeclarationsCount);

		m_whitespaceElements.reserve(
			m_whitespaceElements.size() + theWhitespaceElementsCount);

		while(i != theEnd)
		{
			m_keyDeclarations.insert(
				m_keyDeclarations.end(),
				(*i)->m_keyDeclarations.begin(),
				(*i)->m_keyDeclarations.end());

			KeyDeclarationVectorType().swap((*i)->m_keyDeclarations);

			m_whitespaceElements.insert(
				m_whitespaceElements.end(),
				(*i)->m_whitespaceElements.begin(),
				(*i)->m_whitespaceElements.end());

			WhitespaceElementsVectorType().swap((*i)->m_whitespaceElements);

			++i;
		}
	}

	// Call postConstruction() on our own namespaces handler...
	m_namespacesHandler.postConstruction(constructionContext);

	{
		for (ElemTemplateElement* node = m_firstTemplate;
			 node != 0;
			 node = node->getNextSiblingElem())
		{
			node->postConstruction(constructionContext, m_namespacesHandler);
		}
	}

	{
		for (ElemVariableVectorType::iterator it = m_topLevelVariables.begin();
			 it != m_topLevelVariables.end();
			 ++it)
		{
			(*it)->postConstruction(constructionContext, m_namespacesHandler);
		}
	}

	addToTable(m_elementPatternTable, m_elementAnyPatternList);
	addToTable(m_attributePatternTable, m_attributeAnyPatternList);
}



bool
Stylesheet::isAttrOK(
			const XalanDOMChar* 			attrName,
			const AttributeListType&		/* atts */,
			int 							/* which */,
			StylesheetConstructionContext&	constructionContext) const
{
	// Namespace declarations are OK by definition
	bool attrOK = equals(attrName, DOMServices::s_XMLNamespace) ||
						 startsWith(attrName, DOMServices::s_XMLNamespaceWithSeparator);

	if(!attrOK)
	{
		// Others are OK if their prefix has been
		// bound to a non-null Namespace URI other than XSLT's
		const XalanDOMString::size_type		indexOfNSSep = indexOf(attrName, XalanUnicode::charColon);

		if(indexOfNSSep < length(attrName))
		{
			const XalanDOMString	prefix(attrName, indexOfNSSep);
			const XalanDOMString*	ns = getNamespaceForPrefixFromStack(prefix);

			attrOK = ns != 0 && !ns->empty() && *ns != constructionContext.getXSLTNamespaceURI();
		}
		else if (m_XSLTVerDeclared > constructionContext.getXSLTVersionSupported())
		{
			attrOK = true;
		}
	}

	return attrOK;
}



const XalanDOMString*
Stylesheet::getNamespaceFromStack(const XalanDOMChar* 	nodeName) const
{
	assert(nodeName != 0);

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

	if (indexOfNSSep == length(nodeName))
	{
		return getNamespaceForPrefixFromStack(s_emptyString);
	}
	else
	{
		return getNamespaceForPrefixFromStack(XalanDOMString(nodeName, indexOfNSSep));
	}
}



const XalanDOMString*
Stylesheet::getNamespaceForPrefix(
			const XalanDOMString&			prefix,
			StylesheetConstructionContext&	constructionContext) const
{
	const XalanDOMString* const		theURI = getNamespaceForPrefix(prefix);

	if (theURI == 0)
	{
		constructionContext.error(XalanMessageLoader::getMessage(XalanMessages::UndeclaredNamespacePrefix_1Param, prefix));
	}

	return theURI;
}



const XalanDOMString*
Stylesheet::getNamespaceForPrefix(
			const XalanDOMChar*				prefix,
			StylesheetConstructionContext&	constructionContext) const
{
	StylesheetConstructionContext::GetAndReleaseCachedString	theGuard(constructionContext);

	XalanDOMString&		theTemp = theGuard.get();

	theTemp.assign(prefix);

	return getNamespaceForPrefix(theTemp, constructionContext);
}



bool
Stylesheet::getYesOrNo(
			const XalanDOMChar* 			/* aname */,
			const XalanDOMChar* 			val,
			StylesheetConstructionContext&	constructionContext) const
{
	if(equals(val, Constants::ATTRVAL_YES))
	{
		return true;
	}
	else if(equals(val, Constants::ATTRVAL_NO))
	{
		return false;
	}
	else
	{
		constructionContext.error(XalanMessageLoader::getMessage(XalanMessages::AttributeMustBe_2Params,Constants::ATTRVAL_YES,Constants::ATTRVAL_NO));
		return false;
	}
}



void
Stylesheet::addTemplate(
			ElemTemplate*					theTemplate,
			StylesheetConstructionContext&	constructionContext)
{
	assert(theTemplate != 0);

	if (m_isWrapperless == true)
	{
		if (m_firstTemplate != 0)
		{
			constructionContext.error(
				XalanMessageLoader::getMessage(XalanMessages::StylesheetHasWrapperlessTemplate),
				0,
				theTemplate);
		}
		else
		{
			m_firstTemplate = theTemplate;
		}
	}
	else if(0 == m_firstTemplate)
	{
		m_firstTemplate = theTemplate;
	}
	else
	{
		ElemTemplateElement*	next = m_firstTemplate;

		// Find the last one, then append the new one.
		while(0 != next)
		{
			if(0 == next->getNextSiblingElem())
			{
				next->setNextSiblingElem(theTemplate);
				theTemplate->setNextSiblingElem(0); // just to play it safe.
				theTemplate->setPreviousSiblingElem(next);
				break;
			}

			next = next->getNextSiblingElem();
		}
	}

	// If it's a named template, then we need to
	// and it to the map of named templates.
	const XalanQName&	theName = theTemplate->getNameAttribute();

	if(theName.isEmpty() == false)
	{
		if (m_namedTemplates.find(theName) == m_namedTemplates.end())
		{
			m_namedTemplates[theName] = theTemplate;
		}
		else
		{
			// This is an error...
			constructionContext.error(
				XalanMessageLoader::getMessage(XalanMessages::StylesheetHasDuplicateNamedTemplate),
				0,
				theTemplate);
		}
	}

	// Now, process the match pattern associated with the
	// template.
	const XPath* const	xp = theTemplate->getMatchPattern();

	if(0 != xp)
	{
		/* Each string has a list of pattern tables associated with it; if the
		 * string is not in the map, then create a list of pattern tables with one
		 * entry for the string, otherwise add to the existing pattern table list
		 * for that string
		 */
		typedef XPath::TargetDataVectorType		TargetDataVectorType;

		TargetDataVectorType	data;

		xp->getTargetData(data);

		TargetDataVectorType::size_type	nTargets =
				data.size();

		if(nTargets != 0)
		{
			StylesheetConstructionContext::GetAndReleaseCachedString	theGuard(constructionContext);

			XalanDOMString&	tempString = theGuard.get();

			for(TargetDataVectorType::size_type i = 0;
								i < nTargets; ++i) 
			{
				assert(data[i].getString() != 0);
				
				tempString = data[i].getString();

				const XalanMatchPatternData* const	newMatchPat =
				    constructionContext.createXalanMatchPatternData(
						*theTemplate,
						m_patternCount,
						tempString,
						*xp,
						xp->getExpression().getCurrentPattern(),
						data[i].getDefaultPriority());

                ++m_patternCount;

				// Always put things on the front of the list, so
				// templates later in the stylesheet are always
				// selected first.
				if (equals(tempString, XPath::PSEUDONAME_TEXT) == true)
				{
					addToList(m_textPatternList, newMatchPat);
				}
				else if (equals(tempString, XPath::PSEUDONAME_COMMENT) == true)
				{
					addToList(m_commentPatternList, newMatchPat);
				}
				else if (equals(tempString, XPath::PSEUDONAME_ROOT) == true)
				{
					addToList(m_rootPatternList, newMatchPat);
				}
				else if (equals(tempString, XPath::PSEUDONAME_PI) == true)
				{
					addToList(m_piPatternList, newMatchPat);
				}
				else if (equals(tempString, XPath::PSEUDONAME_NODE) == true)
				{
					addToList(m_nodePatternList, newMatchPat);

					addToList(m_elementAnyPatternList, newMatchPat);
					addToList(m_attributeAnyPatternList, newMatchPat);
					addToList(m_commentPatternList, newMatchPat);
					addToList(m_textPatternList, newMatchPat);
					addToList(m_piPatternList, newMatchPat);
				}
				else if (equals(tempString, XPath::PSEUDONAME_ANY) == true)
				{
					if (data[i].getTargetType() == XPath::TargetData::eElement)
					{
						addToList(m_elementAnyPatternList, newMatchPat);
					}
					else if (data[i].getTargetType() == XPath::TargetData::eAttribute)
					{
						addToList(m_attributeAnyPatternList, newMatchPat);
					}
					else if (data[i].getTargetType() == XPath::TargetData::eAny)
					{
						addToList(m_elementAnyPatternList, newMatchPat);
						addToList(m_attributeAnyPatternList, newMatchPat);
					}
				}
				else
				{
					if (data[i].getTargetType() == XPath::TargetData::eElement)
					{
						addToList(m_elementPatternTable[tempString], newMatchPat);
					}
					else if (data[i].getTargetType() == XPath::TargetData::eAttribute)
					{
						addToList(m_attributePatternTable[tempString], newMatchPat);
					}
				}
			}
		}
	}
}



const ElemTemplate*
Stylesheet::findNamedTemplate(const XalanQName&		qname) const
{
	const ElemTemplateMapType::const_iterator	it = m_namedTemplates.find(qname);

	if(it != m_namedTemplates.end())
	{
		return (*it).second;
	}
	else
	{
		const ElemTemplate*		namedTemplate = 0;

		// Look for the template in the imports
		const StylesheetVectorType::size_type	importsCount = m_imports.size();

		for(StylesheetVectorType::size_type i = 0; i < importsCount; ++i)
		{
			const Stylesheet* const stylesheet = m_imports[i];

			namedTemplate = stylesheet->findNamedTemplate(qname);

			if(0 != namedTemplate)
				break;
		}

		return namedTemplate;
	}
}
	


void
Stylesheet::addObjectIfNotFound(
			const XalanMatchPatternData*    thePattern,
			PatternTableVectorType& 	    theVector)
{
	XALAN_USING_STD(find)

	const PatternTableVectorType::const_iterator 	theResult =
		find(
				theVector.begin(),
				theVector.end(),
				thePattern);

	// Did we find it?
	if(theResult == theVector.end())
	{
		theVector.push_back(thePattern);
	}
}



inline void
Stylesheet::addObjectIfNotFound(
			const XalanMatchPatternData*	thePattern,
			const XalanMatchPatternData* 	thePatternArray[],
			unsigned int&			        thePatternArraySize)
{
	assert(thePattern != 0 && thePatternArray != 0);

	if (thePatternArraySize == 0)
	{
		thePatternArray[0] = thePattern;

		++thePatternArraySize;
	}
	else
	{
		unsigned int i = 0;

		while(i < thePatternArraySize)
		{
			if (thePatternArray[i] != thePattern)
			{
				++i;
			}
			else
			{
				break;
			}
		}

		if (i == thePatternArraySize)
		{
			thePatternArray[thePatternArraySize++] = thePattern;
		}
	}
}



inline const Stylesheet::PatternTableVectorType* 
Stylesheet::locateElementMatchPatternDataList(const XalanDOMString&	    theName) const
{
	assert(m_elementPatternTableEnd == m_elementPatternTable.end());

	const PatternTableMapType::const_iterator	i =
		m_elementPatternTable.find(theName);

	if (i != m_elementPatternTableEnd)
	{
		return &(*i).second;
	}
	else
	{
		return &m_elementAnyPatternList;
	}
}



inline const Stylesheet::PatternTableVectorType* 
Stylesheet::locateAttributeMatchPatternDataList(const XalanDOMString&	theName) const
{
	assert(m_attributePatternTableEnd == m_attributePatternTable.end());

	const PatternTableMapType::const_iterator	i =
		m_attributePatternTable.find(theName);

	if (i != m_attributePatternTableEnd)
	{
		return &(*i).second;
	}
	else
	{
		return &m_attributeAnyPatternList;
	}
}



inline const Stylesheet::PatternTableVectorType*
Stylesheet::locateMatchPatternDataList(
			const XalanNode&		theNode,
			XalanNode::NodeType		targetNodeType) const
{
	assert(theNode.getNodeType() == targetNodeType);

	switch(targetNodeType)
	{
	case XalanNode::ELEMENT_NODE:
		return locateElementMatchPatternDataList(DOMServices::getLocalNameOfNode(theNode));
		break;

	case XalanNode::PROCESSING_INSTRUCTION_NODE:
		return &m_piPatternList;
		break;

	case XalanNode::ATTRIBUTE_NODE:
#if defined(XALAN_OLD_STYLE_CASTS)
		assert(DOMServices::isNamespaceDeclaration((const XalanAttr&)theNode) == false);
#else
		assert(DOMServices::isNamespaceDeclaration(static_cast<const XalanAttr&>(theNode)) == false);
#endif
		return locateAttributeMatchPatternDataList(DOMServices::getLocalNameOfNode(theNode));
		break;

	case XalanNode::CDATA_SECTION_NODE:
	case XalanNode::TEXT_NODE:
		return &m_textPatternList;
		break;

	case XalanNode::COMMENT_NODE:
		return &m_commentPatternList;
		break;

	case XalanNode::DOCUMENT_NODE:
		return &m_rootPatternList;
		break;

	default:
		break;
	}

	return &m_nodePatternList;
}



inline const ElemTemplate*
Stylesheet::findTemplateInImports(
			StylesheetExecutionContext& 	executionContext,
			XalanNode*						targetNode,
			XalanNode::NodeType				targetNodeType,
			const XalanQName&				mode) const
{
	assert(targetNode->getNodeType() == targetNodeType);
	assert(m_importsSize == m_imports.size());

	for(StylesheetVectorType::size_type i = 0; i < m_importsSize; i++)
	{
		const Stylesheet* const 	stylesheet =
			m_imports[i];

		const ElemTemplate* const	bestMatchedRule =
			stylesheet->findTemplate(
				executionContext,
				targetNode,
				targetNodeType,
				mode, 
				false);

		if(bestMatchedRule != 0)
		{
			return bestMatchedRule;
		}
	}

	return 0;
}



const ElemTemplate*
Stylesheet::findTemplate(
			StylesheetExecutionContext& 	executionContext,
			XalanNode*						targetNode,
			XalanNode::NodeType				targetNodeType,
			const XalanQName&				mode,
			bool							onlyUseImports) const
{
	assert(targetNode != 0);
	assert(targetNode->getNodeType() == targetNodeType);

	if(m_isWrapperless == true)
	{
		return m_firstTemplate;
	}
	else if (onlyUseImports == true)
	{
		return findTemplateInImports(executionContext, targetNode, targetNodeType, mode);
	}
	else
	{
		const ElemTemplate*		bestMatchedRule = 0;

		if (executionContext.getQuietConflictWarnings() == true)
		{
			// Points to the current list of match patterns.  Note
			// that this may point to more than one table.
			const PatternTableVectorType* 	matchPatternList =
					locateMatchPatternDataList(*targetNode, targetNodeType);
			assert(matchPatternList != 0);

			PatternTableVectorType::const_iterator		theCurrentEntry =
					matchPatternList->begin();

			const PatternTableVectorType::const_iterator	theTableEnd =
					matchPatternList->end();

			while(theCurrentEntry != theTableEnd)
			{
				const XalanMatchPatternData*	matchPat = *theCurrentEntry;
				assert(matchPat != 0);

				const ElemTemplate*	const	rule = matchPat->getTemplate();
				assert(rule != 0);

				// We'll be needing to match rules according to what 
				// mode we're in.
				const XalanQName&	ruleMode = rule->getMode();

				// The logic here should be that if we are not in a mode AND
				// the rule does not have a node, then go ahead.
				// OR if we are in a mode, AND the rule has a node, 
				// AND the rules match, then go ahead.
				const bool	haveMode = !mode.isEmpty();
				const bool	haveRuleMode = !ruleMode.isEmpty();

				if ((!haveMode && !haveRuleMode) ||
					(haveMode && haveRuleMode && ruleMode.equals(mode)))
				{
					const XPath* const	xpath = matchPat->getExpression();

					XPath::eMatchScore	score =
								xpath->getMatchScore(targetNode, *this, executionContext);

					if(XPath::eMatchScoreNone != score)
					{
						bestMatchedRule = rule;

						break;
					}
				}

				++theCurrentEntry;
			}

			if(0 == bestMatchedRule)
			{
				bestMatchedRule = findTemplateInImports(executionContext, targetNode, targetNodeType, mode);
			}
		}
		else
		{
			const PatternTableVectorType* 	matchPatternList =
					locateMatchPatternDataList(*targetNode, targetNodeType);
			assert(matchPatternList != 0);

			PatternTableVectorType::const_iterator		theCurrentEntry =
					matchPatternList->begin();

			const PatternTableVectorType::const_iterator	theTableEnd =
					matchPatternList->end();

			if (theCurrentEntry != theTableEnd)
			{
				const XalanMatchPatternData*	bestMatchedPattern = 0; // Syncs with bestMatchedRule
				const double			matchScoreNoneValue = 
					XPath::getMatchScoreValue(XPath::eMatchScoreNone);

				double					bestMatchPatPriority = matchScoreNoneValue;

				unsigned int			nConflicts = 0;

				// Use a stack-based array when possible...
				const XalanMatchPatternData*	conflictsArray[100];

				XalanArrayAutoPtr<const XalanMatchPatternData*>		conflictsVector;

				const XalanMatchPatternData**	conflicts = 0;

				const XalanDOMString*	        prevPat = 0;
				const XalanMatchPatternData*	prevMatchPat = 0;

				do
				{
					const XalanMatchPatternData*	matchPat = *theCurrentEntry;
					double					matchPatPriority = matchScoreNoneValue;
					assert(matchPat != 0);

					const ElemTemplate*	const	rule = matchPat->getTemplate();
					assert(rule != 0);

					// We'll be needing to match rules according to what 
					// mode we're in.
					const XalanQName&	ruleMode = rule->getMode();

					// The logic here should be that if we are not in a mode AND
					// the rule does not have a node, then go ahead.
					// OR if we are in a mode, AND the rule has a node, 
					// AND the rules match, then go ahead.
					const bool	haveMode = !mode.isEmpty();
					const bool	haveRuleMode = !ruleMode.isEmpty();

					if ((!haveMode && !haveRuleMode) ||
						(haveMode && haveRuleMode && ruleMode.equals(mode)))
					{
						const XalanDOMString*	patterns = matchPat->getPattern();
						assert(patterns != 0);

						if(!isEmpty(*patterns) &&
						   !(prevMatchPat != 0 &&
							 (prevPat != 0 && equals(*prevPat, *patterns)) &&
							 prevMatchPat->getTemplate()->getPriority() == matchPat->getTemplate()->getPriority()))
						{
							prevPat = patterns;
							prevMatchPat = matchPat;
							matchPatPriority = matchScoreNoneValue;

							const XPath* const	xpath = matchPat->getExpression();

							XPath::eMatchScore	score =
										xpath->getMatchScore(targetNode, *this, executionContext);

							if(XPath::eMatchScoreNone != score)
							{
								const double priorityVal = rule->getPriority();
								const double priorityOfRule 
											  = (matchScoreNoneValue != priorityVal) 
											  ? priorityVal : XPath::getMatchScoreValue(score);

								matchPatPriority = priorityOfRule;
								const double priorityOfBestMatched =
												(0 != bestMatchedPattern) ?
														bestMatchPatPriority : 
														matchScoreNoneValue;

								if(priorityOfRule > priorityOfBestMatched)
								{
									nConflicts = 0;

									bestMatchedRule = rule;
									bestMatchedPattern = matchPat;
									bestMatchPatPriority = matchPatPriority;
								}
								else if(priorityOfRule == priorityOfBestMatched)
								{
									if (conflicts == 0)
									{
										if (m_patternCount > sizeof(conflictsArray) / sizeof(conflictsArray[0]))
										{
											conflictsVector.reset(new const XalanMatchPatternData*[m_patternCount]);

											conflicts = conflictsVector.get();
										}
										else
										{
											conflicts = conflictsArray;
										}
									}

									assert(conflicts != 0);

									// Add the best matched pattern so far.
									addObjectIfNotFound(bestMatchedPattern, conflicts, nConflicts);

									// Add the pattern that caused the conflict...
									conflicts[nConflicts++] = matchPat;

									bestMatchedRule = rule;
									bestMatchedPattern = matchPat;
									bestMatchPatPriority = matchPatPriority;
								}
							}
						}
					}

					++theCurrentEntry;

				} while(theCurrentEntry != theTableEnd);

				if(nConflicts > 0)
				{
					assert(conflicts != 0 && nConflicts <= m_patternCount);

					XalanDOMString	conflictsString(XalanMessageLoader::getMessage(XalanMessages::ConflictsFound));
					
					for(unsigned int i = 0; i < nConflicts; i++)
					{
						const XalanMatchPatternData* const	conflictPat = conflicts[i];

						if(0 != i)
						{
							conflictsString += XALAN_STATIC_UCODE_STRING(", ");

							// Find the furthest one towards the bottom of the document.
							if(conflictPat->getPosition() >
								bestMatchedPattern->getPosition())
							{
								bestMatchedPattern = conflictPat;
							}
						}
						else
						{
							bestMatchedPattern = conflictPat;
						}

						conflictsString += XalanDOMString(XALAN_STATIC_UCODE_STRING("\"")) +
												*conflictPat->getPattern() +
												XalanDOMString(XALAN_STATIC_UCODE_STRING("\""));
					}

					bestMatchedRule = bestMatchedPattern->getTemplate();

					conflictsString += XALAN_STATIC_UCODE_STRING(" ");
					conflictsString += XalanMessageLoader::getMessage(XalanMessages::LastFoundStylesheetWillBeUsed);
					executionContext.warn(conflictsString, targetNode, bestMatchedRule->getLocator());
				}
			}

			if(0 == bestMatchedRule)
			{
				bestMatchedRule = findTemplateInImports(executionContext, targetNode, targetNodeType, mode);
			}
		}

		return bestMatchedRule;
	}
}



void
Stylesheet::processExtensionNamespace(
			StylesheetConstructionContext&	theConstructionContext,
			const XalanDOMString&			uri)
{
	XalanAutoPtr<ExtensionNSHandler>	theGuard(new ExtensionNSHandler(uri));

	m_extensionNamespaces.insert(ExtensionNamespacesMapType::value_type(uri, theGuard.get()));

	theGuard.release();

	m_namespacesHandler.addExtensionNamespaceURI(theConstructionContext, uri);
}



void
Stylesheet::pushTopLevelVariables(
			StylesheetExecutionContext& 	executionContext,
			const ParamVectorType&			topLevelParams) const
{
	{
		// First, push any imports...
		const StylesheetVectorType::const_reverse_iterator	rend = m_imports.rend();

		for(StylesheetVectorType::const_reverse_iterator i = m_imports.rbegin(); i != rend; ++i)
		{
			const Stylesheet* const stylesheet = *i;
			assert(stylesheet != 0);

			stylesheet->pushTopLevelVariables(executionContext, topLevelParams);
		}
	}

	const ParamVectorType::size_type	nVars = m_topLevelVariables.size();

	for(ParamVectorType::size_type i = 0; i < nVars; ++i)
	{
		ElemVariable* const 	var = m_topLevelVariables[i];

		bool					isParam =
				StylesheetConstructionContext::ELEMNAME_PARAM == var->getXSLToken();

		if(isParam == true)
		{
			isParam = false;

			const ParamVectorType::size_type	n = topLevelParams.size();

			for(ParamVectorType::size_type k = 0; k < n; k++)
			{
				const ParamVectorType::value_type&	arg = topLevelParams[k];

				if(arg.getName().equals(var->getNameAttribute()))
				{
					isParam = true;

					if (arg.getXObject().null() == false)
					{
						executionContext.pushVariable(
							arg.getName(),
							arg.getXObject(),
							0);
					}
					else
					{
						executionContext.pushVariable(
							arg.getName(),
							0,
							arg.getExpression(),
							executionContext.getRootDocument(),
							*this);
					}

					break;
				}
			}
		}

		if (isParam == false)
		{
			executionContext.pushVariable(var->getNameAttribute(),
										  var,
										  var->getParentNodeElem());
		}
	}
}



void
Stylesheet::processNSAliasElement(
			const XalanDOMChar*				name,
			const AttributeListType&		atts,
			StylesheetConstructionContext&	constructionContext)
{
	const unsigned int		nAttrs = atts.getLength();

	const XalanDOMString*	stylesheetNamespace = 0;
	const XalanDOMString*	resultNamespace = 0;

	for(unsigned int i = 0; i < nAttrs; i++)
	{
		const XalanDOMChar* const	aname = atts.getName(i);

		if(equals(aname, Constants::ATTRNAME_STYLESHEET_PREFIX) == true)
		{
			const XalanDOMChar* const	value = atts.getValue(i);

			if (equals(value, Constants::ATTRVAL_DEFAULT_PREFIX) == true)
			{
				stylesheetNamespace = getNamespaceForPrefix(DOMServices::s_emptyString, constructionContext);
			}
			else
			{
				stylesheetNamespace = getNamespaceForPrefix(value, constructionContext);
			}
		}
		else if(equals(aname, Constants::ATTRNAME_RESULT_PREFIX))
		{
			const XalanDOMChar* const	value = atts.getValue(i);

			if (equals(value, Constants::ATTRVAL_DEFAULT_PREFIX) == true)
			{
				resultNamespace = getNamespaceForPrefix(DOMServices::s_emptyString, constructionContext);
			}
			else
			{
				resultNamespace = getNamespaceForPrefix(value, constructionContext);
			}
		}
		else if(!isAttrOK(aname, atts, i, constructionContext))
		{
			constructionContext.error(
				XalanMessageLoader::getMessage(
					XalanMessages::TemplateHasIllegalAttribute_2Param,
					name,
					aname));
		}
	}

	// Build a table of aliases, the key is the stylesheet uri and the
	// value is the result uri
	if (stylesheetNamespace == 0)
	{
		constructionContext.error(
			XalanMessageLoader::getMessage(
				XalanMessages::TemplateMustHaveAttribute_2Param,
				name,
				Constants::ATTRNAME_STYLESHEET_PREFIX.c_str()));
	}
	else if (resultNamespace == 0)
	{
		constructionContext.error(
			XalanMessageLoader::getMessage(
				XalanMessages::TemplateMustHaveAttribute_2Param,
				name,
				Constants::ATTRNAME_RESULT_PREFIX.c_str()));
	}
	else
	{
		assert(length(*stylesheetNamespace) != 0  && length(*resultNamespace) != 0);

		m_namespacesHandler.setNamespaceAlias(
				constructionContext,
				*stylesheetNamespace,
				*resultNamespace);
	}
}



void
Stylesheet::processDecimalFormatElement(
			StylesheetConstructionContext&	constructionContext,
			const AttributeListType&		atts,
			const LocatorType*				locator)
{
	const int	lineNumber = XalanLocator::getLineNumber(locator);
	const int	columnNumber = XalanLocator::getColumnNumber(locator);

	m_elemDecimalFormats.reserve(m_elemDecimalFormats.size() + 1);

	m_elemDecimalFormats.push_back(
					new ElemDecimalFormat(
							constructionContext,
							*this,
							atts,
							lineNumber,
							columnNumber));
}



const XalanDecimalFormatSymbols*
Stylesheet::getDecimalFormatSymbols(const XalanQName&	theQName) const
{
	const XalanDecimalFormatSymbols* 				dfs = 0;

	const ElemDecimalFormatVectorType::size_type	theSize =
		m_elemDecimalFormats.size();

	if(theSize > 0)
	{
		// Start from the top of the stack
		for (ElemDecimalFormatVectorType::size_type i = theSize; i > 0; --i)
		{
			assert(m_elemDecimalFormats[i - 1] != 0);

			const ElemDecimalFormat* const	theCurrent =
				m_elemDecimalFormats[i - 1];
			assert(theCurrent != 0);

			if (theCurrent->getQName().equals(theQName) == true)
			{
				dfs = &theCurrent->getDecimalFormatSymbols();

				break;
			}
		}
	}

	// If dfs is null at this point, it should
	// mean there wasn't an xsl:decimal-format declared
	// with the given name.	So go up the import hierarchy
	// and see if one of the imported stylesheets declared
	// it.
	if(dfs == 0)
	{
		for(StylesheetVectorType::size_type i = 0; i < m_importsSize; ++i)
		{
			dfs = m_imports[i]->getDecimalFormatSymbols(theQName);

			if(dfs != 0)
			{
				break;
			}
		}
	}

	return dfs;
}



const XalanDOMString*
Stylesheet::getNamespaceForPrefix(const XalanDOMString& 	prefix) const
{
	return XalanQName::getNamespaceForPrefix(m_namespaceDecls, prefix);
}



const XalanDOMString&
Stylesheet::getURI() const
{
	return m_baseIdent;
}



XALAN_CPP_NAMESPACE_END
