/*
 * @(#)$Id$
 *
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2001 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) 2001, Sun
 * Microsystems., http://www.sun.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * @author Morten Jorgensen
 * @author G. Todd Miller
 *
 */

package org.apache.xalan.xsltc.trax;

import java.io.File;
import java.io.FileOutputStream;
import java.io.Writer;
import java.io.Reader;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.net.UnknownServiceException;

import java.lang.IllegalArgumentException;
import java.util.Enumeration;
import java.util.StringTokenizer;

import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.ext.LexicalHandler;

import org.w3c.dom.Document;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.sax.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

import org.apache.xalan.xsltc.Translet;
import org.apache.xalan.xsltc.TransletException;
import org.apache.xalan.xsltc.TransletOutputHandler;
import org.apache.xalan.xsltc.DOMCache;
import org.apache.xalan.xsltc.dom.*;
import org.apache.xalan.xsltc.compiler.Constants;
import org.apache.xalan.xsltc.runtime.*;
import org.apache.xalan.xsltc.runtime.output.*;
import org.apache.xalan.xsltc.compiler.*;
import org.apache.xalan.xsltc.compiler.util.ErrorMsg;

import java.util.Properties;

public final class TransformerImpl extends Transformer
    implements DOMCache, ErrorListener {

    private AbstractTranslet _translet = null;
    private String           _method   = null;
    private String           _encoding = null;
    private ContentHandler   _handler  = null;

    private ErrorListener _errorListener = this;
    private URIResolver   _uriResolver = null;
    private Properties    _properties, _propertiesClone;

    // Used for default output property settings
    private final static String EMPTY_STRING = "";
    private final static String NO_STRING    = "no";
    private final static String YES_STRING   = "yes";
    private final static String XML_STRING   = "xml";

    // Pre-set DOMImpl to use as input (used only with TransformerHandlerImpl)
    private DOMImpl _dom = null;

    private DTDMonitor _dtdMonitor = null;

    private final static String LEXICAL_HANDLER_PROPERTY =
	"http://xml.org/sax/properties/lexical-handler";
    private static final String NAMESPACE_FEATURE =
	"http://xml.org/sax/features/namespaces";
    
    private TransletOutputHandlerFactory _tohFactory = null;

    private int _indentNumber;

    // Temporary
    private boolean _oldOutputSystem;

    /**
     * Implements JAXP's Transformer constructor
     * Our Transformer objects always need a translet to do the actual work
     */
    protected TransformerImpl(Translet translet, Properties outputProperties,
	int indentNumber, boolean oldOutputSystem) 
    {
	_translet = (AbstractTranslet) translet;
	_properties = createOutputProperties(outputProperties);
	_oldOutputSystem = oldOutputSystem;
	_propertiesClone = (Properties) _properties.clone();
	_indentNumber = indentNumber;
    }

    /**
     * Returns the translet wrapped inside this Transformer
     */
    protected AbstractTranslet getTranslet() {
	return _translet;
    }

    /**
     * Implements JAXP's Transformer.transform()
     *
     * @param source Contains the input XML document
     * @param result Will contain the output from the transformation
     * @throws TransformerException
     */
    public void transform(Source source, Result result)
	throws TransformerException 
    {
	if (_translet == null) {
	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_TRANSLET_ERR);
	    throw new TransformerException(err.toString());
	}

	// Pass output properties to the translet
	setOutputProperties(_translet, _properties);
	    
	if (!_oldOutputSystem) {
	    final TransletOutputHandler toHandler = getOutputHandler(result);

	    if (toHandler == null) {
		ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_HANDLER_ERR);
		throw new TransformerException(err.toString());
	    }

	    if (_uriResolver != null) {
		_translet.setDOMCache(this);
	    }

	    transform(source, toHandler, _encoding);

	    if (result instanceof DOMResult) {
		((DOMResult)result).setNode(_tohFactory.getNode());
	    }
	}
	else {
	    _handler = getOldOutputHandler(result);
	    if (_handler == null) {
		ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_HANDLER_ERR);
		throw new TransformerException(err.toString());
	    }

	    if (_uriResolver != null) {
		_translet.setDOMCache(this);
	    }

	    // Run the transformation
	    transform(source, (ContentHandler)_handler, _encoding);

	    // If a DOMResult, then we must set the DOM Tree so it can
	    // be retrieved later 
	    if (result instanceof DOMResult) {
		((DOMResult)result).setNode(((SAX2DOM)_handler).getDOM());
	    }
	}
    }

    /**
     * Create an output handler for the transformation output based on 
     * the type and contents of the TrAX Result object passed to the 
     * transform() method. 
     */
    private TransletOutputHandler getOutputHandler(Result result) 
	throws TransformerException 
    {
	// Get output method using get() to ignore defaults 
	_method = (String) _properties.get(OutputKeys.METHOD);

	// Get encoding using getProperty() to use defaults
	_encoding = (String) _properties.getProperty(OutputKeys.ENCODING);

	_tohFactory = TransletOutputHandlerFactory.newInstance();
	_tohFactory.setEncoding(_encoding);
	if (_method != null) {
	    _tohFactory.setOutputMethod(_method);
	}

	// Set indentation number in the factory
	if (_indentNumber >= 0) {
	    _tohFactory.setIndentNumber(_indentNumber);
	}

	// Return the content handler for this Result object
	try {
	    // Result object could be SAXResult, DOMResult, or StreamResult 
	    if (result instanceof SAXResult) {
                final SAXResult target = (SAXResult)result;
                final ContentHandler handler = target.getHandler();

		_tohFactory.setHandler(handler);
		if (handler instanceof LexicalHandler) {
		    _tohFactory.setLexicalHandler((LexicalHandler) handler);
		}
		_tohFactory.setOutputType(TransletOutputHandlerFactory.SAX);
		return _tohFactory.getTransletOutputHandler();
            }
	    else if (result instanceof DOMResult) {
		_tohFactory.setNode(((DOMResult) result).getNode());
		_tohFactory.setOutputType(TransletOutputHandlerFactory.DOM);
		return _tohFactory.getTransletOutputHandler();
            }
	    else if (result instanceof StreamResult) {
		// Get StreamResult
		final StreamResult target = (StreamResult) result;	

		// StreamResult may have been created with a java.io.File,
		// java.io.Writer, java.io.OutputStream or just a String
		// systemId. 

		_tohFactory.setOutputType(TransletOutputHandlerFactory.STREAM);

		// try to get a Writer from Result object
		final Writer writer = target.getWriter();
		if (writer != null) {
		    _tohFactory.setWriter(writer);
		    return _tohFactory.getTransletOutputHandler();
		}

		// or try to get an OutputStream from Result object
		final OutputStream ostream = target.getOutputStream();
		if (ostream != null) {
		    _tohFactory.setOutputStream(ostream);
		    return _tohFactory.getTransletOutputHandler();
		}

		// or try to get just a systemId string from Result object
		String systemId = result.getSystemId();
		if (systemId == null) {
		    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_RESULT_ERR);
                    throw new TransformerException(err.toString());
		}

		// System Id may be in one of several forms, (1) a uri
		// that starts with 'file:', (2) uri that starts with 'http:'
		// or (3) just a filename on the local system.
		URL url = null;
		if (systemId.startsWith("file:")) {
                    url = new URL(systemId);
		    _tohFactory.setOutputStream(
			new FileOutputStream(url.getFile()));
		    return _tohFactory.getTransletOutputHandler();
                }
                else if (systemId.startsWith("http:")) {
                    url = new URL(systemId);
                    final URLConnection connection = url.openConnection();
		    _tohFactory.setOutputStream(connection.getOutputStream());
		    return _tohFactory.getTransletOutputHandler();
                }
                else {
                    // system id is just a filename
                    url = new File(systemId).toURL();
		    _tohFactory.setOutputStream(
			new FileOutputStream(url.getFile()));
		    return _tohFactory.getTransletOutputHandler();
                }
	    }
	}
        // If we cannot write to the location specified by the SystemId
        catch (UnknownServiceException e) {
            throw new TransformerException(e);
        }
        catch (ParserConfigurationException e) {
            throw new TransformerException(e);
        }
        // If we cannot create the file specified by the SystemId
        catch (IOException e) {
            throw new TransformerException(e);
        }
	return null;
    }

    /**
     * Create an output handler (SAX2 handler) for the transformation output
     * based on the type and contents of the TrAX Result object passed to
     * the transform() method. 
     */
    private ContentHandler getOldOutputHandler(Result result) throws 
 	TransformerException 
    {
	// Try to get the encoding from the translet (may not be set)
	if (_translet._encoding != null) {
            _encoding = _translet._encoding;
        }
        else {
            _encoding = "UTF-8"; // default output encoding
        }

	// Return the content handler for this Result object
	try {
	    // Result object could be SAXResult, DOMResult, or StreamResult 
	    if (result instanceof SAXResult) {
                final SAXResult target = (SAXResult)result;
                final ContentHandler handler = target.getHandler();
                // Simple as feck, just pass the SAX handler back...
                if (handler != null) return handler;
            }
	    else if (result instanceof DOMResult) {
                return new SAX2DOM(((DOMResult) result).getNode());
            }
	    else if (result instanceof StreamResult) {
		// Get StreamResult
		final StreamResult target = (StreamResult)result;	

		// StreamResult may have been created with a java.io.File,
		// java.io.Writer, java.io.OutputStream or just a String
		// systemId. 

		// try to get a Writer from Result object
		final Writer writer = target.getWriter();
		if (writer != null) {
		    return (new DefaultSAXOutputHandler(writer, _encoding));
		}

		// or try to get an OutputStream from Result object
		final OutputStream ostream = target.getOutputStream();
		if (ostream != null) {
		    return (new DefaultSAXOutputHandler(ostream, _encoding));
		}

		// or try to get just a systemId string from Result object
		String systemId = result.getSystemId();
		if (systemId == null) {
		    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_RESULT_ERR);
                    throw new TransformerException(err.toString());
		}

		// System Id may be in one of several forms, (1) a uri
		// that starts with 'file:', (2) uri that starts with 'http:'
		// or (3) just a filename on the local system.
	        OutputStream os = null;
		URL url = null;
		if (systemId.startsWith("file:")) {
                    url = new URL(systemId);
                    os = new FileOutputStream(url.getFile());
		    return (new DefaultSAXOutputHandler(os, _encoding));
                }
                else if (systemId.startsWith("http:")) {
                    url = new URL(systemId);
                    URLConnection connection = url.openConnection();
                    os = connection.getOutputStream();
		    return (new DefaultSAXOutputHandler(os, _encoding));
                }
                else {
                    // system id is just a filename
                    File tmp = new File(systemId);
                    url = tmp.toURL();
                    os = new FileOutputStream(url.getFile());
		    return (new DefaultSAXOutputHandler(os, _encoding));
                }
	    }
	}
        // If we cannot write to the location specified by the SystemId
        catch (UnknownServiceException e) {
            throw new TransformerException(e);
        }
        // If we cannot create a SAX2DOM adapter
        catch (ParserConfigurationException e) {
            ErrorMsg err = new ErrorMsg(ErrorMsg.SAX2DOM_ADAPTER_ERR);
            throw new TransformerException(err.toString());
        }
        // If we cannot create the file specified by the SystemId
        catch (IOException e) {
            throw new TransformerException(e);
        }
	return null;
    }

    /**
     * Set the internal DOMImpl that will be used for the next transformation
     */
    protected void setDOM(DOMImpl dom) {
	_dom = dom;
    }

    /**
     * Set the internal DOMImpl that will be used for the next transformation
     */
    protected void setDTDMonitor(DTDMonitor dtdMonitor) {
	_dtdMonitor = dtdMonitor;
    }

    /**
     * Builds an internal DOM from a TrAX Source object
     */
    private DOMImpl getDOM(Source source, int mask)
	throws TransformerException 
    {
	try {
	    DOMImpl dom = null;
	    DTDMonitor dtd = null;

	    // Handle SAXSource input
	    if (source instanceof SAXSource) {
		// Get all info from the input SAXSource object
		final SAXSource   sax    = (SAXSource)source;
		XMLReader   reader = sax.getXMLReader();
		final InputSource input  = sax.getInputSource();
		final String      systemId = sax.getSystemId();

		// if reader was not set with setXMLReader by user,
		// then we must create one ourselves.
		if (reader == null) {
		    SAXParserFactory pfactory= SAXParserFactory.newInstance();
		    pfactory.setNamespaceAware(true);
		    reader = pfactory.newSAXParser().getXMLReader();
		}

		// Create a DTD monitor to trap all DTD/declarative events
		dtd = new DTDMonitor();
		dtd.handleDTD(reader);

		// Create a new internal DOM and set up its builder to trap
		// all content/lexical events
		dom = new DOMImpl();
		final DOMBuilder builder = dom.getBuilder();
		try {
		    reader.setProperty(LEXICAL_HANDLER_PROPERTY, builder);
		}
		catch (SAXException e) {
		    // quitely ignored
		}
		reader.setContentHandler(builder);

		// Parse the input and build the internal DOM
		reader.parse(input);
		dom.setDocumentURI(systemId);
	    }
	    // Handle DOMSource input
	    else if (source instanceof DOMSource) {
		final DOMSource   domsrc = (DOMSource)source;
		final org.w3c.dom.Node node = domsrc.getNode();

		boolean isComplete = true;
		if (node.getNodeType() != org.w3c.dom.Node.DOCUMENT_NODE) {
		    isComplete = false;
		}

		final DOM2SAX     dom2sax = new DOM2SAX(node);
		final InputSource input = null; 
		final String      systemId = domsrc.getSystemId(); 

		// Create a DTD monitor to trap all DTD/declarative events
		dtd = new DTDMonitor();
		dtd.handleDTD(dom2sax);

		// Create a new internal DOM and set up its builder to trap
		// all content/lexical events
		dom = new DOMImpl();
		final DOMBuilder builder = dom.getBuilder();
		dom2sax.setContentHandler(builder);

		// Parse the input and build the internal DOM
		if (!isComplete) {
		    builder.startDocument();
		}
		dom2sax.parse(input); // need this parameter?
		if (!isComplete) {
		    builder.endDocument();
		}
		dom.setDocumentURI(systemId);
	    }
	    // Handle StreamSource input
	    else if (source instanceof StreamSource) {
		// Get all info from the input StreamSource object
		final StreamSource stream = (StreamSource)source;
		final InputStream  streamInput = stream.getInputStream();
		final Reader streamReader = stream.getReader();
		final String systemId = stream.getSystemId();

		// With a StreamSource we need to create our own parser
		final SAXParserFactory factory = SAXParserFactory.newInstance();
		try {
		    factory.setFeature(NAMESPACE_FEATURE,true);
		}
		catch (Exception e) {
		    factory.setNamespaceAware(true);
		}

		final SAXParser parser = factory.newSAXParser();
		final XMLReader reader = parser.getXMLReader();

		// Create a DTD monitor to trap all DTD/declarative events
		dtd = new DTDMonitor();
		dtd.handleDTD(reader);

		// Create a new internal DOM and set up its builder to trap
		// all content/lexical events
		dom = new DOMImpl();
		final DOMBuilder builder = dom.getBuilder();
		try {
		    reader.setProperty(LEXICAL_HANDLER_PROPERTY, builder);
		}
		catch (SAXException e) {
		    // quitely ignored
		}
		reader.setContentHandler(builder);

		InputSource input;
		if (streamInput != null) {
		    input = new InputSource(streamInput);
		    input.setSystemId(systemId); 
		} else if (streamReader != null) {
		    input = new InputSource(streamReader);
		    input.setSystemId(systemId); 
		} else if (systemId != null) {
		    input = new InputSource(systemId);
		} else {
		    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_SOURCE_ERR);
		    throw new TransformerException(err.toString());
		}

		// Parse the input and build the internal DOM
		reader.parse(input);
		dom.setDocumentURI(systemId);
	    }
	    // Handle XSLTC-internal Source input
	    else if (source instanceof XSLTCSource) {
		final XSLTCSource xsltcsrc = (XSLTCSource)source;
		dtd = xsltcsrc.getDTD();
		dom = xsltcsrc.getDOM();
	    }
	    // DOM already set via a call to setDOM()
	    else if (_dom != null) {
		dtd = _dtdMonitor;	   // must be set via setDTDMonitor()
		dom = _dom; _dom = null;   // use only once, so reset to 'null'
	    }
	    else {
		return null;
	    }

	    // Set size of key/id indices
	    _translet.setIndexSize(dom.getSize());
	    // If there are any elements with ID attributes, build an index
	    dtd.buildIdIndex(dom, mask, _translet);
	    // Pass unparsed entity URIs to the translet
	    _translet.setDTDMonitor(dtd);
	    return dom;
	}
	catch (FileNotFoundException e) {
	    if (_errorListener != null)	postErrorToListener(e.getMessage());
	    throw new TransformerException(e);
	}
	catch (MalformedURLException e) {
	    if (_errorListener != null)	postErrorToListener(e.getMessage());
	    throw new TransformerException(e);
	}
	catch (UnknownHostException e) {
	    if (_errorListener != null)	postErrorToListener(e.getMessage());
	    throw new TransformerException(e);
	}
	catch (Exception e) {
	    if (_errorListener != null)	postErrorToListener(e.getMessage());
	    throw new TransformerException(e);
	}
    }
 
    /**
     * Internal transformation method - uses the internal APIs of XSLTC
     */
    private void transform(Source src, TransletOutputHandler handler, 
	String encoding) throws TransformerException 
    {
	try {
	    _translet.transform(getDOM(src, 0), handler);
	}
	catch (TransletException e) {
	    if (_errorListener != null)	postErrorToListener(e.getMessage());
	    throw new TransformerException(e);
	}
	catch (RuntimeException e) {
	    if (_errorListener != null)	postErrorToListener(e.getMessage());
	    throw new TransformerException(e);
	}
	catch (Exception e) {
	    if (_errorListener != null)	postErrorToListener(e.getMessage());
	    throw new TransformerException(e);
	}
    }

    /**
     * Internal transformation method - uses the internal APIs of XSLTC
     */
    private void transform(Source src, ContentHandler sax, String encoding)
	throws TransformerException {
	try {
	    // Build an iternal DOMImpl from the TrAX Source
	    DOMImpl dom = getDOM(src, 0);

	    // This handler will post-process the translet output
	    TextOutput handler;

	    // Check if the ContentHandler also implements LexicalHandler
	    if (sax instanceof LexicalHandler) {
		handler = new TextOutput(sax, (LexicalHandler)sax, encoding);
	    }
	    else {
		handler = new TextOutput(sax, encoding);
	    }
	    _translet.transform(dom, handler);
	}
	catch (TransletException e) {
	    if (_errorListener != null)	postErrorToListener(e.getMessage());
	    throw new TransformerException(e);
	}
	catch (RuntimeException e) {
	    if (_errorListener != null)	postErrorToListener(e.getMessage());
	    throw new TransformerException(e);
	}
	catch (Exception e) {
	    if (_errorListener != null)	postErrorToListener(e.getMessage());
	    throw new TransformerException(e);
	}
    }

    /**
     * Implements JAXP's Transformer.getErrorListener()
     * Get the error event handler in effect for the transformation.
     *
     * @return The error event handler currently in effect
     */
    public ErrorListener getErrorListener() {  
	return _errorListener; 
    }

    /**
     * Implements JAXP's Transformer.setErrorListener()
     * Set the error event listener in effect for the transformation.
     *
     * @param listener The error event listener to use
     * @throws IllegalArgumentException
     */
    public void setErrorListener(ErrorListener listener)
	throws IllegalArgumentException {
        if (listener == null) {
	    ErrorMsg err = new ErrorMsg(ErrorMsg.ERROR_LISTENER_NULL_ERR,
					"Transformer");
            throw new IllegalArgumentException(err.toString());
	}
        _errorListener = listener;
    }

    /**
     * Inform TrAX error listener of an error
     */
    private void postErrorToListener(String message) {
        try {
            _errorListener.error(new TransformerException(message));
	}
	catch (TransformerException e) {
            // ignored - transformation cannot be continued
        }
    }

    /**
     * Inform TrAX error listener of a warning
     */
    private void postWarningToListener(String message) {
        try {
            _errorListener.warning(new TransformerException(message));
        }
	catch (TransformerException e) {
            // ignored - transformation cannot be continued
        }
    }

    /**
     * The translet stores all CDATA sections set in the <xsl:output> element
     * in a Hashtable. This method will re-construct the whitespace separated
     * list of elements given in the <xsl:output> element.
     */
    private String makeCDATAString(Hashtable cdata) {
	// Return a 'null' string if no CDATA section elements were specified
	if (cdata == null) return null;

	StringBuffer result = new StringBuffer();

	// Get an enumeration of all the elements in the hashtable
	Enumeration elements = cdata.keys();
	if (elements.hasMoreElements()) {
	    result.append((String)elements.nextElement());
	    while (elements.hasMoreElements()) {
		String element = (String)elements.nextElement();
		result.append(' ');
		result.append(element);
	    }
	}
	
	return(result.toString());
    }

    /**
     * Implements JAXP's Transformer.getOutputProperties().
     * Returns a copy of the output properties for the transformation. This is
     * a set of layered properties. The first layer contains properties set by
     * calls to setOutputProperty() and setOutputProperties() on this class,
     * and the output settings defined in the stylesheet's <xsl:output>
     * element makes up the second level, while the default XSLT output
     * settings are returned on the third level.
     *
     * @return Properties in effect for this Transformer
     */
    public Properties getOutputProperties() {
	return (Properties) _properties.clone();
    }

    /**
     * Implements JAXP's Transformer.getOutputProperty().
     * Get an output property that is in effect for the transformation. The
     * property specified may be a property that was set with setOutputProperty,
     * or it may be a property specified in the stylesheet.
     *
     * @param name A non-null string that contains the name of the property
     * @throws IllegalArgumentException if the property name is not known
     */
    public String getOutputProperty(String name)
	throws IllegalArgumentException 
    {
	if (!validOutputProperty(name)) {
	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
	    throw new IllegalArgumentException(err.toString());
	}
	return _properties.getProperty(name);
    }

    /**
     * Implements JAXP's Transformer.setOutputProperties().
     * Set the output properties for the transformation. These properties
     * will override properties set in the Templates with xsl:output.
     * Unrecognised properties will be quitely ignored.
     *
     * @param properties The properties to use for the Transformer
     * @throws IllegalArgumentException Never, errors are ignored
     */
    public void setOutputProperties(Properties properties)
	throws IllegalArgumentException 
    {
	if (properties != null) {
	    final Enumeration names = properties.propertyNames();

	    while (names.hasMoreElements()) {
		final String name = (String) names.nextElement();

		// Ignore lower layer properties
		if (isDefaultProperty(name, properties)) continue;

		if (validOutputProperty(name)) {
		    _properties.setProperty(name, properties.getProperty(name));
		}
		else {
		    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
		    throw new IllegalArgumentException(err.toString());
		}
	    }
	}
	else {
	    _properties = _propertiesClone;
	}
    }

    /**
     * Implements JAXP's Transformer.setOutputProperty().
     * Get an output property that is in effect for the transformation. The
     * property specified may be a property that was set with 
     * setOutputProperty(), or it may be a property specified in the stylesheet.
     *
     * @param name The name of the property to set
     * @param value The value to assign to the property
     * @throws IllegalArgumentException Never, errors are ignored
     */
    public void setOutputProperty(String name, String value)
	throws IllegalArgumentException 
    {
	if (!validOutputProperty(name)) {
	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
	    throw new IllegalArgumentException(err.toString());
	}
	_properties.setProperty(name, value);
    }

    /**
     * Internal method to pass any properties to the translet prior to
     * initiating the transformation
     */
    private void setOutputProperties(AbstractTranslet translet,
				     Properties properties) 
    {
	// Return right now if no properties are set
	if (properties == null) return;

	// Get a list of all the defined properties
	Enumeration names = properties.propertyNames();
	while (names.hasMoreElements()) {
	    // Note the use of get() instead of getProperty()
	    String name  = (String) names.nextElement();
	    String value = (String) properties.get(name);

	    // Ignore default properties
	    if (value == null) continue;

	    // Pass property value to translet - override previous setting
	    if (name.equals(OutputKeys.ENCODING)) {
		translet._encoding = value;
	    }
	    else if (name.equals(OutputKeys.METHOD)) {
		translet._method = value;
	    }
	    else if (name.equals(OutputKeys.DOCTYPE_PUBLIC)) {
		translet._doctypePublic = value;
	    }
	    else if (name.equals(OutputKeys.DOCTYPE_SYSTEM)) {
		translet._doctypeSystem = value;
	    }
	    else if (name.equals(OutputKeys.MEDIA_TYPE)) {
		translet._mediaType = value;
	    }
	    else if (name.equals(OutputKeys.STANDALONE)) {
		translet._standalone = value;
	    }
	    else if (name.equals(OutputKeys.VERSION)) {
		translet._version = value;
	    }
	    else if (name.equals(OutputKeys.OMIT_XML_DECLARATION)) {
		translet._omitHeader = 
		    (value != null && value.toLowerCase().equals("yes"));
	    }
	    else if (name.equals(OutputKeys.INDENT)) {
		translet._indent = 
		    (value != null && value.toLowerCase().equals("yes"));
	    }
	    else if (name.equals(OutputKeys.CDATA_SECTION_ELEMENTS)) {
		if (value != null) {
		    translet._cdata = null; // clear previous setting
		    StringTokenizer e = new StringTokenizer(value);
		    while (e.hasMoreTokens()) {
			translet.addCdataElement(e.nextToken());
		    }
		}
	    }
	}
    }

    /**
     * Internal method to create the initial set of properties. There
     * are two layers of properties: the default layer and the base layer.
     * The latter contains properties defined in the stylesheet or by
     * the user using this API.
     */
    private Properties createOutputProperties(Properties outputProperties) {
	final Properties defaults = new Properties();
	defaults.setProperty(OutputKeys.ENCODING, "UTF-8");
	defaults.setProperty(OutputKeys.METHOD, XML_STRING);
	defaults.setProperty(OutputKeys.INDENT, NO_STRING);
	defaults.setProperty(OutputKeys.MEDIA_TYPE, "text/xml");
	defaults.setProperty(OutputKeys.OMIT_XML_DECLARATION, NO_STRING);
	defaults.setProperty(OutputKeys.STANDALONE, NO_STRING);
	defaults.setProperty(OutputKeys.VERSION, "1.0");

	// Copy propeties set in stylesheet to base
	final Properties base = new Properties(defaults);
	if (outputProperties != null) {
	    final Enumeration names = outputProperties.propertyNames();
	    while (names.hasMoreElements()) {
		final String name = (String) names.nextElement();
		base.setProperty(name, outputProperties.getProperty(name));
	    }
	}

	// Update defaults based on output method
	final String method = base.getProperty(OutputKeys.METHOD);
	if (method != null) {
	    if (method.equals("html")) {
		defaults.setProperty(OutputKeys.INDENT, "yes");
		defaults.setProperty(OutputKeys.VERSION, "4.0");
		defaults.setProperty(OutputKeys.MEDIA_TYPE, "text/html");
	    }
	    else if (method.equals("text")) {
		defaults.setProperty(OutputKeys.MEDIA_TYPE, "text/plain");
	    }
	}

	return base; 
    }

    /**
     * Verifies if a given output property name is a property defined in
     * the JAXP 1.1 / TrAX spec
     */
    private boolean validOutputProperty(String name) {
	return (name.equals(OutputKeys.ENCODING) ||
		name.equals(OutputKeys.METHOD) ||
		name.equals(OutputKeys.INDENT) ||
		name.equals(OutputKeys.DOCTYPE_PUBLIC) ||
		name.equals(OutputKeys.DOCTYPE_SYSTEM) ||
		name.equals(OutputKeys.CDATA_SECTION_ELEMENTS) ||
		name.equals(OutputKeys.MEDIA_TYPE) ||
		name.equals(OutputKeys.OMIT_XML_DECLARATION)   ||
		name.equals(OutputKeys.STANDALONE) ||
		name.equals(OutputKeys.VERSION) ||
		name.charAt(0) == '{');
    }

    /**
     * Checks if a given output property is default (2nd layer only)
     */
    private boolean isDefaultProperty(String name, Properties properties) {
	return (properties.get(name) == null);
    }

    /**
     * Implements JAXP's Transformer.setParameter()
     * Add a parameter for the transformation. The parameter is simply passed
     * on to the translet - no validation is performed - so any unused
     * parameters are quitely ignored by the translet.
     *
     * @param name The name of the parameter
     * @param value The value to assign to the parameter
     */
    public void setParameter(String name, Object value) { 
	_translet.addParameter(name, value, false);
    }

    /**
     * Implements JAXP's Transformer.clearParameters()
     * Clear all parameters set with setParameter. Clears the translet's
     * parameter stack.
     */
    public void clearParameters() {  
	_translet.clearParameters();
    }

    /**
     * Implements JAXP's Transformer.getParameter()
     * Returns the value of a given parameter. Note that the translet will not
     * keep values for parameters that were not defined in the stylesheet.
     *
     * @param name The name of the parameter
     * @return An object that contains the value assigned to the parameter
     */
    public final Object getParameter(String name) {
	return(_translet.getParameter(name));
    }

    /**
     * Implements JAXP's Transformer.getURIResolver()
     * Set the object currently used to resolve URIs used in document().
     *
     * @returns The URLResolver object currently in use
     */
    public URIResolver getURIResolver() {
	return _uriResolver;
    }

    /**
     * Implements JAXP's Transformer.setURIResolver()
     * Set an object that will be used to resolve URIs used in document().
     *
     * @param resolver The URIResolver to use in document()
     */
    public void setURIResolver(URIResolver resolver) { 
	_uriResolver = resolver;
    }

    /**
     * This class should only be used as a DOMCache for the translet if the
     * URIResolver has been set.
     *
     * The method implements XSLTC's DOMCache interface, which is used to
     * plug in an external document loader into a translet. This method acts
     * as an adapter between TrAX's URIResolver interface and XSLTC's
     * DOMCache interface. This approach is simple, but removes the
     * possibility of using external document caches with XSLTC.
     *
     * @param uri  An URI pointing to the document location
     * @param mask Contains a document ID (passed from the translet)
     * @param translet A reference to the translet requesting the document
     */
    public DOMImpl retrieveDocument(String uri, int mask, Translet translet) {
	try {
	    return(getDOM(_uriResolver.resolve(uri, ""), mask));
	}
	catch (TransformerException e) {
	    if (_errorListener != null)
		postErrorToListener("File not found: " + e.getMessage());
	    return(null);
	}
    }

    /**
     * Receive notification of a recoverable error. 
     * The transformer must continue to provide normal parsing events after
     * invoking this method. It should still be possible for the application
     * to process the document through to the end.
     *
     * @param exception The warning information encapsulated in a transformer 
     * exception.
     * @throws TransformerException if the application chooses to discontinue
     * the transformation (always does in our case).
     */
    public void error(TransformerException e)
	throws TransformerException 
    {
	System.err.println("ERROR: " + e.getMessageAndLocation());
	throw(e); 	
    }

    /**
     * Receive notification of a non-recoverable error. 
     * The application must assume that the transformation cannot continue
     * after the Transformer has invoked this method, and should continue
     * (if at all) only to collect addition error messages. In fact,
     * Transformers are free to stop reporting events once this method has
     * been invoked.
     *
     * @param exception The warning information encapsulated in a transformer
     * exception.
     * @throws TransformerException if the application chooses to discontinue
     * the transformation (always does in our case).
     */
    public void fatalError(TransformerException e)
	throws TransformerException 
    {
	System.err.println("FATAL: " + e.getMessageAndLocation());
	Throwable wrapped = e.getException();
	if (wrapped != null) {
	    System.err.println("     : "+wrapped.getMessage());
	}
	throw(e);
    }

    /**
     * Receive notification of a warning.
     * Transformers can use this method to report conditions that are not
     * errors or fatal errors. The default behaviour is to take no action.
     * After invoking this method, the Transformer must continue with the
     * transformation. It should still be possible for the application to
     * process the document through to the end.
     *
     * @param exception The warning information encapsulated in a transformer
     * exception.
     * @throws TransformerException if the application chooses to discontinue
     * the transformation (never does in our case).
     */
    public void warning(TransformerException e)
	throws TransformerException 
    {
	System.err.println("WARNING: " + e.getMessageAndLocation());
	Throwable wrapped = e.getException();
	if (wrapped != null) {
	    System.err.println("       : "+wrapped.getMessage());
	}
    }

}
