/**
 * 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
 *
 * XSECC14n20010315 := Canonicaliser object to process XML document in line with
 *					     RFC 3076
 *
 * Author(s): Berin Lautenbach
 *
 * $Id$
 *
 */

#ifndef XSECC14n20010315_INCLUDE
#define XSECC14n20010315_INCLUDE

//XSEC includes
#include <xsec/framework/XSECDefs.hpp>
#include <xsec/utils/XSECSafeBuffer.hpp>
#include <xsec/utils/XSECXPathNodeList.hpp>
#include <xsec/canon/XSECCanon.hpp>
#include <xsec/canon/XSECXMLNSStack.hpp>

#include <xercesc/framework/XMLFormatter.hpp>

// General includes
#include <memory.h>
#include <vector>

XSEC_USING_XERCES(XMLFormatter);
XSEC_USING_XERCES(XMLFormatTarget);

class XSECSafeBufferFormatter;

// --------------------------------------------------------------------------------
//           Simple structure for holding a list of nodes
// --------------------------------------------------------------------------------

// NOTE: We don't use NamedNodeMap or DOMNodeList as we are unsure what might happen
// to them in the future.  Also, to add items we would have to delve into the inards
// of Xerces (and use the "...impl" classes).  Such an approach might not be supported
// in the future.

struct XSECNodeListElt {

	XERCES_CPP_NAMESPACE_QUALIFIER DOMNode	*element;	// Element referred to
	safeBuffer						sortString;	// The string that is used to sort the nodes

	XSECNodeListElt					*next,
									*last;		// For the list

};

// Used for the sorting function

#define XMLNS_PREFIX		"a"
#define ATTRIBUTE_PREFIX	"b"

#define NOURI_PREFIX         "a"
#define HAVEURI_PREFIX       "b"

// --------------------------------------------------------------------------------
//           XSECC14n20010315 Object definition
// --------------------------------------------------------------------------------

class XSEC_EXPORT XSECC14n20010315 : public XSECCanon {

	typedef std::vector<char *>			CharListVectorType;
	typedef size_t			size_type;


public:

	// Constructors
	XSECC14n20010315();
	XSECC14n20010315(XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *newDoc);
	XSECC14n20010315(XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *newDoc,
					 XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *newStartNode);
	virtual ~XSECC14n20010315();

	// XPath processor

	int XPathSelectNodes(const char * XPathExpr);
	void setXPathMap(const XSECXPathNodeList & map);

	// Comments processing
	void setCommentsProcessing(bool onoff);
	bool getCommentsProcessing(void);

	// Exclusive processing
	void setExclusive(void);
	void setExclusive(char * xmlnsList);

	// Inclusive 1.1 processing
    void setInclusive11(void);

	// Namespace processing
	void setUseNamespaceStack(bool flag) {m_useNamespaceStack = flag;}

protected:

	// Implementation of virtual function
	XMLSize_t processNextNode();

	// Test whether a name space is in the non-exclusive list
	bool inNonExclNSList(safeBuffer &ns);

private:

	void init();
	bool checkRenderNameSpaceNode(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *e,
								  XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *a);
	void stackInit(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * n);

	// For formatting the buffers
	XSECSafeBufferFormatter		* mp_formatter;
	safeBuffer					m_formatBuffer;

	// For holding state whilst walking the DOM tree
	XSECNodeListElt	* mp_attributes,				// Start of list
					* mp_currentAttribute,			// Where we currently are in list
					* mp_firstNonNsAttribute;		// First NON XMLNS element in list
	XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * mp_attributeParent;			// To return up the tree
	bool m_returnedFromChild;						// Did we get to this node from below?
	XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * mp_firstElementNode;			// The root element of the document
	bool			m_firstElementProcessed;		// Has the first node been handled?

	// For XPath evaluation
	bool			  m_XPathSelection;				// Are we doing an XPath?
	XSECXPathNodeList m_XPathMap;					// The elements in the XPath

	// For comment processing
	bool			m_processComments;				// Whether comments are in or out (in by default)

	// For exclusive canonicalisation
	CharListVectorType		m_exclNSList;
	bool					m_exclusive;
	bool					m_exclusiveDefault;

	// For Inclusive 1.1 support
	bool                    m_incl11;

	// How do we handle namespaces?
	// Use the namespace stack if name space expansion has not been run on the document.
	// NOTE : Using the name space stack *will* cause problems if a full XPath expression
	// has been run to select the input nodeset.  Otherwise we should be fine.

	bool					m_useNamespaceStack;
	XSECXMLNSStack			m_nsStack;



};


#endif /* XSECC14n20010315_INCLUDE */


