package javacodebook.xml.processing.dom.parse;

import java.util.*;

import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
import org.xml.sax.SAXException;

import org.w3c.dom.*;

/**
 * Die OurErrorHandler-Klasse implementiert das org.xml.sax.ErrorHandler
 * Interface und lässt sich somit sowohl bei SAX-Parsern als auch bei
 * DOM-Parsern als ErrorHandler registrieren.  Im Wesentlichen sammeln
 * Objekte dieser Klasse Fehlermeldungen, die beim Parsen aufgetreten sind
 * und stellen diese in aufbereiterter Form zur Verfügung.
 *
 * @author Christoph Leinemann
 */

public class OurErrorHandler implements ErrorHandler {

  private Vector warnings = new Vector();
  private Vector errors = new Vector();
  private Vector fatalErrors = new Vector();

  // dieses Objekt wird ausschließlich als Factory benutzt, um
  // DOM-Knoten zu instanziieren und Fehlermeldungen in XML
  // zur Verfügung stellen zu können.
  private Document domFactory = new org.apache.xerces.dom.DocumentImpl();

  // Eine Methode, die von dem org.xml.sax.ErrorHandler Interface
  // gefordert wird.  Falls ein OurErrorHandler-Objekt bei einem Parser
  // registriert ist, wird sie jedesmal aufgerufen, fall eine Warnung
  // auftritt.
  public void warning(SAXParseException exception) throws SAXException {
    // die Meldungen der Warnung werden in dem Vector namens 'warnings'
    // aufbewahrt.
    warnings.add(exception.getMessage());
  }

  // analog zur warning-Methode
  public void error(SAXParseException exception) throws SAXException {

    // die Meldungen der Fehler werden in dem Vector namens 'errors'
    // aufbewahrt.
    errors.add(exception.getMessage());
  }

  // analog zur warning-Methode
  public void fatalError(SAXParseException exception) throws SAXException {

    // die Meldungen der fatalen Fehler werden in dem Vector namens 'fatalErrors'
    // aufbewahrt.
    fatalErrors.add(exception.getMessage());
  }
  /**
   * Die Methode dien zum Zurücksetzen aller
   * Fehlermeldungen und Warnings.
   */
  public void reset() {
    warnings.removeAllElements();
    errors.removeAllElements();
    fatalErrors.removeAllElements();
  }

  /**
   * Die Methode liefert ein Element welches die Fehler-
   * meldungen wiederum in seinen Unterelementen
   * kapselt.  Auf diese Weise können Fehlermeldungen
   * sehr flexibel weiterverarbeitet werden.
   *
   * @return org.w3c.dom.Element
   */
  public Element getErrorMessagesAsXML() {
    return formatAsXML(errors, "errors");
  }

  // siehe getErrorMessagesAsXML()
  public Element getWarningsMessagesAsXML() {
    return formatAsXML(warnings, "warnings");
  }

  // siehe getErrorMessagesAsXML()
  public Element getFatalErrorMessagesAsXML() {
    return formatAsXML(fatalErrors, "fatalErrors");
  }

  /**
   * Diese Methode liefert die Fehlermeldungen als einfachen leicht
   * formatierten Text.
   *
   * @return java.lang.String
   */
  public String getErrorMessagesAsText() {
    return formatAsText(errors, "errors");
  }

  // siehe getErrorMessagesAsText()
  public String getWarningsMessagesAsText() {
    return formatAsText(warnings, "warnings");
  }

  // siehe getErrorMessagesAsText()
  public String getFatalErrorMessagesAsText() {
    return formatAsText(fatalErrors, "fatalErrors");
  }

  /**
   * Diese Methode liefert die Fehlermeldungen in Form eines
   * Vectors von Strings.
   *
   * @return java.lang.String
   */
  public Vector getErrorMessages() {
    return errors;
  }
  // siehe Methode getErrorMessages()
  public Vector getWarningsMessages() {
    return warnings;
  }

  // siehe Methode getErrorMessages()
  public Vector getFatalErrorMessages() {
    return fatalErrors;
  }

  /**
   * Diese Methode verpackt Fehlermeldungen eines Typs in
   * eine w3c-DOM-Element.  Auf diese Weise können die Fehler-
   * meldungen sehr flexibel weiterverarbeitet werden.
   *
   * @param vectorWithStringElements
   * @param type
   * @return org.w3c.dom.Element
   */
  private Element formatAsXML(Vector vectorWithStringElements, String type) {
    Element messages = domFactory.createElement("messages");
    messages.setAttribute("type", type);
    Enumeration enum = vectorWithStringElements.elements();
    while (enum.hasMoreElements()) {
      Element message = domFactory.createElement("message");
      Text text = domFactory.createTextNode( (String) enum.nextElement());
      message.appendChild(text);
      messages.appendChild(message);
    }
    return messages;
  }

  /**
   * Diese Methode formatiert Fehlermeldungen eines Typs als einfachen String
   *
   * @param vectorWithStringElements
   * @param type
   * @return java.lang.String
   */
  private String formatAsText(Vector vectorWithStringElements, String type) {
    if(vectorWithStringElements.size()==0)return "no "+type+" occured";
    String returnString = "The following " + type + " have occured";
    Enumeration enum = vectorWithStringElements.elements();
    while (enum.hasMoreElements()) {
      String message = (String) enum.nextElement();
      returnString = returnString + "\n\t* " + message + "\n";
    }
    return returnString;
  }

  // Einige Methoden, um den Verlauf des Parsing-Prozesses beurteilen
  // zu können, ohne die Fehlermeldungen zu erfragen.

  public boolean hasWarnings()
  {
    if(warnings.size()>0) return true;
    else return false;
  }
  public boolean hasErrors()
  {
    if(errors.size()>0) return true;
    else return false;
  }
  public boolean hasFatalErrors()
  {
    if(fatalErrors.size()>0) return true;
    else return false;
  }
  public boolean anyProblems()
  {
    if (hasWarnings() || hasErrors() || hasFatalErrors())
      return true;
    else return false;
  }
}