/*
* Copyright (c) 2004-2005, The Hong Kong University of Science and Technology (HKUST)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright notice,
*     this list of conditions,the authors and the following disclaimer.
*   * Redistributions in binary form must reproduce the above copyright notice,
*     this list of conditions,the authors and the following disclaimer in
*     the documentation and/or other materials provided with the distribution.
*   * Neither the name of the university nor the names of its
*     contributors may be used to endorse or promote products derived from
*     this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS 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 COPYRIGHT OWNER OR 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.
*
*/
/*
 * SDGEN: a data generator for Bisque
 * @Author: Bingsheng He (saven@cs.ust.hk)
 * @Date:28/3/3005
 * @Version: 1.0
 * @Function: XML parser based on SAX.
 */



import java.io.PrintWriter;

import org.xml.sax.Attributes;
import org.xml.sax.Parser;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.ParserAdapter;
import org.xml.sax.helpers.ParserFactory;
import java.util.*;


public class OutputParser
    extends DefaultHandler {

    //by saven
    public Topology topo;
    public String query;
    int mode=0;
    Vector oFiles;
    int numNodes=0;
    String fileName="";
    int tmpid=-1;



     /** Default constructor. */
    public OutputParser() {
    	topo=new Topology();
    	query="";
    	oFiles=new Vector();

    } // <init>()



    // default settings

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

    /** Default repetition (1). */
    protected static final int DEFAULT_REPETITION = 1;

    /** Default namespaces support (true). */
    protected static final boolean DEFAULT_NAMESPACES = true;

    /** Default namespace prefixes (false). */
    protected static final boolean DEFAULT_NAMESPACE_PREFIXES = false;

    /** Default validation support (false). */
    protected static final boolean DEFAULT_VALIDATION = false;

    /** Default Schema validation support (false). */
    protected static final boolean DEFAULT_SCHEMA_VALIDATION = false;

    /** Default Schema full checking support (false). */
    protected static final boolean DEFAULT_SCHEMA_FULL_CHECKING = false;

    /** Default dynamic validation support (false). */
    protected static final boolean DEFAULT_DYNAMIC_VALIDATION = false;

    /** Default memory usage report (false). */
    protected static final boolean DEFAULT_MEMORY_USAGE = false;

    /** Default "tagginess" report (false). */
    protected static final boolean DEFAULT_TAGGINESS = false;

    //
    // Data
    //

    /** Number of elements. */
    protected long fElements;

    /** Number of attributes. */
    protected long fAttributes;

    /** Number of characters. */
    protected long fCharacters;

    /** Number of ignorable whitespace characters. */
    protected long fIgnorableWhitespace;

    /** Number of characters of tags. */
    protected long fTagCharacters;

    /** Number of other content characters for the "tagginess" calculation. */
    protected long fOtherCharacters;

    //
    // Constructors
    //



    //
    // Public methods
    //

    /** Prints the results. */
    public void printResults(PrintWriter out, String uri, long time,
                             long memory, boolean tagginess,
                             int repetition) {

        // filename.xml: 631 ms (4 elems, 0 attrs, 78 spaces, 0 chars)
        out.print(uri);
        out.print(": ");
        if (repetition == 1) {
            out.print(time);
        }
        else {
            out.print(time);
            out.print('/');
            out.print(repetition);
            out.print('=');
            out.print(time/repetition);
        }
        out.print(" ms");
        if (memory != Long.MIN_VALUE) {
            out.print(", ");
            out.print(memory);
            out.print(" bytes");
        }
        out.print(" (");
        out.print(fElements);
        out.print(" elems, ");
        out.print(fAttributes);
        out.print(" attrs, ");
        out.print(fIgnorableWhitespace);
        out.print(" spaces, ");
        out.print(fCharacters);
        out.print(" chars)");
        if (tagginess) {
            out.print(' ');
            long totalCharacters = fTagCharacters + fOtherCharacters
                                 + fCharacters + fIgnorableWhitespace;
            long tagValue = fTagCharacters * 100 / totalCharacters;
            out.print(tagValue);
            out.print("% tagginess");
        }
        out.println();
        out.flush();

        //by saven
        System.out.println("Query: "+query);
        topo.print();
        for(int i=0;i<oFiles.size();i++)
        	System.out.println(oFiles.elementAt(i));

    } // printResults(PrintWriter,String,long)

    //
    // ContentHandler methods
    //

    /** Start document. */
    public void startDocument() throws SAXException {

        fElements            = 0;
        fAttributes          = 0;
        fCharacters          = 0;
        fIgnorableWhitespace = 0;
        fTagCharacters       = 0;

    } // startDocument()

    /** Start element. */
    public void startElement(String uri, String local, String raw,
                             Attributes attrs) throws SAXException {

        fElements++;
        fTagCharacters++; // open angle bracket
        fTagCharacters += raw.length();
        mode=0;
        //System.out.println("we are here:"+raw+"#");
        if(raw.equals("outputQuery"))
        {
        	mode=2;//get the SQL
        }
        else if(raw.equals("node"))
        if (attrs != null) {
            int attrCount = attrs.getLength();
            fAttributes += attrCount;
            if(attrCount==4)
            {
            	topo.AddNode(Integer.parseInt(attrs.getValue(0)),Integer.parseInt(attrs.getValue(1)),Integer.parseInt(attrs.getValue(2)));
            	oFiles.add(attrs.getValue(3));

            }
        } //for xrun
       // else
        if(raw.equals("topology"))
        {
        	//System.out.println("we are here1:"+raw+"#");
        	if (attrs != null) {
            int attrCount = attrs.getLength();
            fAttributes += attrCount;
            if(attrCount==1)
            {
            	String xrunFile=attrs.getValue(0);
            	OutputParser counter = new OutputParser();
				XMLReader parser = null;
				try {
	                parser = XMLReaderFactory.createXMLReader(DEFAULT_PARSER_NAME);
	            }
	            catch (Exception e) {
	                System.err.println("error: Unable to instantiate parser ("+DEFAULT_PARSER_NAME+")");
	            }
	            parser.setContentHandler(counter);
		        parser.setErrorHandler(counter);
                try {
                    parser.parse(xrunFile);

                }
                catch (SAXParseException e) {
                    // ignore
                }
                catch (Exception e) {
                    System.err.println("error: Parse error occurred - "+e.getMessage());
                    Exception se = e;
                    if (e instanceof SAXException) {
                        se = ((SAXException)e).getException();
                    }
                    if (se != null)
                      se.printStackTrace(System.err);
                    else
                      e.printStackTrace(System.err);

	            }
	            for(int i=0;i<counter.topo.nodes.size();i++)
	            {
	            	Node n=(Node)(counter.topo.nodes.elementAt(i));
	            	topo.AddNode(n.id,n.x,n.y);
	            }
	            System.out.println("we are here:"+topo.nodes.size());


            }
        }
        }

        //for deal with xrun file
        if(raw.equals("mote"))
        {
        	//get the id and the postion
        	if (attrs != null) {
        		tmpid=Integer.parseInt(attrs.getValue(0));
        	}
        }
        else
        if(raw.equals("param"))
        {
        	//System.out.println(raw);
        	if (attrs != null)
        	if(attrs.getValue(0).equals("position"))
        	{
        		String position=attrs.getValue(1);
        		String []tokens=position.split(",");
        		topo.AddNode(tmpid,Double.parseDouble(tokens[0]),Double.parseDouble(tokens[1]));

        	}
        }

        fTagCharacters++; // close angle bracket

    } // startElement(String,String,StringAttributes)

    /** Characters. */
    public void characters(char ch[], int start, int length)
        throws SAXException {

        fCharacters += length;
        /*if(mode==1) //get the fileName;
       // for(int i=start;i<start+length;i++)
        	fileName=fileName+String.copyValueOf(ch,start,length);
        else*/ if(mode==2)
        	query=query+String.copyValueOf(ch,start,length);



    } // characters(char[],int,int);

    /** Ignorable whitespace. */
    public void ignorableWhitespace(char ch[], int start, int length)
        throws SAXException {

        fIgnorableWhitespace += length;

    } // ignorableWhitespace(char[],int,int);

    /** Processing instruction. */
    public void processingInstruction(String target, String data)
        throws SAXException {
        fTagCharacters += 2; // "<?"
        fTagCharacters += target.length();
        if (data != null && data.length() > 0) {
            fTagCharacters++; // space
            fOtherCharacters += data.length();
        }
        fTagCharacters += 2; // "?>"
    } // processingInstruction(String,String)

    //
    // ErrorHandler methods
    //

    /** Warning. */
    public void warning(SAXParseException ex) throws SAXException {
        printError("Warning", ex);
    } // warning(SAXParseException)

    /** Error. */
    public void error(SAXParseException ex) throws SAXException {
        printError("Error", ex);
    } // error(SAXParseException)

    /** Fatal error. */
    public void fatalError(SAXParseException ex) throws SAXException {
        printError("Fatal Error", ex);
        //throw ex;
    } // fatalError(SAXParseException)

    //
    // Protected methods
    //

    /** Prints the error message. */
    protected void printError(String type, SAXParseException ex) {

        System.err.print("[");
        System.err.print(type);
        System.err.print("] ");
        if (ex== null) {
            System.out.println("!!!");
        }
        String systemId = ex.getSystemId();
        if (systemId != null) {
            int index = systemId.lastIndexOf('/');
            if (index != -1)
                systemId = systemId.substring(index + 1);
            System.err.print(systemId);
        }
        System.err.print(':');
        System.err.print(ex.getLineNumber());
        System.err.print(':');
        System.err.print(ex.getColumnNumber());
        System.err.print(": ");
        System.err.print(ex.getMessage());
        System.err.println();
        System.err.flush();

    } // printError(String,SAXParseException)

    //
    // MAIN
    //

    public void parseXML(String xml)
    {
    	// variables

    	fileName=xml;

        PrintWriter out = new PrintWriter(System.out);
        XMLReader parser = null;
        int repetition = DEFAULT_REPETITION;
        boolean namespaces = DEFAULT_NAMESPACES;
        boolean namespacePrefixes = DEFAULT_NAMESPACE_PREFIXES;
        boolean validation = DEFAULT_VALIDATION;
        boolean schemaValidation = DEFAULT_SCHEMA_VALIDATION;
        boolean schemaFullChecking = DEFAULT_SCHEMA_FULL_CHECKING;
        boolean dynamicValidation = DEFAULT_DYNAMIC_VALIDATION;
        boolean memoryUsage = DEFAULT_MEMORY_USAGE;
        boolean tagginess = DEFAULT_TAGGINESS;



        // use default parser?
        if (parser == null) {

            // create parser
            try {
                parser = XMLReaderFactory.createXMLReader(DEFAULT_PARSER_NAME);
            }
            catch (Exception e) {
                System.err.println("error: Unable to instantiate parser ("+DEFAULT_PARSER_NAME+")");
            }
        }



            // parse file
            parser.setContentHandler(this);
            parser.setErrorHandler(this);
            try {
                long timeBefore = System.currentTimeMillis();
                long memoryBefore = Runtime.getRuntime().freeMemory();
                for (int j = 0; j < repetition; j++) {
                    parser.parse(xml);
                }
                long memoryAfter = Runtime.getRuntime().freeMemory();
                long timeAfter = System.currentTimeMillis();

                long time = timeAfter - timeBefore;
                long memory = memoryUsage
                            ? memoryBefore - memoryAfter : Long.MIN_VALUE;
               /* this.printResults(out, xml, time, memory, tagginess,
                                     repetition);*/
            }
            catch (SAXParseException e) {
                // ignore
            }
            catch (Exception e) {
                System.err.println("error: Parse error occurred - "+e.getMessage());
                Exception se = e;
                if (e instanceof SAXException) {
                    se = ((SAXException)e).getException();
                }
                if (se != null)
                  se.printStackTrace(System.err);
                else
                  e.printStackTrace(System.err);

            }
    }

    /** Main program entry point. */
    public static void main(String argv[]) {

        // is there anything to do?
        if (argv.length == 0) {
            printUsage();
            System.exit(1);
        }

        for(int i=0;i<argv.length;i++)
        System.out.print(argv[i]+" ");
        System.out.println("");

        // variables
        OutputParser counter = new OutputParser();
        PrintWriter out = new PrintWriter(System.out);
        XMLReader parser = null;
        int repetition = DEFAULT_REPETITION;
        boolean namespaces = DEFAULT_NAMESPACES;
        boolean namespacePrefixes = DEFAULT_NAMESPACE_PREFIXES;
        boolean validation = DEFAULT_VALIDATION;
        boolean schemaValidation = DEFAULT_SCHEMA_VALIDATION;
        boolean schemaFullChecking = DEFAULT_SCHEMA_FULL_CHECKING;
        boolean dynamicValidation = DEFAULT_DYNAMIC_VALIDATION;
        boolean memoryUsage = DEFAULT_MEMORY_USAGE;
        boolean tagginess = DEFAULT_TAGGINESS;



        // use default parser?
        if (parser == null) {

            // create parser
            try {
                parser = XMLReaderFactory.createXMLReader(DEFAULT_PARSER_NAME);
            }
            catch (Exception e) {
                System.err.println("error: Unable to instantiate parser ("+DEFAULT_PARSER_NAME+")");
            }
        }



            // parse file
            parser.setContentHandler(counter);
            parser.setErrorHandler(counter);
            try {
                long timeBefore = System.currentTimeMillis();
                long memoryBefore = Runtime.getRuntime().freeMemory();
                for (int j = 0; j < repetition; j++) {
                    parser.parse(argv[0]);
                }
                long memoryAfter = Runtime.getRuntime().freeMemory();
                long timeAfter = System.currentTimeMillis();

                long time = timeAfter - timeBefore;
                long memory = memoryUsage
                            ? memoryBefore - memoryAfter : Long.MIN_VALUE;
                counter.printResults(out, argv[0], time, memory, tagginess,
                                     repetition);
            }
            catch (SAXParseException e) {
                // ignore
            }
            catch (Exception e) {
                System.err.println("error: Parse error occurred - "+e.getMessage());
                Exception se = e;
                if (e instanceof SAXException) {
                    se = ((SAXException)e).getException();
                }
                if (se != null)
                  se.printStackTrace(System.err);
                else
                  e.printStackTrace(System.err);

            }


    } // main(String[])

    //
    // Private static methods
    //

    /** Prints the usage. */
    private static void printUsage() {

        System.err.println("usage: java sax.OutputParser (options) uri ...");
        System.err.println();



    } // printUsage()

} // class OutputParser
