001package edu.pdx.cs410J.family;
002
003import java.io.*;
004import java.net.URL;
005import java.util.*;
006import org.xml.sax.*;
007import org.w3c.dom.*;
008
009/**
010 * This class contains fields and methods that are useful when dealing
011 * with XML data.
012 */
013class XmlHelper implements EntityResolver, ErrorHandler {
014
015  /** The System ID for the Family Tree DTD */
016  protected static final String systemID = 
017    "http://www.cs.pdx.edu/~whitlock/dtds/familytree.dtd";
018
019  /** The Public ID for the Family Tree DTD */
020  protected static final String publicID = 
021    "-//Portland State University//DTD CS410J Family Tree//EN";
022
023  ////////////////////  EntityResolver Methods  //////////////////
024
025  /**
026   * Attempt to resolve the external entity (such as a DTD) described
027   * by the given public and system ID.  The external entity is
028   * returned as a <code>InputSource</code>
029   */
030  public InputSource resolveEntity (String publicId, String systemId)
031    throws SAXException, IOException {
032
033    if (publicId != null && publicId.equals(XmlHelper.publicID)) {
034      // We're resolving the external entity for the Family Tree's
035      // DTD.  Check to see if its in the jar file.  This way we don't
036      // need to go all the way to the website to find the DTD.
037      String location = "/edu/pdx/cs410J/family/familytree.dtd";
038      InputStream stream =
039        this.getClass().getResourceAsStream(location);
040      if (stream != null) {
041        return new InputSource(stream);
042      }
043    }
044
045    // Try to access the DTD using the URL
046    try {
047      URL url = new URL(systemId);
048      InputStream stream = url.openStream();
049      return new InputSource(stream);
050
051    } catch (Exception ex) {
052      return null;
053    }
054  }
055
056  //////////////////  ErrorHandler Methods  ////////////////////////
057  
058  public void warning(SAXParseException ex) throws SAXException { 
059    String s = "Warning while parsing XML (" + ex.getLineNumber() +
060      ":" + ex.getColumnNumber() + "): " + ex.getMessage();
061    System.err.println(s);
062  }
063
064  public void error(SAXParseException ex) throws SAXException {
065    String s = "Error while parsing XML (" + ex.getLineNumber() +
066      ":" + ex.getColumnNumber() + "): " + ex.getMessage();
067    throw new SAXException(s);
068  }
069  
070  public void fatalError(SAXParseException ex) throws SAXException {
071    String s = "Fatal error while parsing XML (" + ex.getLineNumber()
072      + ":" + ex.getColumnNumber() + "): " + ex.getMessage();
073    throw new SAXException(s);
074  }
075
076  ///////////////////  Other Helper Methods  ///////////////////////
077
078  /**
079   * Extracts a bunch of notes from an <code>Element</code>
080   */
081  protected static List<String> extractNotesFrom(Element element) {
082    List<String> list = new ArrayList<String>();
083
084    NodeList children = element.getChildNodes();
085    for (int i = 0; i < children.getLength(); i++) {
086      Node node = children.item(i);
087      if (!(node instanceof Element)) {
088        continue;
089      }
090
091      Element child = (Element) node;
092      if (child.getTagName().equals("note")) {
093        list.add(extractTextFrom(child));
094      }
095    }
096
097    return list;
098  }
099
100  /**
101   * Extracts the text from an <code>Element</code>.
102   */
103  protected static String extractTextFrom(Element element) {
104    Text text = (Text) element.getFirstChild();
105    return (text == null ? "" : text.getData());
106  }
107
108}