/**
 * 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
 *
 * XSECNameSpaceExander := Class for expanding out a document's name space axis
 *							and then shrinking again
 *
 * $Id$
 *
 */

// XSEC Includes
#include <xsec/utils/XSECNameSpaceExpander.hpp>
#include <xsec/dsig/DSIGConstants.hpp>
#include <xsec/framework/XSECError.hpp>

#include "XSECDOMUtils.hpp"

XERCES_CPP_NAMESPACE_USE

XSECNameSpaceExpander::XSECNameSpaceExpander(DOMDocument *d) {

	mp_doc = d;
	mp_fragment = d->getDocumentElement();
	XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes, 
												XMLFormatter::UnRep_CharRef));

	m_expanded = false;
	
}

XSECNameSpaceExpander::XSECNameSpaceExpander(DOMElement *f) {

	mp_doc = NULL;
	mp_fragment = f;
	XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes, 
												XMLFormatter::UnRep_CharRef));

	m_expanded = false;
	
}

XSECNameSpaceExpander::~XSECNameSpaceExpander() {

	if (mp_formatter != NULL)
		delete mp_formatter;

}

void XSECNameSpaceExpander::recurse(DOMElement *n) {

	// Recursively go down the tree adding namespaces

	DOMNode *p = n->getParentNode();
	if (p->getNodeType() != DOMNode::ELEMENT_NODE)
		return;

	DOMNamedNodeMap *pmap = p->getAttributes();
	XMLSize_t psize = pmap->getLength();

	DOMNamedNodeMap *nmap = n->getAttributes();

	safeBuffer pname, pURI, nURI;
	DOMNode *finder;

	XSECNameSpaceEntry * tmpEnt;

	for (XMLSize_t i = 0; i < psize; i++) {

		// Run through each parent node to find namespaces
		pname << (*mp_formatter << pmap->item(i)->getNodeName());

		// See if this is an xmlns node
		
		if (pname.sbStrncmp("xmlns", 5) == 0) {

			// It is - see if it already exists
			finder = nmap->getNamedItem(pname.sbStrToXMLCh());
			if (finder == 0) {

				// Need to add
				n->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS, 
					pmap->item(i)->getNodeName(),
					pmap->item(i)->getNodeValue());

				// Add it to the list so it can be removed later
				XSECnew(tmpEnt, XSECNameSpaceEntry);
				tmpEnt->m_name.sbStrcpyIn(pname);
				tmpEnt->mp_node = n;
				tmpEnt->mp_att = nmap->getNamedItem(pname.sbStrToXMLCh());
				m_lst.push_back(tmpEnt);

			}

		}

	}

	// Do the children

	DOMNode *c;

	c = n->getFirstChild();

	while (c != NULL) {
		if (c->getNodeType() == DOMNode::ELEMENT_NODE)
			recurse((DOMElement *) c);
		c = c->getNextSibling();
	}

}

int attNodeCount(DOMElement * d) {

	XMLSize_t ret;

	ret = d->getAttributes()->getLength();

	DOMNode *c;

	c = d->getFirstChild();

	while (c != NULL) {

		if (c->getNodeType() == DOMNode::ELEMENT_NODE)
			ret += attNodeCount((DOMElement *) c);

		c = c->getNextSibling();

	}

	return (int) ret;

}

void XSECNameSpaceExpander::expandNameSpaces() {

	if (m_expanded)
		return;				// Don't do this twice!

	DOMElement	*docElt;		// The document element - do not expand it's namespaces
	
	docElt = mp_fragment; //mp_doc->getDocumentElement();

	DOMNode *c;

	c = docElt->getFirstChild();

	while (c != NULL) {
		if (c->getNodeType() == DOMNode::ELEMENT_NODE)
			recurse((DOMElement *) c);
		c = c->getNextSibling();
	}

	m_expanded = true;

}


void XSECNameSpaceExpander::deleteAddedNamespaces() {

	NameSpaceEntryListVectorType::size_type size = m_lst.size();
	XSECNameSpaceEntry *e;

	NameSpaceEntryListVectorType::size_type i;

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

		// Delete the element attribute, and then this node
		e = m_lst[i];
		if (e->m_name[5] == ':')
			e->mp_node->removeAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS,
										MAKE_UNICODE_STRING((char *) &((e->m_name.rawBuffer())[6])));
		else
			e->mp_node->removeAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS,
										MAKE_UNICODE_STRING((char *) e->m_name.rawBuffer()));

		// Delete the entry
		delete e;

	}

	// Now done - empty everything
	m_lst.clear();
	m_expanded = false;

}

bool XSECNameSpaceExpander::nodeWasAdded(DOMNode *n) const {

	NameSpaceEntryListVectorType::size_type size = m_lst.size();
	XSECNameSpaceEntry *e;

	NameSpaceEntryListVectorType::size_type i;
	for (i = 0; i < size; ++i) {

		// Delete the element attribute, and then this node
		e = m_lst[i];
		
		if (e->mp_att == n)
			return true;

	}

	return false;

}
