/*
 * @(#)$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 G. Todd Miller 
 * @author Morten Jorgensen
 *
 */


package org.apache.xalan.xsltc.trax;

import java.io.File;
import java.io.Reader;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.Vector;
import java.util.Hashtable;

import javax.xml.transform.*;
import javax.xml.transform.sax.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

import org.w3c.dom.Document;
import org.xml.sax.XMLFilter;
import org.xml.sax.InputSource;

import org.apache.xalan.xsltc.Translet;
import org.apache.xalan.xsltc.compiler.XSLTC;
import org.apache.xalan.xsltc.compiler.SourceLoader;
import org.apache.xalan.xsltc.compiler.CompilerException;
import org.apache.xalan.xsltc.compiler.util.Util;
import org.apache.xalan.xsltc.runtime.AbstractTranslet;

/**
 * Implementation of a JAXP1.1 TransformerFactory for Translets.
 */
public class TransformerFactoryImpl
    extends SAXTransformerFactory implements SourceLoader {

    // This constant should be removed once all abstract methods are impl'ed.
    private static final String NYI = "Not yet implemented";

    // This error listener is used only for this factory and is not passed to
    // the Templates or Transformer objects that we create!!!
    private ErrorListener _errorListener = null; 

    // This URIResolver is passed to all created Templates and Transformers
    private URIResolver _uriResolver = null;

    // Cache for the newTransformer() method - see method for details
    private String      _defaultTransletName = "GregorSamsa";
    private Transformer _copyTransformer = null;
    private static final String COPY_TRANSLET_CODE =
	"<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"+
	"<xsl:template match=\"/\"><xsl:copy-of select=\".\"/></xsl:template>"+
	"</xsl:stylesheet>";

    // All used error messages should be listed here
    private static final String ERROR_LISTENER_NULL =
	"Attempting to set ErrorListener for TransformerFactory to null";
    private static final String UNKNOWN_SOURCE_ERR =
	"Only StreamSource and SAXSource are supported by XSLTC";
    private static final String NO_SOURCE_ERR =
	"Source object passed to newTemplates() has no contents";
    private static final String NO_ACCESS_ERR =
	"Cannot access file or URL ";
    private static final String COMPILE_ERR =
	"Could not compile stylesheet";

    // This Hashtable is used to store parameters for locating
    // <?xml-stylesheet ...?> processing instructions in XML documents.
    private Hashtable _piParams = null;

    // The above hashtable stores objects of this class only:
    private class PIParamWrapper {
	public String _media = null;
	public String _title = null;
	public String _charset = null;
	
	public PIParamWrapper(String media, String title, String charset) {
	    _media = media;
	    _title = title;
	    _charset = charset;
	}
    }


    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Contains nothing yet
     */
    public TransformerFactoryImpl() {
	// Don't need anything here so far...
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Set the error event listener for the TransformerFactory, which is used
     * for the processing of transformation instructions, and not for the
     * transformation itself.
     *
     * @param listener The error listener to use with the TransformerFactory
     * @throws IllegalArgumentException
     */
    public void setErrorListener(ErrorListener listener) 
	throws IllegalArgumentException {
	if (listener == null)
            throw new IllegalArgumentException(ERROR_LISTENER_NULL);
	_errorListener = listener;
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Get the error event handler for the TransformerFactory.
     *
     * @return The error listener used with the TransformerFactory
     */
    public ErrorListener getErrorListener() { 
	return _errorListener;
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Returns the value set for a TransformerFactory attribute
     *
     * @param name The attribute name
     * @return An object representing the attribute value
     * @throws IllegalArgumentException
     */
    public Object getAttribute(String name) 
	throws IllegalArgumentException { 
	if (name.equals("translet-name"))
	    return(_defaultTransletName);
	return(null);
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Sets the value for a TransformerFactory attribute.
     *
     * @param name The attribute name
     * @param value An object representing the attribute value
     * @throws IllegalArgumentException
     */
    public void setAttribute(String name, Object value) 
	throws IllegalArgumentException { 
	// Set the default translet name (ie. class name), which will be used
	// for translets that cannot be given a name from their system-id.
	if ((name.equals("translet-name")) && (value instanceof String))
	    _defaultTransletName = (String)value;
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Look up the value of a feature (to see if it is supported).
     * This method must be updated as the various methods and features of this
     * class are implemented.
     *
     * @param name The feature name
     * @return 'true' if feature is supported, 'false' if not
     */
    public boolean getFeature(String name) { 
	// All supported features should be listed here
	String[] features = {
	    DOMSource.FEATURE,
	    DOMResult.FEATURE,
	    SAXSource.FEATURE,
	    SAXResult.FEATURE,
	    StreamSource.FEATURE,
	    StreamResult.FEATURE
	};

	// Inefficient, but it really does not matter in a function like this
	for (int i=0; i<features.length; i++)
	    if (name.equals(features[i])) return true;

	// Feature not supported
	return false;
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Get the object that is used by default during the transformation to
     * resolve URIs used in document(), xsl:import, or xsl:include.
     *
     * @return The URLResolver used for this TransformerFactory and all
     * Templates and Transformer objects created using this factory
     */    
    public URIResolver getURIResolver() {
	return(_uriResolver);
    } 

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Set the object that is used by default during the transformation to
     * resolve URIs used in document(), xsl:import, or xsl:include. Note that
     * this does not affect Templates and Transformers that are already
     * created with this factory.
     *
     * @param resolver The URLResolver used for this TransformerFactory and all
     * Templates and Transformer objects created using this factory
     */    
    public void setURIResolver(URIResolver resolver) {
	_uriResolver = resolver;
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Get the stylesheet specification(s) associated via the xml-stylesheet
     * processing instruction (see http://www.w3.org/TR/xml-stylesheet/) with
     * the document document specified in the source parameter, and that match
     * the given criteria.
     *
     * @param source The XML source document.
     * @param media The media attribute to be matched. May be null, in which
     * case the prefered templates will be used (i.e. alternate = no).
     * @param title The value of the title attribute to match. May be null.
     * @param charset The value of the charset attribute to match. May be null.
     * @return A Source object suitable for passing to the TransformerFactory.
     * @throws TransformerConfigurationException
     */
    public Source getAssociatedStylesheet(Source source, String media,
					  String title, String charset)
	throws TransformerConfigurationException {
	// First create a hashtable that maps Source refs. to parameters
	if (_piParams == null) _piParams = new Hashtable();
	// Store the parameters for this Source in the Hashtable
	_piParams.put(source, new PIParamWrapper(media, title, charset));
	// Return the same Source - we'll locate the stylesheet later
	return(source);
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Create a Transformer object that copies the input document to the result.
     *
     * @return A Transformer object that simply copies the source to the result.
     * @throws TransformerConfigurationException
     */    
    public Transformer newTransformer()
	throws TransformerConfigurationException { 

	if (_copyTransformer != null) {
	    if (_uriResolver != null)
		_copyTransformer.setURIResolver(_uriResolver);
	    return _copyTransformer;
	}

	XSLTC xsltc = new XSLTC();
	xsltc.init();

	// Compile the default copy-stylesheet
	byte[] bytes = COPY_TRANSLET_CODE.getBytes();
	ByteArrayInputStream bytestream = new ByteArrayInputStream(bytes);
	InputSource input = new InputSource(bytestream);
	input.setSystemId(_defaultTransletName);
	byte[][] bytecodes = xsltc.compile(_defaultTransletName, input);

	// Check that the transformation went well before returning
	if (bytecodes == null) {
	    throw new TransformerConfigurationException(COMPILE_ERR);
	}

	// Create a Transformer object and store for other calls
	Templates templates = new TemplatesImpl(bytecodes,_defaultTransletName);
	_copyTransformer = templates.newTransformer();
	if (_uriResolver != null) _copyTransformer.setURIResolver(_uriResolver);
	return(_copyTransformer);
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Process the Source into a Templates object, which is a a compiled
     * representation of the source. Note that this method should not be
     * used with XSLTC, as the time-consuming compilation is done for each
     * and every transformation.
     *
     * @return A Templates object that can be used to create Transformers.
     * @throws TransformerConfigurationException
     */
    public Transformer newTransformer(Source source) throws
	TransformerConfigurationException {
	final Templates templates = newTemplates(source);
	final Transformer transformer = templates.newTransformer();
	if (_uriResolver != null) transformer.setURIResolver(_uriResolver);
	return(transformer);
    }

    /**
     * Pass warning messages from the compiler to the error listener
     */
    private void passWarningsToListener(Vector messages) {
	try {
	    // Nothing to do if there is no registered error listener
	    if (_errorListener == null) return;
	    // Nothing to do if there are not warning messages
	    if (messages == null) return;
	    // Pass messages to listener, one by one
	    final int count = messages.size();
	    for (int pos=0; pos<count; pos++) {
		String message = messages.elementAt(pos).toString();
		_errorListener.warning(new TransformerException(message));
	    }
	}
	catch (TransformerException e) {
	    // nada
	}
    }

    /**
     * Pass error messages from the compiler to the error listener
     */
    private void passErrorsToListener(Vector messages) {
	try {
	    // Nothing to do if there is no registered error listener
	    if (_errorListener == null) return;
	    // Nothing to do if there are not warning messages
	    if (messages == null) return;
	    // Pass messages to listener, one by one
	    final int count = messages.size();
	    for (int pos=0; pos<count; pos++) {
		String message = messages.elementAt(pos).toString();
		_errorListener.error(new TransformerException(message));
	    }
	}
	catch (TransformerException e) {
	    // nada
	}
    }

    /**
     * Creates a SAX2 InputSource object from a TrAX Source object
     */
    private InputSource getInputSource(XSLTC xsltc, Source source)
	throws TransformerConfigurationException {

	InputSource input = null;
	final String systemId = source.getSystemId();

	try {

	    // Try to get InputSource from SAXSource input
	    if (source instanceof SAXSource) {
		final SAXSource sax = (SAXSource)source;
		input = sax.getInputSource();
		// Pass the SAX parser to the compiler
		xsltc.setXMLReader(sax.getXMLReader());
	    }
	    // handle  DOMSource  
	    else if (source instanceof DOMSource) {
		final DOMSource domsrc = (DOMSource)source;
		final Document dom = (Document)domsrc.getNode();
		final DOM2SAX dom2sax = new DOM2SAX(dom);
		xsltc.setXMLReader(dom2sax);  
	        // try to get SAX InputSource from DOM Source.
		input = SAXSource.sourceToInputSource(source);
	    }
	    // Try to get InputStream or Reader from StreamSource
	    else if (source instanceof StreamSource) {
		final StreamSource stream = (StreamSource)source;
		final InputStream istream = stream.getInputStream();
		final Reader reader = stream.getReader();
		// Create InputSource from Reader or InputStream in Source
		if (istream != null)
		    input = new InputSource(istream);
		else if (reader != null)
		    input = new InputSource(reader);
	    }
	    else {
		throw new TransformerConfigurationException(UNKNOWN_SOURCE_ERR);
	    }
	    // Try to create an InputStream from the SystemId if no input so far
	    if (input == null) {
		if ((new File(systemId)).exists())
		    input = new InputSource("file:/"+systemId);
		else
		    input = new InputSource(systemId);
	    }

	    // Pass system id to InputSource just to be on the safe side
	    input.setSystemId(systemId);
	}
	catch (NullPointerException e) {
	    throw new TransformerConfigurationException(NO_SOURCE_ERR);
	}
	catch (SecurityException e) {
	    throw new TransformerConfigurationException(NO_ACCESS_ERR+systemId);
	}
	finally {
	    return(input);
	}
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Process the Source into a Templates object, which is a a compiled
     * representation of the source.
     *
     * @param stylesheet The input stylesheet - DOMSource not supported!!!
     * @return A Templates object that can be used to create Transformers.
     * @throws TransformerConfigurationException
     */
    public Templates newTemplates(Source source)
	throws TransformerConfigurationException {

	// Create and initialize a stylesheet compiler
	final XSLTC xsltc = new XSLTC();
	xsltc.init();

	// Set a document loader (for xsl:include/import) if defined
	if (_uriResolver != null) xsltc.setSourceLoader(this);

	// Pass parameters to the Parser to make sure it locates the correct
	// <?xml-stylesheet ...?> PI in an XML input document
	if ((_piParams != null) && (_piParams.get(source) != null)) {
	    // Get the parameters for this Source object
	    PIParamWrapper p = (PIParamWrapper)_piParams.get(source);
	    // Pass them on to the compiler (which will pass then to the parser)
	    if (p != null) 
		xsltc.setPIParameters(p._media, p._title, p._charset);
	}

	// Compile the stylesheet
	final InputSource input = getInputSource(xsltc, source);
	byte[][] bytecodes = xsltc.compile(null, input);
	final String transletName = xsltc.getClassName();

	// Pass compiler warnings to the error listener
	if (_errorListener != null)
	    passWarningsToListener(xsltc.getWarnings());
	else
	    xsltc.printWarnings();

	// Check that the transformation went well before returning
	if (bytecodes == null) {
	    // Pass compiler errors to the error listener
	    if (_errorListener != null)
		passErrorsToListener(xsltc.getErrors());
	    else
		xsltc.printErrors();
	    throw new TransformerConfigurationException(COMPILE_ERR);
	}
	return(new TemplatesImpl(bytecodes, transletName));
    }

    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Get a TemplatesHandler object that can process SAX ContentHandler
     * events into a Templates object.
     *
     * @return A TemplatesHandler object that can handle SAX events
     * @throws TransformerConfigurationException
     */
    public TemplatesHandler newTemplatesHandler() 
	throws TransformerConfigurationException { 
	return(new TemplatesHandlerImpl());
    }

    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Get a TransformerHandler object that can process SAX ContentHandler
     * events into a Result. This method will return a pure copy transformer.
     *
     * @return A TransformerHandler object that can handle SAX events
     * @throws TransformerConfigurationException
     */
    public TransformerHandler newTransformerHandler() 
	throws TransformerConfigurationException {
	final Transformer transformer = newTransformer();
	final TransformerImpl internal = (TransformerImpl)transformer;
	return(new TransformerHandlerImpl(internal));
    }

    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Get a TransformerHandler object that can process SAX ContentHandler
     * events into a Result, based on the transformation instructions
     * specified by the argument.
     *
     * @param src The source of the transformation instructions.
     * @return A TransformerHandler object that can handle SAX events
     * @throws TransformerConfigurationException
     */
    public TransformerHandler newTransformerHandler(Source src) 
	throws TransformerConfigurationException { 
	final Transformer transformer = newTransformer(src);
	final TransformerImpl internal = (TransformerImpl)transformer;
	return(new TransformerHandlerImpl(internal));
    }

    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Get a TransformerHandler object that can process SAX ContentHandler
     * events into a Result, based on the transformation instructions
     * specified by the argument.
     *
     * @param templates Represents a pre-processed stylesheet
     * @return A TransformerHandler object that can handle SAX events
     * @throws TransformerConfigurationException
     */    
    public TransformerHandler newTransformerHandler(Templates templates) 
	throws TransformerConfigurationException  {
	final Transformer transformer = templates.newTransformer();
	final TransformerImpl internal = (TransformerImpl)transformer;
	return(new TransformerHandlerImpl(internal));
    }


    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Create an XMLFilter that uses the given source as the
     * transformation instructions.
     *
     * @param src The source of the transformation instructions.
     * @return An XMLFilter object, or null if this feature is not supported.
     * @throws TransformerConfigurationException
     */
    public XMLFilter newXMLFilter(Source src) 
	throws TransformerConfigurationException {
	Templates templates = newTemplates(src);
	if (templates == null ) return null; 
	return newXMLFilter(templates);
    }

    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Create an XMLFilter that uses the given source as the
     * transformation instructions.
     *
     * @param src The source of the transformation instructions.
     * @return An XMLFilter object, or null if this feature is not supported.
     * @throws TransformerConfigurationException
     */
    public XMLFilter newXMLFilter(Templates templates) 
	throws TransformerConfigurationException {
	try {
      	    return new org.apache.xalan.xsltc.trax.TrAXFilter(templates);
    	}
	catch(TransformerConfigurationException e1) {
      	    if(_errorListener != null) {
                try {
          	    _errorListener.fatalError(e1);
          	    return null;
        	}
		catch( TransformerException e2) {
          	    new TransformerConfigurationException(e2);
        	}
      	    }
      	    throw e1;
    	}
    }

    /**
     * This method implements XSLTC's SourceLoader interface. It is used to
     * glue a TrAX URIResolver to the XSLTC compiler's Input and Import classes.
     *
     * @param href The URI of the document to load
     * @param context The URI of the currently loaded document
     * @param xsltc The compiler that resuests the document
     * @return An InputSource with the loaded document
     */
    public InputSource loadSource(String href, String context, XSLTC xsltc) {
	try {
	    final Source source = _uriResolver.resolve(href, context);
	    final InputSource input = getInputSource(xsltc, source);
	    return(input);
	}
	catch (TransformerConfigurationException e) {
	    return null;
	}
	catch (TransformerException e) {
	    return null;
	}
    }

}
