/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id$
 */

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;

/**
 * What it does: this sample creates multiple threads 
 * and runs them. Each thread will be assigned a particular
 * stylesheet. Each thread will run multiple transformations on
 * various xml files using its own transformer.
 * 
 * Note: the flavors used by the transformations can be
 * configured below by changing SOURCE_FLAVOR and
 * RESULT_FLAVOR. XSLTC can also be used by changing
 * USE_XSLTC.
 * 
 * Description of files included with the sample:
 * 
 * foo0.xsl and foo1.xsl: foo0.xsl is the stylesheet used 
 * for transformations by thread #0, foo1.xsl is the stylesheet
 * used by thread #1.
 * 
 * foo0.xml and foo1.xml: foo0.xml and foo1.xml are the XML
 * files used for the first and second transformations done
 * by each thread.
 * 
 * Output will go to *.out files in the TransformThread directory.
 * 
 * @author <a href="mailto:richcao@ca.ibm.com">Richard Cao</a>
 */
public class TransformThread implements Runnable
{    
  // Flavors
  public final static int STREAM = 0;
  public final static int SAX = 1;
  public final static int DOM = 2;
  public final static String[] flavorNames =
    new String[] { "Stream", "SAX", "DOM" };

  // Configurable options
  private static int SOURCE_FLAVOR = STREAM;
    // private static int SOURCE_FLAVOR = SAX;
    // private static int SOURCE_FLAVOR = DOM;
    
  private static int RESULT_FLAVOR = STREAM;
    // private static int RESULT_FLAVOR = SAX;
    // private static int RESULT_FLAVOR = DOM;
  
  private static boolean USE_XSLTC = false;
    // private static boolean useXSLTC = true;


  // Threads
  private final static int NUM_THREADS = 2;
  private static TransformThread INSTANCES[] = null;
  protected Thread m_thread = null;
  
  // Number of transformations per thread
  private final static int NUM_TRANSFORMATIONS = 2;

  // Files names and extensions
  private final static String XML_IN_BASE = "foo";
  private final static String XML_EXT = ".xml";
  private final static String XSL_IN_BASE = "foo";
  private final static String XSL_EXT = ".xsl";
  private final static String FILE_OUT_BASE = "foo_";
  private final static String FILE_OUT_EXT = ".out";

  // Thread identifier
  private int m_thrdNum = -1;

  private InputStream[] m_inStream = null;

  private Source[] m_inSource = null;
  private Result[] m_outResult = null;

  // One Transformer per thread since Transformers
  // are _NOT_ thread-safe
  private Transformer m_transformer = null;

  /** Constructs the TransformThread object
   * @param thrdNum a unique identifier for this object
   */
  public TransformThread(int thrdNum)
  {
    m_thrdNum = thrdNum;

    m_inStream = new InputStream[NUM_TRANSFORMATIONS];
    m_inSource = new Source[NUM_TRANSFORMATIONS];
    m_outResult = new Result[NUM_TRANSFORMATIONS];

    try
    {
      initSource();
      initResult();

      // ensure xslSourceURI is a valid URI
      final String xslSourceFileName = XSL_IN_BASE + m_thrdNum + XSL_EXT;
      final String xslSourceURI = (new File(xslSourceFileName)).toURL().toString();
      StreamSource xslSource = new StreamSource(xslSourceFileName);
      xslSource.setSystemId(xslSourceURI);
      
      // Initialize the transformer
      m_transformer =
        TransformerFactory.newInstance().newTransformer(xslSource);
      m_thread = new Thread(this);
    }
    catch (Throwable e)
    {
      e.printStackTrace();
      System.exit(1);
    }
  }

  /** Initialize the results (m_outResult) according
   * to RESULT_FLAVOR
   */
  private void initResult()
  {
    try 
    {
      for (int i = 0; i < NUM_TRANSFORMATIONS; i++)
      {
        switch (RESULT_FLAVOR) 
        {
          case STREAM :
              OutputStream outStream =
                new FileOutputStream(FILE_OUT_BASE + "thread_" 
                  + m_thrdNum + "_transformation_" + i + FILE_OUT_EXT);
                
              m_outResult[i] = new StreamResult(outStream);
            break;

          case SAX :
            DefaultHandler defaultHandler = new DefaultHandler();
            m_outResult[i] = new SAXResult(defaultHandler);
            break;

          case DOM :
            m_outResult[i] = new DOMResult();
            break;
        }  
      }
    }
    catch (Exception e)
    { 
      e.printStackTrace();
      System.exit(1);
    }
  }

  /** Initialize the sources (m_inSource) according
   * to SOURCE_FLAVOR
   */
  private void initSource()
  {
    try 
    {
      for (int i = 0; i < NUM_TRANSFORMATIONS; i++)
      {
        // Ensure we get a valid URI
        final String sourceXMLURI = (new File(XML_IN_BASE + i + XML_EXT)).toURL().toString();
        
        // Open for input
        m_inStream[i] = new FileInputStream(XML_IN_BASE + i + XML_EXT);
        
        switch (SOURCE_FLAVOR)
        {
          case STREAM :
            m_inSource[i] = new StreamSource(m_inStream[i]);
            break;
  
          case SAX :
            m_inSource[i] = new SAXSource(new InputSource(m_inStream[i]));
            break;
  
          case DOM :
            try
            {
              DocumentBuilderFactory dfactory =
                DocumentBuilderFactory.newInstance();
  
              // Must always setNamespaceAware when 
              // building xsl stylesheets
              dfactory.setNamespaceAware(true);
              m_inSource[i] =
                new DOMSource(dfactory.newDocumentBuilder().parse(m_inStream[i]));
            }
            catch (Exception e)
            {
              e.printStackTrace();
            }
            break;
        }
  
        if (m_inSource[i] != null)
        {
          // If we don't do this, the transformer 
          // won't know how to resolve relative URLs 
          // in the stylesheet.
          m_inSource[i].setSystemId(sourceXMLURI);
        }
      }
    }
    catch (Exception e)
    { 
      e.printStackTrace();
      System.exit(1);
    }
  }

  /**
   * @see java.lang.Runnable#run()
   */
  public void run()
  {
    try
    {
      // Perform multiple transformations with the same
      // transformer
      for (int i = 0; i < NUM_TRANSFORMATIONS; i++)
      {
        m_transformer.transform(m_inSource[i], m_outResult[i]);
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
      System.exit(1);
    }
  }

  /** Creates thread instances
   */
  private static void initThreads()
  {
    INSTANCES = new TransformThread[NUM_THREADS];

    for (int count = 0; count < NUM_THREADS; count++)
    {
      INSTANCES[count] = new TransformThread(count);
    }
  }
  
  /** Sets the appropriate system properties if XSLTC is
   * to be used (according to USE_XSLTC)
   */
  private static void initSystemProperties()
  {
    if (USE_XSLTC) 
    {
      // Set the TransformerFactory system property if XSLTC is required
      // Note: To make this sample more flexible, load properties from a properties file.
      // The setting for the Xalan Transformer is "org.apache.xalan.processor.TransformerFactoryImpl"
      String key = "javax.xml.transform.TransformerFactory";
      String value = "org.apache.xalan.xsltc.trax.TransformerFactoryImpl";
      Properties props = System.getProperties();
      props.put(key, value); 
      System.setProperties(props);
    }
  }

  /**
   * Usage:
   * java TransformThread
   */
  public static void main(String argv[])
  {
    try
    { 
      initSystemProperties();
      initThreads();

      for (int count = 0; count < NUM_THREADS; count++)
      {
        INSTANCES[count].m_thread.start();
      }
    }
    catch (Throwable e)
    {
      e.printStackTrace();
      System.exit(1);
    }
  }
}
