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

import org.w3c.dom.*;
import java.util.*;
import java.net.*;
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import org.apache.xml.serialize.*;
import org.apache.xalan.serialize.*;
import org.apache.xalan.templates.ElemTemplate;
import org.apache.xalan.templates.OutputProperties;
import javax.xml.transform.OutputKeys;
import org.apache.xalan.xpath.xml.FormatterToXML;
import org.apache.xalan.xpath.xml.FormatterToHTML;
import org.apache.xalan.xpath.xml.FormatterToText;
import org.apache.xalan.xpath.xml.FormatterToDOM;
import org.apache.xalan.res.XSLTErrorResources;

/**
 * <meta name="usage" content="general"/> 
 * Binary representation of a stylesheet -- use the {@link org.apache.xalan.xslt.XSLTProcessor} ProcessStylesheet
 * method to create a StylesheetRoot and improve performance for a stylesheet performing multiple transformations.
 * Also required for XSLTProcessor to function as SAX DocumentHandler.
 */
public class StylesheetRoot extends Stylesheet
{
  
  private String m_liaisonClassUsedToCreate = null;
  private org.apache.xalan.templates.StylesheetRoot m_sRootObject;
  
  /**
   * Uses an XSL stylesheet document.
   * @param processor  The XSLTProcessor implementation.
   * @param baseIdentifier The file name or URL for the XSL stylesheet.
   * @exception TransformerConfigurationException thrown 
   */
  public StylesheetRoot(XSLTEngineImpl processor,
                        String baseIdentifier)
    throws TransformerConfigurationException
  { 
		super(null);
    m_sRootObject = new org.apache.xalan.templates.StylesheetRoot(processor.getTransformerFactory().getErrorListener()); 
    if (processor.getXMLProcessorLiaison()!= null)
      m_liaisonClassUsedToCreate = ((Object)processor.getXMLProcessorLiaison()).getClass().getName();
    
  }  


  /**
   * Constructor using an org.apache.xalan.templates.StylesheetRoot.
   * 
   * @param s an org.apache.xalan.templates.StylesheetRoot object
   */
  public StylesheetRoot(org.apache.xalan.templates.StylesheetRoot s)    
  { 
		super(null);
    m_sRootObject = s;     
  }
  
  /**
   * Return the org.apache.xalan.templates.StylesheetRoot object
   * associated with this stylesheet root.
   *  
   * @return an org.apache.xalan.templates.StylesheetRoot object
   */
  public org.apache.xalan.templates.StylesheetRoot getObject()
  {
    return m_sRootObject;
  }  
  
  /**
   * Transform the XML source tree and place the output in the result tree target.
   * This method uses a new XSLTProcessor instance to track the running state.
   * @param xmlSource  The XML input source tree.
   * @param outputTarget The output result tree.
   * @exception SAXException
   * @see org.apache.xalan.xslt.XSLTProcessor#process(org.apache.xalan.xslt.XSLTInputSource, org.apache.xalan.xslt.XSLTInputSource, org.apache.xalan.xslt.XSLTResultTarget)
   */
  public void process( XSLTInputSource xmlSource,
                       XSLTResultTarget outputTarget)
    throws SAXException,
           MalformedURLException,
           FileNotFoundException,
           IOException
  {
    XSLTProcessor iprocessor =
                              (null != m_liaisonClassUsedToCreate) ?
                              new XSLTProcessorFactory().getProcessorUsingLiaisonName(m_liaisonClassUsedToCreate)
                              : new XSLTProcessorFactory().getProcessor();
    process(iprocessor, iprocessor.getSourceTreeFromInput(xmlSource), outputTarget);
    // System.out.println("Number counters made: "+
    //                   ((XSLTEngineImpl)iprocessor).getCountersTable().m_countersMade);
  }

  /**
   * Transform the XML source tree and place the output in the result tree target.
   * Use this version of the StylesheetRoot process() method if you have used an
   * XSLTProcessor object to set a stylesheet parameter. That object is now the iprocessor parameter.
   * @param iprocessor  The XSLTProcessor that will track the running state.
   * @param xmlSource  The XML input source tree.
   * @param outputTarget The output result tree.
   * @exception SAXException
   * @see org.apache.xalan.xslt.XSLTProcessor#process(org.apache.xalan.xslt.XSLTInputSource, org.apache.xalan.xslt.XSLTInputSource, org.apache.xalan.xslt.XSLTResultTarget)
   */
  public void process( XSLTProcessor iprocessor, XSLTInputSource xmlSource,
                       XSLTResultTarget outputTarget)
    throws SAXException,
           MalformedURLException,
           FileNotFoundException,
           IOException
  {
    process(iprocessor, iprocessor.getSourceTreeFromInput(xmlSource), outputTarget);
  }

  /**
   * Transform the XML source tree (a DOM Node) and place the output in the result tree target.
   * This is a convenience method. You can also use a DOM Node to instantiate an XSLTInputSource object,
   * and call {@link #process(org.apache.xalan.xslt.XSLTProcessor, org.apache.xalan.xslt.XSLTInputSource, org.apache.xalan.xslt.XSLTResultTarget)} or
   * {@link org.apache.xalan.xslt.XSLTProcessor#process(org.apache.xalan.xslt.XSLTInputSource, org.apache.xalan.xslt.XSLTInputSource, org.apache.xalan.xslt.XSLTResultTarget)}.
   * @param iprocessor  The processor that will track the running state.
   * @param sourceTree  The input source tree in the form of a DOM Node.
   * @param outputTarget The output result tree.
   * @exception SAXException
   */
  public void process( XSLTProcessor iprocessor, Node sourceTree,
                       XSLTResultTarget outputTarget)
    throws SAXException,
           MalformedURLException,
           FileNotFoundException,
           IOException
  {
    XSLTEngineImpl processor = (XSLTEngineImpl)iprocessor; // TODO: Check for class cast exception
		//checkInit(processor);
    synchronized(processor)
    {
      //processor.switchLiaisonsIfNeeded(sourceTree, outputTarget.getNode());

      processor.setStylesheet(this);

      OutputStream ostream = null;

      try
      {
        // Double-check the node to make sure it matches the processor liaison.
        //processor.getXMLProcessorLiaison().checkNode(sourceTree);

        // Needs work: We have to put the extension namespaces
        // into the liaison's table.  We wouldn't have to do this
        // if the stylesheet handled it's own extensions, which
        // I'll fix on a later date.
  /*      Enumeration keys = m_extensionNamespaces.keys();
        while(keys.hasMoreElements())
        {
          Object key = keys.nextElement();
          // System.out.println("Putting ext namespace: "+key);
          processor.getExecContext().addExtensionNamespace ((String)key,
                                                            (ExtensionFunctionHandler)m_extensionNamespaces.get(key));
        }*/

        // Find the root pattern in the XSL.
        ElemTemplate rootRule = m_sRootObject.getTemplateComposed(processor.getTransformer().getXPathContext(), sourceTree, null, -1, false);
                               //this.findTemplate(processor, sourceTree, sourceTree);

        if(null == rootRule)
        {
          rootRule = m_sRootObject.getDefaultRootRule();
        }

        DocumentHandler docHandler = outputTarget.getDocumentHandler();

        OutputFormat formatter = getOutputFormat();

        if(null != outputTarget.getEncoding())
          formatter.setEncoding(outputTarget.getEncoding());

        if(null != docHandler)
        {
          processor.setDocumentHandler(docHandler);
        }
        else if(null != outputTarget.getByteStream())
        {
         /* if (!(processor.getXMLProcessorLiaison()..getIndent() < 0))
          {
            // This is to get around differences between Xalan and Xerces.
            // Xalan uses -1 as default for no indenting, Xerces uses 0.
            // So we just bump up the indent value here because we will
            // subtract from it at output time (FormatterToXML.init());
            formatter.setIndent(processor.m_parserLiaison.getIndent() + 1);
          }*/
          processor.setDocumentHandler(makeSAXSerializer(outputTarget.getByteStream(),
                                                               formatter));
        }
        else if(null != outputTarget.getCharacterStream())
        {
        /*  if (!(processor.m_parserLiaison.getIndent() < 0))
          {
            formatter.setIndent(processor.m_parserLiaison.getIndent() + 1);
          }*/
          processor.setDocumentHandler(makeSAXSerializer(outputTarget.getCharacterStream(),
                                                               formatter));
        }
        else if(null != outputTarget.getFileName())
        {
          /*if (!(processor.m_parserLiaison.getIndent() < 0))
          {
            formatter.setIndent(processor.m_parserLiaison.getIndent() + 1);
          }*/
          ostream = new FileOutputStream(outputTarget.getFileName());
          processor.setDocumentHandler( makeSAXSerializer(ostream, formatter));
        }
        else if(null != outputTarget.getNode())
        {
          ParserAdapter handler = new ParserAdapter(new org.apache.xerces.parsers.SAXParser());
          // Patch from Costin Manolache
//          if( "org.apache.xalan.xpath.dtm.DTMLiaison".equals( processor.getXMLProcessorLiaison().getClass().getName()))
//            processor.error(XSLTErrorResources.ER_CANT_USE_DTM_FOR_OUTPUT); //Can't use a DTMLiaison for an output DOM node... pass a org.apache.xalan.xpath.xdom.XercesLiaison instead!");
          
          switch(outputTarget.getNode().getNodeType())
          {
          case Node.DOCUMENT_NODE:            
            handler.setContentHandler(new FormatterToDOM((Document)outputTarget.getNode()).getSerializerObject());
            processor.setDocumentHandler(handler);
            break;
          case Node.DOCUMENT_FRAGMENT_NODE:
            handler.setContentHandler(new FormatterToDOM(outputTarget.getNode().getOwnerDocument(), // PR:DMAN4M6PK5 Submitted by:<bk@viae.de>
                                                       (DocumentFragment)outputTarget.getNode()).getSerializerObject());
            processor.setDocumentHandler(handler);
            break;
          case Node.ELEMENT_NODE:
            handler.setContentHandler(new FormatterToDOM(outputTarget.getNode().getOwnerDocument(), // PR:DMAN4M6PK5 Submitted by:<bk@viae.de>
                                                       (Element)outputTarget.getNode()).getSerializerObject());
            processor.setDocumentHandler(handler);
            break;
          default:
            m_sRootObject.error(XSLTErrorResources.ER_CAN_ONLY_OUTPUT_TO_ELEMENT); //"Can only output to an Element, DocumentFragment, Document, or PrintWriter.");
          }
        }
        else
        {
          ParserAdapter handler = new ParserAdapter(new org.apache.xerces.parsers.SAXParser());
          outputTarget.setNode(processor.getXMLProcessorLiaison().createDocument());
          handler.setContentHandler(new FormatterToDOM((Document)outputTarget.getNode()).getSerializerObject());
          processor.setDocumentHandler(handler);
        }

       // processor.resetCurrentState(sourceTree);
       // processor.m_rootDoc = sourceTree;

        if(null != processor.m_diagnosticsPrintWriter)
        {
          processor.diag("=============================");
          processor.diag("Transforming...");
          processor.pushTime(sourceTree);
        }

       // processor.getVarStack().pushContextMarker();
      //  try
      //  {
      //    processor.resolveTopLevelParams();
      //  }
      //  catch(Exception e)
      //  {
      //    throw new SAXException(XSLMessages.createMessage(XSLTErrorResources.ER_PROCESS_ERROR, null), e); //"StylesheetRoot.process error", e);
      //  }

        processor.getTransformer().getResultTreeHandler().startDocument();

        // Output the action of the found root rule.  All processing
        // occurs from here.  buildResultFromTemplate is highly recursive.
        rootRule.execute(processor.getTransformer(), sourceTree, null);

         processor.getTransformer().getResultTreeHandler().endDocument();

        // Reset the top-level params for the next round.
        // processor.m_topLevelParams = new Vector();

        if(null != processor.m_diagnosticsPrintWriter)
        {
          processor.displayDuration("transform", sourceTree);
        }
      }
      catch(TransformerException te)
      {
        throw new SAXException(te);
      }  
      finally
      {
        if (null != ostream)
        {
          ostream.close();
        }
      }
    }

  }
  
  /**
   * Creates a compatible SAX serializer for the specified writer
   * and output format. If the output format is missing, the default
   * is an XML format with UTF8 encoding.
   *
   * @param writer The writer
   * @param format The output format
   * @return A compatible SAX serializer
   */
  public DocumentHandler makeSAXSerializer( Writer writer, OutputFormat format )
    throws IOException, SAXException 
  {
    DocumentHandler handler;
    if ( format == null )
    {
      format = new OutputFormat( "xml", "UTF-8", false );
      handler = null;
    }
    else 
    {
      handler = new ParserAdapter(new org.apache.xerces.parsers.SAXParser());
      OutputProperties props = m_sRootObject.getOutputComposed();
      
      if ( format.getMethod().equalsIgnoreCase( "html" ) )
      {
        FormatterToHTML serializer = new FormatterToHTML(writer);
        serializer.getSerializerObject().setOutputFormat(props.getProperties());
        ((ParserAdapter)handler).setContentHandler(serializer.getSerializerObject());
      }
      else if ( format.getMethod().equalsIgnoreCase( "xml" ) )
      {
        FormatterToXML serializer = new FormatterToXML(writer);
        serializer.getSerializerObject().setOutputFormat(props.getProperties());
        ((ParserAdapter)handler).setContentHandler(serializer.getSerializerObject());
      }
      else if ( format.getMethod().equalsIgnoreCase( "text" ) )
      {
        FormatterToText serializer = new FormatterToText(writer); 
        ((ParserAdapter)handler).setContentHandler(serializer.getSerializerObject());
      }
      else
      {
        handler = null;
      }
    }
    
    if(null == handler)
    {
      String method = format.getMethod();
      org.apache.xml.serialize.SerializerFactory factory = org.apache.xml.serialize.SerializerFactory.getSerializerFactory(method);
      org.apache.xml.serialize.Serializer serializer = factory.makeSerializer(writer, format);
      handler = serializer.asDocumentHandler();
    }

    return handler;
  }
  
  /**
   * Creates a compatible SAX serializer for the specified output stream
   * and output format. If the output format is missing, the default
   * is an XML format with UTF8 encoding.
   *
   * @param ostream The output stream.
   * @param format The output format
   * @return A compatible SAX serializer
   */
  public DocumentHandler makeSAXSerializer( OutputStream ostream, OutputFormat format )
    throws UnsupportedEncodingException, IOException, SAXException
  {
    DocumentHandler handler;
    OutputProperties props;
        
    if ( format == null )
    {
      props = new OutputProperties();
      handler = null;
    }
    else
    { 
      handler = new ParserAdapter(new org.apache.xerces.parsers.SAXParser());
      props = m_sRootObject.getOutputComposed();
      if ( format.getMethod().equalsIgnoreCase( "html" ) )
      {
        FormatterToHTML serializer = new FormatterToHTML(ostream);
        serializer.getSerializerObject().setOutputFormat(props.getProperties());
        ((ParserAdapter)handler).setContentHandler(serializer.getSerializerObject());
      }
      else if ( format.getMethod().equalsIgnoreCase( "xml" ) )
      {
        FormatterToXML serializer = new FormatterToXML(ostream);
        serializer.getSerializerObject().setOutputFormat(props.getProperties());
        ((ParserAdapter)handler).setContentHandler(serializer.getSerializerObject());
      }
      else if ( format.getMethod().equalsIgnoreCase( "text" ) )
      {
        String encoding = format.getEncoding();
        if(null == encoding)
        {
          try
          {
            encoding = System.getProperty("file.encoding");
            encoding = (null != encoding) ?
                       org.apache.xalan.serialize.Encodings.convertJava2MimeEncoding( encoding ) : "ASCII";
            if(null == encoding)
            {
              encoding = "ASCII";
            }
          }
          catch(SecurityException se)
          {
            encoding = "ASCII";
          }
        }

        //this.m_encoding =   encoding;

        String javaEncoding = org.apache.xalan.serialize.Encodings.convertMime2JavaEncoding(encoding);

        Writer w = new OutputStreamWriter( ostream, javaEncoding );
        ((ParserAdapter)handler).setContentHandler(new FormatterToText(w).getSerializerObject());
      }
      else if ( format.getMethod().equalsIgnoreCase( "xhtml" ) )
      {
        handler = new XMLSerializer(ostream, format);
        //handler = Serializer.makeSAXSerializer(ostream, format);
      }
      else
      {
        handler = new XMLSerializer(ostream, format);
        //handler = Serializer.makeSAXSerializer(ostream, format);
      }
    }
    if(null == handler)
    {
      String method = props.getProperty(OutputKeys.METHOD);
      org.apache.xml.serialize.SerializerFactory factory = org.apache.xml.serialize.SerializerFactory.getSerializerFactory(method);
      org.apache.xml.serialize.Serializer serializer = factory.makeSerializer(ostream, format);
      handler = serializer.asDocumentHandler();
    }

    return handler;
  }

  /**
   * Creates a compatible SAX serializer for the specified output stream
   * and output format. If the output format is missing, the default
   * is an XML format with UTF8 encoding.
   *
   * @param ostream The output stream.
   * @return A compatible SAX serializer
   */
  public DocumentHandler getSAXSerializer( OutputStream ostream )
    throws UnsupportedEncodingException, IOException, SAXException
  {
   return makeSAXSerializer(ostream, getOutputFormat());
  }
  
  /**
   * Get a new OutputFormat object according to the xsl:output attributes.
   */
  public OutputFormat getOutputFormat()
  {
    OutputProperties outputFormat = m_sRootObject.getOutputComposed();
    if (outputFormat == null)
      return null;
    OutputFormat formatter = new OutputFormat(outputFormat.getProperty(OutputKeys.METHOD),
                                              outputFormat.getProperty(OutputKeys.ENCODING),
                                              OutputProperties.getBooleanProperty(OutputKeys.INDENT, outputFormat.getProperties()));
    formatter.setDoctype(outputFormat.getProperty(OutputKeys.DOCTYPE_PUBLIC), 
                         outputFormat.getProperty(OutputKeys.DOCTYPE_SYSTEM));
    formatter.setOmitXMLDeclaration(OutputProperties.getBooleanProperty(OutputKeys.OMIT_XML_DECLARATION, outputFormat.getProperties()));
    formatter.setStandalone(OutputProperties.getBooleanProperty(OutputKeys.STANDALONE, outputFormat.getProperties()));
    formatter.setMediaType(outputFormat.getProperty(OutputKeys.MEDIA_TYPE));
    formatter.setVersion(outputFormat.getProperty(OutputKeys.VERSION));
    // This is to get around differences between Xalan and Xerces.
    // Xalan uses -1 as default for no indenting, Xerces uses 0.
    // So we just bump up the indent value here because we will
    // subtract from it at output time (FormatterToXML.init());
   // if (getOutputIndent())
   //   formatter.setIndent(formatter.getIndent()+1);

    
    return formatter;
  }
  
  /** 
   * Get the encoding string that was specified in the stylesheet. 
   */
  public String getOutputEncoding()
  {
    return m_sRootObject.getOutputComposed().getProperty(OutputKeys.ENCODING);
  }

  /** 
   * Get the media-type string that was specified in the stylesheet. 
   */
  public String getOutputMediaType() 
  { 
    return m_sRootObject.getOutputComposed().getProperty(OutputKeys.MEDIA_TYPE); 
  }
  
  /** 
   * Get the output method that was specified in the stylesheet. 
   */
  public String getOutputMethod() 
  { 
    return m_sRootObject.getOutputComposed().getProperty(OutputKeys.METHOD); 
  }
  
  /**
   * Get the base identifier with which this stylesheet is associated.
   */
  public String getBaseIdentifier()
  {
    return m_sRootObject.getBaseIdentifier();
  }

  /**
   * Get the base identifier with which this stylesheet is associated.
   */
  public void setBaseIdentifier(String baseIdent)
  {
    m_sRootObject.setHref(baseIdent);
  }
  
}
