/**
 * 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
 *
 * DSIGTransformXPath := Class that holds XPath transforms
 *
 * $Id$
 *
 */

#include <xsec/dsig/DSIGSignature.hpp>
#include <xsec/dsig/DSIGTransformXPath.hpp>
#include <xsec/transformers/TXFMXPath.hpp>
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/framework/XSECException.hpp>
#include <xsec/transformers/TXFMC14n.hpp>
#include <xsec/transformers/TXFMChain.hpp>

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


XERCES_CPP_NAMESPACE_USE

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

DSIGTransformXPath::DSIGTransformXPath(const XSECEnv * env, DOMNode * node) :
DSIGTransform(env, node) {

	mp_exprTextNode = NULL;
	mp_xpathNode = NULL;
	mp_NSMap = NULL;
	m_expr = "";

}
	

DSIGTransformXPath::DSIGTransformXPath(const XSECEnv * env) :
DSIGTransform(env) {

	mp_exprTextNode = NULL;
	mp_xpathNode = NULL;
	mp_NSMap = NULL;
	m_expr = "";
}
		  
DSIGTransformXPath::~DSIGTransformXPath() {};

// --------------------------------------------------------------------------------
//           Interface Methods
// --------------------------------------------------------------------------------

void DSIGTransformXPath::appendTransformer(TXFMChain * input) {

#ifndef XSEC_HAVE_XPATH

	throw XSECException(XSECException::UnsupportedFunction,
		"XPath transforms are not supported in this compilation of the XSEC library");

#else

	TXFMXPath *x;
	// XPath transform
	XSECnew(x, TXFMXPath(mp_txfmNode->getOwnerDocument()));
	input->appendTxfm(x);

	// These can throw, but the TXFMXPath is now owned by the chain, so will
	// be cleaned up down the calling stack.

	x->setNameSpace(mp_NSMap);
	x->evaluateExpr(mp_txfmNode, m_expr);
	
#endif /* XSEC_HAVE_XPATH */

}

DOMElement * DSIGTransformXPath::createBlankTransform(DOMDocument * parentDoc) {

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

	prefix = mp_env->getDSIGNSPrefix();
	
	// Create the transform node
	makeQName(str, prefix, "Transform");
	ret = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	ret->setAttributeNS(NULL,DSIGConstants::s_unicodeStrAlgorithm, DSIGConstants::s_unicodeStrURIXPATH);
	
	// Create the XPath element
	
	makeQName(str, prefix, "XPath");
	mp_xpathNode = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	mp_exprTextNode = doc->createTextNode(MAKE_UNICODE_STRING(""));
	ret->appendChild(mp_xpathNode);
	mp_xpathNode->appendChild(mp_exprTextNode);

	mp_txfmNode = ret;

	return ret;

}

void DSIGTransformXPath::load(void) {

	// Find the XPath expression
	
	mp_xpathNode = mp_txfmNode->getFirstChild();

	while (mp_xpathNode != 0 && 
		mp_xpathNode->getNodeType() != DOMNode::ELEMENT_NODE && !strEquals(mp_xpathNode->getNodeName(), "XPath"))
		mp_xpathNode = mp_xpathNode->getNextSibling();
	
	if (mp_xpathNode == 0) {

		throw XSECException(XSECException::ExpectedDSIGChildNotFound,
			"Expected <XPath> Node in DSIGTransformXPath::load");
	}
	
	else {
		
		// Check for attributes - in particular any namespaces

		mp_NSMap = mp_xpathNode->getAttributes();
		
		// Find the text node
		mp_exprTextNode = findFirstChildOfType(mp_xpathNode, DOMNode::TEXT_NODE);

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

		// Gather the text
		safeBuffer exprSB;

		gatherChildrenText(mp_xpathNode, exprSB);

		m_expr << (*(mp_env->getSBFormatter()) << exprSB.rawXMLChBuffer());

		//m_expr << (*(mp_env->getSBFormatter()) << mp_exprTextNode->getNodeValue());
				
	}

}


// --------------------------------------------------------------------------------
//           XPath Transform Specific Methods
// --------------------------------------------------------------------------------

void DSIGTransformXPath::setExpression(const char* expr) {

	mp_exprTextNode->setNodeValue(MAKE_UNICODE_STRING(expr));

	m_expr.sbStrcpyIn((char *) expr);

}



const char* DSIGTransformXPath::getExpression() const {

	return m_expr.rawCharBuffer();

}


void DSIGTransformXPath::setNamespace(const char * prefix, const char * value) {

	safeBuffer str;

	str.sbStrcpyIn("xmlns:");
	str.sbStrcatIn((char *) prefix);

	DOMElement *x;

	x = static_cast <DOMElement *> (mp_xpathNode);

//	if (x == NULL) {
//
//		throw XSECException(XSECException::TransformError,
//			"Found a non ELEMENT node as the XPath node in DSIGTransformXPath");
//	}

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

	mp_NSMap = mp_xpathNode->getAttributes();


}

void DSIGTransformXPath::deleteNamespace(const char * prefix) {

	DOMElement *x;

	x = static_cast <DOMElement *> (mp_xpathNode);

//	if (x == NULL) {
//
//		throw XSECException(XSECException::TransformError,
//			"Found a non ELEMENT node as the XPath node in DSIGTransformXPath");
//	}

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

}

