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

// Class header file
#include "StylesheetRoot.hpp"



#include <algorithm>
#include <memory>



#include <xalanc/XalanDOM/XalanDocumentFragment.hpp>



#include <xalanc/PlatformSupport/AttributeListImpl.hpp>
#include <xalanc/PlatformSupport/PrintWriter.hpp>
#include <xalanc/PlatformSupport/StringTokenizer.hpp>
#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>



#include <xalanc/DOMSupport/DOMServices.hpp>



#include <xalanc/XPath/XalanQNameByReference.hpp>
#include <xalanc/XPath/XPathFactory.hpp>
#include <xalanc/XPath/XPathProcessor.hpp>



#include <xalanc/XMLSupport/FormatterToHTML.hpp>
#include <xalanc/XMLSupport/FormatterToText.hpp>
#include <xalanc/XMLSupport/FormatterToXML.hpp>



#include "Constants.hpp"
#include "ElemApplyTemplates.hpp"
#include "ElemAttributeSet.hpp"
#include "ElemTemplate.hpp"
#include "ElemValueOf.hpp"
#include "KeyTable.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetExecutionContext.hpp"
#include "TraceListener.hpp"
#include "XSLTResultTarget.hpp"



//#define XALAN_VQ_SPECIAL_TRACE
#if defined(XALAN_VQ_SPECIAL_TRACE)
#include "C:/Program Files/Rational/Quantify/pure.h"
#endif



namespace XALAN_CPP_NAMESPACE {



StylesheetRoot::StylesheetRoot(
        const XalanDOMString&           baseIdentifier,
        StylesheetConstructionContext&  constructionContext) :
    Stylesheet(*this,
               baseIdentifier,
               constructionContext),    
    m_version(constructionContext.getMemoryManager()),
    m_indentResult(eIndentNoImplicit),
    m_encoding(constructionContext.getMemoryManager()),
    m_mediatype(constructionContext.getMemoryManager()),
    m_doctypeSystem(constructionContext.getMemoryManager()),
    m_doctypePublic(constructionContext.getMemoryManager()),
    m_omitxmlDecl(false),
    m_standalone(constructionContext.getMemoryManager()),
    m_resultNameSpaceURL(constructionContext.getMemoryManager()),
    m_outputMethod(FormatterListener::OUTPUT_METHOD_NONE),
    m_cdataSectionElems(constructionContext.getMemoryManager()),
    m_hasCDATASectionElems(false),
    m_importStack(constructionContext.getMemoryManager()),
    m_defaultTextRule(0),
    m_defaultRule(0),
    m_defaultRootRule(0),
    m_needToBuildKeysTable(false),
    m_outputEscapeURLs(true),
    m_indentAmount(-1),
    m_omitMETATag(false),
    m_elemNumberNextID(0),
    m_attributeSetsMap(constructionContext.getMemoryManager()),
    m_hasStripOrPreserveSpace(false)
{
    // Our base class has already resolved the URI and pushed it on
    // the back of the include stack, so get it from there...
    assert(getIncludeStack().empty() == false);

    m_importStack.push_back(getIncludeStack().back());
}               



StylesheetRoot*
StylesheetRoot::create(
            MemoryManager&                   theManager,
            const XalanDOMString&            baseIdentifier,
            StylesheetConstructionContext&   constructionContext)
{
    typedef StylesheetRoot  ThisType;

    XalanAllocationGuard    theGuard(theManager, theManager.allocate(sizeof(ThisType)));

    ThisType* const     theResult =
        new (theGuard.get()) ThisType(
                                baseIdentifier,
                                constructionContext);

    theGuard.release();

    return theResult;
}



StylesheetRoot::~StylesheetRoot()
{
}



void
StylesheetRoot::postConstruction(StylesheetConstructionContext&     constructionContext)
{
    // Chain-up first...
    Stylesheet::postConstruction(constructionContext);

    initDefaultRule(constructionContext);

    {
        AttributeSetMapType::iterator           theCurrentMap = m_attributeSetsMap.begin();
        const AttributeSetMapType::iterator     theEndMap = m_attributeSetsMap.end();

        while(theCurrentMap != theEndMap)
        {
            AttributeSetVectorType::iterator        theCurrentVector = (*theCurrentMap).second.begin();
            const AttributeSetVectorType::iterator  theEndVector = (*theCurrentMap).second.end();

            while(theCurrentVector != theEndVector)
            {
                (*theCurrentVector)->postConstruction(constructionContext, getNamespacesHandler());

                ++theCurrentVector;
            }

            ++theCurrentMap;
        }   
    }

    // We may need to build keys, since we may have inherited them from
    // our imports.
    if (m_needToBuildKeysTable == false &&
        m_keyDeclarations.empty() == false)
    {
        m_needToBuildKeysTable = true;
    }

    // cdata-section-elements only applies to the XML output method...
    if (m_outputMethod != FormatterListener::OUTPUT_METHOD_XML &&
        m_outputMethod != FormatterListener::OUTPUT_METHOD_NONE)
    {
        m_cdataSectionElems.clear();
    }
    else if (m_cdataSectionElems.empty() == false)
    {
        using std::sort;

        sort(
            m_cdataSectionElems.begin(),
            m_cdataSectionElems.end(),
            pointer_less<XalanQName>());

        m_hasCDATASectionElems = true;
    }

    m_hasStripOrPreserveSpace = m_whitespaceElements.empty() == false;
}



typedef StylesheetExecutionContext::GetCachedString     GetCachedString;



void
StylesheetRoot::process(
            XalanNode*                      sourceTree, 
            XSLTResultTarget&               outputTarget,
            StylesheetExecutionContext&     executionContext) const
{
    assert(m_defaultRule != 0);
    assert(m_defaultTextRule != 0);
    assert(m_defaultRootRule != 0);

    // Find the root pattern in the XSL.
    const ElemTemplateElement*      rootRule =
            findTemplate(executionContext, sourceTree);

    if(0 == rootRule)
    {
        rootRule = m_defaultRootRule;
    }
    assert(rootRule != 0);

    executionContext.setStylesheetRoot(this);

    setupFormatterListener(outputTarget, executionContext);

    executionContext.setRootDocument(sourceTree);

#if defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
    typedef StylesheetExecutionContext::PushAndPopContextMarker PushAndPopContextMarker;
    typedef StylesheetExecutionContext::PushAndPopElementFrame  PushAndPopElementFrame;
    typedef StylesheetExecutionContext::ResolveAndClearTopLevelParams   ResolveAndClearTopLevelParams;

    PushAndPopContextMarker     thePushAndPopContextMarker(executionContext);

    PushAndPopElementFrame      thePushAndPopElementFrame(
                executionContext,
                0);

    ResolveAndClearTopLevelParams   theResolveAndClearTopLevelParams(executionContext);
#else
    executionContext.pushContextMarker();
    executionContext.pushElementFrame(0);
    executionContext.resolveTopLevelParams();
#endif

#if defined(XALAN_VQ_SPECIAL_TRACE)
    QuantifyStartRecordingData();
#endif

    executionContext.startDocument();

    executionContext.pushCurrentMode(&s_emptyQName);

    const XPathExecutionContext::CurrentNodePushAndPop  theCurrentNodePushAndPop(executionContext, sourceTree);

    // Output the action of the found root rule.  All processing
    // occurs from here.
    
    rootRule->execute(executionContext);

    // At this point, anything transient during the tranformation
    // may have been deleted, so we may not refer to anything the
    // execution context may have created for us.
    executionContext.endDocument();

#if defined(XALAN_VQ_SPECIAL_TRACE)
    QuantifyStopRecordingData();
#endif

#if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
    executionContext.clearTopLevelParams();
    executionContext.popElementFrame();
    executionContext.popContextMarker();
#endif
}



const XalanDOMString&
StylesheetRoot::getEncoding(const XSLTResultTarget&     outputTarget) const
{
    const XalanDOMString&   theEncoding = outputTarget.getEncoding();

    if (theEncoding.length() != 0)
    {
        return theEncoding;
    }
    else
    {
        return m_encoding;
    }
}



FormatterListener*
StylesheetRoot::setupFormatterListener(
            XSLTResultTarget&               outputTarget,
            StylesheetExecutionContext&     executionContext) const
{
    typedef StylesheetExecutionContext::GetCachedString     GetCachedString;

    FormatterListener*  flistener = outputTarget.getFormatterListener();

    if (flistener != 0)
    {
        // Do encoding stuff here...
    }
    else if (0 != outputTarget.getCharacterStream() ||
             0 != outputTarget.getByteStream() ||
             0 != outputTarget.getStream() ||
             !outputTarget.getFileName().empty())
    {
        /*
         * Output target has a character or byte stream or file
         */
        Writer*     pw = 0;

        if (0 != outputTarget.getCharacterStream())
        {
            pw = outputTarget.getCharacterStream();
        }
        else
        {
            if (0 != outputTarget.getByteStream())
            {
                pw = executionContext.createPrintWriter(*outputTarget.getByteStream());
            }
            else if (0 != outputTarget.getStream())
            {
                pw = executionContext.createPrintWriter(outputTarget.getStream());
            }
            else if (!outputTarget.getFileName().empty())
            {
                const GetCachedString   theGuard(executionContext);

                pw = executionContext.createPrintWriter(
                            outputTarget.getFileName(),
                            theGuard.get());
            }
            else
            {
                const GetCachedString   theGuard(executionContext);

                executionContext.problem(
                    StylesheetExecutionContext::eXSLTProcessor,
                    StylesheetExecutionContext::eError,
                    XalanMessageLoader::getMessage(
                        theGuard.get(),
                        XalanMessages::NoValidResultTarget),
                    0,
                    executionContext.getCurrentNode());
            }
        }

        int     indentAmount = executionContext.getIndent();

        // If the indent amount is less than 0, that means use
        // the value specified in the stylesheet.
        if (indentAmount < 0)
        {
            indentAmount = m_indentAmount;
        }

        const bool  doIndent = (indentAmount > -1) ? true : getOutputIndent();

        const XalanDOMString&   theEncoding = getEncoding(outputTarget);

        switch(m_outputMethod)
        {
        case FormatterListener::OUTPUT_METHOD_HTML:
            {
                if (doIndent == true && indentAmount < 0)
                {
                    indentAmount = FormatterToHTML::eDefaultIndentAmount;
                }

                // Start with the default that was set in the stylesheet...
                bool    outputEscapeURLs = m_outputEscapeURLs;

                {
                    const StylesheetExecutionContext::eEscapeURLs   eEscapeURLs =
                        executionContext.getEscapeURLs();

                    // If it's anything other than StylesheetExecutionContext::eEscapeURLsDefault,
                    // use the property from the execution context...
                    if (eEscapeURLs == StylesheetExecutionContext::eEscapeURLsNo)
                    {
                        outputEscapeURLs = false;
                    }
                    else if (eEscapeURLs == StylesheetExecutionContext::eEscapeURLsYes)
                    {
                        outputEscapeURLs = true;
                    }
                }

                // Start with the default that was set in the stylesheet...
                bool    omitMETATag = m_omitMETATag;

                {
                    const StylesheetExecutionContext::eOmitMETATag  eOmitMETATag =
                        executionContext.getOmitMETATag();

                    // If it's anything other than StylesheetExecutionContext::eOmitMETATagDefault,
                    // use the property from the execution context...
                    if (eOmitMETATag == StylesheetExecutionContext::eOmitMETATagNo)
                    {
                        omitMETATag = false;
                    }
                    else if (eOmitMETATag == StylesheetExecutionContext::eOmitMETATagYes)
                    {
                        omitMETATag = true;
                    }
                }

                flistener = executionContext.createFormatterToHTML(
                                *pw,
                                theEncoding,
                                m_mediatype,
                                m_doctypeSystem,
                                m_doctypePublic,
                                doIndent,
                                indentAmount,
                                outputEscapeURLs,
                                omitMETATag);
            }
            break;

        case FormatterListener::OUTPUT_METHOD_TEXT:
            flistener = executionContext.createFormatterToText(*pw, theEncoding);
            break;

        case FormatterListener::OUTPUT_METHOD_NONE:
        case FormatterListener::OUTPUT_METHOD_XML:
        default:
            // Make sure we don't have a negative indent amount if we're
            // indenting
            if (doIndent == true && indentAmount < 0)
            {
                indentAmount = FormatterToXML::eDefaultIndentAmount;
            }

            flistener = executionContext.createFormatterToXML(
                        *pw, m_version, doIndent, indentAmount, theEncoding, m_mediatype,
                        m_doctypeSystem, m_doctypePublic, !m_omitxmlDecl, m_standalone);
            break;
        }

        executionContext.setFormatterListener(flistener);
    }
    else
    {
        const GetCachedString   theGuard(executionContext);

       executionContext.problem(
           StylesheetExecutionContext::eXSLTProcessor,
           StylesheetExecutionContext::eError,
            XalanMessageLoader::getMessage(
                theGuard.get(),
                XalanMessages::NoValidResultTarget),
            0,
            executionContext.getCurrentNode());
    }

    executionContext.setFormatterListener(flistener);

    return flistener;
}



void 
StylesheetRoot::processOutputSpec(
            const XalanDOMChar*             name, 
            const AttributeListType&        atts,
            StylesheetConstructionContext&  constructionContext)
{
    const XalanSize_t   nAttrs = atts.getLength();

    const Locator* const    theLocator = constructionContext.getLocatorFromStack();

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

        if (equals(aname, Constants::ATTRNAME_OUTPUT_METHOD))
        {
            const XalanDOMChar* const   method = atts.getValue(i);

            if (equals(method, Constants::ATTRVAL_OUTPUT_METHOD_HTML))
            {
                m_outputMethod = FormatterListener::OUTPUT_METHOD_HTML;
            }
            else if (equals(method, Constants::ATTRVAL_OUTPUT_METHOD_XML))
            {
                m_outputMethod = FormatterListener::OUTPUT_METHOD_XML;
            }
            else if (equals(method, Constants::ATTRVAL_OUTPUT_METHOD_TEXT))
            {
                m_outputMethod = FormatterListener::OUTPUT_METHOD_TEXT;
            }
            else
            {
                const StylesheetConstructionContext::GetCachedString    theGuard(constructionContext);

                constructionContext.problem(
                    StylesheetConstructionContext::eXSLTProcessor,
                    StylesheetConstructionContext::eWarning,
                    XalanMessageLoader::getMessage(
                        theGuard.get(),
                        XalanMessages::OutputHasAnUnknownMethod_1Param,
                        method),
                    theLocator,
                    0);
            }
        }
        else if (equals(aname, Constants::ATTRNAME_OUTPUT_VERSION))
        {
            m_version = atts.getValue(i);
        }
        else if (equals(aname,Constants::ATTRNAME_OUTPUT_INDENT))
        {
            m_indentResult =
                getYesOrNo(aname, atts.getValue(i), constructionContext) == true ?
                    eIndentYesExplicit :
                    eIndentNoExplicit;
        }
        else if (equals(aname,Constants::ATTRNAME_OUTPUT_ENCODING))
        {
            m_encoding = atts.getValue(i);
        }
        else if (equals(aname,Constants::ATTRNAME_OUTPUT_MEDIATYPE))
        {
            m_mediatype = atts.getValue(i);
        }
        else if (equals(aname,Constants::ATTRNAME_OUTPUT_DOCTYPE_SYSTEM))
        {
            m_doctypeSystem = atts.getValue(i);
        }
        else if (equals(aname,Constants::ATTRNAME_OUTPUT_DOCTYPE_PUBLIC))
        {
            m_doctypePublic = atts.getValue(i);
        }
        else if (equals(aname,Constants::ATTRNAME_OUTPUT_OMITXMLDECL))
        {
            m_omitxmlDecl = getYesOrNo(aname, atts.getValue(i), constructionContext);
        }
        else if (equals(aname,Constants::ATTRNAME_OUTPUT_STANDALONE))
        {
            m_standalone = atts.getValue(i);
        }
        else if (equals(aname,Constants::ATTRNAME_OUTPUT_CDATA_SECTION_ELEMENTS))
        {
            if (m_outputMethod == FormatterListener::OUTPUT_METHOD_NONE ||
                m_outputMethod == FormatterListener::OUTPUT_METHOD_XML)
            {
                StringTokenizer theTokenizer(atts.getValue(i));

                StringTokenizer::size_type  theTokenCount =
                    theTokenizer.countTokens();

                m_cdataSectionElems.reserve(m_cdataSectionElems.size() + theTokenCount);

                const StylesheetConstructionContext::GetCachedString    theGuard(constructionContext);

                XalanDOMString& theToken = theGuard.get();

                while (theTokenCount > 0)
                {
                    theTokenizer.nextToken(theToken);

                    --theTokenCount;

                    m_cdataSectionElems.push_back(
                        constructionContext.createXalanQName(theToken, getNamespaces(), theLocator, true));
                }

                assert(theTokenizer.hasMoreTokens() == false);
            }
        }
        else
        {
            const XalanQNameByValue     theAttributeName(aname, getNamespaces(), constructionContext.getMemoryManager(), theLocator );

            if (theAttributeName.getNamespace() == constructionContext.getXalanXSLNameSpaceURL())
            {
                if (theAttributeName.getLocalPart() == Constants::ATTRNAME_ESCAPE_URLS)
                {
                    m_outputEscapeURLs = getYesOrNo(aname, atts.getValue(i), constructionContext);
                }
                else if (theAttributeName.getLocalPart() == Constants::ATTRNAME_INDENTAMOUNT)
                {
                    m_indentAmount = WideStringToInt(atts.getValue(i));

                    if (m_indentAmount < 0)
                    {
                        m_indentAmount = 0;
                    }
                }
                else if (theAttributeName.getLocalPart() == Constants::ATTRNAME_OMIT_META_TAG)
                {
                    m_omitMETATag = getYesOrNo(aname, atts.getValue(i), constructionContext);
                }
                else
                {
                    const StylesheetConstructionContext::GetCachedString    theGuard(constructionContext);

                    constructionContext.problem(
                        StylesheetConstructionContext::eXSLTProcessor,
                        StylesheetConstructionContext::eWarning,
                        XalanMessageLoader::getMessage(
                            theGuard.get(),
                            XalanMessages::UnsupportedXalanSpecificAttribute_1Param,
                            theAttributeName.getLocalPart()),
                        theLocator,
                        0);
                }
            }
            else if (isAttrOK(aname, atts, i, constructionContext) == false)
            {
                const StylesheetConstructionContext::GetCachedString    theGuard(constructionContext);

                constructionContext.problem(
                    StylesheetConstructionContext::eXSLTProcessor,
                    StylesheetConstructionContext::eError,
                    XalanMessageLoader::getMessage(
                        theGuard.get(),
                        XalanMessages::HasIllegalAttribute_2Param,
                        name,
                        aname),
                    theLocator,
                    0);
            }
        }
    }

    // If HTML output 
    if (m_outputMethod == FormatterListener::OUTPUT_METHOD_HTML &&
        m_indentResult == eIndentNoImplicit)
    {
        m_indentResult = eIndentYesImplicit;
    }
}



void 
StylesheetRoot::initDefaultRule(StylesheetConstructionContext&  constructionContext)
{
    if (m_defaultRule == 0)
    {
        assert(m_defaultTextRule == 0);
        assert(m_defaultRootRule == 0);

        AttributeListImpl       attrs(constructionContext.getMemoryManager());

        attrs.addAttribute(
            Constants::ATTRNAME_MATCH.c_str(),
            Constants::ATTRTYPE_CDATA.c_str(),
            XPath::PSEUDONAME_ANY);

        m_defaultRule =
            constructionContext.createElement(
                StylesheetConstructionContext::ELEMNAME_TEMPLATE,
                *this,
                attrs);
        assert(m_defaultRule != 0);

        attrs.clear();

        ElemTemplateElement*    childrenElement =
            constructionContext.createElement(
                StylesheetConstructionContext::ELEMNAME_APPLY_TEMPLATES,
                *this,
                attrs);
        assert(childrenElement != 0);

        m_defaultRule->appendChildElem(childrenElement);

        m_defaultRule->setDefaultTemplate(true);

        // -----------------------------

        attrs.clear();
        attrs.addAttribute(
            Constants::ATTRNAME_MATCH.c_str(),
            Constants::ATTRTYPE_CDATA.c_str(),
            Constants::ATTRVAL_DEFAULT_TEXT_RULE.c_str());

        m_defaultTextRule =
            constructionContext.createElement(
                StylesheetConstructionContext::ELEMNAME_TEMPLATE,
                *this,
                attrs);
        assert(m_defaultTextRule != 0);

        attrs.clear();
        attrs.addAttribute(
            Constants::ATTRNAME_SELECT.c_str(),
            Constants::ATTRTYPE_CDATA.c_str(),
            Constants::ATTRVAL_THIS.c_str());

        childrenElement =
            constructionContext.createElement(
                StylesheetConstructionContext::ELEMNAME_VALUE_OF,
                *this,
                attrs);
        assert(childrenElement != 0);

        m_defaultTextRule->appendChildElem(childrenElement);

        m_defaultTextRule->setDefaultTemplate(true);

        //--------------------------------
    
        attrs.clear();
        attrs.addAttribute(
            Constants::ATTRNAME_MATCH.c_str(),
            Constants::ATTRTYPE_CDATA.c_str(),
            XPath::PSEUDONAME_ROOT);

        m_defaultRootRule =
            constructionContext.createElement(
                StylesheetConstructionContext::ELEMNAME_TEMPLATE,
                *this,
                attrs);
        assert(m_defaultRootRule != 0);

        attrs.clear();

        childrenElement =
            constructionContext.createElement(
                StylesheetConstructionContext::ELEMNAME_APPLY_TEMPLATES,
                *this,
                attrs);
        assert(childrenElement != 0);

        m_defaultRootRule->appendChildElem(childrenElement);

        m_defaultRootRule->setDefaultTemplate(true);
    }

    assert(m_defaultRule != 0);
    assert(m_defaultTextRule != 0);
    assert(m_defaultRootRule != 0);
}



bool
StylesheetRoot::isCDATASectionElementName(const XalanQName&     theQName) const
{
    using std::find_if;

    return find_if(
            m_cdataSectionElems.begin(),
            m_cdataSectionElems.end(),
            pointer_equals_predicate<XalanQName>(&theQName)) != m_cdataSectionElems.end() ? true : false;
}



inline XalanNode*
getKeyNode(XalanNode*   context)
{
    assert(context != 0);

    XalanDocument* const    docNode = 
            XalanNode::DOCUMENT_NODE == context->getNodeType() ?
                    static_cast<XalanDocument*>(context) :
                        context->getOwnerDocument();

    assert(docNode != 0);

    // This is a big hack for dealing with result tree fragments coerced to node-sets using the
    // node-set extension function.  For such cases, the "document" is really the
    // XalanDocumentFragment instance that owns the nodes, not the owner document.
    if (docNode->getFirstChild() != 0)
    {
        return docNode;
    }
    else
    {
        XalanNode*  currentNode = context;

        // OK, the current node belongs to the document, but the document
        // is just a factory for fragments.  This loop will find the
        // parent document fragment.
        for(;;)
        {
            if (currentNode->getNodeType() == XalanNode::DOCUMENT_FRAGMENT_NODE)
            {
                break;
            }
            else
            {
                currentNode = DOMServices::getParentOfNode(*currentNode);

                assert(currentNode != 0);
            }
        }

        return currentNode;
    }
}



void
StylesheetRoot::getNodeSetByKey(
            XalanNode*                      context,
            const XalanQName&               qname,
            const XalanDOMString&           ref,
            const PrefixResolver&           resolver,
            MutableNodeRefList&             nodelist,
            StylesheetExecutionContext&     executionContext,
            const Locator*                  locator,
            KeyTablesTableType&             theKeysTable) const
{
    assert(
        nodelist.empty() == true ||
        nodelist.getDocumentOrder() == true);

    const MutableNodeRefList* nl = 0;
    XalanNode* const    theKeyNode = getKeyNode(context);
    assert(theKeyNode != 0);

    if (m_needToBuildKeysTable == true)
    {
        assert(m_keyDeclarations.empty() == false);

        const KeyTablesTableType::const_iterator    i =
            theKeysTable.find(theKeyNode);

        if (i != theKeysTable.end())
        {
            nl = i->second->getNodeSetByKey(qname, ref);
        }
        else
        {
            XalanMemMgrAutoPtr<KeyTable>    kt(
                        executionContext.getMemoryManager(),
                        KeyTable::create(
                            executionContext.getMemoryManager(),
                             theKeyNode,
                             resolver,
                             m_keyDeclarations,
                             executionContext));

            theKeysTable[theKeyNode] = kt.get();

            const KeyTable* const   theNewTable = kt.releasePtr();

            nl = theNewTable->getNodeSetByKey(qname, ref);
        }
    }

    if (nl == 0)
    {
        typedef StylesheetExecutionContext::GetCachedString     GetCachedString;

        const GetCachedString   theGuard1(executionContext);
        const GetCachedString   theGuard2(executionContext);

        executionContext.problem(
            StylesheetExecutionContext::eXSLTProcessor,
            StylesheetExecutionContext::eError,
            XalanMessageLoader::getMessage(
                theGuard1.get(),
                XalanMessages::UnknownKey_1Param,
                qname.format(theGuard2.get())),
            locator,
            executionContext.getCurrentNode());
    }
    else if (nodelist.empty() == true)
    {
        nodelist = *nl;
    }
    else
    {
        nodelist.addNodesInDocOrder(*nl, executionContext);
    }
}



bool
StylesheetRoot::internalShouldStripSourceNode(const XalanText&  textNode) const
{
    assert(
        textNode.isWhitespace() == true &&
        hasPreserveOrStripSpaceElements() == true);

    const XalanNode* const  parent = textNode.getParentNode();

//  assert(parent != 0);
//  Constructed nodesets may not have parents - see xalan:nodeset()
    if (parent == 0)
        return false;

    if (parent->getNodeType() == XalanNode::ELEMENT_NODE)
    {
        const XalanElement* const   theElement =
                static_cast<const XalanElement*>(parent);

        typedef WhitespaceElementsVectorType::const_iterator    const_iterator;

        const_iterator i = m_whitespaceElements.begin();

        do
        {
            const XalanSpaceNodeTester&     theTester = *i;

            if (theTester(*theElement) != XPath::eMatchScoreNone)
            {
                return theTester.getType() == XalanSpaceNodeTester::eStrip;
            }

            ++i;
        } while (i != m_whitespaceElements.end());
    }

    return false;
}



void
StylesheetRoot::addAttributeSet(ElemAttributeSet&   theAttributeSet)
{
    m_attributeSetsMap[&theAttributeSet.getQName()].push_back(&theAttributeSet);
}



#if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)

const ElemAttributeSet*
StylesheetRoot::getAttributeSet(
            StylesheetExecutionContext&     executionContext,
            const XalanQName&               theQName,
            size_type                       matchingIndex,
            const Locator*                  theLocator) const
{
    const AttributeSetMapType::const_iterator   i =
        m_attributeSetsMap.find(&theQName);

    if (i == m_attributeSetsMap.end())
    {
        const StylesheetExecutionContext::GetCachedString   theGuard(executionContext);

        executionContext.problem(
            StylesheetExecutionContext::eXSLTProcessor,
            StylesheetExecutionContext::eError,
            XalanMessageLoader::getMessage(
                theGuard.get(),
                XalanMessages::UnknownNodeType_1Param,
                Constants::ELEMNAME_ATTRIBUTESET_WITH_PREFIX_STRING),
            theLocator,
            executionContext.getCurrentNode());
    }
    else
    {
        const AttributeSetVectorType&   theAttributeSets = i->second;

        if (matchingIndex < theAttributeSets.size())
        {
            return theAttributeSets[matchingIndex];
        }
    }

    return 0;

}

#else

void
StylesheetRoot::executeAttributeSet(
            StylesheetExecutionContext&     theExecutionContext,
            const XalanQName&               theQName,
            const Locator*                  theLocator) const
{
    const AttributeSetMapType::const_iterator   i =
        m_attributeSetsMap.find(&theQName);

    if (i == m_attributeSetsMap.end())
    {
        const GetCachedString   theGuard(theExecutionContext);

        theExecutionContext.error(
            XalanMessageLoader::getMessage(
                theGuard.get(),
                XalanMessages::UnknownNodeType_1Param,
                Constants::ELEMNAME_ATTRIBUTESET_WITH_PREFIX_STRING),
            theExecutionContext.getCurrentNode(),
            theLocator);
    }
    else
    {
        const AttributeSetVectorType&                   theAttributeSets = (*i).second;
        const AttributeSetVectorType::const_iterator    theEnd = theAttributeSets.end();

        for(AttributeSetVectorType::const_iterator i = theAttributeSets.begin(); i != theEnd; ++i)
        {
            assert(*i != 0);

            (*i)->execute(theExecutionContext);
        }
    }
}
#endif



}
