RegionsHandler.java

package gov.usgs.earthquake.qdm;

import java.util.Date;
import java.util.logging.Logger;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

import gov.usgs.util.SAXAdapter;
import gov.usgs.util.XmlUtils;


/**
 * XML SAX Handler for ANSS "regions.xml".
 *
 * See the resource file <code>etc/config/regions.xml</code>
 *
 * Example:
 * <pre>{@code
 * InputStream in = ...
 * RegionsHanlder handler = new RegionsHandler();
 * try {
 *     handler.parse(in)
 * } finally {
 *     in.close();
 * }
 * return handler.regions;
 * }</pre>
 */
public class RegionsHandler extends SAXAdapter {

    /** Logger object */
    public static final Logger LOGGER = Logger.getLogger(RegionsHandler.class.getName());

    /** the regions that have been parsed */
    public Regions regions = new Regions();
    /** update timestamp */
    public Date updated = null;
    /** reported format version (no version-specific logic implemented) */
    public String formatVersion = null;

    // variables for tracking state
    private boolean inRegions = false;
    private String netid = null;
    private Region region = null;

    /**
     * Start Element handler.
     *
     * Builds region objects, and parses other information.
     *
     * @param uri namespace of element.
     * @param localName name of element.
     * @param qName qualified name of element.
     * @param attributes element attributes.
     */
    @Override
    public void onStartElement(final String uri, final String localName,
            final String qName, final Attributes attributes)
            throws SAXException {
        if ("regions".equals(localName)) {
            this.inRegions = true;
            LOGGER.finer("Parsing regions xml");
        } else if (!inRegions) {
            throw new SAXException("Expected 'regions' root element");
        } else if ("update".equals(localName)) {
            this.updated = XmlUtils.getDate(attributes.getValue("date"));
            LOGGER.finer("\tupdated " + XmlUtils.formatDate(updated));
        } else if ("format".equals(localName)) {
            this.formatVersion = attributes.getValue("version");
            LOGGER.finer("\tversion " + formatVersion);
        } else if ("net".equals(localName)) {
            if (this.region != null) {
                throw new SAXException("Unexpected 'net' element inside 'region'");
            }
            this.netid = attributes.getValue("code");
            LOGGER.finer("\tnetid=" + netid);
        } else if ("region".equals(localName)) {
            if (this.region != null) {
                throw new SAXException("Unexpected 'region' element inside 'region'");
            }
            String regionid = attributes.getValue("code");
            this.region = new Region(netid, regionid);
            LOGGER.finer("\t\tregionid=" + regionid);
        } else if ("coordinate".equals(localName)) {
            if (region == null) {
                throw new SAXException("Unexpected 'coordinate' element outside 'region'");
            }
            Double latitude = Double.valueOf(attributes.getValue("latitude"));
            Double longitude = Double.valueOf(attributes.getValue("longitude"));
            this.region.points.add(new Point(longitude, latitude));
            LOGGER.finer("\t\t\tcoordinate = " + latitude + ", " + longitude);
        }
    }

    /**
     * End element handler.
     *
     * Adds built region objects to regions object.
     *
     * @param uri namespace of element.
     * @param localName name of element.
     * @param qName qualified name of element.
     * @param content element content.
     */
    @Override
    public void onEndElement(final String uri, final String localName,
            final String qName, final String content) throws SAXException {
        if ("region".equals(localName)) {
            if (this.region == null) {
                throw new SAXException("Unexpected closing 'region' element");
            }
            regions.regions.add(this.region);
            if (this.region.points.size() == 0) {
                regions.defaultNetid = this.region.netid;
            }
            this.region = null;
        } else if ("regions".equals(localName)) {
            this.inRegions = false;
        }
    }

}