/* GnomeTransformer.java - 
   Copyright (C) 2004 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package gnu.xml.libxmlj.transform;

import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;

import java.net.URL;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.Result;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;

import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Node;

import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;

import gnu.xml.libxmlj.dom.GnomeDocument;
import gnu.xml.libxmlj.sax.GnomeXMLReader;
import gnu.xml.libxmlj.util.NamedInputStream;
import gnu.xml.libxmlj.util.StandaloneLocator;
import gnu.xml.libxmlj.util.XMLJ;

/**
 * An implementation of {@link javax.xml.transform.Transformer} which
 * performs XSLT transformation using <code>libxslt</code>.
 *
 * @author Julian Scheid
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 */
public class GnomeTransformer
  extends Transformer
  implements Templates
{

  /**
   * The parameters added by the user via {@link setParameter()}.
   */
  private Map parameters;

  /**
   * The output properties set by the user.
   */
  private Properties outputProperties;

  /**
   * The URI resolver to use during transformation.
   */
  private URIResolver resolver;

  /**
   * The error listener for transformation errors.
   */
  private ErrorListener errorListener;

  /**
   * Handle to the source stylesheet.
   * This is a native pointer of type xsltStylesheetPtr.
   */
  private Object stylesheet;

  /**
   * Constructor.
   * @param source the XSLT stylesheet document source
   * @param resolver the resolver to use during transformation
   * @param errorListener the error listener for transformation errors
   */
  GnomeTransformer (Source source,
                    URIResolver resolver, 
                    ErrorListener errorListener) 
    throws TransformerConfigurationException
  {
    this.resolver = resolver;
    this.errorListener = errorListener;
    parameters = new HashMap ();
    outputProperties = new Properties ();
   
    if (source == null)
      {
        stylesheet = newStylesheet ();
      } 
    else if (source instanceof StreamSource)
      {
        try
          {
            StreamSource ss = (StreamSource) source;
            NamedInputStream in = XMLJ.getInputStream (ss);
            String systemId = ss.getSystemId ();
            String publicId = ss.getPublicId ();
            String base = XMLJ.getBaseURI (systemId);
            byte[] detectBuffer = in.getDetectBuffer ();
            if (detectBuffer == null)
              {
                String msg = "No document element";
                throw new TransformerConfigurationException (msg);
              }
            stylesheet = newStylesheetFromStream (in, detectBuffer, publicId,
                                                  systemId, base,
                                                  (resolver != null),
                                                  (errorListener != null));
          }
        catch (IOException e)
          {
            throw new TransformerConfigurationException (e);
          }
      }
    else if (source instanceof DOMSource)
      {
        DOMSource ds = (DOMSource) source;
        Node node = ds.getNode ();
        if (!(node instanceof GnomeDocument))
          {
            String msg = "Node is not a GnomeDocument";
            throw new TransformerConfigurationException (msg);
          }
        GnomeDocument doc = (GnomeDocument) node;
        stylesheet = newStylesheetFromDoc (doc);
      }
    else
      {
        String msg = "Source type not supported (" + source + ")";
        throw new TransformerConfigurationException (msg);
      }
  }
  
  /**
   * Copy constructor.
   */
  private GnomeTransformer (Object stylesheet,
                            URIResolver resolver, 
                            ErrorListener errorListener,
                            Map parameters,
                            Properties outputProperties)
  {
    this.stylesheet = stylesheet;
    this.resolver = resolver;
    this.errorListener = errorListener;
    this.parameters = parameters;
    this.outputProperties = outputProperties;
  }

  private native Object newStylesheet ()
    throws TransformerConfigurationException;

  private native Object newStylesheetFromStream (InputStream in,
                                                 byte[] detectBuffer,
                                                 String publicId,
                                                 String systemId,
                                                 String base,
                                                 boolean entityResolver,
                                                 boolean errorHandler)
    throws TransformerConfigurationException;

  private native Object newStylesheetFromDoc (GnomeDocument doc)
    throws TransformerConfigurationException;

  //--- Implementation of javax.xml.transform.Transformer follows.

  // Set, get and clear the parameters to use on transformation

  public synchronized void setParameter (String parameter, Object value)
  {
    parameters.put (parameter, value);
  } 

  public synchronized Object getParameter (String name)
  {
    return parameters.get (name);
  }

  public synchronized void clearParameters ()
  {
    parameters.clear ();
  }

  // Set and get the ErrorListener to use on transformation

  public void setErrorListener (ErrorListener listener)
  {
    this.errorListener = listener;
  } 

  public ErrorListener getErrorListener ()
  {
    return errorListener;
  }

  // Set and get the URIResolver to use on transformation

  public void setURIResolver (URIResolver resolver)
  {
    this.resolver = resolver;
  } 

  public URIResolver getURIResolver ()
  {
    return resolver;
  }

  // Set the output properties to use on transformation; get default
  // output properties and output properties specified in the
  // stylesheet or by the user.

  public void setOutputProperties (Properties outputProperties)
  {
    // Note: defensive copying
    this.outputProperties = new Properties (outputProperties);
  } 

  public void setOutputProperty (String name, String value)
  {
    outputProperties.setProperty (name, value);
  } 

  public Properties getOutputProperties ()
  {
    // Note: defensive copying
    return new Properties (this.outputProperties);
  }

  public String getOutputProperty (String name)
  {
    return outputProperties.getProperty (name);
  }

  // -- Templates --

  public Transformer newTransformer ()
  {
    return new GnomeTransformer (stylesheet, resolver, errorListener,
                                 new HashMap (parameters),
                                 new Properties (outputProperties));
  }

  // -- transform --

  /**
   * Transforms the given source and writes the result to the
   * given target.
   */
  public void transform (Source source, Result result)
    throws TransformerException
  {
    if (source instanceof StreamSource)
      {
        try
          {
            StreamSource ss = (StreamSource) source;
            NamedInputStream in = XMLJ.getInputStream (ss);
            String publicId = ss.getPublicId ();
            String systemId = ss.getSystemId ();
            String base = XMLJ.getBaseURI (systemId);
            byte[] detectBuffer = in.getDetectBuffer ();
            if (detectBuffer == null)
              {
                throw new TransformerException ("No document element");
              }
            if (result instanceof StreamResult)
              {
                OutputStream out = XMLJ.getOutputStream ((StreamResult) result);
                transformStreamToStream (in, detectBuffer, publicId, systemId,
                                         base, (resolver != null),
                                         (errorListener != null), out);
              }
            else if (result instanceof DOMResult)
              {
                DOMResult dr = (DOMResult) result;
                GnomeDocument ret =
                  transformStreamToDoc (in, detectBuffer, publicId, systemId,
                                        base, (resolver != null),
                                        (errorListener != null));
                dr.setNode (ret);
                dr.setSystemId (null);
              }
            else if (result instanceof SAXResult)
              {
                SAXResult sr = (SAXResult) result;
                transformStreamToSAX (in, detectBuffer, publicId, systemId,
                                      base, (resolver != null),
                                      (errorListener != null),
                                      getSAXContext (sr));
              }
            else
              {
                String msg = "Result type not supported (" + result + ")";
                throw new TransformerConfigurationException (msg);
              }
          }
        catch (IOException e)
          {
            throw new TransformerException (e);
          }
      }
    else if (source instanceof DOMSource)
      {
        DOMSource ds = (DOMSource) source;
        Node node = ds.getNode ();
        if (!(node instanceof GnomeDocument))
          {
            String msg = "Node is not a GnomeDocument (" + node + ")";
            throw new TransformerException (msg);
          }
        GnomeDocument doc = (GnomeDocument) node;
        if (result instanceof StreamResult)
          {
            try
              {
                OutputStream out = XMLJ.getOutputStream ((StreamResult) result);
                transformDocToStream (doc, out);
              }
            catch (IOException e)
              {
                throw new TransformerException (e);
              }
          }
        else if (result instanceof DOMResult)
          {
            DOMResult dr = (DOMResult) result;
            GnomeDocument ret = transformDocToDoc (doc);
            dr.setNode (ret);
            dr.setSystemId (null);
          }
        else if (result instanceof SAXResult)
          {
            SAXResult sr = (SAXResult) result;
            transformDocToSAX (doc, getSAXContext (sr));
          }
        else
          {
            String msg = "Result type not supported";
            throw new TransformerConfigurationException (msg);
          }
      }
    else
      {
        String msg = "Source type not supported";
        throw new TransformerConfigurationException (msg);
      }
  }

  private GnomeXMLReader getSAXContext (SAXResult result)
  {
    GnomeXMLReader ctx = new GnomeXMLReader ();
    ctx.setContentHandler (result.getHandler ());
    ctx.setLexicalHandler (result.getLexicalHandler ());
    if (errorListener != null)
      {
        ErrorHandler errorHandler =
          new ErrorListenerErrorHandler (errorListener);
        ctx.setErrorHandler (errorHandler);
      }
    if (resolver != null)
      {
        EntityResolver entityResolver =
          new URIResolverEntityResolver (resolver);
        ctx.setEntityResolver (entityResolver);
      }
    return ctx;
  }

  private native void transformStreamToStream (InputStream in,
                                               byte[] detectBuffer,
                                               String publicId,
                                               String systemId,
                                               String base,
                                               boolean entityResolver,
                                               boolean errorHandler,
                                               OutputStream out)
    throws TransformerException;

  private native GnomeDocument transformStreamToDoc (InputStream in,
                                                     byte[] detectBuffer,
                                                     String publicId,
                                                     String systemId,
                                                     String base,
                                                     boolean entityResolver,
                                                     boolean errorHandler)
    throws TransformerException;

  private native void transformStreamToSAX (InputStream in,
                                            byte[] detectBuffer,
                                            String publicId,
                                            String systemId,
                                            String base,
                                            boolean entityResolver,
                                            boolean errorHandler,
                                            GnomeXMLReader out)
    throws TransformerException;

  private native void transformDocToStream (GnomeDocument in,
                                            OutputStream out)
    throws TransformerException;

  private native GnomeDocument transformDocToDoc (GnomeDocument in)
    throws TransformerException;

  private native void transformDocToSAX (GnomeDocument in,
                                         GnomeXMLReader out)
    throws TransformerException;

  /*
   * Retrieve parameters as a string array.
   * This is a convenience method called from native code.
   */
  private String[] getParameterArray ()
  {
    String[] parameterArray = new String[parameters.size () * 2];
    int index = 0;
    for (Iterator it = parameters.keySet ().iterator ();
         it.hasNext ();
         ++index)
      {
        String parameterKey = (String) it.next ();
        String parameterValue = (String) parameters.get (parameterKey);
        parameterArray[index * 2 + 0] = parameterKey;
        parameterArray[index * 2 + 1] =
          "'" + ((parameterValue != null) ? parameterValue : "") + "'";
        // FIXME encode parameter value correctly for XPath
      }
    return parameterArray;
  }

  // -- Free xsltStylesheet handle --

  public void finalize ()
  {
    if (stylesheet != null)
      {
        free ();
        stylesheet = null;
      }
  }

  private native void free ();

  // -- Callbacks --

  private InputStream resolveEntity (String publicId, String systemId)
    throws TransformerException
  {
    if (resolver != null)
      {
        systemId = resolver.resolve (null, systemId).getSystemId ();
      }
    if (systemId == null)
      {
        return null;
      }
    try
      {
        URL url = new URL (systemId);
        return XMLJ.getInputStream (url);
      }
    catch (IOException e)
      {
        throw new TransformerException (e);
      }
  }
  
  private void setDocumentLocator (Object ctx, Object loc)
  {
  }

  private void warning (String message,
                        int lineNumber,
                        int columnNumber,
                        String publicId,
                        String systemId)
    throws TransformerException
  {
    if (errorListener == null)
      {
        return;
      }
    SourceLocator l = new StandaloneLocator (lineNumber,
                                             columnNumber,
                                             publicId,
                                             systemId);
    errorListener.warning (new TransformerException (message, l));
  }

  private void error (String message,
                      int lineNumber,
                      int columnNumber,
                      String publicId,
                      String systemId)
    throws TransformerException
  {
    if (errorListener == null)
      {
        return;
      }
    SourceLocator l = new StandaloneLocator (lineNumber,
                                             columnNumber,
                                             publicId,
                                             systemId);
    errorListener.error (new TransformerException (message, l));
  }
  
  private void fatalError (String message,
                           int lineNumber,
                           int columnNumber,
                           String publicId,
                           String systemId)
    throws TransformerException
  {
    if (errorListener == null)
      {
        return;
      }
    SourceLocator l = new StandaloneLocator (lineNumber,
                                             columnNumber,
                                             publicId,
                                             systemId);
    errorListener.fatalError (new TransformerException (message, l));
  }
  
}
