import java.io.*;
import java.util.Vector;
import java.util.Stack;

import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.Attributes;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.XMLReader;

/**
 *  xml engine code salvaged from paperplane
 *  http://www.hackorama.com/paperplane
 *
 *  original code                  circa 2002
 *  enhanced and generalised       circa 2003
 * 
 *  major revision                 01/25/2004
 *    ported to new SAX interfaces   
 *    clean up and bit rot check
 * 
 * latest version at :
 * http://www.hackorama.com/xengine
 */

public class XEngine {

	private static final String B = "b ";
	private static final String A = "a ";
	private static final String C = "c ";
	private static final String E = "e ";
	private static final String EQUALS = " = ";
	private boolean debug   = false;
	private Vector xmlstore = new Vector();
	private String filename = "null";

	public Vector getData() {
		return xmlstore;
	}

	public void setData(Vector data) {
		xmlstore = data;
	}

	public String fileName() {
		return filename;
	}

	private int count(String marker) {
		return (marker.length()+EQUALS.length());
	}

	public boolean parseFile(String filename) {
		this.filename = filename;
		String uri = "file:" + new File(filename).getAbsolutePath();
		MyHandler handler = new MyHandler();
		handler.setStore(xmlstore);
		handler.setMarkers(B,A,C,E,EQUALS);
		CreateParser parser = new CreateParser(handler);
		parser.parse(uri);
		return  ( ! parser.checkError() );
	}

	
	public int getElementCount(String tag) {
		return (getElementCount(xmlstore, tag));
	}


	public int getElementCount(Vector element, String tag) {
		boolean mark = false;
		int count = 0;
		for (int i = 0; i < element.size(); i++) {
			String line = (String) element.elementAt(i);
			if (line.equals(B + tag)) {
				mark = true;
			}
			if (mark) {
				if (line.equals(E + tag)) {
					count++;
					mark = false;
				}
			}
		}
		return count;
	}


	public Vector getElement(String tag) {
		return (getElement(xmlstore, tag));
	}


	public Vector getElement(Vector element, String tag) {
		boolean mark = false;
		Vector result = new Vector();
		for (int i = 0; i < element.size(); i++) {
			String line = (String) element.elementAt(i);
			if (line.equals(B + tag)) {
				mark = true;
			}
			if (mark) {
				result.add(line);
				if (line.equals(E + tag)) {
					return result;
				}
			}
		}
		printError("NO ELEMENT CALLED \"" + tag + "\"");
		return null;
	}

	public String getElementAttr(Vector element, String type) {
		for (int i = 0; i < element.size(); i++) {
			String line = (String) element.elementAt(i);
			if (line.startsWith(A + type + EQUALS)) 
				return (line.substring( count(A) + type.length()));
		}
		printError("NO ATTRIBUTE CALLED \"" +  type + "\"");
		return null;
	}

	public Vector getElementType(String tag, String type, String value) {
		return (getElementType(xmlstore, tag, type, value));
	}

	public Vector getElementType(Vector element, String tag,
			String type, String value) {
		boolean mark = false;
		Vector result = new Vector();
		for (int i = 0; i < element.size(); i++) {
			String line = (String) element.elementAt(i);
			if (line.equals(B + tag)) {
				result.add(line);
				line = (String) element.elementAt(++i);
				while (line.startsWith(A + type + EQUALS) &&
						i < element.size() && !mark) {
					result.add(line);
					if (line.equals(A + type + EQUALS + value)) {
						mark = true;
					}
					line = (String) element.elementAt(++i);
				}
				if (!mark) {
					result.removeAllElements();
				}
			}
			if (mark) {
				result.add(line);
				if (line.equals(E + tag)) {
					return result;
				}
			}
		}
		printError("NO ELEMENT TYPE \"" + tag + ":" + type + "\"");
		return null;
	}


	public Vector getElements(String tag) {
		return (getElements(xmlstore, tag));
	}


	public Vector getElements(Vector element, String tag) {
		boolean mark = false;
		int count = 0;
		Vector fullresult = new Vector();
		Vector result = new Vector();
		for (int i = 0; i < element.size(); i++) {
			String line = (String) element.elementAt(i);
			if (line.equals(B + tag)) {
				mark = true;
			}
			if (mark) {
				result.add(line);
				if (line.equals(E + tag)) {
					fullresult.add(result);
					mark = false;
					result = new Vector();
				}
			}
		}
		if (fullresult == null) {
			printError("NO ELEMENTS FOR \"" + tag + "\"");
		}
		return fullresult;
	}


	public Vector getElement(String tag, int index) {
		return (getElement(xmlstore, tag, index));
	}


	public Vector getElement(Vector element, String tag, int index) {
		boolean mark = false;
		int count = 0;
		Vector result = new Vector();
		for (int i = 0; i < element.size(); i++) {
			String line = (String) element.elementAt(i);
			if (line.equals(B + tag)) {
				mark = true;
			}
			if (mark) {
				result.add(line);
				if (line.equals(E + tag)) {
					if (count == index) {
						return result;
					}
					mark = false;
					result.removeAllElements();
					count++;
				}
			}
		}
		printError("NO ELEMENT \"" + tag + "\"");
		return null;
	}


	public String getElementValue(String tag) {
		return (getElementValue(xmlstore, tag));
	}


	private String getTag(Vector element) {
		if (element == null) {
			printError("NO ELEMENT FOUND");
			return null;
		}
		String line = (String) element.elementAt(0);
		if (line == null) {
			printError("NO ELEMENT TAG FOUND");
			return null;
		}
		return (line.substring(2));
	}


	public String getElementValue(Vector element) {
		return (getElementValue(element, getTag(element)));
	}


	public String getElementValue(Vector element, String tag) {
		if (element == null || tag == null) {
			return null;
		}
		boolean mark = false;
		int count = 0;
		String value = null;
		for (int i = 0; i < element.size(); i++) {
			String line = (String) element.elementAt(i);
			if (line.equals(B + tag)) {
				mark = true;
			}
			if (mark) {
				if (line.startsWith(C + tag + EQUALS)) {
					return (line.substring(count(C)+ tag.length()));
				}
			}
		}
		if (value == null) {
			debugPrint("FOUND NO VALUE FOR \"" + tag + "\"");
		}
		return value;
	}

	public Vector getElement(String tag, String type) {
		Vector result = new Vector();
		return result;
	}

        public void printElement(Vector elem) {
                if (elem == null) {
                        printError("EMPTY ELEMENT");
                        return;
                }
                int tab = 0;
                String value = null, line = null, TAB = "   ";
                for (int i = 0; i < elem.size(); i++) {
                        line = (String) elem.elementAt(i);
                        if( line.startsWith( B ) ){
                                System.out.println( "" );
                                for( int j = 0; j < tab ; j++)
                                        System.out.print(TAB);
                                value = line.substring( B.length() );
                                System.out.print(  value  );
                                tab++;
                        } else if( line.startsWith( E ) ){
                                for( int j = 0; j < tab ; j++)
                                        System.out.print(TAB);
                                tab--;
                        } else if( line.startsWith( A ) ){
                                value = line.substring( A.length() );
                                System.out.println( "" );
                                for( int j = 0; j < tab ; j++)
                                        System.out.print(TAB);
                                System.out.print( value );
                        } else if( line.startsWith( C ) ){
                                if( line.length() > C.length() ){
                                        value = line.substring( C.length() );
                                        if( value.lastIndexOf(EQUALS) > 0 ){
                                             value = value.substring(
                                                value.lastIndexOf(EQUALS) );
                                            if( value.length() > 0 )
                                                System.out.print(  value );
                                        }
                                }
                        }
                }
                System.out.println( "" );
                System.out.println( "" );
        }


        private void printError(String s) {
                System.out.println("XML ERROR : " + s);
        }

        public  void setDebug(boolean flag) {
                debug = flag;
        }

        private void debugPrint(String s) {
                if( ! debug ) return;
                System.out.println("XML DEBUG : " + s);
        }

	public class CreateParser {

		private DefaultHandler handler;
		private SAXParser saxParser;
		private boolean error = false;

		public boolean checkError(){
			return error;
		}

		private void printError(String s) {
			System.out.println("XML ERROR : " + s);
		}

		public CreateParser(DefaultHandler handler) {
			this.handler = handler;
			create();
		}

		private void create() {
			try {
				SAXParserFactory factory = SAXParserFactory.newInstance();
				factory.setNamespaceAware(true);
				factory.setValidating(true);
				saxParser = factory.newSAXParser();
			} catch (SAXParseException err) {
                        	error = true;
                        	printError("PARSING ERROR IN CREATE "
                                         + ", line " + err.getLineNumber());
                        	printError(err.getMessage());
                	} catch (SAXException e) {
                        	error = true;
                        	printError("SAXEXCEPTION ");
                        	Exception x = e;
                        	if (e.getException() != null) {
                                	x = e.getException();
                        	}
                        	x.printStackTrace();
			} catch (Throwable t) {
				error = true;
				printError("ERROR WHILE PARSING");
				t.printStackTrace();
			}
		}

		public void parse(File file) {
			try {
				saxParser.parse(file, handler);
			} catch (SAXParseException err) {
                        	error = true;
                        	printError("PARSING ERROR IN PARSE FILE "
                                         + ", line " + err.getLineNumber());
                        	printError(err.getMessage());
                	} catch (SAXException e) {
                        	error = true;
                        	printError("SAXEXCEPTION ");
                        	Exception x = e;
                        	if (e.getException() != null) {
                                	x = e.getException();
                        	}
                        	x.printStackTrace();
			} catch (Throwable t) {
				error = true;
				printError("ERROR WHILE PARSING");
				t.printStackTrace();
			}
		}

		public void parse(String uri) {
			try {
				saxParser.parse(uri, handler);
			} catch (SAXParseException e) {
                        	error = true;
                        	printError("PARSING ERROR IN PARSE URI "
                                         + ", line " + e.getLineNumber());
                        	printError("WHILE PARSING " + uri );
                        	printError(e.getMessage());
				e.printStackTrace();
                	} catch (SAXException e) {
                        	error = true;
                        	printError("SAXEXCEPTION ");
                        	Exception x = e;
                        	if (e.getException() != null) {
                                	x = e.getException();
                        	}
                        	x.printStackTrace();
			} catch (Throwable t) {
				error = true;
				printError("ERROR WHILE PARSING");
				t.printStackTrace();
			}
		}

		public void parse(InputStream stream) {
			try {
				saxParser.parse(stream, handler);
			} catch (SAXParseException e) {
                        	error = true;
                        	printError("PARSING ERROR IN PARSE STREAM "
                                         + ", line " + e.getLineNumber());
                        	printError(e.getMessage());
				e.printStackTrace();
                	} catch (SAXException e) {
                        	error = true;
                        	printError("SAXEXCEPTION ");
                        	Exception x = e;
                        	if (e.getException() != null) {
                                	x = e.getException();
                        	}
                        	x.printStackTrace();
			} catch (Throwable t) {
				error = true;
				printError("ERROR WHILE PARSING");
				t.printStackTrace();
			}
		}
	}

	
	public class MyHandler extends DefaultHandler {

		private boolean debug    = false;
		private boolean OK       = false;
                private Stack tagstack   = new Stack();
                private Stack childstack = new Stack();
                private Vector xmlstore  = null;
		private String EQUALS    = null;
		private String B,A,C,E;

		public void setStore(Vector xmlstore){
			this.xmlstore = xmlstore;
			if( EQUALS != null ) OK=true;
		}

		public void setMarkers(String b, String a, String c, String e, String equals){
			B = b; A = a; C = c; E = e;
			EQUALS = equals;
			if( xmlstore != null ) OK=true;
		}
		
		public void startElement(String namespaceURI,
				String tag,
				String qName,
				Attributes attrs)
				 throws SAXException {
			if( ! OK  ) { 
				error("HANDLER NOT SETUP CORRECTLY");
				return;
			}
			boolean first = false;

			tagstack.push(tag);
			if (childstack.empty()) { //first tag
				childstack.push(new Vector());
				first = true;
			}
			Vector children = (Vector) childstack.peek();
			children.addElement(tag);
			store(B + tag);
			if (attrs != null) {
				for (int i = 0; i < attrs.getLength(); i++) 
					store( A + attrs.getLocalName(i) + EQUALS + attrs.getValue(i));
			} 
			if (!first) childstack.push(new Vector());
		}

		public void endElement(String namespaceURI,
				String name,
				String qName)
				 throws SAXException {
			if( ! OK  ) { 
				error("HANDLER NOT SETUP CORRECTLY");
				return;
			}
			tagstack.pop();
			childstack.pop();
			store(E + name);
		}

		public void characters(char[] buf, int offset, int len)
				 throws SAXException {
			if( ! OK  ) { 
				error("HANDLER NOT SETUP CORRECTLY");
				return;
			}
			String value = String.copyValueOf(buf, offset, len);
			value = value.trim();
			if (value.length() > 0) {
				store(C + tagstack.peek() + EQUALS + value);
			} else {
				store(C + tagstack.peek());
			}
		}

		private void error(String s) {
			System.out.println("SETUP ERROR : " + s);
			return;
		}

		private void printError(String s) {
			System.out.println("XML ERROR : " + s);
		}

		public void setDebug(boolean flag) {
			debug = flag;
		}

		private void debugPrint(String s) {
			if (!debug) return;
			System.out.println("XML DEBUG : " + s);
		}

		private void store(String s){
			String clean = s.trim();
			xmlstore.add(clean);
		}

	}
}



syntax highlighted by Code2HTML, v. 0.9