
import com.ispsoft.upx.manager.xml.*;

import java.io.*;
import java.util.Stack;
import javax.xml.transform.*;
import org.apache.xalan.transformer.TransformerImpl;
import javax.xml.transform.dom.*;
import javax.xml.transform.sax.*;
import javax.xml.transform.stream.*;
import org.apache.xalan.templates.Constants;
import org.apache.xalan.templates.ElemTemplate;
import org.apache.xalan.templates.ElemTemplateElement;
import org.apache.xalan.templates.ElemTextLiteral;
import org.apache.xerces.dom.*;
import org.apache.xerces.framework.XMLParser;
import org.apache.xerces.parsers.*;
import org.apache.xml.serialize.*;
import org.apache.xpath.XPathAPI;
import org.apache.xpath.axes.ContextNodeList;
import org.w3c.dom.*;
import org.w3c.dom.traversal.NodeIterator;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import org.apache.xalan.trace.*;

public class ParseWorkflow
extends DefaultHandler
{
//    public final static String WORKFLOW_FILE = "file:///c:/cao/upx/xmlstylesheet/workflow/TestTrace.xsl";
    public final static String WORKFLOW_FILE = "file:///c:/cao/upx/xmlstylesheet/workflow/IPSecIntranetService.xsl";
//    public final static String WORKFLOW_FILE = "file:///c:/cao/upx/test.xsl";

    private static final String DEFAULT_PARSER_NAME = "org.apache.xerces.parsers.SAXParser";

    private static boolean setValidation    = false; //defaults
    private static boolean setNameSpaces    = true;
    private static boolean setSchemaSupport = true;

    static Stack hasNoData = new Stack();

    //
    // Data
    //

    /** Print writer. */
    protected PrintWriter out;

    /** Canonical output. */
    protected boolean canonical;

    //
    // Constructors
    //

    /** Default constructor. */
    public ParseWorkflow(boolean canonical) throws UnsupportedEncodingException {
        this(null, canonical);
    }

    protected ParseWorkflow(String encoding, boolean canonical) throws UnsupportedEncodingException {
        if (encoding == null) {
            encoding = "UTF8";
        }
        out = new PrintWriter(new OutputStreamWriter(System.out, encoding));
        this.canonical = canonical;
    }

    //
    // DocumentHandler methods
    //

    /** Processing instruction. */
    public void processingInstruction(String target, String data) {
//        out.print("<?");
//        out.print(target);
//        if (data != null && data.length() > 0) {
//            out.print(' ');
//            out.print(data);
//        }
//        out.print("?>");
//        out.flush();
    }

    /** Start document. */
    public void startDocument() {
    }

    /** Start element. */
    public void startElement(String uri, String local, String raw, Attributes attrs) {
        if (!hasNoData.empty()) {
            Boolean noData = (Boolean)(hasNoData.pop());
            if (noData.booleanValue())
                out.print(">");
            hasNoData.push(new Boolean(false));
        }
        out.print('<');
        out.print(raw);
//        out.print('>');
        out.flush();
        hasNoData.push(new Boolean(true));
    }

    /** Characters. */
    public void characters(char ch[], int start, int length) {
//        out.print(normalize(new String(ch, start, length)));
//        out.flush();
    }

    /** Ignorable whitespace. */
    public void ignorableWhitespace(char ch[], int start, int length) {
//        characters(ch, start, length);
//        out.flush();
    }

    /** End element. */
    public void endElement(String uri, String local, String raw) {
        Boolean noData = (Boolean)(hasNoData.pop());
        if (noData.booleanValue()) {
            out.print("/>");
        } else {
            out.print("</");
            out.print(raw);
            out.print('>');
        }
        out.flush();

    } // endElement(String)

//    //
//    // ErrorHandler methods
//    //
//
//    /** Warning. */
//    public void warning(SAXParseException ex) {
//        System.err.println("[Warning] "+
//                           getLocationString(ex)+": "+
//                           ex.getMessage());
//    }
//
//    /** Error. */
//    public void error(SAXParseException ex) {
//        System.err.println("[Error] "+
//                           getLocationString(ex)+": "+
//                           ex.getMessage());
//    }
//
//    /** Fatal error. */
//    public void fatalError(SAXParseException ex) throws SAXException {
//        System.err.println("[Fatal Error] "+
//                           getLocationString(ex)+": "+
//                           ex.getMessage());
//        throw ex;
//    }

    /** Returns a string of the location. */
    private String getLocationString(SAXParseException ex) {
        StringBuffer str = new StringBuffer();

        String systemId = ex.getSystemId();
        if (systemId != null) {
            int index = systemId.lastIndexOf('/');
            if (index != -1)
                systemId = systemId.substring(index + 1);
            str.append(systemId);
        }
        str.append(':');
        str.append(ex.getLineNumber());
        str.append(':');
        str.append(ex.getColumnNumber());

        return str.toString();
    }

    //
    // Protected static methods
    //

//    /** Normalizes the given string. */
//    protected String normalize(String s) {
//        StringBuffer str = new StringBuffer();
//
//        int len = (s != null) ? s.length() : 0;
//        for (int i = 0; i < len; i++) {
//            char ch = s.charAt(i);
//            switch (ch) {
//                case '<':
//                    str.append("&lt;");
//                    break;
//
//                case '>':
//                    str.append("&gt;");
//                    break;
//
//                case '&':
//                    str.append("&amp;");
//                    break;
//
//                case '"':
//                    str.append("&quot;");
//                    break;
//
//                case '\r':
//                case '\n':
//                    if (canonical) {
//                        str.append("&#");
//                        str.append(Integer.toString(ch));
//                        str.append(';');
//                        break;
//                    }
//
//                default: // else, default append char
//                    str.append(ch);
//
//            }
//        }
//        return str.toString();
//    }


    public static void main(String[] args) {
        try {
            TransformerFactory tfactory = TransformerFactory.newInstance();

            // check if this factory support SAX features.
            if (tfactory.getFeature(SAXSource.FEATURE)) {
                SAXTransformerFactory stfactory = ((SAXTransformerFactory) tfactory);
                TransformerHandler handler = stfactory.newTransformerHandler(new SAXSource(new InputSource(WORKFLOW_FILE)));
                Transformer transformer = handler.getTransformer();

//                transformer.setParameter("WorkflowType", "Normal");
//                transformer.setParameter("requestId", "req000");

                TraceWF traceWF = new TraceWF(handler);
                Locator locator = new LocatorImpl();
                traceWF.setDocumentLocator(locator);

                // Cast the Transformer object to TransformerImpl.
                if (transformer instanceof TransformerImpl) {
                    TransformerImpl transformerImpl = (TransformerImpl) transformer;
                    // Register the TraceListener with a TraceManager associated
                    // with the TransformerImpl.
                    TraceManager trMgr = transformerImpl.getTraceManager();
                    trMgr.addTraceListener(traceWF);
                }

                Document resultDoc = new DocumentImpl();
                Result result = new SAXResult(new ParseWorkflow(false));
                handler.setResult(result);

                // Create a reader, and set it's ContentHandler to be
                // the TransformerHandler.
                XMLReader reader = null;

                reader = XMLReaderFactory.createXMLReader();

                reader.setContentHandler(traceWF);
                InputSource inputSrc = new InputSource(args[0]);
                reader.parse(inputSrc);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}


class TraceWF
implements ContentHandler, org.apache.xalan.trace.TraceListener
{
    TransformerHandler handler;
    Locator locator;
    Stack elements;

    //
    // Constants
    //

    /** Default parser name. */
    private static final String DEFAULT_PARSER_NAME = "org.apache.xerces.parsers.SAXParser";


    private static boolean setValidation    = false; //defaults
    private static boolean setNameSpaces    = true;
    private static boolean setSchemaSupport = true;

    //
    // Data
    //

    /** Print writer. */
    protected PrintWriter out;

    /** Canonical output. */
    protected boolean canonical = false;

    public TraceWF(TransformerHandler handler)
    {
        this.handler = handler;
        try {
            out = new PrintWriter(new OutputStreamWriter(System.out, "UTF8"));
        } catch (Exception ex) {
            out = new PrintWriter(new OutputStreamWriter(System.out));
        }
        elements = new Stack();
    }

    public void setDocumentLocator(Locator locator)
    {
        this.locator = locator;
    }
    public void startDocument() throws SAXException
    {
        out.print("<root>");
        out.flush();
        handler.startDocument();
//        if (!canonical) {
//            out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
//        }
    }
    public void endDocument() throws SAXException
    {
        handler.endDocument();
        out.print("</root>");
        out.flush();
    }
    public void startPrefixMapping(String prefix, String uri) throws SAXException
    {
        handler.startPrefixMapping(prefix, uri);
    }
    public void endPrefixMapping(String prefix) throws SAXException
    {
        handler.endPrefixMapping(prefix);
    }
    public void startElement(String namespaceURI, String localName, String qName, Attributes attrs) throws SAXException
    {
        handler.startElement(namespaceURI, localName, qName, attrs);
//        out.print('<');
//        out.print(qName);
//        if (attrs != null) {
//            int len = attrs.getLength();
//            for (int i = 0; i < len; i++) {
//                out.print(' ');
//                out.print(attrs.getQName(i));
//                out.print("=\"");
//                out.print(normalize(attrs.getValue(i)));
//                out.print('"');
//            }
//        }
//        out.print('>');
//        out.flush();
    }
    public void endElement(String namespaceURI, String localName, String qName) throws SAXException
    {
        handler.endElement(namespaceURI, localName, qName);
//        out.print("</");
//        out.print(qName);
//        out.print('>');
//        out.flush();
    }
    public void characters(char[] ch, int start, int length) throws SAXException
    {
//        handler.characters(ch, start, length);
//
//        out.print(normalize(new String(ch, start, length)));
//        out.flush();
    }
    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
    {
//        handler.ignorableWhitespace(ch, start, length);

//        characters(ch, start, length);
//        out.flush();
    }
    public void processingInstruction(String target, String data) throws SAXException
    {
//        handler.processingInstruction(target, data);
//
//        out.print("<?");
//        out.print(target);
//        if (data != null && data.length() > 0) {
//            out.print(' ');
//            out.print(data);
//        }
//        out.print("?>");
//        out.flush();
    }
    public void skippedEntity(String name) throws SAXException
    {
        handler.skippedEntity(name);
    }

//    /** Normalizes the given string. */
//    protected String normalize(String s) {
//        StringBuffer str = new StringBuffer();
//
//        int len = (s != null) ? s.length() : 0;
//        for (int i = 0; i < len; i++) {
//            char ch = s.charAt(i);
//            switch (ch) {
//                case '<':
//                    str.append("&lt;");
//                    break;
//
//                case '>':
//                    str.append("&gt;");
//                    break;
//
//                case '&':
//                    str.append("&amp;");
//                    break;
//
//                case '"':
//                    str.append("&quot;");
//                    break;
//
//                case '\r':
//                case '\n':
//                    if (canonical) {
//                        str.append("&#");
//                        str.append(Integer.toString(ch));
//                        str.append(';');
//                        break;
//                    }
//
//                default: // else, default append char
//                    str.append(ch);
//            }
//        }
//        return str.toString();
//    } // normalize(String):String

    public void trace(org.apache.xalan.trace.TracerEvent e)
    {
        switch (e.m_styleNode.getXSLToken())
        {
            case Constants.ELEMNAME_TEXTLITERALRESULT:
                break;

            case Constants.ELEMNAME_TEMPLATE:
                ElemTemplate et = (ElemTemplate) e.m_styleNode;
                if (!ParseWorkflow.hasNoData.empty()) {
                    Boolean noData = (Boolean)(ParseWorkflow.hasNoData.pop());
                    if (noData.booleanValue())
                        out.print(">");
                    ParseWorkflow.hasNoData.push(new Boolean(false));
                }

                out.print("<TEMPLATE");
                if (et.getLineNumber() > 0)
                {
                    out.print(" Line=\""+et.getLineNumber()+"\"");
                }

                if (null != et.getName())
                {
                    out.print(" Name=\""+et.getName().toString()+"\"/>");
                    break;
                }

                if (null != e.m_mode)
                {
                    out.print(" Mode=\""+e.m_mode.getLocalName()+"\"");
                }

                if (null != et.getMatch())
                {
                    out.print(" Match=\""+et.getMatch().getPatternString()+"\"");
                }
                out.print("/>");
                break;

            default:
        }
        out.flush();
    }

    public void selected(org.apache.xalan.trace.SelectionEvent e)
    throws javax.xml.transform.TransformerException
    {
//        if ("select".equals(e.m_attributeName))
//        {
//            Element select = traceToDoc.createElement("Select");
//            select.appendChild(traceToDoc.createTextNode(e.m_xpath.getPatternString()));
//            getCurrentNode().appendChild(select);
//        }
    }

    public void generated(org.apache.xalan.trace.GenerateEvent e)
    {
//        if (e.m_eventtype == e.EVENTTYPE_STARTDOCUMENT)
//        {
//        }
//        else if (e.m_eventtype == e.EVENTTYPE_ENDDOCUMENT)
//        {
//        }
//        else if (e.m_eventtype == e.EVENTTYPE_STARTELEMENT)
//        {
//            elements.push(getCurrentNode().appendChild(traceToDoc.createElement(e.m_name)));
//        }
//        else if (e.m_eventtype == e.EVENTTYPE_ENDELEMENT)
//        {
//            Element currentNode = getCurrentNode();
//            Attributes attrs = e.m_atts;
//            for (int i=0; attrs != null && i < attrs.getLength(); i++)
//                currentNode.setAttribute(attrs.getQName(i), attrs.getValue(i));
//
//            elements.pop();
//        }
    }
}
