/*
 * 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$
 */
package org.apache.qetest.xslwrapper;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Hashtable;
import java.util.Properties;

import org.apache.xalan.xsltc.cmdline.Compile;
import org.apache.xalan.xsltc.cmdline.Transform;

/**
 * Implementation of TransformWrapper that uses the command line 
 * wrappers of XSLTC - interim use only.
 *
 * <b>Important!</b> This wrapper is for temporary use only: we 
 * should really focus on getting XSLTC to use JAXP 1.1 as it's 
 * interface, and then (as needed) write another custom wrapper 
 * that calls XSLTC API's directly.
 * 
 * @author Shane Curcuru
 * @version $Id$
 */
public class XsltcMainWrapper extends TransformWrapperHelper
{

    private static final char CLEAN_CHAR = '_';
    protected static final String XSLTC_COMPILER_CLASS = "org.apache.xalan.xsltc.cmdline.Compile";
    protected static final String XSLTC_RUNTIME_CLASS = "org.apache.xalan.xsltc.cmdline.Transform";

    private static final char FILE_SEPARATOR = System.getProperty("file.separator").charAt(0);
    
    /**
     * Cached copy of newProcessor() Hashtable.
     */
    protected Hashtable newProcessorOpts = null;


    /**
     * Get a general description of this wrapper itself.
     *
     * @return Uses XSLTC command line to perform transforms
     */
    public String getDescription()
    {
        return "Uses XSLTC command line to perform transforms";
    }


    /**
     * Get a specific description of the wrappered processor.  
     *
     * @return specific description of the underlying processor or 
     * transformer implementation: this should include both the 
     * general product name, as well as specific version info.  If 
     * possible, should be implemented without actively creating 
     * an underlying processor.
     */
    public Properties getProcessorInfo()
    {
        Properties p = TraxWrapperUtils.getTraxInfo();
        p.put("traxwrapper.method", "streams");
        p.put("traxwrapper.desc", getDescription());
        return p;
    }


    /**
     * Actually create/initialize an underlying processor or factory.
     * 
     * Effectively a no-op; returns null.  Just forces a reset().
     *
     * @param options Hashtable of options, unused.
     *
     * @return (Object)getProcessor() as a side-effect, this will 
     * be null if there was any problem creating the processor OR 
     * if the underlying implementation doesn't use this
     *
     * @throws Exception covers any underlying exceptions thrown 
     * by the actual implementation
     */
    public Object newProcessor(Hashtable options) throws Exception
    {
        newProcessorOpts = options;
        //@todo do we need to do any other cleanup?
        reset(false);
        return null;
    }


    /**
     * Transform supplied xmlName file with the stylesheet in the 
     * xslName file into a resultName file.
     *
     * Names are assumed to be local path\filename references, and 
     * will be converted to URLs as needed for any underlying 
     * processor implementation.
     *
     * @param xmlName local path\filename of XML file to transform
     * @param xslName local path\filename of XSL stylesheet to use
     * @param resultName local path\filename to put result in
/* TWA - temp hack; use results dir to get path for to use for a dir to put
the translets
*/
     /*
     * @return array of longs denoting timing of only these parts of 
     * our operation: IDX_OVERALL, IDX_XSLBUILD, IDX_TRANSFORM
     *
     * @throws Exception any underlying exceptions from the 
     * wrappered processor are simply allowed to propagate; throws 
     * a RuntimeException if any other problems prevent us from 
     * actually completing the operation
     */
    public long[] transform(String xmlName, String xslName, String resultName)
        throws Exception
    {
        long startTime = 0;
        long xslBuild = 0;
        long transform = 0;

        // java org.apache.xalan.xlstc.cmdline.Compile play1.xsl
        // java org.apache.xalan.xlstc.cmdline.Transform play.xml play1 >stdout

        // Timed: compile stylesheet class from XSL file
//        String[] args1 = new String[2];
/* TWA - commented out the following for short-term
Problem when local path/file is being used, somewhere a file://// prefix is 
being appended to the filename and xsltc can't find the file even with the -u
So I strip off the protocol prefix and pass the local path/file
        args1[0] = "-u"; // Using URIs
        args1[1] = xslName;
*/
/* TWA - temporay hack to construct and pass a directory for translets */
        int last = resultName.lastIndexOf(FILE_SEPARATOR);
        String tdir = resultName.substring(0, last);
        int next = tdir.lastIndexOf(FILE_SEPARATOR);
        String transletsdirName = tdir.substring(0, next);

        String[] args1 = new String[3];
        args1[0] = "-d";
        args1[1] = transletsdirName;
        args1[2] = xslName;
        int idx = xslName.indexOf("file:////");
        if (idx != -1){
               xslName = new String(xslName.substring(8));
               args1[2] = xslName;
        }
        startTime = System.currentTimeMillis();
        /// Transformer transformer = factory.newTransformer(new StreamSource(xslName));
        Compile.main(args1);
        xslBuild = System.currentTimeMillis() - startTime;

        // Verify output file was created
        // WARNING: assumption of / here, which means we assume URI not local path - needs revisiting
        int nameStart = xslName.lastIndexOf(FILE_SEPARATOR) + 1;
        String baseName = xslName.substring(nameStart);
        int extStart = baseName.lastIndexOf('.');
        if (extStart > 0) {
            baseName = baseName.substring(0, extStart);
        }
        
        // Replace illegal class name chars with underscores.
        StringBuffer sb = new StringBuffer(baseName.length());
        char charI = baseName.charAt(0);
        sb.append(Character.isJavaLetter(charI) ? charI :CLEAN_CHAR);
        for (int i = 1; i < baseName.length(); i++) {
            charI = baseName.charAt(i);
            sb.append(Character.isJavaLetterOrDigit(charI) ? charI :CLEAN_CHAR);
        }
        baseName = sb.toString();
        
        // Untimed: Apply any parameters needed
        // applyParameters(transformer);

        // Timed: read/build xml, transform, and write results

/* TWA - I don't see how this could have worked, there is no -s option in DefaultRun
so passing it in the args2 caused usage messages to be output.
Also, we shouldn't use the -u option unless we are really using URLs, 
I'm just trying to get it to work with local path/files. With or without the 
-u option, the files were getting a file://// prefix with caused them to be not found
        String[] args2 = new String[3];
        args2[0] = "-s"; // Don't allow System.exit
        args2[1] = "-u"; // Using URIs
        args2[2] = xmlName;
        args2[3] = baseName;    // Just basename of the .class file, without the .class
                                // Note that . must be on CLASSPATH to work!
*/
        String[] args2 = new String[2];
        args2[0] = xmlName;
        int idx2 = xmlName.indexOf("file:////");
        if (idx2 != -1){
               args2[0] = new String(xmlName.substring(8));
        }
        args2[1] = baseName;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PrintStream newSystemOut = new PrintStream(baos);
        PrintStream saveSystemOut = System.out;
        startTime = System.currentTimeMillis();
        // transformer.transform(new StreamSource(xmlName), new StreamResult(resultName));
        try
        {
            // Capture System.out into our byte array
            System.setOut(new PrintStream(baos));
            Transform.main(args2);
        }
        finally
        {
            // Be sure to restore System stuff!
            System.setOut(saveSystemOut);
        }
        // Writing data should really go in separate timing loop
        FileOutputStream fos = new FileOutputStream(resultName);
        fos.write(baos.toByteArray());
        fos.close();
        transform = System.currentTimeMillis() - startTime;

        File compiledXslClass = new File(baseName + ".class");
        //@todo WARNING! We REALLY need to clean up the name*.class files when we're done!!! -sc
        // TWA - we should probably use the -d option to put them in a desired directory first
        // I commented out the delete, to see if the translets were getting compiled
//        if (compiledXslClass.exists())
//             compiledXslClass.delete();

        long[] times = getTimeArray();
        times[IDX_OVERALL] = xslBuild + transform;
        times[IDX_XSLBUILD] = xslBuild;
        times[IDX_TRANSFORM] = transform;
        return times;
    }


    /**
     * Pre-build/pre-compile a stylesheet.
     *
     * Although the actual mechanics are implementation-dependent, 
     * most processors have some method of pre-setting up the data 
     * needed by the stylesheet itself for later use in transforms.
     * In TrAX/javax.xml.transform, this equates to creating a 
     * Templates object.
     * 
     * Sets isStylesheetReady() to true if it succeeds.  Users can 
     * then call transformWithStylesheet(xmlName, resultName) to 
     * actually perform a transformation with this pre-built 
     * stylesheet.
     *
     * @param xslName local path\filename of XSL stylesheet to use
     *
     * @return array of longs denoting timing of only these parts of 
     * our operation: IDX_OVERALL, IDX_XSLBUILD
     *
     * @throws Exception any underlying exceptions from the 
     * wrappered processor are simply allowed to propagate; throws 
     * a RuntimeException if any other problems prevent us from 
     * actually completing the operation
     *
     * @see #transformWithStylesheet(String xmlName, String resultName)
     */
    public long[] buildStylesheet(String xslName) throws Exception
    {
        throw new RuntimeException("buildStylesheet not implemented yet!");
    }


    /**
     * Transform supplied xmlName file with a pre-built/pre-compiled 
     * stylesheet into a resultName file.  
     *
     * User must have called buildStylesheet(xslName) beforehand,
     * obviously.
     * Names are assumed to be local path\filename references, and 
     * will be converted to URLs as needed.
     *
     * @param xmlName local path\filename of XML file to transform
     * @param resultName local path\filename to put result in
     *
     * @return array of longs denoting timing of only these parts of 
     * our operation: IDX_OVERALL, IDX_XSLBUILD, IDX_TRANSFORM
     *
     * @throws Exception any underlying exceptions from the 
     * wrappered processor are simply allowed to propagate; throws 
     * a RuntimeException if any other problems prevent us from 
     * actually completing the operation; throws an 
     * IllegalStateException if isStylesheetReady() == false.
     *
     * @see #buildStylesheet(String xslName)
     */
    public long[] transformWithStylesheet(String xmlName, String resultName)
        throws Exception
    {
        if (!isStylesheetReady())
            throw new IllegalStateException("transformWithStylesheet() when isStylesheetReady() == false");

        throw new RuntimeException("transformWithStylesheet not implemented yet!");
    }


    /**
     * Transform supplied xmlName file with a stylesheet found in an 
     * xml-stylesheet PI into a resultName file.
     *
     * Names are assumed to be local path\filename references, and 
     * will be converted to URLs as needed.  Implementations will 
     * use whatever facilities exist in their wrappered processor 
     * to fetch and build the stylesheet to use for the transform.
     *
     * @param xmlName local path\filename of XML file to transform
     * @param resultName local path\filename to put result in
     *
     * @return array of longs denoting timing of only these parts of 
     * our operation: IDX_OVERALL, IDX_XSLREAD (time to find XSL
     * reference from the xml-stylesheet PI), IDX_XSLBUILD, (time 
     * to then build the Transformer therefrom), IDX_TRANSFORM
     *
     * @throws Exception any underlying exceptions from the 
     * wrappered processor are simply allowed to propagate; throws 
     * a RuntimeException if any other problems prevent us from 
     * actually completing the operation
     */
    public long[] transformEmbedded(String xmlName, String resultName)
        throws Exception
    {
        throw new RuntimeException("transformEmbedded not implemented yet!");
    }


    /**
     * Reset our parameters and wrapper state, and optionally 
     * force creation of a new underlying processor implementation.
     *
     * This always clears our built stylesheet and any parameters 
     * that have been set.  If newProcessor is true, also forces a 
     * re-creation of our underlying processor as if by calling 
     * newProcessor().
     *
     * @param newProcessor if we should reset our underlying 
     * processor implementation as well
     */
    public void reset(boolean newProcessor)
    {
        super.reset(newProcessor); // clears indent and parameters
        m_stylesheetReady = false;
        // builtTemplates = null;
        if (newProcessor)
        {
            try
            {
                newProcessor(newProcessorOpts);
            }
            catch (Exception e)
            {
                //@todo Hmm: what should we do here?
            }
        }
    }


    /**
     * Apply a single parameter to a Transformer.
     *
     * WARNING: Not implemented! 27-Apr-01
     *
     * @param passThru to be passed to each applyParameter() method 
     * call - for TrAX, you might pass a Transformer object.
     * @param namespace for the parameter, may be null
     * @param name for the parameter, should not be null
     * @param value for the parameter, may be null
     */
    protected void applyParameter(Object passThru, String namespace, 
                                  String name, Object value)
    {
        /* WARNING: Not implemented! 27-Apr-01 */
    }
}
