package sax;

import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class SAX2Count extends DefaultHandler {

  private static final String  DEFAULT_PARSER_NAME = "org.apache.xerces.parsers.SAXParser";

  private long elements;            /** Elementos */
  private long attributes;          /** Atributos */
  private long characters;          /** Caracteres */
  private long ignorableWhitespace; /** espacios en blanco */

  /** Prints the output from the SAX callbacks. */
  public static void print(String uri) {
   try {
    SAX2Count counter = new SAX2Count();

    XMLReader parser = new org.apache.xerces.parsers.SAXParser();
    parser.setContentHandler(counter);
    parser.setErrorHandler(counter);

    parser.setFeature( "http://xml.org/sax/features/validation", false);
    parser.setFeature( "http://xml.org/sax/features/namespaces", true);
    parser.setFeature( "http://apache.org/xml/features/validation/schema", true);

    long before = System.currentTimeMillis();
    parser.parse(uri);
    long after = System.currentTimeMillis();
    counter.printResults(uri, after - before);
   } catch (org.xml.sax.SAXParseException spe) {  
    spe.printStackTrace(System.err);
   } catch (org.xml.sax.SAXException se) {
    if (se.getException() != null)
      se.getException().printStackTrace(System.err);
    else se.printStackTrace(System.err);
   } catch (Exception e) {
     e.printStackTrace(System.err);
   }
  }

  // DocumentHandler methods

  public void startDocument() {
    elements = 0;
    attributes = 0;
    characters = 0;
    ignorableWhitespace = 0;
  }

  public void startElement(String uri, String local, String raw, Attributes attrs) {
    elements++;
    if (attrs != null) attributes += attrs.getLength();
  }

  public void characters(char ch[], int start, int length) {
    characters += length;
  }

  public void ignorableWhitespace(char ch[], int start, int length) {
    ignorableWhitespace += length;
  }

  // ErrorHandler methods

  public void warning(SAXParseException ex) {
    System.err.println("[Aviso] "+getLoc(ex)+": "+ ex.getMessage());
  }

  public void error(SAXParseException ex) {
    System.err.println("[Error] "+getLoc(ex)+": "+ex.getMessage());
  }

  public void fatalError(SAXParseException ex) throws SAXException {
    System.err.println("[Error!] "+getLoc(ex)+": "+ex.getMessage());
  }

  private String getLoc(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 += ":" + ex.getLineNumber() + ":" + ex.getColumnNumber();
    str.append(':');
    str.append(ex.getLineNumber());
    str.append(':');
    str.append(ex.getColumnNumber());

    return str.toString();
  }

  // Public methods

  public void printResults(String uri, long time) {
    // filename.xml: 631 ms (4 elems, 0 attrs, 78 spaces, 0 chars)
    System.out.println (uri+":"+time+"time ms ("
     +elements+" elems, "+attributes+" attrs, "
     +ignorableWhitespace+" spaces, "+characters+" chars)");
    }

  public static void main(String argv[]) {
    print(argv[0]);
  }
}