/**
 * 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
 *
 * DSIGXPathFilterExpr := Class that holds an XPath Filter expression
 *
 * Author(s): Berin Lautenbach
 *
 * $Id$
 *
 */

#include <xsec/dsig/DSIGSignature.hpp>
#include <xsec/dsig/DSIGXPathFilterExpr.hpp>
#include <xsec/framework/XSECDefs.hpp>
#include <xsec/framework/XSECException.hpp>
#include <xsec/framework/XSECEnv.hpp>

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

#include <xercesc/dom/DOMNode.hpp>
#include <xercesc/dom/DOMNamedNodeMap.hpp>
#include <xercesc/util/XMLUniDefs.hpp>

XERCES_CPP_NAMESPACE_USE

XMLCh filterStr[] = {
    chLatin_F,
    chLatin_i,
    chLatin_l,
    chLatin_t,
    chLatin_e,
    chLatin_r,
    chNull
};


// --------------------------------------------------------------------------------
//           Constructors and Destructors
// --------------------------------------------------------------------------------

DSIGXPathFilterExpr::DSIGXPathFilterExpr(const XSECEnv* env, DOMNode* node) :
mp_env(env),
mp_xpathFilterNode(node),
mp_exprTextNode(NULL),
mp_NSMap(NULL),
m_filterType(FILTER_UNION),
m_loaded(false) {

}

DSIGXPathFilterExpr::DSIGXPathFilterExpr(const XSECEnv* env) :
mp_env(env),
mp_xpathFilterNode(NULL),
mp_exprTextNode(NULL),
mp_NSMap(NULL),
m_filterType(FILTER_UNION),
m_loaded(false)  {

}


DSIGXPathFilterExpr::~DSIGXPathFilterExpr() {}

// --------------------------------------------------------------------------------
//           Load existing DOM structure
// --------------------------------------------------------------------------------

void DSIGXPathFilterExpr::load() {

    // Find the XPath expression

    if (mp_xpathFilterNode == NULL ||
        !strEquals(getXPFLocalName(mp_xpathFilterNode), "XPath")) {

        throw XSECException(XSECException::ExpectedDSIGChildNotFound,
            "Expected <XPath> as first node in DSIGXPathFilterExpr::load");
    }


    // Check for attributes - in particular any namespaces

    mp_NSMap = mp_xpathFilterNode->getAttributes();

    // Find the filter type
    DOMNode * a;
    if (mp_NSMap == NULL ||
        ((a = mp_NSMap->getNamedItem(filterStr)) == NULL)) {

        throw XSECException(XSECException::ExpectedDSIGChildNotFound,
            "Expected Filter attribute of <XPath> node in in DSIGXPathFilterExpr::load");
    }

    const XMLCh * f = a->getNodeValue();
    if (strEquals(f, "intersect")) {
        m_filterType = FILTER_INTERSECT;
    }
    else if (strEquals(f, "union")) {
        m_filterType = FILTER_UNION;
    }
    else if (strEquals(f, "subtract")) {
        m_filterType = FILTER_SUBTRACT;
    }
    else {
        throw XSECException(XSECException::ExpectedDSIGChildNotFound,
                "DSIGXPathFilterExpr::load Expected on of intersect, union or subtract as filter type");
    }

    // Find the text node
    mp_exprTextNode = findFirstChildOfType(mp_xpathFilterNode, DOMNode::TEXT_NODE);

    if (mp_exprTextNode == NULL) {
        throw XSECException(XSECException::ExpectedDSIGChildNotFound,
            "Expected Text Node in beneath <XPath> in DSIGXPathFilterExpr::load");
    }

    // Gather the text - hold it in UTF16 format
    gatherChildrenText(mp_xpathFilterNode, m_expr);

    m_loaded = true;
}

// --------------------------------------------------------------------------------
//           Create a new filter
// --------------------------------------------------------------------------------

DOMElement* DSIGXPathFilterExpr::setFilter(DSIGXPathFilterExpr::XPathFilterType filterType,
                        const XMLCh * filterExpr) {

    if (m_loaded == true) {
        throw XSECException(XSECException::XPathFilterError,
            "DSIGXPathFilterExpr::setFilter - called when already loaded");
    }

    safeBuffer str;
    const XMLCh * prefix;
    DOMDocument *doc = mp_env->getParentDocument();
    DOMElement * xe;

    // Create the XPath element
    prefix = mp_env->getXPFNSPrefix();
    makeQName(str, prefix, "XPath");
    xe = doc->createElementNS(DSIGConstants::s_unicodeStrURIXPF, str.rawXMLChBuffer());
    mp_xpathFilterNode = xe;

    // Put in correct namespace
    prefix = mp_env->getXPFNSPrefix();

    // Set the namespace attribute
    if (prefix[0] == '\0') {
        str.sbTranscodeIn("xmlns");
    }
    else {
        str.sbTranscodeIn("xmlns:");
        str.sbXMLChCat(prefix);
    }

    xe->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS,
                            str.rawXMLChBuffer(),
                            DSIGConstants::s_unicodeStrURIXPF);

    // Set the filter type
    m_filterType = filterType;

    switch (filterType) {

    case FILTER_INTERSECT :
        xe->setAttributeNS(NULL,MAKE_UNICODE_STRING("Filter"), MAKE_UNICODE_STRING("intersect"));
        break;

    case FILTER_SUBTRACT :
        xe->setAttributeNS(NULL,MAKE_UNICODE_STRING("Filter"), MAKE_UNICODE_STRING("subtract"));
        break;

    case FILTER_UNION :
        xe->setAttributeNS(NULL,MAKE_UNICODE_STRING("Filter"), MAKE_UNICODE_STRING("union"));
        break;

    default :
        mp_xpathFilterNode->release();
        throw XSECException(XSECException::XPathFilterError,
            "DSIGXPathFilterExpr::appendFilter - Unexpected Filter Type");
    }

    // Now add the actual filter

    mp_exprTextNode = doc->createTextNode(filterExpr);
    mp_xpathFilterNode->appendChild(mp_exprTextNode);

    mp_NSMap = mp_xpathFilterNode->getAttributes();

    m_expr.sbXMLChIn(filterExpr);
    m_loaded = true;
    return xe;
}


// --------------------------------------------------------------------------------
//           Find the type
// --------------------------------------------------------------------------------

DSIGXPathFilterExpr::XPathFilterType DSIGXPathFilterExpr::getFilterType() const {

    if (m_loaded == false) {
        throw XSECException(XSECException::LoadEmptyXPathFilter,
            "DSIGXPathFilterExpr::Element node loaded");
    }

    return m_filterType;
}

// --------------------------------------------------------------------------------
//           Set and clear namespaces
// --------------------------------------------------------------------------------

void DSIGXPathFilterExpr::setNamespace(const XMLCh* prefix, const XMLCh* value) {

    if (mp_xpathFilterNode == NULL) {
        throw XSECException(XSECException::XPathFilterError,
            "DSIGXPathFilterExpr::setNamespace - load not called");
    }

    safeBuffer str;

    str.sbTranscodeIn("xmlns:");
    str.sbXMLChCat(prefix);

    DOMElement* x = static_cast <DOMElement *> (mp_xpathFilterNode);

    x->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS,
        str.rawXMLChBuffer(),
        value);

    mp_NSMap = mp_xpathFilterNode->getAttributes();
}

void DSIGXPathFilterExpr::deleteNamespace(const XMLCh* prefix) {

    if (mp_xpathFilterNode == NULL) {
        throw XSECException(XSECException::XPathFilterError,
            "DSIGXPathFilterExpr::deleteNamespace - load not called");
    }

    DOMElement* x = static_cast <DOMElement *> (mp_xpathFilterNode);

    x->removeAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS, prefix);
}
