/* 
 * E-XML Library:  For XML, XML-RPC, HTTP, and related.
 * Copyright (C) 2002-2008  Elias Ross
 * 
 * genman@noderunner.net
 * http://noderunner.net/~genman
 * 
 * 1025 NE 73RD ST
 * SEATTLE WA 98115
 * USA
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * $Id$
 */

package net.noderunner.exml;

import java.io.StringWriter;

/**
 * This class is for performance testing.
 *
 * @author Elias Ross
 * @version 1.0
 */
public class XmlPerfTest
	extends junit.framework.TestCase
{
	public XmlPerfTest(String name) {
		super(name);
	}

	static boolean sax = false;
	static boolean dom = false;
	static boolean minml = false;
	static int times = 4;

	public static void main(String[] args) {
		for (int i = 0; i < args.length; i++) {
			if (args[i].equals("sax"))
				sax = true;
			if (args[i].equals("dom"))
				dom = true;
			if (args[i].equals("minml"))
				minml = true;
			if (args[i].equals("times"))
				times = Integer.parseInt(args[i+1]);
		}
		junit.textui.TestRunner.run(XmlPerfTest.class);
	}

	static StringWriter sw;
	static XmlCharArrayWriter xcaw;
	static XmlWriter xw;
	static XmlReader xr;
	static XmlParser xp;
	static XmlSParser xsp;

	long start;
	long total;
	void start() { start = System.currentTimeMillis(); }
	void stop(String s) { 
		long took = System.currentTimeMillis() - start; 
		System.out.println(s + " took: " + took); 
		total += took;
	}
	void average(String s) {
		System.out.println(s + " average: " + total / times); 
		total = 0;
	}
	

	/**
	 * Create a new XmlWriter around a StringWriter for testing.
	 */
	static void newWriter() {
		// sw = new StringWriter();
		xcaw = new XmlCharArrayWriter();
		xw = new XmlWriter(xcaw);
		// xw = new XmlWriter(new BufferedWriter(sw));
	}

	static void newParser()
		throws java.io.IOException
	{
		newReader();
		Dtd dtd = xr.getDtd();
		ElementRule rule = new ElementRule();
		dtd.addElementRule("element", rule);

		ElementRule rule2 = new ElementRule();
		rule2.setAllowPCData(true);
		dtd.addElementRule("stuff", rule2);
		xp = new XmlParser(xr);
	}

	static void newSParser()
		throws java.io.IOException
	{
		newReader();
		xsp = new XmlSParser(xr);
	}

	static void newReader() 
		throws java.io.IOException
	{
		xr = new XmlReader();
		xr.setReadString(xcaw.toString());
	}

		/*
	public void testReaderPerformance() 
		throws Exception
	{
		newWriter();
		xw.startElement("document");
		Element se = new Element("stuff");
		se.appendAttribute(new Attribute("name", "value"));
		se.appendAttribute(new Attribute("name2", "value2"));
		for (int i = 0; i < 2048; i++) {
			xw.startElement(se);
			for (int j = 0; j < 64; j++) {
				xw.startElement("stuff" + j);
				xw.endElement();
			}
			xw.endElement();
		}
		xw.up(0);
		xw.close();
		for (int i = 0; i < times; i++) {
			start();
			newReader();
			Document d = xr.document();
			Element e = d.getRootElement();
			//ElementToSAX.pipe(e, new DefaultHandler());
			stop("net.noderunner.exml.XmlReader.document");
		}
		average("net.noderunner.exml.XmlReader.document");

		if (sax) {
			SAXParser parser = new SAXParser();
			ContentHandler handler = new DefaultHandler();
			for (int i = 0; i < times; i++)
			{
				start();
				parser.setContentHandler(handler);
				parser.parse(new InputSource(new StringReader(sw.getBuffer().toString())));
				stop("apache.xerces.parsers.SAXParser");
			}
			average("apache.xerces.parsers.SAXParser");
		}
		if (dom) {
			DOMParser dparser = new DOMParser();
			for (int i = 0; i < times; i++)
			{
				start();
				dparser.parse(new InputSource(new StringReader(sw.getBuffer().toString())));
				stop("apache.xerces.parsers.DOMParser");
			}
			average("apache.xerces.parsers.DOMParser");
		}
		if (minml) {
			uk.co.wilson.xml.MinML parser = new uk.co.wilson.xml.MinML(4092, 1024);
			for (int i = 0; i < times; i++)
			{
				start();
				parser.parse(new StringReader(sw.getBuffer().toString()));
				stop("uk.co.wilson.xml.MinML");
			}
			average("uk.co.wilson.xml.MinML");
		}
	}
		*/

	public void testCanonicalPerformance() 
		throws Exception
	{
		start();
		newWriter();
		String FISH = "fish heads fish heads";
		for (int j = 0; j < 2048 * 40; j++) {
			xw.startElement("element");
			xw.startElement("stuff");
			xw.writeCData(FISH);
			xw.endElement();
		}
		xw.up(0);
		xw.close();
		stop("newWriter");

		for (int i = 0; i < times; i++) {
			newSParser();
			xsp.setEvents(XmlEvent.EOD | XmlEvent.CHARDATA);
			start();
			while (xsp.hasNext()) {
				xsp.next();
				if (xsp.isEvent(XmlEvent.CHARDATA)){
					assertEquals(FISH, xsp.getText());
				}
			}
			xsp.up(0);
			stop("testSParserPerformance");
		}
		average("net.noderunner.exml.SParser");
		System.out.println("-------------");

		for (int i = 0; i < times; i++) {
			newSParser();
			xr.getStringPool().add(FISH);
			xsp.setEvents(XmlEvent.EOD | XmlEvent.CHARDATA);
			start();
			while (xsp.hasNext()) {
				xsp.next();
				if (xsp.isEvent(XmlEvent.CHARDATA)){
					//String s = xsp.getCanonicalText();
					//assertTrue(s, FISH == s);
					assertEquals(FISH, xsp.getCanonicalText());
				}
			}
			xsp.up(0);
			stop("testSParserPerformance");
		}
		average("net.noderunner.exml.SParser");
		System.out.println("-------------");
		/*
		*/

	}

	/*
	public void testParserPerformance() 

		throws Exception
	{
		start();
		for (int i = 0; i < times; i++) {
			newWriter();
			for (int j = 0; j < 2048 * 1; j++) {
				xw.startElement("element");
				xw.startElement("stuff");
				xw.writeCData("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
				xw.writeCData("xxxxxxxxx&xxxxxxxx&xxxxxxxx&xxxxxxxxxxx&xxxxxxxxxxx'xxxxxxxxxxxxx\"xxxxxxxxxxxxxx");
				xw.writeCDSection("xxxxxxxxx&xxxxxxxx&xxxxxxxx&xxxxxxxxxxx&xxxxxxxxxxx'xxxxxxxxxxxxx\"xxxxxxxxxxxxxx");
				xw.write("<!-- COMMENT  COMMENT  COMMENT  COMMENT  COMMENT  COMMENT  COMMENT  COMMENT  COMMENT  COMMENT  COMMENT  -->");
				xw.endElement();
				xw.startElement("stuff");
				xw.writeCData("yyyyyyyyy&yyyyyyyy&yyyyyyyy&yyyyyyyyyyy&yyyyyyyyyyy'yyyyyyyyyyyyy\"yyyyyyyyyyyyyy");
				xw.writeCData("yyyyyyyyyzzzzzzzzz");
				xw.endElement();
			}
			xw.up(0);
			xw.close();
			stop("newWriter");
		}
		average("net.noderunner.exml.XmlWriter");


		final char stuff[] = "stuff".toCharArray(); 
		for (int i = 0; i < times; i++) {
			newSParser();
			start();
			while (xsp.hasNext()) {
				xsp.next();
				//if (xsp.matches(stuff)) {
				//}
			}
			xsp.up(0);
			stop("testSParserPerformance");
		}
		average("net.noderunner.exml.SParser");

		DefaultHandler handler = new DefaultHandler();

		if (minml) {
			for (int i = 0; i < times; i++)
			{
				start();
				//parser.setContentHandler(handler);
				//parser.parse(new InputSource(new StringReader(sw.getBuffer().toString())));
				uk.co.wilson.xml.MinML parser = new uk.co.wilson.xml.MinML(4092, 1024);
				parser.parse(new StringReader(sw.getBuffer().toString()));
				stop("uk.co.wilson.xml.MinML");
			}
			average("uk.co.wilson.xml.MinML");
		}

		if (sax) {
			SAXParserFactory pf = SAXParserFactory.newInstance();
			SAXParser parser = pf.newSAXParser();
			char c[] = xcaw.toString().toCharArray();
			for (int i = 0; i < times; i++)
			{
				start();
				CharArrayReader car = new CharArrayReader(c);
				parser.parse(new InputSource(car), handler);
				stop("apache.xerces.parsers.SAXParser");
			}
			average("apache.xerces.parsers.SAXParser");
		}

		/*
		if (dom) {
			DOMParser parser = new DOMParser();
			for (int i = 0; i < times; i++)
			{
				start();
				parser.parse(new InputSource(new StringReader(sw.getBuffer().toString())));
				stop("apache.xerces.parsers.DOMParser");
			}
			average("apache.xerces.parsers.DOMParser");
		}
		*/
	//}
}
