/* TransformerImpl.java --
   Copyright (C) 2004,2005,2006 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.transform;

import gnu.java.lang.CPStringBuilder;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.UnknownServiceException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.xml.namespace.QName;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
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.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import gnu.xml.dom.DomDoctype;
import gnu.xml.dom.DomDocument;
import gnu.xml.dom.ls.WriterOutputStream;

/**
 * The transformation process for a given stylesheet.
 *
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 */
class TransformerImpl
  extends Transformer
{

  final TransformerFactoryImpl factory;
  final Stylesheet stylesheet;
  URIResolver uriResolver;
  ErrorListener errorListener;
  Properties outputProperties;

  TransformerImpl(TransformerFactoryImpl factory,
                  Stylesheet stylesheet,
                  Properties outputProperties)
    throws TransformerConfigurationException
  {
    this.factory = factory;
    uriResolver = factory.userResolver;
    errorListener = factory.userListener;
    this.stylesheet = stylesheet;
    this.outputProperties = outputProperties;
    if (stylesheet != null)
      {
        // Set up parameter context for this transformer
        stylesheet.bindings.push(Bindings.PARAM);
      }
  }

  public void transform(Source xmlSource, Result outputTarget)
    throws TransformerException
  {
    // Get the source tree
    DOMSource source;
    synchronized (factory.resolver)
      {
        factory.resolver.setUserResolver(uriResolver);
        factory.resolver.setUserListener(errorListener);
        source = factory.resolver.resolveDOM(xmlSource, null, null);
      }
    Node context = source.getNode();
    Document doc = (context instanceof Document) ? (Document) context :
      context.getOwnerDocument();
    if (doc instanceof DomDocument)
      {
        // Suppress mutation events
        ((DomDocument) doc).setBuilding(true);
      }
    // Get the result tree
    Node parent = null, nextSibling = null;
    if (outputTarget instanceof DOMResult)
      {
        DOMResult dr = (DOMResult) outputTarget;
        parent = dr.getNode();
        nextSibling = dr.getNextSibling();

        Document rdoc = (parent instanceof Document) ? (Document) parent :
          parent.getOwnerDocument();
        if (rdoc instanceof DomDocument)
          {
            // Suppress mutation events and allow multiple root elements
            DomDocument drdoc = (DomDocument) rdoc;
            drdoc.setBuilding(true);
            drdoc.setCheckWellformedness(false);
          }
      }
    boolean created = false;
    // Transformation
    if (stylesheet != null)
      {
        if (parent == null)
          {
            // Create a new document to hold the result
            DomDocument resultDoc = new DomDocument();
            resultDoc.setBuilding(true);
            resultDoc.setCheckWellformedness(false);
            parent = resultDoc;
            created = true;
          }
        // Make a copy of the source node, and strip it
        context = context.cloneNode(true);
        strip(stylesheet, context);
        // XSLT transformation
        try
          {
            // Set output properties in the underlying stylesheet
            ((TransformerOutputProperties) outputProperties).apply();
            stylesheet.initTopLevelVariables(context);
            TemplateNode t = stylesheet.getTemplate(null, context, false);
            if (t != null)
              {
                stylesheet.current = context;
                t.apply(stylesheet, null, context, 1, 1, parent, nextSibling);
              }
          }
        catch (TransformerException e)
          {
            // Done transforming, reset document
            if (doc instanceof DomDocument)
              ((DomDocument) doc).setBuilding(false);
            throw e;
          }
      }
    else
      {
        // Identity transform
        Node clone = context.cloneNode(true);
        if (context.getNodeType() != Node.DOCUMENT_NODE)
          {
            Document resultDoc;
            if (parent == null)
              {
                // Create a new document to hold the result
                DomDocument rd = new DomDocument();
                rd.setBuilding(true);
                rd.setCheckWellformedness(false);
                parent = resultDoc = rd;
                created = true;
              }
            else
              {
                resultDoc = (parent instanceof Document) ?
                  (Document) parent :
                  parent.getOwnerDocument();
              }
            Document sourceDoc = context.getOwnerDocument();
            if (sourceDoc != resultDoc)
              clone = resultDoc.adoptNode(clone);
            if (nextSibling != null)
              parent.insertBefore(clone, nextSibling);
            else
              parent.appendChild(clone);
          }
        else
          {
            // Cannot append document to another tree
            parent = clone;
            created = true;
          }
      }
    String method = outputProperties.getProperty(OutputKeys.METHOD);
    int outputMethod = "html".equals(method) ? Stylesheet.OUTPUT_HTML :
      "text".equals(method) ? Stylesheet.OUTPUT_TEXT :
      Stylesheet.OUTPUT_XML;
    String encoding = outputProperties.getProperty(OutputKeys.ENCODING);
    String publicId = outputProperties.getProperty(OutputKeys.DOCTYPE_PUBLIC);
    String systemId = outputProperties.getProperty(OutputKeys.DOCTYPE_SYSTEM);
    String version = outputProperties.getProperty(OutputKeys.VERSION);
    boolean omitXmlDeclaration =
      "yes".equals(outputProperties.getProperty(OutputKeys.OMIT_XML_DECLARATION));
    boolean standalone =
      "yes".equals(outputProperties.getProperty(OutputKeys.STANDALONE));
    String mediaType = outputProperties.getProperty(OutputKeys.MEDIA_TYPE);
    String cdataSectionElements =
      outputProperties.getProperty(OutputKeys.CDATA_SECTION_ELEMENTS);
    boolean indent =
      "yes".equals(outputProperties.getProperty(OutputKeys.INDENT));
    if (created && parent instanceof DomDocument)
      {
        // Discover document element
        DomDocument resultDoc = (DomDocument) parent;
        Node root = resultDoc.getDocumentElement();
        // Add doctype if specified
        if (publicId != null || systemId != null)
          {
            if (root != null)
              {
                // We must know the name of the root element to
                // create the document type
                DocumentType doctype = new DomDoctype(resultDoc,
                                                      root.getNodeName(),
                                                      publicId,
                                                      systemId);
                resultDoc.insertBefore(doctype, root);
              }
          }
        resultDoc.setBuilding(false);
        resultDoc.setCheckWellformedness(true);
      }
    else if (publicId != null || systemId != null)
      {
        switch (parent.getNodeType())
          {
          case Node.DOCUMENT_NODE:
          case Node.DOCUMENT_FRAGMENT_NODE:
            Document resultDoc = (parent instanceof Document) ?
              (Document) parent :
              parent.getOwnerDocument();
            DOMImplementation impl = resultDoc.getImplementation();
            Node root = resultDoc.getDocumentElement();
            if (root != null)
              {
                DocumentType doctype =
                  impl.createDocumentType(root.getNodeName(),
                                          publicId,
                                          systemId);
                resultDoc.insertBefore(doctype, root);
              }
          }
      }
    if (version != null)
      parent.setUserData("version", version, stylesheet);
    if (omitXmlDeclaration)
      parent.setUserData("omit-xml-declaration", "yes", stylesheet);
    if (standalone)
      parent.setUserData("standalone", "yes", stylesheet);
    if (mediaType != null)
      parent.setUserData("media-type", mediaType, stylesheet);
    if (cdataSectionElements != null)
      {
        List list = new LinkedList();
        StringTokenizer st = new StringTokenizer(cdataSectionElements);
        while (st.hasMoreTokens())
          {
            String name = st.nextToken();
            String localName = name;
            String uri = null;
            String prefix = null;
            int ci = name.indexOf(':');
            if (ci != -1)
              {
                // Use namespaces defined on xsl:output node to resolve
                // namespaces for QName
                prefix = name.substring(0, ci);
                localName = name.substring(ci + 1);
                uri = stylesheet.output.lookupNamespaceURI(prefix);
              }
            list.add(new QName(uri, localName, prefix));
          }
        if (!list.isEmpty())
          {
            Document resultDoc = (parent instanceof Document) ?
              (Document) parent :
              parent.getOwnerDocument();
            convertCdataSectionElements(resultDoc, parent, list);
          }
      }
    if (indent)
      {
        if (created && parent instanceof DomDocument)
          {
            DomDocument domDoc = (DomDocument) parent;
            domDoc.setBuilding(true);
            domDoc.setCheckWellformedness(false);
          }
        parent.normalize();
        if (stylesheet != null)
          strip(stylesheet, parent);
        Document resultDoc = (parent instanceof Document) ?
          (Document) parent :
          parent.getOwnerDocument();
        reindent(resultDoc, parent, 0);
        if (created && parent instanceof DomDocument)
          {
            DomDocument domDoc = (DomDocument) parent;
            domDoc.setBuilding(false);
            domDoc.setCheckWellformedness(true);
          }
      }
    // Render result to the target device
    if (outputTarget instanceof DOMResult)
      {
        if (created)
          {
            DOMResult dr = (DOMResult) outputTarget;
            dr.setNode(parent);
            dr.setNextSibling(null);
          }
      }
    else if (outputTarget instanceof StreamResult)
      {
        StreamResult sr = (StreamResult) outputTarget;
        IOException ex = null;
        try
          {
            writeStreamResult(parent, sr, outputMethod, encoding);
          }
        catch (UnsupportedEncodingException e)
          {
            try
              {
                writeStreamResult(parent, sr, outputMethod, "UTF-8");
              }
            catch (IOException e2)
              {
                ex = e2;
              }
          }
        catch (IOException e)
          {
            ex = e;
          }
        if (ex != null)
          {
            if (errorListener != null)
              errorListener.error(new TransformerException(ex));
            else
              ex.printStackTrace(System.err);
          }
      }
    else if (outputTarget instanceof SAXResult)
      {
        SAXResult sr = (SAXResult) outputTarget;
        try
          {
            ContentHandler ch = sr.getHandler();
            LexicalHandler lh = sr.getLexicalHandler();
            if (lh == null && ch instanceof LexicalHandler)
              lh = (LexicalHandler) ch;
            SAXSerializer serializer = new SAXSerializer();
            serializer.serialize(parent, ch, lh);
          }
        catch (SAXException e)
          {
            if (errorListener != null)
              errorListener.error(new TransformerException(e));
            else
              e.printStackTrace(System.err);
          }
      }
  }

  /**
   * Strip whitespace from the source tree.
   */
  static boolean strip(Stylesheet stylesheet, Node node)
    throws TransformerConfigurationException
  {
    short nt = node.getNodeType();
    if (nt == Node.ENTITY_REFERENCE_NODE)
      {
        // Replace entity reference with its content
        Node parent = node.getParentNode();
        Node nextSibling = node.getNextSibling();
        Node child = node.getFirstChild();
        while (child != null)
          {
            Node next = child.getNextSibling();
            node.removeChild(child);
            if (nextSibling != null)
              parent.insertBefore(child, nextSibling);
            else
              parent.appendChild(child);
            child = next;
          }
        return true;
      }
    if (nt == Node.TEXT_NODE || nt == Node.CDATA_SECTION_NODE)
      {
        // Denormalize text into whitespace and non-whitespace nodes
        String text = node.getNodeValue();
        String[] tokens = tokenizeWhitespace(text);
        if (tokens.length > 1)
          {
            node.setNodeValue(tokens[0]);
            Node parent = node.getParentNode();
            Node nextSibling = node.getNextSibling();
            Document doc = node.getOwnerDocument();
            for (int i = 1; i < tokens.length; i++)
              {
                Node newChild = (nt == Node.CDATA_SECTION_NODE) ?
                  doc.createCDATASection(tokens[i]) :
                  doc.createTextNode(tokens[i]);
                if (nextSibling != null)
                  parent.insertBefore(newChild, nextSibling);
                else
                  parent.appendChild(newChild);
              }
          }
        return !stylesheet.isPreserved((Text) node, true);
      }
    else
      {
        Node child = node.getFirstChild();
        while (child != null)
          {
            boolean remove = strip(stylesheet, child);
            Node next = child.getNextSibling();
            if (remove)
              node.removeChild(child);
            child = next;
          }
      }
    return false;
  }

  /**
   * Tokenize the specified text into contiguous whitespace-only and
   * non-whitespace chunks.
   */
  private static String[] tokenizeWhitespace(String text)
  {
    int len = text.length();
    int start = 0, end = len - 1;
    // Find index of text start
    for (int i = 0; i < len; i++)
      {
        char c = text.charAt(i);
        boolean whitespace = (c == ' ' || c == '\n' || c == '\t' || c == '\r');
        if (whitespace)
          start++;
        else
          break;
      }
    if (start == end) // all whitespace
      return new String[] { text };
    // Find index of text end
    for (int i = end; i > start; i--)
      {
        char c = text.charAt(i);
        boolean whitespace = (c == ' ' || c == '\n' || c == '\t' || c == '\r');
        if (whitespace)
          end--;
        else
          break;
      }
    if (start == 0 && end == len - 1) // all non-whitespace
      return new String[] { text };
    // whitespace, then text, then whitespace
    String[] ret = (start > 0 && end < len - 1) ?
      new String[3] : new String[2];
    int i = 0;
    if (start > 0)
      ret[i++] = text.substring(0, start);
    ret[i++] = text.substring(start, end + 1);
    if (end < len - 1)
      ret[i++] = text.substring(end + 1);
    return ret;
  }

  /**
   * Obtain a suitable output stream for writing the result to,
   * and use the StreamSerializer to write the result tree to the stream.
   */
  void writeStreamResult(Node node, StreamResult sr, int outputMethod,
                         String encoding)
    throws IOException
  {
    OutputStream out = null;
    boolean created = false;
    try
      {
        out = sr.getOutputStream();
        if (out == null)
          {
            Writer writer = sr.getWriter();
            if (writer != null)
              out = new WriterOutputStream(writer);
          }
        if (out == null)
          {
            String systemId = sr.getSystemId();
            try
              {
                URL url = new URL(systemId);
                URLConnection connection = url.openConnection();
                // We need to call setDoInput(false), because our
                // implementation of the file protocol allows writing
                // (unlike Sun), but it will fail with a FileNotFoundException
                // if we also open the connection for input and the output
                // file doesn't yet exist.
                connection.setDoInput(false);
                connection.setDoOutput(true);
                out = connection.getOutputStream();
              }
            catch (MalformedURLException e)
              {
                out = new FileOutputStream(systemId);
              }
            catch (UnknownServiceException e)
              {
                URL url = new URL(systemId);
                out = new FileOutputStream(url.getPath());
              }
            created = true;
          }
        out = new BufferedOutputStream(out);
        StreamSerializer serializer =
          new StreamSerializer(outputMethod, encoding, null);
        if (stylesheet != null)
          {
            Collection celem = stylesheet.outputCdataSectionElements;
            serializer.setCdataSectionElements(celem);
          }
        serializer.serialize(node, out);
        out.flush();
      }
    finally
      {
        try
          {
            if (out != null && created)
              out.close();
          }
        catch (IOException e)
          {
            if (errorListener != null)
              {
                try
                  {
                    errorListener.error(new TransformerException(e));
                  }
                catch (TransformerException e2)
                  {
                    e2.printStackTrace(System.err);
                  }
              }
            else
              e.printStackTrace(System.err);
          }
      }
  }

  void copyChildren(Document dstDoc, Node src, Node dst)
  {
    Node srcChild = src.getFirstChild();
    while (srcChild != null)
      {
        Node dstChild = dstDoc.adoptNode(srcChild);
        dst.appendChild(dstChild);
        srcChild = srcChild.getNextSibling();
      }
  }

  public void setParameter(String name, Object value)
  {
    if (stylesheet != null)
      stylesheet.bindings.set(new QName(null, name), value, Bindings.PARAM);
  }

  public Object getParameter(String name)
  {
    if (stylesheet != null)
      return stylesheet.bindings.get(new QName(null, name), null, 1, 1);
    return null;
  }

  public void clearParameters()
  {
    if (stylesheet != null)
      {
        stylesheet.bindings.pop(Bindings.PARAM);
        stylesheet.bindings.push(Bindings.PARAM);
      }
  }

  public void setURIResolver(URIResolver resolver)
  {
    uriResolver = resolver;
  }

  public URIResolver getURIResolver()
  {
    return uriResolver;
  }

  public void setOutputProperties(Properties oformat)
    throws IllegalArgumentException
  {
    if (oformat == null)
      outputProperties.clear();
    else
      outputProperties.putAll(oformat);
  }

  public Properties getOutputProperties()
  {
    return (Properties) outputProperties.clone();
  }

  public void setOutputProperty(String name, String value)
    throws IllegalArgumentException
  {
    outputProperties.put(name, value);
  }

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

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

  public ErrorListener getErrorListener()
  {
    return errorListener;
  }

  static final String INDENT_WHITESPACE = "  ";

  /*
   * Apply indent formatting to the given tree.
   */
  void reindent(Document doc, Node node, int offset)
  {
    if (node.hasChildNodes())
      {
        boolean markupContent = false;
        boolean textContent = false;
        List children = new LinkedList();
        Node ctx = node.getFirstChild();
        while (ctx != null)
          {
            switch (ctx.getNodeType())
              {
              case Node.ELEMENT_NODE:
              case Node.PROCESSING_INSTRUCTION_NODE:
              case Node.DOCUMENT_TYPE_NODE:
                markupContent = true;
                break;
              case Node.TEXT_NODE:
              case Node.CDATA_SECTION_NODE:
              case Node.ENTITY_REFERENCE_NODE:
              case Node.COMMENT_NODE:
                textContent = true;
                break;
              }
            children.add(ctx);
            ctx = ctx.getNextSibling();
          }
        if (markupContent)
          {
            if (textContent)
              {
                // XXX handle mixed content differently?
              }
            int nodeType = node.getNodeType();
            if (nodeType == Node.DOCUMENT_NODE)
              {
                for (Iterator i = children.iterator(); i.hasNext(); )
                  {
                    ctx = (Node) i.next();
                    reindent(doc, ctx, offset);
                  }
              }
            else
              {
                CPStringBuilder buf = new CPStringBuilder();
                buf.append('\n');
                for (int i = 0; i < offset + 1; i++)
                  buf.append(INDENT_WHITESPACE);
                String ws = buf.toString();
                for (Iterator i = children.iterator(); i.hasNext(); )
                  {
                    ctx = (Node) i.next();
                    node.insertBefore(doc.createTextNode(ws), ctx);
                    reindent(doc, ctx, offset + 1);
                  }
                buf = new CPStringBuilder();
                buf.append('\n');
                for (int i = 0; i < offset; i++)
                  buf.append(INDENT_WHITESPACE);
                ws = buf.toString();
                node.appendChild(doc.createTextNode(ws));
              }
          }
      }
  }

  /**
   * Converts the text node children of any cdata-section-elements in the
   * tree to CDATA section nodes.
   */
  void convertCdataSectionElements(Document doc, Node node, List list)
  {
    if (node.getNodeType() == Node.ELEMENT_NODE)
      {
        boolean match = false;
        for (Iterator i = list.iterator(); i.hasNext(); )
          {
            QName qname = (QName) i.next();
            if (match(qname, node))
              {
                match = true;
                break;
              }
          }
        if (match)
          {
            Node ctx = node.getFirstChild();
            while (ctx != null)
              {
                if (ctx.getNodeType() == Node.TEXT_NODE)
                  {
                    Node cdata = doc.createCDATASection(ctx.getNodeValue());
                    node.replaceChild(cdata, ctx);
                    ctx = cdata;
                  }
                ctx = ctx.getNextSibling();
              }
          }
      }
    Node ctx = node.getFirstChild();
    while (ctx != null)
      {
        if (ctx.hasChildNodes())
          convertCdataSectionElements(doc, ctx, list);
        ctx = ctx.getNextSibling();
      }
  }

  boolean match(QName qname, Node node)
  {
    String ln1 = qname.getLocalPart();
    String ln2 = node.getLocalName();
    if (ln2 == null)
      return ln1.equals(node.getNodeName());
    else
      {
        String uri1 = qname.getNamespaceURI();
        String uri2 = node.getNamespaceURI();
        return (uri1.equals(uri2) && ln1.equals(ln2));
      }
  }

}
