/**
 *
 * @author  unknown
 * @version
 */

import java.io.*;

/****************************/
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
/************************/

import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
/**
 * Builds a simple HTML page which lists tip titles
 * and provides links to HTML and text versions
 */
public class UseOfSax2EchoV2 extends DefaultHandler
{
  //
   static private Writer  out;
   static private String  eName;
   private String indentString = "    "; // Amount to indent
   private int indentLevel = 0;
  //
  public static void main(String argv[]) throws Exception
    {
        if (argv.length != 1) {
            System.err.println("Usage: java UseOfSax2EchoV2 input_filename");
            System.exit(1);
        }
  /*********/
    String document = argv[0];
    /********/
    /*Create a SAX Parser Factory*/
		    SAXParserFactory parseFactory = SAXParserFactory.newInstance();

	/*Obtain a SAX Parser */
    SAXParser saxParser = parseFactory.newSAXParser();

    /*XML Reader is the interface for reading an XML
	     document using callbacks*/
	    XMLReader xmlReader = saxParser.getXMLReader();

	    /*Attach ContentHandler - the callbacks like
	    startDocument,startElement etc. are
	     overridden by the setContentHandler to
	 trap them into user code*/
	    xmlReader.setContentHandler(new UseOfSax2EchoV2());


        try {
            // Set up output stream
            out = new OutputStreamWriter(System.out, "UTF8");

            // Parse the input
            /*Parse an XML document - the document is read and
				    overridden callbacks in the MyXMLHandler are invoked*/
    xmlReader.parse(document);

        } catch (Throwable t) {
            t.printStackTrace();
        }
        System.exit(0);
 }



/**
*  The SAX parser will invoke this method
*           startDocument()
*   only once,
*  before any other methods in this interface
**/
    public void startDocument()
    throws SAXException
        {
			 System.out.println("\n Start Document: --Reading the document ----\n");
			nl();
			 nl();
			 emit("<!--"+ "START DOCUMENT"+" -->");
        nl();
			emit("<?xml version='1.0' encoding='UTF-8'?>");
        nl();
    }
/**
* The SAX parser will invoke this method
*           endDocument()
*   only once,
*  and it will be the last method invoked during the parse.
*  The parser shall not invoke this method until it has either
*  abandoned parsing (because of an unrecoverable error)
* or reached the end of input.
**/
    public void endDocument()
    throws SAXException
    { nl();
    emit("<!--"+"END DOCUMENT"+"-->");
        try {
            nl();
            out.flush();
        } catch (IOException e) {
            throw new SAXException("I/O error", e);
        }
    }
/**
* The Parser will invoke this method
*        startElement()
* at the beginning of every element
* in the XML document;
* there will be a corresponding endElement event
* for every startElement event (even when the element is empty).
* All of the element's content will be reported, in order,
* before the corresponding endElement event.
**/
    public void startElement(String namespaceURI,
                             String lName, // local elementname
                             String qName, // qualified name
                             Attributes attrs)//  The attributes attached  to theelement                                             /* to the element.
                  throws SAXException
    {
		 System.out.println("Start Element-> "+qName);
		indentLevel++;
        nl(); emit("ELEMENT: ");
      String   eName = qName; // element name
        if ("".equals(eName)) eName = qName; // namespaceAware = false
        emit("<"+eName);
        if (attrs != null) {
            for (int i = 0; i < attrs.getLength(); i++) {// Return the number of attributes in the list.
                String aName = attrs.getLocalName(i); // Attribute  name, Look up an attribute's local name by index.
                if ("".equals(aName)) aName = attrs.getQName(i);  // Look up an attribute's XML 1.0 qualified name by index.
                emit(" ");
                emit(aName+"=\""+attrs.getValue(i)+"\"");//   Look up an attribute's value by index.
            }
        }
         if (attrs.getLength() > 0) nl();
        emit(">");
        nl();
   }
/****
*  The SAX parser will invoke this method at the end of every element
* in the XML document; there will be a corresponding startElement event
* for every endElement event (even when the element is empty).
****/
    public void endElement(String namespaceURI,
                           String sName, // simple name
                           String qName  // qualified name
                          )
    throws SAXException
    {
		System.out.println("End Element-> "+qName);
		nl();
	    emit("END_ELM: ");
		emit("</"+qName+">");
		indentLevel--;
    }
   /**********
   ******/
    public void characters(char buf[], int offset, int len)
       throws SAXException
       {
           String s = new String(buf, offset, len);
           emit(s);
    }
//===========================================================
    // Utility Methods ...
    //===========================================================

    // Wrap I/O exceptions in SAX exceptions, to
    // suit handler signature requirements
    private void emit(String s)
    throws SAXException
    {
        try {
            out.write(s);
            out.flush();
        } catch (IOException e) {
            throw new SAXException("I/O error", e);
        }
    }

    // Start a new line
    private void nl()
    throws SAXException
    {
        String lineEnd =  System.getProperty("line.separator");
        try {
            out.write(lineEnd);
             for (int i=0; i < indentLevel; i++) out.write(indentString);
        } catch (IOException e) {
            throw new SAXException("I/O error", e);
        }
    }
}