/*
 * 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 "ElemNumber.hpp"



#include <xercesc/sax/AttributeList.hpp>



#include <XalanDOM/XalanDocument.hpp>



#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/DoubleSupport.hpp>
#include <PlatformSupport/XalanNumberFormat.hpp>
#include <PlatformSupport/XalanSimplePrefixResolver.hpp>
#include <PlatformSupport/XalanUnicode.hpp>



#include <DOMSupport/DOMServices.hpp>



#include <Include/XalanAutoPtr.hpp>



#include <XPath/ElementPrefixResolverProxy.hpp>
#include <XPath/XPath.hpp>
#include <XPath/XObjectFactory.hpp>



#include "AVT.hpp"
#include "Constants.hpp"
#include "CountersTable.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetExecutionContext.hpp"



#if !defined(XALAN_NO_NAMESPACES)
using std::vector;
#endif



ElemNumber::ElemNumber(
			StylesheetConstructionContext&	constructionContext,
			Stylesheet&						stylesheetTree,
			const AttributeList&			atts,
			int								lineNumber,
			int								columnNumber) :
	ElemTemplateElement(constructionContext,
						stylesheetTree,
						lineNumber,
						columnNumber,
						Constants::ELEMNAME_NUMBER),	
	m_countMatchPattern(0),
	m_fromMatchPattern(0),
	m_valueExpr(0),
	m_level(Constants::NUMBERLEVEL_SINGLE),
	m_format_avt(0),
	m_lang_avt(0),
	m_lettervalue_avt(0),
	m_groupingSeparator_avt(0),
	m_groupingSize_avt(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_LEVEL))
		{
			const XalanDOMChar*	const	levelValue = atts.getValue(i);

			if(equals(Constants::ATTRVAL_MULTI, levelValue))
				m_level = Constants::NUMBERLEVEL_MULTI;
			else if(equals(levelValue,Constants::ATTRVAL_ANY))
				m_level = Constants::NUMBERLEVEL_ANY;
			else if(equals(levelValue,Constants::ATTRVAL_SINGLE))
				m_level = Constants::NUMBERLEVEL_SINGLE;
			else
				constructionContext.error(
					"The attribute 'level' has an illegal value",
					0,
					this);
		}
		else if(equals(aname, Constants::ATTRNAME_COUNT))
		{
			m_countMatchPattern = constructionContext.createMatchPattern(getLocator(), atts.getValue(i), *this);
		}
		else if(equals(aname, Constants::ATTRNAME_FROM))
		{
			m_fromMatchPattern = constructionContext.createMatchPattern(getLocator(), atts.getValue(i), *this);
		}
		else if(equals(aname, Constants::ATTRNAME_VALUE))
		{
			m_valueExpr = constructionContext.createXPath(getLocator(), atts.getValue(i), *this);
		}
		else if(equals(aname, Constants::ATTRNAME_FORMAT))
		{
			m_format_avt = new AVT(getLocator(), aname, atts.getType(i),
						atts.getValue(i), *this, constructionContext);
		}
		else if(equals(aname, Constants::ATTRNAME_LANG))
		{
			m_lang_avt = new AVT(getLocator(), aname, atts.getType(i),
						atts.getValue(i), *this, constructionContext);
		}
		else if(equals(aname, Constants::ATTRNAME_LETTERVALUE))
		{
			m_lettervalue_avt = new AVT(getLocator(), aname, atts.getType(i),
						atts.getValue(i), *this, constructionContext);
		}
		else if(equals(aname,Constants::ATTRNAME_GROUPINGSEPARATOR))
		{
			m_groupingSeparator_avt = new AVT(getLocator(), aname, atts.getType(i),
						atts.getValue(i), *this, constructionContext);
		}
		else if(equals(aname,Constants::ATTRNAME_GROUPINGSIZE))
		{
			m_groupingSize_avt = new AVT(getLocator(), aname, atts.getType(i),
						atts.getValue(i), *this, constructionContext);
		}
		else if(!isAttrOK(aname, atts, i, constructionContext))
		{
			constructionContext.error(
				"xsl:number has an illegal attribute",
				0,
				this);
		}
	}
}

	
ElemNumber::~ElemNumber()
{
#if defined(XALAN_CANNOT_DELETE_CONST)
	delete	(AVT*)m_format_avt;
	delete	(AVT*)m_lang_avt;
	delete	(AVT*)m_lettervalue_avt;
	delete	(AVT*)m_groupingSeparator_avt;
	delete	(AVT*)m_groupingSize_avt;
#else
	delete	m_format_avt;
	delete	m_lang_avt;
	delete	m_lettervalue_avt;
	delete	m_groupingSeparator_avt;
	delete	m_groupingSize_avt;
#endif
}


const XalanDOMString&
ElemNumber::getElementName() const
{
	return Constants::ELEMNAME_NUMBER_WITH_PREFIX_STRING;
}



void
ElemNumber::execute(StylesheetExecutionContext&		executionContext) const
{
	ElemTemplateElement::execute(executionContext);

	typedef XPathExecutionContext::GetAndReleaseCachedString	GetAndReleaseCachedString;

	GetAndReleaseCachedString	theGuard(executionContext);

	XalanDOMString&				countString = theGuard.get();

	getCountString(executionContext, countString);

	if (!isEmpty(countString))
	{
		executionContext.characters(toCharArray(countString), 0, length(countString));
	}
}



XalanNode*
ElemNumber::findAncestor(
			StylesheetExecutionContext&		executionContext,
			const XPath*					fromMatchPattern,
			const XPath*					countMatchPattern,
			XalanNode*						context,
			const XalanElement*				/* namespaceContext */) const
{
	XalanNode*	contextCopy = context;

	while(contextCopy != 0)
	{
		if(0 != fromMatchPattern)
		{
			if(fromMatchPattern->getMatchScore(contextCopy, *this,
						executionContext) !=
							XPath::eMatchScoreNone)
			{
				break;
			}
		}
		
		if(0 != countMatchPattern)
		{
			if(countMatchPattern->getMatchScore(contextCopy, *this,
						executionContext) !=
							XPath::eMatchScoreNone)
			{
				break;
			}
		}
		
		contextCopy = DOMServices::getParentOfNode(*contextCopy);
	}

	return contextCopy;
}					



XalanNode*
ElemNumber::findPrecedingOrAncestorOrSelf(
			StylesheetExecutionContext&		executionContext,
			const XPath*					fromMatchPattern,
			const XPath*					countMatchPattern,
			XalanNode*						context,
			const XalanElement*				/* namespaceContext */) const
{  
	XalanNode*	contextCopy = context;

	while(contextCopy != 0)
	{
		if(0 != fromMatchPattern)
		{
			if(fromMatchPattern->getMatchScore(contextCopy, *this,
						executionContext) !=
							XPath::eMatchScoreNone)
			{
				contextCopy = 0;
				break;
			}
		}
		
		if(0 != countMatchPattern)
		{
			if(countMatchPattern->getMatchScore(contextCopy, *this,
						executionContext) !=
							XPath::eMatchScoreNone)
			{
				break;
			}
		}

		XalanNode* const	prevSibling = contextCopy->getPreviousSibling();

		if(prevSibling == 0)
		{
			contextCopy = DOMServices::getParentOfNode(*contextCopy);
		}
		else
		{
			// Now go down the chain of children of this sibling 
			contextCopy = prevSibling->getLastChild();
			if (contextCopy == 0)
				contextCopy = prevSibling;
		}
	}

	return contextCopy;
}



const XPath*
ElemNumber::getCountMatchPattern(
			StylesheetExecutionContext&		executionContext,
			XalanNode*						contextNode) const
{
	const XPath*	countMatchPattern = 0;

	switch(contextNode->getNodeType())
	{
	case XalanNode::ELEMENT_NODE:
		{
			// Check to see if we have any fiddling to do with the match pattern
			// we create...
			const XalanDOMString&	theNamespaceURI = contextNode->getNamespaceURI();
			const XalanDOMString&	theNodeName = contextNode->getNodeName();

			if (isEmpty(theNamespaceURI) == true)
			{
				// No namespace URI means no prefix, so this is easy...
				assert(isEmpty(contextNode->getLocalName()) == true);

				// We can pass any PrefixResolver instance, so just
				// pass ourself...
				countMatchPattern =
						executionContext.createMatchPattern(theNodeName, *this);
			}
			else if (length(theNodeName) != length(contextNode->getLocalName()))
			{
				// OK, there's a prefix, so create a prefix resolver so the
				// prefix can be properly resolved...
				const XalanElement* const	theElement =
#if defined(XALAN_OLD_STYLE_CASTS)
					(const XalanElement*)contextNode;
#else
					static_cast<const XalanElement*>(contextNode);
#endif
					const ElementPrefixResolverProxy	theProxy(theElement);

				countMatchPattern =
						executionContext.createMatchPattern(theNodeName, theProxy);
			}
			else
			{
				// OK, this is ugly.  We have to get a unique prefix and
				// construct a match pattern with that prefix...
				StylesheetExecutionContext::GetAndReleaseCachedString	thePrefix(executionContext);

				executionContext.getUniqueNamespaceValue(thePrefix.get());

				StylesheetExecutionContext::GetAndReleaseCachedString	theMatchPatternString(executionContext);

				assign(theMatchPatternString.get(), thePrefix.get());
				append(theMatchPatternString.get(), XalanDOMChar(XalanUnicode::charColon));
				append(theMatchPatternString.get(), theNodeName);

				// Use this class to resolve the synthesized prefix to the
				// appropriate namespace URI.  We could see if a prefix is
				// already in scope for the namespace URI, but it would take
				// more effort to find that out than it would to just
				// create this simple resolver.
				const XalanSimplePrefixResolver		theResolver(
														thePrefix.get(),
														theNamespaceURI,
														getURI());

				countMatchPattern =
						executionContext.createMatchPattern(
							theMatchPatternString.get(),
							theResolver);
			}
		}
		break;

	case XalanNode::ATTRIBUTE_NODE:
		{
			const XalanAttr* const	theAttribute =
#if defined(XALAN_OLD_STYLE_CASTS)
				(const XalanAttr*)contextNode;
#else
				static_cast<const XalanAttr*>(contextNode);
#endif
			assert(theAttribute->getOwnerElement() != 0);

			const XalanDOMString&	theNodeName = theAttribute->getNodeName();

			const ElementPrefixResolverProxy	theProxy(theAttribute->getOwnerElement());

			StylesheetExecutionContext::GetAndReleaseCachedString	theMatchPatternString(executionContext);

			assign(theMatchPatternString.get(), s_atString);
			append(theMatchPatternString.get(), theNodeName);

			countMatchPattern = executionContext.createMatchPattern(
							theMatchPatternString.get(),
							theProxy);
		}
		break;

	case XalanNode::CDATA_SECTION_NODE:
	case XalanNode::TEXT_NODE:
		countMatchPattern = executionContext.createMatchPattern(
					s_textString, *this);
		break;

	case XalanNode::COMMENT_NODE:
		countMatchPattern = executionContext.createMatchPattern(
					s_commentString, *this);
		break;

	case XalanNode::DOCUMENT_NODE:
		countMatchPattern = executionContext.createMatchPattern(
					s_slashString, *this);
		break;

	case XalanNode::PROCESSING_INSTRUCTION_NODE:
		{
			StylesheetExecutionContext::GetAndReleaseCachedString	theMatchPatternString(executionContext);

			assign(theMatchPatternString.get(), s_piString);
			append(theMatchPatternString.get(), contextNode->getNodeName());
			append(theMatchPatternString.get(), s_leftParenString);

			countMatchPattern = executionContext.createMatchPattern(
					theMatchPatternString.get(),
					*this);
		}
		break;

	default:
		break;
	}

	return countMatchPattern;
}



inline void
ElemNumber::getCountString(
			StylesheetExecutionContext&		executionContext,
			XalanNode*						sourceNode,
			const MutableNodeRefList&		ancestors,
			CountersTable&					ctable,
			int								numberList[],
			NodeRefListBase::size_type		numberListLength,
			XalanDOMString&					theResult) const
{
	for(NodeRefListBase::size_type i = 0; i < numberListLength; i++)
	{
		XalanNode* const target = ancestors.item(numberListLength - i - 1);

		numberList[i] = ctable.countNode(
							executionContext,
							this,
							target);
	}

	formatNumberList(
			executionContext,
			numberList,
			numberListLength,
			sourceNode,
			theResult);
}



void
ElemNumber::getCountString(
			StylesheetExecutionContext&		executionContext,
			XalanDOMString&					theResult) const
{
	XalanNode* sourceNode = executionContext.getCurrentNode();

	assert(sourceNode != 0);

	if(0 != m_valueExpr)
	{
		const XObjectPtr	countObj(m_valueExpr->execute(sourceNode, *this, executionContext));
		assert(countObj.null() == false);

		const double	theValue = countObj->num();

		int	theNumber = 0;

		if (DoubleSupport::isNaN(theValue) == false)
		{
			theNumber = int(DoubleSupport::round(theValue));
		}

		formatNumberList(
				executionContext,
				&theNumber,
				1,
				sourceNode,
				theResult);
	}
	else
	{
		CountersTable&	ctable = executionContext.getCountersTable();

		if(Constants::NUMBERLEVEL_ANY == m_level)
		{
			const int	theNumber =
				ctable.countNode(executionContext, this, sourceNode);

			formatNumberList(
				executionContext,
				&theNumber,
				1,
				sourceNode,
				theResult);
		}
		else
		{
			typedef XPathExecutionContext::BorrowReturnMutableNodeRefList	BorrowReturnMutableNodeRefList;

			BorrowReturnMutableNodeRefList	ancestors(executionContext);

			getMatchingAncestors(
				executionContext,
				sourceNode,
				Constants::NUMBERLEVEL_SINGLE == m_level,
				*ancestors.get());

			const NodeRefListBase::size_type	lastIndex = ancestors->getLength();

			if(lastIndex > 0)
			{
				const NodeRefListBase::size_type	theStackArrayThreshold = 100;

				if (lastIndex < theStackArrayThreshold)
				{
					int		numberList[theStackArrayThreshold];

					getCountString(
						executionContext,
						sourceNode,
						*ancestors.get(),
						ctable,
						numberList,
						lastIndex,
						theResult);
				}
				else
				{
					IntArrayType	numberList;

					numberList.resize(lastIndex);

					getCountString(
						executionContext,
						sourceNode,
						*ancestors.get(),
						ctable,
						&*numberList.begin(),
						lastIndex,
						theResult);
				}
			}
		}
	}
}



XalanNode*
ElemNumber::getPreviousNode(
			StylesheetExecutionContext&		executionContext,
			XalanNode*						pos) const
{
	// Create an XPathGuard, since we may need to
	// create a new XPath...
	StylesheetExecutionContext::XPathGuard	xpathGuard(
			executionContext);

	const XPath*	countMatchPattern = m_countMatchPattern;

	if (countMatchPattern == 0)
	{
		// Get the XPath...
		xpathGuard.reset(getCountMatchPattern(executionContext, pos));

		countMatchPattern = xpathGuard.get();
	}

	if(Constants::NUMBERLEVEL_ANY == m_level)
	{
		const XPath* const	fromMatchPattern = m_fromMatchPattern;

		// Do a backwards document-order walk 'till a node is found that matches 
		// the 'from' pattern, or a node is found that matches the 'count' pattern, 
		// or the top of the tree is found.
		while(0 != pos)
		{            
			// Get the previous sibling, if there is no previous sibling, 
			// then count the parent, but if there is a previous sibling, 
			// dive down to the lowest right-hand (last) child of that sibling.
			XalanNode* next = pos->getPreviousSibling();

			if(0 == next)
			{
				next = pos->getParentNode();

				if(0 != next &&
				   next->getNodeType() == XalanNode::DOCUMENT_NODE ||
				   (0 != fromMatchPattern &&
						fromMatchPattern->getMatchScore(
							next,
							*this,
							executionContext) != XPath::eMatchScoreNone))
				{
					pos = 0; // return 0 from function.

					break; // from while loop
				}
			}
			else
			{
				// dive down to the lowest right child.
				XalanNode* child = next;

				while(0 != child)
				{
					child = next->getLastChild();

					if(0 != child)
						next = child;
				}
			}

			pos = next;

			if(0 != pos &&
			   (0 == countMatchPattern ||
				countMatchPattern->getMatchScore(
						pos,
						*this,
						executionContext) != XPath::eMatchScoreNone))
			{
				break;
			}
		}
	}
	else // NUMBERLEVEL_MULTI or NUMBERLEVEL_SINGLE
	{
		while(0 != pos)
		{            
			pos = pos->getPreviousSibling();

			if(0 != pos &&
			   (0 == countMatchPattern ||
				countMatchPattern->getMatchScore(
						pos,
						*this,
						executionContext) != XPath::eMatchScoreNone))
			{
				break;
			}
		}
	}

	return pos;
}



XalanNode*
ElemNumber::getTargetNode(
		StylesheetExecutionContext&		executionContext,
		XalanNode*						sourceNode) const
{
	XalanNode* target = 0;

	// Create an XPathGuard, since we may need to
	// create a new XPath...
	StylesheetExecutionContext::XPathGuard	xpathGuard(
			executionContext);

	const XPath*	countMatchPattern = m_countMatchPattern;

	if (countMatchPattern == 0)
	{
		// Get the XPath...
		xpathGuard.reset(getCountMatchPattern(executionContext, sourceNode));

		countMatchPattern = xpathGuard.get();
	}

	if(Constants::NUMBERLEVEL_ANY == m_level)
	{
		target = findPrecedingOrAncestorOrSelf(
				executionContext,
				m_fromMatchPattern,
				countMatchPattern,
				sourceNode,
				this);
	}
	else
	{
		target = findAncestor(
				executionContext,
				m_fromMatchPattern,
				countMatchPattern,
				sourceNode,
				this);
	}

	return target;
}



void
ElemNumber::getMatchingAncestors(
			StylesheetExecutionContext&		executionContext,
			XalanNode*						node, 
			bool							stopAtFirstFound,
			MutableNodeRefList&				ancestors) const
{
	// Create an XPathGuard, since we may need to
	// create a new XPath...
	StylesheetExecutionContext::XPathGuard	xpathGuard(
			executionContext);

	const XPath*	countMatchPattern = m_countMatchPattern;

	if (countMatchPattern == 0)
	{
		// Get the XPath...
		xpathGuard.reset(getCountMatchPattern(executionContext, node));

		countMatchPattern = xpathGuard.get();
	}

	while(0 != node)
	{
		if((0 != m_fromMatchPattern) &&
				(m_fromMatchPattern->getMatchScore(node, *this, executionContext) !=
				 XPath::eMatchScoreNone))
		{
			// The following if statement gives level="single" different 
			// behavior from level="multiple", which seems incorrect according 
			// to the XSLT spec.  For now we are leaving this in to replicate 
			// the same behavior in XT, but, for all intents and purposes we 
			// think this is a bug, or there is something about level="single" 
			// that we still don't understand.
			if(!stopAtFirstFound)
				break;
		}

		if(0 == countMatchPattern)
			executionContext.error(
				"Programmer error! countMatchPattern should never be 0!",
				node,
				getLocator());

		if(countMatchPattern->getMatchScore(node, *this, executionContext) !=
				XPath::eMatchScoreNone)
		{
			ancestors.addNode(node);

			if(stopAtFirstFound)
				break;
		}

		node = DOMServices::getParentOfNode(*node);
	}
}



XalanNumberFormat*
ElemNumber::getNumberFormatter(
			StylesheetExecutionContext&		executionContext,
			XalanNode*						contextNode) const
{
    // Helper to format local specific numbers to strings.
	XalanAutoPtr<XalanNumberFormat>		formatter(executionContext.createXalanNumberFormat());

	typedef XPathExecutionContext::GetAndReleaseCachedString	GetAndReleaseCachedString;

	GetAndReleaseCachedString	theGuard1(executionContext);

	XalanDOMString&				digitGroupSepValue = theGuard1.get();

	if (0 != m_groupingSeparator_avt)
		m_groupingSeparator_avt->evaluate(digitGroupSepValue, contextNode,
				 *this, executionContext);
									 
	if (length(digitGroupSepValue) > 1)
	{
		executionContext.error(
			"The grouping-separator value must be one character in length",
			contextNode,
			getLocator());
	}

	GetAndReleaseCachedString	theGuard2(executionContext);

	XalanDOMString&				nDigitsPerGroupValue = theGuard2.get();

	if (0 != m_groupingSize_avt)
		m_groupingSize_avt->evaluate(nDigitsPerGroupValue, contextNode, *this,
				executionContext);

    // TODO: Handle digit-group attributes
	// 7.7.1 If one is empty, it is ignored	(numb81 conf test)
	if(!isEmpty(digitGroupSepValue) && !isEmpty(nDigitsPerGroupValue))
	{
		formatter->setGroupingUsed(true);
		formatter->setGroupingSeparator(digitGroupSepValue);
		formatter->setGroupingSize(DOMStringToUnsignedLong(nDigitsPerGroupValue));
	}

	return formatter.release();
}



void
ElemNumber::formatNumberList(
			StylesheetExecutionContext&		executionContext,
			const int						theList[],
			NodeRefListBase::size_type		theListLength,
			XalanNode*						contextNode,
			XalanDOMString&					theResult) const
{
	assert(theListLength > 0);

	// Pathological cases
	if (contextNode == 0) return;

	XalanDOMChar	numberType = XalanUnicode::charDigit_1;

	XalanDOMString::size_type	numberWidth = 1;

	typedef vector<XalanDOMString>		StringVectorType;
	typedef StringVectorType::iterator	StringVectorTypeIterator;

	// Construct an array of tokens.  We need to be able to check if the last
	// token in non-alphabetic, in which case the penultimate non-alphabetic is
	// the repeating separator.
	//
	// We should be able to replace this with a vector of the indexes in
	// the evaluated string where the tokens start.  But for now, this will
	// have to do...
	StringVectorType	tokenVector;

	{
		typedef XPathExecutionContext::GetAndReleaseCachedString	GetAndReleaseCachedString;

		GetAndReleaseCachedString	theGuard1(executionContext);

		XalanDOMString&				formatValue = theGuard1.get();

		if (m_format_avt != 0)
		{
			 m_format_avt->evaluate(formatValue, contextNode, *this, executionContext);
		}

		if(isEmpty(formatValue) == true)
		{
			formatValue = XalanUnicode::charDigit_1;
		}

		NumberFormatStringTokenizer						formatTokenizer(formatValue);

		const NumberFormatStringTokenizer::size_type	theTokenCount = formatTokenizer.countTokens();

		tokenVector.resize(theTokenCount);

		// Tokenize directly into the vector...
		for(NumberFormatStringTokenizer::size_type i = 0; i < theTokenCount; ++i)
		{
			formatTokenizer.nextToken(tokenVector[i]);
		}

		assert(theTokenCount == tokenVector.size());
	}

	// These are iterators which will either point to tokenVector.end(),
	// or the appropriate string in the vector...
	StringVectorTypeIterator		leaderStrIt = tokenVector.end();
	StringVectorTypeIterator		trailerStrIt = leaderStrIt;
	StringVectorTypeIterator		sepStringIt = leaderStrIt;
	const StringVectorTypeIterator	endIt = leaderStrIt;

	StringVectorTypeIterator	it = tokenVector.begin();

	const StringVectorType::size_type	theVectorSize =
		tokenVector.size();

	if (theVectorSize > 0)
	{
		if(!isXMLLetterOrDigit(charAt(*it, 0)))
		{
			leaderStrIt = it;

			// Move the iterator up one, so it
			// points at the first numbering token...
			++it;
		}

		if (theVectorSize > 1)
		{
			if(!isXMLLetterOrDigit(charAt(tokenVector.back(), 0)))
			{
				// Move the iterator back one, so it's pointing
				// at the trailing string...
				--trailerStrIt;
			}
		}
	}

	// Now we're left with a sequence of alpha,non-alpha tokens, format them
	// with the corresponding entry in the format string, or the last one if no
	// more matching ones

	if (leaderStrIt != endIt)
	{
		theResult += *leaderStrIt;
	}

	typedef XPathExecutionContext::GetAndReleaseCachedString	GetAndReleaseCachedString;

	GetAndReleaseCachedString	theGuard2(executionContext);

	XalanDOMString&				theIntermediateResult = theGuard2.get();

	for(unsigned int i = 0; i < theListLength; i++)
	{
		if (it != trailerStrIt)
		{
			assert(isXMLLetterOrDigit(charAt(*it, 0)));

			numberWidth = length(*it);

			numberType = charAt(*it, numberWidth - 1);

			++it;
		}

		if (it != trailerStrIt)
		{
			assert(!isXMLLetterOrDigit(charAt(*it, 0)));

			sepStringIt = it;

			++it;
		}

		getFormattedNumber(
				executionContext,
				contextNode,
				numberType,
				numberWidth,
				theList[i],
				theIntermediateResult);

		theResult += theIntermediateResult;

		// All but the last one
		if (i < theListLength - 1)
		{
			if (sepStringIt != endIt)
			{
				theResult += *sepStringIt;
			}
			else
			{
				theResult += s_defaultSeparatorString;
			}

			clear(theIntermediateResult);
		}
	}

	if (trailerStrIt != endIt)
	{
		theResult += *trailerStrIt;
	}
}



void
ElemNumber::evaluateLetterValueAVT(
			StylesheetExecutionContext&		executionContext,
			XalanNode* 						contextNode,
			XalanDOMString&					value) const
{
	if (m_lettervalue_avt == 0)
	{
		clear(value);
	}
	else
	{
		m_lettervalue_avt->evaluate(
				value,
				contextNode,
				*this,
				executionContext);
	}
}



void
ElemNumber::traditionalAlphaCount(
			int										theValue,
			const XalanNumberingResourceBundle&		theResourceBundle,
			XalanDOMString&							theResult) const
{
	typedef XalanNumberingResourceBundle::IntVectorType			IntVectorType;
	typedef XalanNumberingResourceBundle::DigitsTableVectorType	DigitsTableVectorType;
	typedef XalanNumberingResourceBundle::eNumberingMethod		eNumberingMethod;
	typedef XalanNumberingResourceBundle::eMultiplierOrder		eMultiplierOrder;

	bool	fError = false;

	// if this number is larger than the largest number we can represent, error!
	//if (val > theResourceBundle.getMaxNumericalValue())
	//return XSLTErrorResources.ERROR_STRING;
	XalanDOMCharVectorType	table;

	// index in table of the last character that we stored
	IntVectorType::size_type	lookupIndex = 1;  // start off with anything other than zero to make correction work

	// Create a buffer to hold the result
	// TODO:  size of the table can be determined by computing
	// logs of the radix.  For now, we fake it.
	XalanDOMChar	buf[100];

	//some languages go left to right(ie. english), right to left (ie. Hebrew),
	//top to bottom (ie.Japanese), etc... Handle them differently
	//String orientation = thisBundle.getString(Constants.LANG_ORIENTATION);

	// next character to set in the buffer
	int charPos = 0;

	// array of number groups: ie.1000, 100, 10, 1
	const IntVectorType&	groups = theResourceBundle.getNumberGroups();

	const IntVectorType::size_type	groupsSize = groups.size();

	// array of tables of hundreds, tens, digits. Indexes into the vectors
	// in the digits table.
	const IntVectorType&	tables = theResourceBundle.getDigitsTableTable();

	const DigitsTableVectorType&	digitsTable = theResourceBundle.getDigitsTable();

	assert(tables.size() == digitsTable.size());

	// some languages have additive alphabetical notation,
	// some multiplicative-additive, etc... Handle them differently.
	const eNumberingMethod	numbering = theResourceBundle.getNumberingMethod();

	// do multiplicative part first
	if (numbering == XalanNumberingResourceBundle::eMultiplicativeAdditive)
	{
		const eMultiplierOrder	mult_order = theResourceBundle.getMultiplierOrder();

		const IntVectorType&	multiplier = theResourceBundle.getMultipliers();

		const IntVectorType::size_type	multiplierSize = multiplier.size();

		const XalanDOMCharVectorType&	zeroChar = theResourceBundle.getZeroChar();

		const XalanDOMCharVectorType::size_type		zeroCharSize = zeroChar.size();

		const XalanDOMCharVectorType&	multiplierChars = theResourceBundle.getMultiplierChars();

		IntVectorType::size_type	i = 0;

		// skip to correct multiplier
		while (i < multiplierSize && theValue < multiplier[i])
		{
			i++;
		}

		do
		{
			if (i >= multiplierSize)
				break;			  //number is smaller than multipliers

			// some languages (ie chinese) put a zero character (and only one) when
			// the multiplier is multiplied by zero. (ie, 1001 is 1X1000 + 0X100 + 0X10 + 1)
			// 0X100 is replaced by the zero character, we don't need one for 0X10
			if (theValue < multiplier[i])
			{
				if (zeroCharSize == 0)
				{
					i++;
				} 
				else
				{
					if (buf[charPos - 1] != zeroChar[0])
					{
						buf[charPos++] = zeroChar[0];
					}

					i++;
				}
			}
			else if (theValue >= multiplier[i])
			{

				int mult = theValue / multiplier[i];

				theValue = theValue % multiplier[i];		 // save this.

				IntVectorType::size_type	k = 0;

				while (k < groupsSize)
				{
					lookupIndex = 1;				 // initialize for each table
			
					if (mult / groups[k] <= 0) 		 // look for right table
					{
						k++;
					}
					else
					{
						assert(digitsTable.size() > DigitsTableVectorType::size_type(tables[k]));

						// get the table
						const XalanDOMCharVectorType&	THEletters =
								digitsTable[tables[k]];

						const XalanDOMCharVectorType::size_type		THElettersSize =
							THEletters.size();

						table.resize(THElettersSize + 1);					

						const IntVectorType::size_type	tableSize = table.size();

						XalanDOMCharVectorType::size_type	j = 0;

						for (; j < THElettersSize; j++)
						{
							table[j + 1] = THEletters[j];
						}

						table[0] = THEletters[j - 1];	 // don't need this

						// index in "table" of the next char to emit
						lookupIndex  = mult / groups[k];

						//this should not happen
						if (lookupIndex == 0 && mult == 0)
						{
							break;
						}

						assert(i < multiplierChars.size());

						const XalanDOMChar	multiplierChar = multiplierChars[i];

						// put out the next character of output	
						if (lookupIndex < tableSize)
						{
							if(mult_order == XalanNumberingResourceBundle::ePrecedes)
							{
								buf[charPos++] = multiplierChar;
								buf[charPos++] = table[lookupIndex];
							}
							else
							{
								// don't put out 1 (ie 1X10 is just 10)
								if (lookupIndex == 1 && i == multiplierSize - 1)
								{
								}
								else
								{
									buf[charPos++] = table[lookupIndex];
								}

								buf[charPos++] = multiplierChar;
							}

							break;		 // all done!
						}
						else
						{
							fError = true;

							break;
						}
					} //end else
				} // end while	

				i++;

			} // end else if
		} // end do while
		while (i < multiplierSize && fError == false);		
	}

	// Now do additive part...
	IntVectorType::size_type	count = 0;

	// do this for each table of hundreds, tens, digits...
	while (count < groupsSize)
	{
		if (theValue / groups[count] <= 0)
		{
			// look for correct table
			count++;
		}
		else
		{
			const XalanDOMCharVectorType&	theletters =
								digitsTable[tables[count]];

			const XalanDOMCharVectorType::size_type		thelettersSize =
							theletters.size();

			table.resize(thelettersSize + 1);
		
			const IntVectorType::size_type	tableSize = table.size();

			XalanDOMCharVectorType::size_type	j = 0;

			// need to start filling the table up at index 1
			for (; j < thelettersSize; j++)
			{
				table[j + 1] = theletters[j];
			}

			table[0] = theletters[j - 1];  // don't need this

			// index in "table" of the next char to emit
			lookupIndex  = theValue / groups[count];

			// shift input by one "column"
			theValue = theValue % groups[count];

			// this should not happen
			if (lookupIndex == 0 && theValue == 0)
				break;					

			if (lookupIndex < tableSize)
			{
				// put out the next character of output	
				buf[charPos++] = table[lookupIndex];	// left to right or top to bottom					
			}
			else
			{
				fError = true;

				break;
			}

			count++;
		}
	} // end while

	if (fError == true)
	{
		theResult = XALAN_STATIC_UCODE_STRING("#error");
	}
	else
	{
		assign(theResult, buf, charPos);
	}
}



const XalanDOMChar	elalphaNumberType = 0x03B1;



void
ElemNumber::getFormattedNumber(
			StylesheetExecutionContext&		executionContext,
			XalanNode*						contextNode,
			XalanDOMChar					numberType,
			XalanDOMString::size_type		numberWidth,
			int								listElement,
			XalanDOMString&					theResult) const
{
	switch(numberType)
	{
		case XalanUnicode::charLetter_A:
			int2alphaCount(listElement, s_alphaCountTable, theResult);
			break;

		case XalanUnicode::charLetter_a:
			int2alphaCount(listElement, s_alphaCountTable, theResult);

			theResult = toLowerCaseASCII(theResult);
			break;

		case XalanUnicode::charLetter_I:
			long2roman(executionContext, contextNode, listElement, true, theResult);
			break;

		case XalanUnicode::charLetter_i:
			long2roman(executionContext, contextNode, listElement, true, theResult);

			theResult = toLowerCaseASCII(theResult);
			break;

		case 0x3042:
		case 0x3044:
		case 0x30A2:
		case 0x30A4:
		case 0x4E00:
		case 0x58F9:
		case 0x0E51:
		case 0x05D0:
		case 0x10D0:
		case 0x0430:
			executionContext.error(
				"Numbering format not supported yet",
				contextNode,
				getLocator());
			break;

		// Handle the special case of Greek letters for now
		case elalphaNumberType:
			{
				// A string to hold the result.
				StylesheetExecutionContext::GetAndReleaseCachedString	theGuard(executionContext);

				XalanDOMString&		letterVal = theGuard.get();

				evaluateLetterValueAVT(executionContext, contextNode, letterVal);

				if (equals(letterVal, Constants::ATTRVAL_TRADITIONAL) == true)
				{
					NumberingResourceBundleMapType::const_iterator	i = s_resourceBundles.find(0x03B1);

					if (i != s_resourceBundles.end())
					{
						traditionalAlphaCount(listElement, (*i).second, theResult);
					}
				}
				else if (equals(letterVal, Constants::ATTRVAL_ALPHABETIC) == true)
				{
					int2alphaCount(listElement, s_elalphaCountTable, theResult);
				}
				else
				{
					executionContext.error(
						"The legal values for letter-value are 'alphabetic' and 'traditional'",
						contextNode,
						getLocator());
				}
			}
			break;

		default: // "1"
			{
				StylesheetExecutionContext::XalanNumberFormatAutoPtr	formatter(
						getNumberFormatter(executionContext, contextNode));

				formatter->format(listElement, theResult);

				const XalanDOMString::size_type		lengthNumString = length(theResult);

				if (numberWidth > lengthNumString)
				{
					const XalanDOMString::size_type	nPadding = numberWidth - lengthNumString;

					const XalanDOMString	padString = formatter->format(0);

					reserve(theResult, nPadding * length(padString) + lengthNumString + 1);

					for(XalanDOMString::size_type i = 0; i < nPadding; i++)
					{
						insert(theResult, 0, padString);
					}
				}
			}
			break;
	}
}



void
ElemNumber::int2singlealphaCount(
		int						val, 
		const XalanDOMString&	table,
		XalanDOMString&			theResult)
{
	assert(int(length(table)) == length(table));

	const int	radix = int(length(table));

	// TODO:  throw error on out of range input
	if (val > radix)
	{
		theResult = XalanDOMString(XALAN_STATIC_UCODE_STRING("#E(") +
				LongToDOMString(val) +
				XALAN_STATIC_UCODE_STRING(")"));
	}
	else
	{
		const XalanDOMChar	theChar = charAt(table, val - 1);

		assign(theResult, &theChar, 1);
	}
}



void
ElemNumber::int2alphaCount(
			int						val,
			const XalanDOMString&	table,
			XalanDOMString&			theResult)
{
	assert(int(length(table)) == length(table));

	const int	radix = int(length(table));

	// Create a buffer to hold the result
	// TODO:  size of the table can be determined by computing
	// logs of the radix.  For now, we fake it.  
	const int		buflen = 100;

	XalanDOMChar	buf[buflen + 1];

#if defined(XALAN_STRICT_ANSI_HEADERS)
	std::memset(buf, 0, (buflen + 1) * sizeof(XalanDOMChar));
#else
	memset(buf, 0, (buflen + 1) * sizeof(XalanDOMChar));
#endif

	// next character to set in the buffer
	int charPos = buflen - 1 ;    // work backward through buf[]

	// index in table of the last character that we stored
	int lookupIndex = 1;  // start off with anything other than zero to make correction work
	
	//						Correction number
	//
	//	Correction can take on exactly two values:
	//
	//		0	if the next character is to be emitted is usual
	//
	//      radix - 1 
	//			if the next char to be emitted should be one less than
	//			you would expect 
	//			
	// For example, consider radix 10, where 1="A" and 10="J"
	//
	// In this scheme, we count: A, B, C ...   H, I, J (not A0 and certainly
	// not AJ), A1
	//
	// So, how do we keep from emitting AJ for 10?  After correctly emitting the
	// J, lookupIndex is zero.  We now compute a correction number of 9 (radix-1).
	// In the following line, we'll compute (val+correction) % radix, which is,
	// (val+9)/10.  By this time, val is 1, so we compute (1+9) % 10, which 
	// is 10 % 10 or zero.  So, we'll prepare to emit "JJ", but then we'll
	// later suppress the leading J as representing zero (in the mod system, 
	// it can represent either 10 or zero).  In summary, the correction value of
	// "radix-1" acts like "-1" when run through the mod operator, but with the 
	// desireable characteristic that it never produces a negative number.

	int correction = 0;

	// TODO:  throw error on out of range input

	do
	{
		// most of the correction calculation is explained above,  the reason for the
		// term after the "|| " is that it correctly propagates carries across
		// multiple columns.  
		correction = ((lookupIndex == 0) || 
			(correction != 0 && lookupIndex == radix - 1 )) ? (radix - 1) : 0;

		// index in "table" of the next char to emit
		lookupIndex  = (val + correction) % radix;  

		// shift input by one "column"
		val = (val / radix);

		// if the next value we'd put out would be a leading zero, we're done.
		if (lookupIndex == 0 && val == 0)
			break;

		// put out the next character of output
		buf[charPos--] = charAt(table, lookupIndex);
	}
	while (val > 0);

	assign(theResult, buf + charPos + 1, buflen - charPos - 1);
}



void
ElemNumber::tradAlphaCount(
			int					/* val */,
			XalanDOMString&		/* theResult */)
{
//	@@ JMD: We don't do languages yet, so this is just a placeholder
	assert(false);
}



void
ElemNumber::long2roman(
			StylesheetExecutionContext&		executionContext,
			XalanNode*						contextNode,
			long							val,
			bool							prefixesAreOK,
			XalanDOMString&					theResult) const
{
	if(val < 0)
	{
		executionContext.error(
			"I and i can only format positive numbers",
			contextNode,
			getLocator());

	}
	else
	{
		long2roman(val, prefixesAreOK, theResult);
	}
}



void
ElemNumber::long2roman(
			long				val,
			bool				prefixesAreOK,
			XalanDOMString&		theResult)
{
	if(val < 0)
	{
		theResult = XalanDOMString(XALAN_STATIC_UCODE_STRING("#E(") +
								LongToDOMString(val) +
								XALAN_STATIC_UCODE_STRING(")"));
	}
	else if(val == 0)
	{
		theResult = XALAN_STATIC_UCODE_STRING("0");
	}
	else if (val <= 3999L)
	{
		clear(theResult);

		int	place = 0;

		do      
		{
			while (val >= s_romanConvertTable[place].m_postValue)
			{
				theResult += s_romanConvertTable[place].m_postLetter;
				val -= s_romanConvertTable[place].m_postValue;
			}

			if (prefixesAreOK)
			{
				if (val >= s_romanConvertTable[place].m_preValue)
				{
					theResult += s_romanConvertTable[place].m_preLetter;
					val -= s_romanConvertTable[place].m_preValue;
				}
			} 

			++place;      
		}
		while (val > 0);
	}
	else
	{
		theResult = XALAN_STATIC_UCODE_STRING("#error");
	}
}



ElemNumber::NumberFormatStringTokenizer::NumberFormatStringTokenizer(
			const XalanDOMString&	theString) :
	m_currentPosition(0),
	m_maxPosition(length(theString)),
	m_string(&theString)
{
}



void
ElemNumber::NumberFormatStringTokenizer::setString(const XalanDOMString&	theString)
{
	m_string = &theString;

	m_currentPosition = 0;
	m_maxPosition = length(theString);
}



XalanDOMString
ElemNumber::NumberFormatStringTokenizer::nextToken() 
{
	if (m_currentPosition >= m_maxPosition) 
	{
		return XalanDOMString();
	}

	const size_type		start = m_currentPosition;

	if (isXMLLetterOrDigit(charAt(*m_string, m_currentPosition)))
	{
		while (m_currentPosition < m_maxPosition &&
			   isXMLLetterOrDigit(charAt(*m_string, m_currentPosition)))
		{
			m_currentPosition++;
		}
	}
	else
	{
		while (m_currentPosition < m_maxPosition &&
			   !isXMLLetterOrDigit(charAt(*m_string, m_currentPosition)))
		{
			m_currentPosition++;
		}
	}

	return XalanDOMString(*m_string, start, m_currentPosition);
}



void
ElemNumber::NumberFormatStringTokenizer::nextToken(XalanDOMString&	theToken)
{
	if (m_currentPosition >= m_maxPosition) 
	{
		clear(theToken);
	}

	const size_type		start = m_currentPosition;

	if (isXMLLetterOrDigit(charAt(*m_string, m_currentPosition)))
	{
		while (m_currentPosition < m_maxPosition &&
			   isXMLLetterOrDigit(charAt(*m_string, m_currentPosition)))
		{
			m_currentPosition++;
		}
	}
	else
	{
		while (m_currentPosition < m_maxPosition &&
			   !isXMLLetterOrDigit(charAt(*m_string, m_currentPosition)))
		{
			m_currentPosition++;
		}
	}

	substring(*m_string, theToken, start, m_currentPosition);
}



ElemNumber::NumberFormatStringTokenizer::size_type
ElemNumber::NumberFormatStringTokenizer::countTokens() const
{
	size_type 	count = 0;
	size_type 	currpos = m_currentPosition;

	// Tokens consist of sequences of alphabetic characters and sequences of
	// non-alphabetic characters
	while (currpos < m_maxPosition) 
	{
		if (isXMLLetterOrDigit(charAt(*m_string, currpos)))
		{
			while (currpos < m_maxPosition &&
				   isXMLLetterOrDigit(charAt(*m_string, currpos)))
			{
				currpos++;
			}
		}
		else
		{
			while (currpos < m_maxPosition &&
				   !isXMLLetterOrDigit(charAt(*m_string, currpos)))
			{
				currpos++;
			}
		}

		count++;
	}

	return count;
}



static const XalanDOMChar	alphaCountTable[] =
{
	XalanUnicode::charLetter_Z,
	XalanUnicode::charLetter_A,
	XalanUnicode::charLetter_B,
	XalanUnicode::charLetter_C,
	XalanUnicode::charLetter_D,
	XalanUnicode::charLetter_E,
	XalanUnicode::charLetter_F,
	XalanUnicode::charLetter_G,
	XalanUnicode::charLetter_H,
	XalanUnicode::charLetter_I,
	XalanUnicode::charLetter_J,
	XalanUnicode::charLetter_K,
	XalanUnicode::charLetter_L,
	XalanUnicode::charLetter_M,
	XalanUnicode::charLetter_N,
	XalanUnicode::charLetter_O,
	XalanUnicode::charLetter_P,
	XalanUnicode::charLetter_Q,
	XalanUnicode::charLetter_R,
	XalanUnicode::charLetter_S,
	XalanUnicode::charLetter_T,
	XalanUnicode::charLetter_U,
	XalanUnicode::charLetter_V,
	XalanUnicode::charLetter_W,
	XalanUnicode::charLetter_X,
	XalanUnicode::charLetter_Y,
	0
};



static const XalanDOMChar	elalphaCountTable[] =
{
	0x03c9,
	0x03b1,
	0x03b2,
	0x03b3,
	0x03b4,
	0x03b5,
	0x03b6,
	0x03b7,
	0x03b8,
	0x03b9,
	0x03ba,
	0x03bb,
	0x03bc,
	0x03bd,
	0x03be,
	0x03bf,
	0x03c0,
	0x03c1,
	0x03c2,
	0x03c3,
	0x03c4,
	0x03c5,
	0x03c6,
	0x03c7,
	0x03c8,
	0
};



static XalanDOMString								s_atString;

static XalanDOMString								s_textString;

static XalanDOMString								s_commentString;

static XalanDOMString								s_slashString;

static XalanDOMString								s_piString;

static XalanDOMString								s_leftParenString;

static XalanDOMString								s_dotString;

static XalanDOMString								s_oneString;

static XalanDOMString								s_defaultSeparatorString;

static XalanDOMString								s_alphaCountTable;

static XalanDOMString								s_elalphaCountTable;



static ElemNumber::DecimalToRomanVectorType			s_romanConvertTable;

static ElemNumber::NumberingResourceBundleMapType	s_resourceBundles;


const XalanDOMString&	ElemNumber::s_atString = ::s_atString;

const XalanDOMString&	ElemNumber::s_textString = ::s_textString;

const XalanDOMString&	ElemNumber::s_commentString = ::s_commentString;

const XalanDOMString&	ElemNumber::s_slashString = ::s_slashString;

const XalanDOMString&	ElemNumber::s_piString = ::s_piString;

const XalanDOMString&	ElemNumber::s_leftParenString = ::s_leftParenString;

const XalanDOMString&	ElemNumber::s_dotString = ::s_dotString;

const XalanDOMString&	ElemNumber::s_oneString = ::s_oneString;

const XalanDOMString&	ElemNumber::s_defaultSeparatorString = ::s_defaultSeparatorString;

const XalanDOMString&	ElemNumber::s_alphaCountTable = ::s_alphaCountTable;

const XalanDOMString&	ElemNumber::s_elalphaCountTable = ::s_elalphaCountTable;

const ElemNumber::DecimalToRomanVectorType&		ElemNumber::s_romanConvertTable =
				::s_romanConvertTable;

const ElemNumber::NumberingResourceBundleMapType&	ElemNumber::s_resourceBundles =
				::s_resourceBundles;



static void
addTraditionalElalphaBundle(ElemNumber::NumberingResourceBundleMapType&		theBundleMap)
{

	// The following are a bunch of static data the comprise the contents of the bundle.
	static const XalanDOMChar	elalphaAlphabet[] =
	{
		0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,  0x03b8,
		0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0,
		0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8,
		0x03c9, 0
	};

	static const XalanDOMChar	elalphaTraditionalAlphabet[] =
	{
		XalanUnicode::charLetter_A, XalanUnicode::charLetter_B, XalanUnicode::charLetter_C,
		XalanUnicode::charLetter_D, XalanUnicode::charLetter_E, XalanUnicode::charLetter_F,
		XalanUnicode::charLetter_G, XalanUnicode::charLetter_H, XalanUnicode::charLetter_I,
		XalanUnicode::charLetter_J, XalanUnicode::charLetter_K, XalanUnicode::charLetter_L,
		XalanUnicode::charLetter_M, XalanUnicode::charLetter_N, XalanUnicode::charLetter_O,
		XalanUnicode::charLetter_P, XalanUnicode::charLetter_Q, XalanUnicode::charLetter_R,
		XalanUnicode::charLetter_S, XalanUnicode::charLetter_T, XalanUnicode::charLetter_U,
		XalanUnicode::charLetter_V, XalanUnicode::charLetter_W, XalanUnicode::charLetter_X,
		XalanUnicode::charLetter_Y, XalanUnicode::charLetter_Z, 0
	};

	static const int	elalphaNumberGroups[] =
	{
		100, 10, 1
	};

	const size_t	elalphaNumberGroupsCount = sizeof(elalphaNumberGroups) / sizeof(int);

	static const int	elalphaMultipliers[] = { 1000 };

	const size_t	elalphaMultipliersCount = sizeof(elalphaMultipliers) / sizeof(int);

	static const XalanDOMChar	elalphaMultiplierChars[] = { 0x03d9, 0 };

	static const XalanDOMChar	elalphaDigits[] =
	{
		0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03db, 0x03b6, 0x03b7, 0x03b8, 0
	};

	static const XalanDOMChar	elalphaTens[] =
	{
		0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03df, 0
	};

	static const XalanDOMChar	elalphaHundreds[] =
	{
		0x03c1, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03e1, 0
	};

	typedef XalanNumberingResourceBundle::DigitsTableVectorType		DigitsTableVectorType;
	typedef XalanNumberingResourceBundle::IntVectorType				IntVectorType;

	// Create the table of characters for the various digit positions...
	DigitsTableVectorType			theElalphaDigitsTable;

	// Since we know the size, create the empty vectors in the table...
	theElalphaDigitsTable.resize(3);

	// Swap the empty tables with temporary ones...
	XalanDOMCharVectorType(elalphaDigits, elalphaDigits + length(elalphaDigits)).swap(theElalphaDigitsTable[0]);
	XalanDOMCharVectorType(elalphaTens, elalphaTens + length(elalphaTens)).swap(theElalphaDigitsTable[1]);
	XalanDOMCharVectorType(elalphaHundreds, elalphaHundreds + length(elalphaHundreds)).swap(theElalphaDigitsTable[2]);

	// This table will indicate which positions the vectors of digits are in
	// the table...
	IntVectorType	theDigitsTableTable;

	theDigitsTableTable.reserve(3);

	// Push the positions on in reverse order, since that's how things work...
	theDigitsTableTable.push_back(2);
	theDigitsTableTable.push_back(1);
	theDigitsTableTable.push_back(0);

	const XalanDOMString	theLanguageString("el");

	const XalanNumberingResourceBundle	theElaphaBundle(
		theLanguageString,
		theLanguageString,
		theLanguageString,
		XalanDOMCharVectorType(elalphaAlphabet, elalphaAlphabet + length(elalphaAlphabet)),
		XalanDOMCharVectorType(elalphaTraditionalAlphabet, elalphaTraditionalAlphabet + length(elalphaTraditionalAlphabet)),
		XalanNumberingResourceBundle::eLeftToRight,
		XalanNumberingResourceBundle::eMultiplicativeAdditive,
		XalanNumberingResourceBundle::ePrecedes,
		~0,
		IntVectorType(elalphaNumberGroups, elalphaNumberGroups + elalphaNumberGroupsCount),
		IntVectorType(elalphaMultipliers, elalphaMultipliers + elalphaMultipliersCount),
		XalanDOMCharVectorType(),
		XalanDOMCharVectorType(elalphaMultiplierChars, elalphaMultiplierChars + length(elalphaMultiplierChars)),
		theElalphaDigitsTable,
		theDigitsTableTable);

	typedef ElemNumber::NumberingResourceBundleMapType::value_type	value_type;

	theBundleMap[elalphaNumberType] = theElaphaBundle;
}



void
ElemNumber::initialize()
{
	::s_atString = XALAN_STATIC_UCODE_STRING("@");

	::s_textString = XALAN_STATIC_UCODE_STRING("text()");

	::s_commentString = XALAN_STATIC_UCODE_STRING("comment()");

	::s_slashString = XALAN_STATIC_UCODE_STRING("/");

	::s_piString = XALAN_STATIC_UCODE_STRING("pi(");

	::s_leftParenString = XALAN_STATIC_UCODE_STRING(")");

	::s_dotString = XALAN_STATIC_UCODE_STRING(".");

	::s_oneString = XALAN_STATIC_UCODE_STRING("1");

	::s_defaultSeparatorString = XALAN_STATIC_UCODE_STRING(".");

	::s_alphaCountTable = alphaCountTable;

	::s_elalphaCountTable = elalphaCountTable;

	::s_romanConvertTable.reserve(7);

	::s_romanConvertTable.push_back(
		DecimalToRoman(
			1000L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("M")),
			900L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("CM"))));

	::s_romanConvertTable.push_back(
		DecimalToRoman(
			500L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("D")),
			400,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("CD"))));

	::s_romanConvertTable.push_back(
		DecimalToRoman(
			100L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("C")),
			90L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("XC"))));

	::s_romanConvertTable.push_back(
		DecimalToRoman(
			50L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("L")),
			40L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("XL"))));

	::s_romanConvertTable.push_back(
		DecimalToRoman(
			10L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("X")),
			9L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("IX"))));

	::s_romanConvertTable.push_back(
		DecimalToRoman(
			5L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("V")),
			4L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("IV"))));

	::s_romanConvertTable.push_back(
		DecimalToRoman(
			1L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("I")),
			1L,
			StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("I"))));

	addTraditionalElalphaBundle(::s_resourceBundles);
}



void
ElemNumber::terminate()
{
	releaseMemory(::s_atString);
	releaseMemory(::s_textString);
	releaseMemory(::s_commentString);
	releaseMemory(::s_slashString);
	releaseMemory(::s_piString);
	releaseMemory(::s_leftParenString);
	releaseMemory(::s_dotString);
	releaseMemory(::s_oneString);
	releaseMemory(::s_defaultSeparatorString);

	releaseMemory(::s_alphaCountTable);
	releaseMemory(::s_elalphaCountTable);

	DecimalToRomanVectorType().swap(::s_romanConvertTable);

	NumberingResourceBundleMapType().swap(::s_resourceBundles);
}
