/**
 * 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.
 */

/*
 * XSEC
 *
 * TXFMXPathFilter := Class that performs XPath transforms
 *
 * $Id$
 *
 */


#include <xsec/dsig/DSIGConstants.hpp>
#include <xsec/dsig/DSIGXPathFilterExpr.hpp>
#include <xsec/dsig/DSIGXPathHere.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/transformers/TXFMXPathFilter.hpp>
#include <xsec/transformers/TXFMParser.hpp>

XERCES_CPP_NAMESPACE_USE

#ifdef XSEC_HAVE_XALAN

#include "../utils/XSECDOMUtils.hpp"

#include <xercesc/util/Janitor.hpp>

#if defined(_MSC_VER)
#    pragma warning(disable: 4267)
#endif

#include <xalanc/XalanDOM/XalanDocument.hpp>
#include <xalanc/XalanDOM/XalanDOMString.hpp>
#include <xalanc/XercesParserLiaison/XercesDocumentWrapper.hpp>
#include <xalanc/XercesParserLiaison/XercesDOMSupport.hpp>
#include <xalanc/XercesParserLiaison/XercesParserLiaison.hpp>
#include <xalanc/XPath/XPathEvaluator.hpp>
#include <xalanc/XPath/XPathProcessorImpl.hpp>
#include <xalanc/XPath/XPathFactoryDefault.hpp>
#include <xalanc/XPath/NodeRefList.hpp>
#include <xalanc/XPath/XPathEnvSupportDefault.hpp>
#include <xalanc/XPath/XPathConstructionContextDefault.hpp>
#include <xalanc/XPath/ElementPrefixResolverProxy.hpp>
#include <xalanc/XPath/XObjectFactoryDefault.hpp>
#include <xalanc/XPath/XPathExecutionContextDefault.hpp>
#include <xalanc/XSLT/XSLTResultTarget.hpp>

#if defined(_MSC_VER)
#    pragma warning(default: 4267)
#endif

// Xalan namespace usage
XALAN_USING_XALAN(XPathProcessorImpl)
XALAN_USING_XALAN(XalanDOMString)
XALAN_USING_XALAN(XercesDOMSupport)
XALAN_USING_XALAN(XercesParserLiaison)
XALAN_USING_XALAN(XercesDocumentWrapper)
XALAN_USING_XALAN(XercesWrapperNavigator)
XALAN_USING_XALAN(XPathEvaluator)
XALAN_USING_XALAN(XPathFactoryDefault)
XALAN_USING_XALAN(XPathConstructionContextDefault)
XALAN_USING_XALAN(XalanDocument)
XALAN_USING_XALAN(XalanNode)
XALAN_USING_XALAN(XalanDOMChar)
XALAN_USING_XALAN(XPathEnvSupportDefault)
XALAN_USING_XALAN(XObjectFactoryDefault)
XALAN_USING_XALAN(XObjectPtr)
XALAN_USING_XALAN(XPathExecutionContextDefault)
XALAN_USING_XALAN(ElementPrefixResolverProxy)
XALAN_USING_XALAN(XPath)
XALAN_USING_XALAN(NodeRefListBase)
XALAN_USING_XALAN(XSLTResultTarget)
XALAN_USING_XALAN(XSLException)

#endif

#ifdef XSEC_HAVE_XPATH

#include <iostream>

#define KLUDGE_PREFIX "berindsig"

// Helper functions - come from DSIGXPath

void setXPathNS(DOMDocument* d,
                DOMNamedNodeMap* xAtts,
                XSECXPathNodeList& addedNodes,
                XSECSafeBufferFormatter* formatter,
                XSECNameSpaceExpander* nse);

void clearXPathNS(DOMDocument*d,
                  XSECXPathNodeList& toRemove,
                  XSECSafeBufferFormatter* formatter,
                  XSECNameSpaceExpander* nse);

bool separator(unsigned char c);
XalanNode* findHereNodeFromXalan(XercesWrapperNavigator* xwn, XalanNode* n, DOMNode* h);


TXFMXPathFilter::TXFMXPathFilter(DOMDocument* doc) :
    TXFMBase(doc) {

    document = NULL;
    XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes,
                                                XMLFormatter::UnRep_CharRef));
}

TXFMXPathFilter::~TXFMXPathFilter() {

    lstsVectorType::iterator i;

    for (i = m_lsts.begin(); i != m_lsts.end(); ++i) {

        if ((*i)->lst != NULL)
            delete ((*i)->lst);

        delete (*i);
    }

    if (mp_formatter != NULL)
        delete mp_formatter;
}

// Methods to set the inputs

void TXFMXPathFilter::setInput(TXFMBase* newInput) {

    if (newInput->getOutputType() == TXFMBase::BYTE_STREAM) {

        // Need to parse into DOM_NODES

        TXFMParser * parser;
        XSECnew(parser, TXFMParser(mp_expansionDoc));
        try{
            parser->setInput(newInput);
        }
        catch (...) {
            delete parser;
            input = newInput;
            throw;
        }

        input = parser;
        parser->expandNameSpaces();
    }
    else {
        input = newInput;
    }

    // Set up for the new document
    document = input->getDocument();

    // Expand if necessary
    this->expandNameSpaces();

    keepComments = input->getCommentsStatus();
}

XSECXPathNodeList* TXFMXPathFilter::evaluateSingleExpr(DSIGXPathFilterExpr* expr) {

    // Have a single expression that we wish to find the resultant nodeset for

    XSECXPathNodeList addedNodes;
    setXPathNS(document, expr->mp_NSMap, addedNodes, mp_formatter, mp_nse);

    XPathProcessorImpl    xppi;                    // The processor
    XercesParserLiaison xpl;
    XercesDOMSupport    xds(xpl);
    XPathEvaluator        xpe;
    XPathFactoryDefault xpf;
    XPathConstructionContextDefault xpcc;

    XalanDocument        * xd;
    XalanNode            * contextNode;

    // Xalan can throw exceptions in all functions, so do one broad catch point.

    try {

        // Map to Xalan
        xd = xpl.createDocument(document);

        // For performing mapping
        XercesDocumentWrapper *xdw = xpl.mapDocumentToWrapper(xd);
        XercesWrapperNavigator xwn(xdw);

        // Map the "here" node

        XalanNode * hereNode = NULL;

        hereNode = xwn.mapNode(expr->mp_xpathFilterNode);

        if (hereNode == NULL) {

            hereNode = findHereNodeFromXalan(&xwn, xd, expr->mp_exprTextNode);

            if (hereNode == NULL) {
                throw XSECException(XSECException::XPathFilterError,
                   "Unable to find here node in Xalan Wrapper map");
            }
        }

        // Now work out what we have to set up in the new processing

        XalanDOMString cd;        // For XPath Filter, the root is always the context node

        cd = XalanDOMString("/");        // Root node

        // The context node is the "root" node
        contextNode =
            xpe.selectSingleNode(
            xds,
            xd,
            cd.c_str(),
            xd->getDocumentElement());

        XPathEnvSupportDefault xpesd;
        XObjectFactoryDefault            xof;
        XPathExecutionContextDefault    xpec(xpesd, xds, xof);

        ElementPrefixResolverProxy pr(xd->getDocumentElement(), xpesd, xds);

        // Work around the fact that the XPath implementation is designed for XSLT, so does
        // not allow here() as a NCName.

        // THIS IS A KLUDGE AND SHOULD BE DONE BETTER

        safeBuffer k(KLUDGE_PREFIX);
        k.sbStrcatIn(":");

        // Map the expression into a local code page string (silly - should be XMLCh)
        safeBuffer exprSB;
        exprSB << (*mp_formatter << expr->m_expr.rawXMLChBuffer());

        XMLSSize_t offset = exprSB.sbStrstr("here()");

        while (offset >= 0) {

            if (offset == 0 || offset == 1 ||
                (!(exprSB[offset - 1] == ':' && exprSB[offset - 2] != ':') &&
                separator(exprSB[offset - 1]))) {

                exprSB.sbStrinsIn(k.rawCharBuffer(), offset);
            }

            offset = exprSB.sbOffsetStrstr("here()", offset + 11);
        }

        // Install the External function in the Environment handler

        if (hereNode != NULL) {
            xpesd.installExternalFunctionLocal(XalanDOMString(URI_ID_DSIG), XalanDOMString("here"), DSIGXPathHere(hereNode));
        }

        XPath * xp = xpf.create();

        XalanDOMString Xexpr((char *) exprSB.rawBuffer());
        xppi.initXPath(*xp, xpcc, Xexpr, pr);

        // Now resolve

        XObjectPtr xObj = xp->execute(contextNode, pr, xpec);

        // Now map to a list that others can use (naieve list at this time)

        const NodeRefListBase&    lst = xObj->nodeset();

        int size = (int) lst.getLength();
        const DOMNode *item;

        XSECXPathNodeList * ret;
        XSECnew(ret, XSECXPathNodeList);
        Janitor<XSECXPathNodeList> j_ret(ret);

        for (int i = 0; i < size; ++ i) {

            if (lst.item(i) == xd)
                ret->addNode(document);
            else {
                item = xwn.mapNode(lst.item(i));
                ret->addNode(item);
            }
        }

        xpesd.uninstallExternalFunctionGlobal(XalanDOMString(URI_ID_DSIG), XalanDOMString("here"));

        clearXPathNS(document, addedNodes, mp_formatter, mp_nse);

        j_ret.release();
        return ret;
    }
    catch (const XSLException &e) {

        safeBuffer msg;

        // Whatever happens - fix any changes to the original document
        clearXPathNS(document, addedNodes, mp_formatter, mp_nse);

        // Collate the exception message into an XSEC message.
        msg.sbTranscodeIn("Xalan Exception : ");
        msg.sbXMLChCat(e.getType());
        msg.sbXMLChCat(" caught.  Message : ");
        msg.sbXMLChCat(e.getMessage().c_str());

        throw XSECException(XSECException::XPathFilterError,
            msg.rawXMLChBuffer());
    }
    catch (...) {
        clearXPathNS(document, addedNodes, mp_formatter, mp_nse);
        throw;
    }

    return NULL;
}

bool TXFMXPathFilter::checkNodeInInput(DOMNode* n, DOMNode* attParent) {

    if (mp_fragment != NULL) {

        DOMNode * p = n;

        /* Check attParent here to reduce cycles */
        if (attParent != NULL) {
            if (p == mp_fragment)
                return true;
            p = attParent;
        }

        while (p != NULL) {

            if (p == mp_fragment)
                return true;

            p = p->getParentNode();
        }

        return false;
    }

    return mp_inputList->hasNode(n);
}

bool TXFMXPathFilter::checkNodeInScope(DOMNode* n) {

    // Walk backwards through the lists
    lstsVectorType::iterator lstsIter;

    lstsIter = m_lsts.end();
    filterSetHolder *sh;

    while (lstsIter != m_lsts.begin()) {

        lstsIter--;
        sh = *lstsIter;
        if (sh->ancestorInScope != NULL) {

            // Have an ancestor in scope, so this node is in this list
            if (sh->type == DSIGXPathFilterExpr::FILTER_UNION)
                // Got this far, must be OK!
                return true;
            if (sh->type == DSIGXPathFilterExpr::FILTER_SUBTRACT)
                return false;
        }
        else {
            if (sh->type == DSIGXPathFilterExpr::FILTER_INTERSECT)
                return false;
        }
    }

    return true;
}

#if 1

void TXFMXPathFilter::walkDocument(DOMNode* n) {

    // Non-recursive version

    DOMNode * current = n;
    DOMNode * next;
    DOMNode * attParent = NULL;     /* Assign NULL to remove spurious Forte warning */
    bool done = false;
    bool treeUp = false;
    DOMNamedNodeMap * atts = n->getAttributes();
    int attsSize = -1;
    int currentAtt = -1;
    lstsVectorType::iterator lstsIter;

    while (done == false && current != NULL) {

        if (treeUp == true) {

            if (current == n) {
                // We are complete.
                done = true;
            }
            else {
                // Remove this node from the ancestor lists
                for (lstsIter = m_lsts.begin(); lstsIter != m_lsts.end(); ++lstsIter) {

                    if ((*lstsIter)->ancestorInScope == current) {
                        (*lstsIter)->ancestorInScope = NULL;
                    }
                }

                // Check for another sibling
                next = current->getNextSibling();

                if (next == NULL) {
                    current = current->getParentNode();
                    treeUp = true;
                }
                else {
                    current = next;
                    treeUp = false;
                }
            }
        } /* treeUp == true */
        else {
            // Check if the current node is in the result set.  The walk the children

            // First check if this node is in any lists, and if so,
            // set the appropriate ancestor nodes (if necessary)

            for (lstsIter = m_lsts.begin(); lstsIter != m_lsts.end(); ++lstsIter) {

                if ((*lstsIter)->ancestorInScope == NULL &&
                    (*lstsIter)->lst->hasNode(current)) {

                    (*lstsIter)->ancestorInScope = current;
                }
            }

            // Now that the ancestor setup is done, check to see if this node is
            // in scope.

            if (checkNodeInScope(current) &&
                checkNodeInInput(current, (atts != NULL ? attParent : NULL))) {

                m_xpathFilterMap.addNode(current);
            }

            // Now find the next node!

            if (atts != NULL) {

                // Working on an attribute list
                currentAtt++;

                if (currentAtt == attsSize) {

                    // Attribute list complete
                    atts = NULL;
                    current = attParent;
                    next = current->getFirstChild();
                    if (next == NULL)
                        treeUp = true;
                    else {
                        current = next;
                        treeUp = false;
                    }
                }
                else {
                    current = atts->item(currentAtt);
                }
            }
            else {
                // Working on an element or other non-attribute node
                atts = current->getAttributes();

                if (atts != NULL && ((attsSize = atts->getLength()) > 0)) {
                    currentAtt = 0;
                    attParent = current;
                    current = atts->item(0);
                    treeUp = false;
                }
                else {
                    atts = NULL;

                    next = current->getFirstChild();

                    if (next != NULL) {
                        current = next;
                        treeUp = false;
                    }
                    else {
                        treeUp = true;
                    }
                }
            } /* ! atts == NULL */
        }
    } /* while */
}
#endif

#if 0

void TXFMXPathFilter::walkDocument(DOMNode * n) {

    // Check if the current node is in the result set.  The walk the children
    lstsVectorType::iterator lstsIter;

    // First check if this node is in any lists, and if so,
    // set the appropriate ancestor nodes (if necessary)

    for (lstsIter = m_lsts.begin(); lstsIter != m_lsts.end(); ++lstsIter) {

        if ((*lstsIter)->ancestorInScope == NULL && (*lstsIter)->lst->hasNode(n)) {
            (*lstsIter)->ancestorInScope = n;
        }
    }

    // Now that the ancestor setup is done, check to see if this node is
    // in scope.

    if (checkNodeInScope(n) && checkNodeInInput(n)) {
        m_xpathFilterMap.addNode(n);
    }

    // Do any attributes

    DOMNamedNodeMap * atts = n->getAttributes();
    if (atts != NULL) {
        unsigned int s = atts->getLength();
        for (unsigned int i = 0; i < s; ++i) {
            walkDocument(atts->item(i));
        }
    }

    // Do any childeren

    DOMNode * c = n->getFirstChild();

    while (c != NULL) {
        walkDocument(c);
        c = c->getNextSibling();
    }

    // Now remove from ancestor lists if we are that ancestor
    for (lstsIter = m_lsts.begin(); lstsIter != m_lsts.end(); ++lstsIter) {

        if ((*lstsIter)->ancestorInScope == n) {
            (*lstsIter)->ancestorInScope = NULL;
        }
    }
}
#endif

void TXFMXPathFilter::evaluateExprs(DSIGTransformXPathFilter::exprVectorType* exprs) {

    if (exprs == NULL || exprs->size() < 1) {
        throw XSECException(XSECException::XPathFilterError,
            "TXFMXPathFilter::evaluateExpr - no expression list set");
    }

    DSIGTransformXPathFilter::exprVectorType::iterator i;

    for (i = exprs->begin(); i != exprs->end(); ++i) {

        XSECXPathNodeList * lst = evaluateSingleExpr(*i);
        filterSetHolder * sh;
        XSECnew(sh, filterSetHolder);

        sh->lst = lst;
        sh->type = (*i)->m_filterType;
        sh->ancestorInScope = NULL;

        if (lst != NULL) {
            m_lsts.push_back(sh);
        }
    }

    // Well we appear to have successfully run through all the nodelists!

    mp_fragment = NULL;
    mp_inputList = NULL;

    // Find the input nodeset
    TXFMBase::nodeType inputType = input->getNodeType();
    switch (inputType) {

    case DOM_NODE_DOCUMENT :
        mp_fragment = document;
        break;

    case DOM_NODE_DOCUMENT_FRAGMENT :
        mp_fragment = input->getFragmentNode();
        break;

    case DOM_NODE_XPATH_NODESET :
        mp_inputList = &(input->getXPathNodeList());
        break;

    default :
        throw XSECException(XSECException::XPathFilterError,
            "TXFMXPathFilter::evaluateExprs - unknown input type");

    }

    // Now just recurse through each node in the document
    walkDocument(document);
}


// Methods to get tranform output type and input requirement

TXFMBase::ioType TXFMXPathFilter::getInputType() const {
    return TXFMBase::DOM_NODES;
}

TXFMBase::ioType TXFMXPathFilter::getOutputType() const {
    return TXFMBase::DOM_NODES;
}

TXFMBase::nodeType TXFMXPathFilter::getNodeType() const {
    return TXFMBase::DOM_NODE_XPATH_NODESET;
}

// Methods to get output data

unsigned int TXFMXPathFilter::readBytes(XMLByte* const toFill, unsigned int maxToFill) {
    return 0;
}

DOMDocument* TXFMXPathFilter::getDocument() const {
    return document;
}

XSECXPathNodeList& TXFMXPathFilter::getXPathNodeList() {
    return m_xpathFilterMap;
}

#endif /* XSEC_HAVE_XPATH */



