/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2004 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:  
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.	IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#if !defined(XALANTRANSFORMER_HEADER_GUARD)
#define XALANTRANSFORMER_HEADER_GUARD



// Base include file.  Must be first.
#include <xalanc/XalanTransformer/XalanTransformerDefinitions.hpp>



#include <cassert>
#include <vector>

#if defined(XALAN_CLASSIC_IOSTREAMS)
class ostream;
#else
#include <iosfwd>
#endif



#include <xalanc/XPath/XalanQNameByValue.hpp>



#include <xalanc/XSLT/XSLTInputSource.hpp>
#include <xalanc/XSLT/XSLTResultTarget.hpp>



XALAN_DECLARE_XERCES_CLASS(EntityResolver)
XALAN_DECLARE_XERCES_CLASS(ErrorHandler)



XALAN_CPP_NAMESPACE_BEGIN



typedef XERCES_CPP_NAMESPACE_QUALIFIER EntityResolver	EntityResolverType;
typedef XERCES_CPP_NAMESPACE_QUALIFIER ErrorHandler		ErrorHandlerType;



class Function;
class StylesheetExecutionContextDefault;
class ProblemListener;
class TraceListener;
class XSLTInit;
class XalanDocumentBuilder;
class XalanCompiledStylesheet;
class XalanParsedSource;
class XalanTransformerOutputStream;



/**
 * This is a simple C++ interface for some common usage patterns. It's 
 * the user's responsibility to call initialize and terminate for Xerces 
 * and Xalan before creating and after deleting any XalanTransformer  
 * instances.
*/
class XALAN_TRANSFORMER_EXPORT XalanTransformer
{
public:
	
#if defined(XALAN_NO_STD_NAMESPACE)
	typedef ostream			StreamType;
#else
	typedef std::ostream	StreamType;
#endif

	XalanTransformer();

	virtual
	~XalanTransformer();

	/**
	 * Initialize Xalan.
	 *
	 * Should be called only once per process before creating any
	 * instances of XalanTransformer.  This call is not thread-safe,
	 * so you must serialize any calls to it, and you must track the
	 * initialization state, so you do not call it more than once.
	 */
	static void
	initialize();

	/**
	 * Terminate Xalan.
	 *
	 * Should be called only once per process after deleting all
	 * instances of XalanTransformer.  This call is not thread-safe,
	 * so you must serialize any calls to it, and you must track the
	 * initialization state, so you do not call it more than once.
	 *
	 * This is handy when using leak-detection software, as all
	 * static data allocated by Xalan is freed.
	 *
	 */
	static void
	terminate();

	/**
	 * Clean up the ICU, if ICU integration is enabled.
	 *
	 * This should be called only once per process after calling
	 * XalanTransformer::terminate() and XMLPlatformUtils::Terminate.
	 *
	 * This must only be done if the ICU will no longer be used by
	 * the process, since the ICU will no longer be in a usable state.
	 * See the ICU documentation for more details.
	 *
	 * This call is not thread-safe, so you must serialize any calls
	 * to it, and you must track the initialization state, so you do
	 * not call it more than once.
	 *
	 * This is handy when using leak-detection software, as all
	 * static data allocated by the ICU is freed.
	 *
	 */
	static void
	ICUCleanUp();


	/**
	 * Transform will apply the stylesheet source to the parsed xml source
	 * and write the transformation output to the target. 
	 *
	 * @param theParsedXML			the parsed input source
	 * @param theStylesheetSource	stylesheet source
	 * @param theResultTarget		output source
	 * @return	0 for success
	 */
	int
	transform(
			const XalanParsedSource&	theParsedXML, 
			const XSLTInputSource&		theStylesheetSource,
			const XSLTResultTarget& 	theResultTarget)
	{
		return doTransform(theParsedXML, 0, &theStylesheetSource, theResultTarget);
	}

	/**
	 * Transform will apply the compiled stylesheet to the parsed xml source
	 * and write the transformation output to the target. 
	 *
	 * @param theParsedXML			the parsed input source
	 * @param theCompiledStylesheet pointer to a compiled stylesheet.  Must not be null.
	 * @param theResultTarget		output source 
	 * @return	0 for success
	 */
	int
	transform(
			const XalanParsedSource&		theParsedXML,
			const XalanCompiledStylesheet*	theCompiledStylesheet,
			const XSLTResultTarget& 		theResultTarget)
	{
		assert(theCompiledStylesheet != 0);

		return doTransform(theParsedXML, theCompiledStylesheet, 0, theResultTarget);
	}

	/**
	 * Transform will apply the stylesheet provided as a PI in the 
	 * XML of the parsed xml source and write the transformation output to 
	 * the target. 
	 *
	 * @param theParsedXML		the parsed input source
	 * @param theResultTarget	output source tree
	 * @return					0 for success
	 */
	int
	transform(
			const XalanParsedSource&	theParsedXML, 		 		 
			const XSLTResultTarget&		theResultTarget)
	{
		assert(s_emptyInputSource != 0);

		return transform(theParsedXML, *s_emptyInputSource, theResultTarget);
	}

	/**
	 * Transform will apply the stylesheet source to the input source
	 * and write the transformation output to the target. The input 
	 * source and result target can be a file name, a stream or a root
	 * node.
	 *
	 * @param theInputSource		input source
	 * @param theStylesheetSource	stylesheet source
	 * @param theResultTarget		output source
	 * @return	0 for success
	 */
	int
	transform(
			const XSLTInputSource&		theInputSource,
			const XSLTInputSource&		theStylesheetSource,
			const XSLTResultTarget& 	theResultTarget);

	/**
	 * Transform will apply the stylesheet provided as a PI in the 
	 * XML of the input source and write the transformation output to 
	 * the target. The input source and result target can be a file 
	 * name, a stream or a root node.
	 *
	 * @param theInputSource		input source
	 * @param theResultTarget		output source tree
	 * @return	0 for success
	 */
	int
	transform(
			const XSLTInputSource&		theInputSource,
			const XSLTResultTarget& 	theResultTarget)
	{
		assert(s_emptyInputSource != 0);

		return transform(
						theInputSource, 
						*s_emptyInputSource,
						theResultTarget);
	}

	/**
	 * Transform will apply the stylesheet source to the input source
	 * and write the transformation result to a callback function  
	 * in pre-allocated blocks. The input source can be a file name, 
	 * a stream or a root node. Upon termination, Xalan releases any 
	 * allocated memory. Data passed to the callback is not guaranteed to 
	 * be null terminated.
	 *
	 * - See XalanTransformerOutputStream and XalanOutputHandlerType 
	 * for more details.
	 * 
	 * @param theInputSource		input source
	 * @param theStylesheetSource	stylesheet source	
	 * @param theOutputHandle		void pointer passed through to callback.
	 * @param theOutputHandler		a user defined (callback) function.
	 * @param theFlushHandler		(optional) a user defined (callback) function.
	 * @return	0 for success 
	 */
	int
	transform(
			const XSLTInputSource&		theInputSource, 
			const XSLTInputSource&		theStylesheetSource,
			void*						theOutputHandle, 
			XalanOutputHandlerType		theOutputHandler,
			XalanFlushHandlerType		theFlushHandler = 0);
	
	/**
	 * Transform will apply the compiled stylesheet to the input source
	 * and write the transformation output to the target. The input 
	 * source and result target can be a file name, a stream or a root
	 * node. 
	 *
	 * @param theInputSource		input source
	 * @param theCompiledStylesheet pointer to a compiled stylesheet.  Must not be null.
	 * @param theResultTarget		output source 
	 * @return	0 for success
	 */
	int
	transform(
			const XSLTInputSource&			theInputSource, 
			const XalanCompiledStylesheet*	theCompiledStylesheet,
			const XSLTResultTarget& 		theResultTarget);
 
	/**
	 * Transform will apply the compiled stylesheet to the source
	 * and write the transformation result to a callback function  
	 * in pre-allocated blocks. The input source can be a file name, 
	 * a stream or a root node. Upon termination, Xalan releases any 
	 * allocated memory. Data passed to the callback is not guaranteed to 
	 * be null terminated.
	 *
	 * - See XalanTransformerOutputStream and XalanOutputHandlerType 
	 * for more details.
	 * 
	 * @param theParsedSource		Parsed source instance
	 * @param theCompiledStylesheet pointer to a compiled stylesheet.  Must not be null.
	 * @param theOutputHandle		void pointer passed through to callback.
	 * @param theOutputHandler		a user defined callback function.
	 * @param theFlushHandler		An optional user-defined callback function.
	 * @return	0 for success 
	 */
	int
	transform(
			const XalanParsedSource&		theParsedSource,
			const XalanCompiledStylesheet*	theCompiledStylesheet,
			void*							theOutputHandle,
			XalanOutputHandlerType			theOutputHandler,
			XalanFlushHandlerType			theFlushHandler = 0);

	/**
	 * Transform will apply the stylesheet provided as a PI in the 
	 * XML of the input source and write  the transformation result to a  
	 * callback function in pre-allocated blocks. The input source can be 
	 * a file name, a stream or a root node. Upon termination, Xalan 
	 * releases any allocated memory. Data passed to the callback is not 
	 * guaranteed to be null terminated.
	 *
	 * - See XalanTransformerOutputStream and XalanOutputHandlerType 
	 * for more details.
	 * 
	 * @param theInputSource		input source
	 * @param theOutputHandle		void pointer passed through to callback.
	 * @param theOutputHandler		a user defined callback function.
	 * @param theFlushHandler		an optional user-defined callback function.
	 * @return	0 for success 
	 */
	int
	transform(
			const XSLTInputSource&		theInputSource,
			void*						theOutputHandle,
			XalanOutputHandlerType		theOutputHandler,
			XalanFlushHandlerType		theFlushHandler = 0);

	/**
	 * Creates a compiled stylesheet.  The input source can be 
	 * a file name, a stream or a root node.   The XalanTransformer
	 * instance owns the XalanCompiledStylesheet instance and will
	 * delete it when the XalanTransformer instance goes out of scope,
	 * or you explicitly call destroyStylesheet().	You must not delete
	 * the instance yourself.
	 *
	 * @param theStylesheetSource input source
	 * @param theCompiledStylesheet a reference to a pointer to a XalanCompileStylesheet.
	 * @return 0 for success 
	 */
	int
	compileStylesheet(
			const XSLTInputSource&				theStylesheetSource,
			const XalanCompiledStylesheet*& 	theCompiledStylesheet);

	/**
	 * Destroy a XalanCompiledStylesheet instance created by a previous
	 * call to compileStylesheet().
	 *
	 * @param theStylesheet The instance to destroy.
	 * @return 0 for success 
	 */
	int
	destroyStylesheet(const XalanCompiledStylesheet*	theStylesheet);

	/**
	 * Parse a source XML document.  The input source can be 
	 * a file name, a stream or a root node.  The XalanTransformer
	 * instance owns the XalanParsedSource instance and will
	 * delete it when the XalanTransformer instance goes out of scope,
	 * or you explicitly call destroyParsedSource().  You must not
	 * delete the instance yourself.
	 *
	 * @param theInputSource input source
	 * @param theParsedSource a reference to a pointer to a XalanParsedSource.
	 * @param useXercesDOM input use default or xerces DOM source tree
	 * @return 0 for success 
	 */
	int
	parseSource(
			const XSLTInputSource&		theInputSource,
			const XalanParsedSource*&	theParsedSource,
			bool						useXercesDOM = false);

	/**
	 * Destroy a parsed source created by a previous call to parseSource().
	 *
	 * @param theParsedSource The XalanParsedSource instance to destroy.
	 * @return 0 for success 
	 */
	int
	destroyParsedSource(const XalanParsedSource*	theParsedSource);

	/**
	 * Create a document builder.  Using the document builder, you
	 * can construct a document using SAX2 interfaces.	The XalanTransformer
	 * instance owns the document builder and will delete it when the
	 * XalanTransformer instance goes out of scope, or you explicitly call
	 * destroyDocumentBuilder().  You must not delete the instance yourself.
	 *
	 * @param theURI The base URI for the document instance.
	 * @return	a pointer to a XalanDocumentBuilder instance or 0 for failure.
	 */
	XalanDocumentBuilder*
	createDocumentBuilder(const XalanDOMString&		theURI = XalanDOMString());

	/**
	 * Destroy a document builder created by a previous call to createDocumentBuilder().
	 * Passing a pointer that is not created by a call to createDocumentBuilder() can
	 * result in undefined behavior.
	 *
	 * @param theDocumentBuilder The document builder to destroy.
	 */
	void
	destroyDocumentBuilder(XalanDocumentBuilder*	theDocumentBuilder);

	/**
	 * Install an external function in the local space.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 * @param function The function to install.
	 */
	void
	installExternalFunction(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName,
			const Function& 		function);

	/**
	 * Install an external function in the global space.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 * @param function The function to install.
	 */
	static void
	installExternalFunctionGlobal(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName,
			const Function& 		function);

	/**
	 * Uninstall an external local function.
	 *
	 * @param theNamespace The namespace for the function
	 * @param functionName The name of the function.
	 */
	void
	uninstallExternalFunction(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName);

	/**
	 * Uninstall an external global function.
	 *
	 * @param theNamespace The namespace for the function
	 * @param functionName The name of the function.
	 */
	static void
	uninstallExternalFunctionGlobal(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName);

	/**
	 * Set a top-level stylesheet parameter.  This value can be evaluated via
	 * xsl:param-variable.  These values are cleared after a call to transform().
	 *
	 * @param key name of the param
	 * @param expression expression that will be evaluated
	 */
	void
	setStylesheetParam(
			const XalanDOMString&	key,
			const XalanDOMString&	expression);

	/**
	 * Set a top-level stylesheet parameter.  This value can be evaluated via
	 * xsl:param-variable.  These values are cleared after a call to transform().
	 *
	 * @param key name of the param
	 * @param expression expression that will be evaluated
	 */
	void
	setStylesheetParam(
			const char*		key,
			const char*		expression);

	/**
	 * Add a TraceListener instance.  TraceListeners instances are preserved
	 * between calls to transform(), so they will be called until they are
	 * removed.
	 *
	 * @param theTraceListener The instance to add.
	 */
	void
	addTraceListener(TraceListener*		theTraceListener)
	{
		m_traceListeners.push_back(theTraceListener);
	}

	/**
	 * Remove a TraceListener instance
	 *
	 * @param theTraceListener The instance to remove.
	 * @return true if the instance was removed, false if not.
	 */
	bool
	removeTraceListener(TraceListener*	theTraceListener);

	/**
	 * Remove all TraceListener instances.
	 */
	void
	removeTraceListeners()
	{
		m_traceListeners.clear();
	}

	/**
	 * Set a flag to indicate whether or not the source file(s) for the
	 * transformation will be validated.
	 *
	 * @param fValue the new value for the flag.
	 */
	bool
	getUseValidation() const
	{
		return m_useValidation;
	}

	/**
	 * Set a flag to indicate whether or not the source file(s) for the
	 * transformation will be validated.
	 *
	 * @param fValue the new value for the flag.
	 */
	void
	setUseValidation(bool	fValue)
	{
		m_useValidation = fValue;
	}

	/**
	 * This method returns the installed entity resolver.
	 *
	 * @return The pointer to the installed entity resolver object.
	 */
	EntityResolverType*
	getEntityResolver() const
	{
		return m_entityResolver;
	}

	/**
	 * This method installs the user-specified entity resolver.
	 * It allows applications to trap and redirect calls to
	 * external entities.
	 *
	 * @param handler A pointer to the entity resolver to be called
	 * 			   when the parser comes across references to
	 * 			   entities in the XML file.
	 */
	void
	setEntityResolver(EntityResolverType*	theResolver)
	{
		m_entityResolver = theResolver;
	}

	/**
	 * This method returns the installed error handler.
	 *
	 * @return The pointer to the installed error handler object.
	 */
	ErrorHandlerType*
	getErrorHandler() const
	{
		return m_errorHandler;
	}

	/**
	 * This method installs the user-specified error handler.
	 *
	 * @param handler A pointer to the error handler to be called upon error.
	 */
	void
	setErrorHandler(ErrorHandlerType*	theErrorHandler)
	{
		m_errorHandler = theErrorHandler;
	}

	/**
	  * This method returns the location for an external schema document
	  * for parsing.
	  *
	  * @return A string representing the location of the external schema document
	  */
	const XalanDOMChar*
	getExternalSchemaLocation() const
	{
		return m_externalSchemaLocation.empty() == true ? 0 : m_externalSchemaLocation.c_str();
	}

	/**
	  * This method sets the location for an external schema document
	  * for parsing.
	  *
	  * @param location A string representing the location of the external schema document
	  */
	void
	setExternalSchemaLocation(const XalanDOMChar*	location)
	{
		assert(location != 0);

		m_externalSchemaLocation = location;
	}

	/**
	  * This method returns the location for an external schema document
	  * for parsing.
	  *
	  * @return A string representing the location of the external schema document
	  */
	const XalanDOMChar*
	getExternalNoNamespaceSchemaLocation() const
	{
		return m_externalNoNamespaceSchemaLocation.empty() == true ? 0 : m_externalNoNamespaceSchemaLocation.c_str();
	}

	/**
	  * This method sets the location for an external schema document
	  * for parsing.
	  *
	  * @param location A string representing the location of the external schema document
	  */
	void
	setExternalNoNamespaceSchemaLocation(const XalanDOMChar*	location)
	{
		assert(location != 0);

		m_externalNoNamespaceSchemaLocation = location;
	}

	/**
	 * This method returns the installed ProblemListener instance.
	 *
	 * @return The pointer to the installed ProblemListener instance.
	 */
	ProblemListener*
	getProblemListener() const
	{
		return 	m_problemListener;
	}

	/**
	 * This method installs the user-specified ProblemListener instance.
	 *
	 * @param handler A pointer to the ProblemListener to be called when a problem occurs.
	 */
	void
	setProblemListener(ProblemListener*		theProblemListener)
	{
		m_problemListener = theProblemListener;
	}

	/**
	 * Returns the last error that occurred as a 
	 * result of calling transform. 
	 *
	 * @return	error message const character pointer.
	 */
	const char*
	getLastError() const
	{
		assert(m_errorMessage.empty() == false);

		return &m_errorMessage[0]; 
	}

	/**
	 * Get the current output encoding, if any.  Note this is not the output encoding
	 * specified in a stylesheet.  Rather, it can override that encoding, if the
	 *
	 * @return A string containing the current encoding
	 */
	const XalanDOMString&
	getOutputEncoding() const
	{
		return m_outputEncoding;
	}

	/**
	 * Set the current output encoding.  Note this will override the encoding
	 * specified in the stylesheet, if the encoding is available.  However,
	 * it will not override any encoding specified by an XSLTResultTarget
	 * parameter to one of the transform() member functions.
	 *
	 * @param theEncoding The encoding to use.
	 */
	void
	setOutputEncoding(const XalanDOMString&		theEncoding)
	{
		m_outputEncoding = theEncoding;
	}

	/**
	 * Get the current number of spaces to indent.
	 * 
	 * @return number of spaces
	 */
	int
	getIndent() const;

	/**
	 * Set the current number of spaces to indent.
	 * 
	 * @param indentAmount The number of spaces to indent.  Use -1 for the default amount.
	 */
	void
	setIndent(int	indentAmount);

	/**
	 * Enums to determine whether or not run-time escaping of URLs has been set.
	 */
	enum eEscapeURLs
	{
		eEscapeURLsDefault,		// Use the value in the stylesheet
		eEscapeURLsNo,			// Don't escape URLs
		eEscapeURLsYes			// Escape URLs
	};

	/**
	 * Get the value for run-time escaping of URLs.  This can
	 * override the property specified by the stylesheet.  The
	 * default behavior is to honor the property in the stylesheet.
	 *
	 * @return The value of the enum
	 */
	eEscapeURLs
	getEscapeURLs() const;

	/**
	 * Set the value for run-time escaping of URLs.  This can
	 * override the property specified by the stylesheet.  The
	 * default behavior is to honor the property in the stylesheet.
	 *
	 * @param value The value of the enum
	 */
	void
	setEscapeURLs(eEscapeURLs	value);

	/**
	 * Enums to determine whether or not run-time omission of the META tag has been set.
	 * Relevant only for HTML output
	 */
	enum eOmitMETATag
	{
		eOmitMETATagDefault,	// Use the value in the stylesheet
		eOmitMETATagNo,			// Don't omit the META tag
		eOmitMETATagYes			// Omit the META tag
	};

	/**
	 * Get the value for run-time omission of the META tag.  This can
	 * override the property specified by the stylesheet.  The
	 * default behavior is to honor the property in the stylesheet.
	 *
	 * @return The value of the enum
	 */
	eOmitMETATag
	getOmitMETATag() const;

	/**
	 * Get the value for run-time omission of the META tag.  This can
	 * override the property specified by the stylesheet.  The
	 * default behavior is to honor the property in the stylesheet.
	 *
	 * @param value The value of the enum
	 */
	void
	setOmitMETATag(eOmitMETATag		value);

	/**
	 * Set the ostream instance for reporting warnings and messages.  The default
	 * is std::cerr.  If set to 0, no warnings or messages will be written.  If
	 * there is a user-installed ProblemListener instance, this is not used, as
	 * all such warnings and messages are handled by the user's ProblemListener.
	 *
	 * @param theStream A pointer to the ostream instance.
	 */
	void
	setWarningStream(StreamType*	theStream)
	{
		m_warningStream = theStream;
	}

	/**
	 * Get the current warning stream ostream instance.
	 *
	 * @return A pointer to the instance.  Can be 0.
	 */
	StreamType*
	getWarningStream() const
	{
		return m_warningStream;
	}

#if defined(XALAN_NO_STD_NAMESPACE)
	typedef vector<const XalanCompiledStylesheet*>		CompiledStylesheetPtrVectorType;
	typedef vector<const XalanParsedSource*>			ParsedSourcePtrVectorType;
	typedef pair<XalanDOMString, XalanDOMString>		ParamPairType;
	typedef vector<ParamPairType>						ParamPairVectorType;
	typedef pair<XalanQNameByValue, Function*>			FunctionPairType;
	typedef vector<FunctionPairType>					FunctionParamPairVectorType;
	typedef vector<TraceListener*>						TraceListenerVectorType;
#else
	typedef std::vector<const XalanCompiledStylesheet*> CompiledStylesheetPtrVectorType;
	typedef std::vector<const XalanParsedSource*>		ParsedSourcePtrVectorType;
	typedef std::pair<XalanDOMString, XalanDOMString>	ParamPairType;
	typedef std::vector<ParamPairType>					ParamPairVectorType;
	typedef std::pair<XalanQNameByValue, Function*>		FunctionPairType;
	typedef std::vector<FunctionPairType>				FunctionParamPairVectorType;
	typedef std::vector<TraceListener*>					TraceListenerVectorType;
#endif

	class EnsureDestroyParsedSource
	{
	public:

		EnsureDestroyParsedSource(
				XalanTransformer&			theTransformer,
				const XalanParsedSource*	theParsedSource) :
			m_transformer(theTransformer),
			m_parsedSource(theParsedSource)
		{
		}

		~EnsureDestroyParsedSource()
		{
			m_transformer.destroyParsedSource(m_parsedSource);
		}

	private:

		XalanTransformer&				m_transformer;

		const XalanParsedSource* const	m_parsedSource;
	};

	struct EnsureDestroyCompiledStylesheet
	{
		EnsureDestroyCompiledStylesheet(
				XalanTransformer&				theTransformer,
				const XalanCompiledStylesheet*	theCompiledStylesheet) :
			m_transformer(theTransformer),
			m_compiledStylesheet(theCompiledStylesheet)
		{
		}

		~EnsureDestroyCompiledStylesheet()
		{
			m_transformer.destroyStylesheet(m_compiledStylesheet);
		}

	private:

		XalanTransformer&						m_transformer;

		const XalanCompiledStylesheet* const	m_compiledStylesheet;
	};

	struct EnsureDestroyDocumentBuilder
	{
		EnsureDestroyDocumentBuilder(
				XalanTransformer&		theTransformer,
				XalanDocumentBuilder*	theDocumentBuilder) :
			m_transformer(theTransformer),
			m_documentBuilder(theDocumentBuilder)
		{
		}

		~EnsureDestroyDocumentBuilder()
		{
			m_transformer.destroyDocumentBuilder(m_documentBuilder);
		}

	private:

		XalanTransformer&			m_transformer;

		XalanDocumentBuilder* const m_documentBuilder;
	};

protected:

private:

	void
	reset();

	class EnsureReset
	{
	public:

		EnsureReset(XalanTransformer&	theTransformer) :
			m_transformer(theTransformer)
		{
		}

		~EnsureReset();

	private:

		XalanTransformer&	m_transformer;
	};

	friend class EnsureReset;

	int
	doTransform(
			const XalanParsedSource&		theParsedXML, 
			const XalanCompiledStylesheet*	theCompiledStylesheet,
			const XSLTInputSource*			theStylesheetSource,
			const XSLTResultTarget&			theResultTarget);


	// Data members...
	CompiledStylesheetPtrVectorType 		m_compiledStylesheets;

	ParsedSourcePtrVectorType				m_parsedSources;

	ParamPairVectorType 					m_paramPairs;

	FunctionParamPairVectorType 			m_functionPairs;

	TraceListenerVectorType					m_traceListeners;

	CharVectorType							m_errorMessage;

	bool									m_useValidation;

	EntityResolverType*						m_entityResolver;

	ErrorHandlerType*						m_errorHandler;

	XalanDOMString							m_externalSchemaLocation;

	XalanDOMString							m_externalNoNamespaceSchemaLocation;

	ProblemListener*						m_problemListener;

	StreamType*								m_warningStream;

	XalanDOMString							m_outputEncoding;

	// This should always be the latest data member!!!
	StylesheetExecutionContextDefault*		m_stylesheetExecutionContext;

	static const XSLTInputSource*			s_emptyInputSource;

	static const XSLTInit*					s_xsltInit;
};



XALAN_CPP_NAMESPACE_END



#endif	// XALANTRANSFORMER_HEADER_GUARD
