GridXMLHandler.java

package gov.usgs.earthquake.shakemap;

import gov.usgs.util.XmlUtils;

import java.util.HashMap;

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

/**
 * Parser for ShakeMap grid.xml metadata.
 *
 * Accepts a ShakeMap object and updates the properties of that product based on
 * the product's grid.xml file.
 */
public class GridXMLHandler extends DefaultHandler {

  // ShakeMap grid parameters
  /** Element for shakemap grid */
  public static final String SHAKEMAPGRID_ELEMENT = "shakemap_grid";
  /** Shakemap grid id */
  public static final String SHAKEMAPGRID_ID = "shakemap_id";
  /** Shakemap grid originator */
  public static final String SHAKEMAPGRID_ORIGINATOR = "shakemap_originator";
  /** Shakemap grid process timestamp */
  public static final String SHAKEMAPGRID_TIMESTAMP = "process_timestamp";
  /** Shakemap grid version */
  public static final String SHAKEMAPGRID_VERSION = "shakemap_version";
  /** Shakemap grid event type */
  public static final String SHAKEMAPGRID_EVENT_TYPE = "shakemap_event_type";
  /** Shakemap grid event/map status */
  public static final String SHAKEMAPGRID_EVENT_STATUS = "map_status";

  // ShakeMap event parameters
  /** Element for event */
  public static final String EVENT_ELEMENT = "event";
  /** Event latitude */
  public static final String EVENT_LATITUDE = "lat";
  /** Event longitude */
  public static final String EVENT_LONGITUDE = "lon";
  /** Event magnitude */
  public static final String EVENT_MAGNITUDE = "magnitude";
  /** Event timestamp */
  public static final String EVENT_TIMESTAMP = "event_timestamp";
  /** Event description */
  public static final String EVENT_DESCRIPTION = "event_description";
  /** Event depth */
  public static final String EVENT_DEPTH = "depth";

  // These are new parameters used by GSM when it is contributing to a
  // different
  // network as a backup
  /** GSM Parameter when using a different network as a backup */
  public static final String EVENT_NETWORK = "event_network";
  /** GSM Parameter when using a different network as a backup */
  public static final String EVENT_ID = "event_id";

  // ShakeMap gridspec parameters
  /** Element for grid specification */
  public static final String GRIDSPEC_ELEMENT = "grid_specification";
  /** gridspec longitude min */
  public static final String GRIDSPEC_LONMIN = "lon_min";
  /** gridspec longitude max */
  public static final String GRIDSPEC_LONMAX = "lon_max";
  /** gridspec latitude min */
  public static final String GRIDSPEC_LATMIN = "lat_min";
  /** gridspec latitude max */
  public static final String GRIDSPEC_LATMAX = "lat_max";

  /** XML for SHAKEMAPGRID_ELEMENT */
  public static final String SHAKEMAPGRID_ELEMENT_XML = SHAKEMAPGRID_ELEMENT;
  /** XML for SHAKEMAPGRID_ID */
  public static final String SHAKEMAPGRID_ID_XML = SHAKEMAPGRID_ELEMENT + "[" + SHAKEMAPGRID_ID + "]";
  /** XML for SHAKEMAPGRID_ORIGINATOR */
  public static final String SHAKEMAPGRID_ORIGINATOR_XML = SHAKEMAPGRID_ELEMENT + "[" + SHAKEMAPGRID_ORIGINATOR + "]";
  /** XML for SHAKEMAPGRID_TIMESTAMP */
  public static final String SHAKEMAPGRID_TIMESTAMP_XML = SHAKEMAPGRID_ELEMENT + "[" + SHAKEMAPGRID_TIMESTAMP + "]";
  /** XML for SHAKEMAPGRID_VERSION */
  public static final String SHAKEMAPGRID_VERSION_XML = SHAKEMAPGRID_ELEMENT + "[" + SHAKEMAPGRID_VERSION + "]";
  /** XML for SHAKEMAPGRID_EVENT_TYPE */
  public static final String SHAKEMAPGRID_EVENT_TYPE_XML = SHAKEMAPGRID_ELEMENT + "[" + SHAKEMAPGRID_EVENT_TYPE + "]";
  /** XML for SHAKEMAPGRID_EVENT_STATUS */
  public static final String SHAKEMAPGRID_EVENT_STATUS_XML = SHAKEMAPGRID_ELEMENT + "[" + SHAKEMAPGRID_EVENT_STATUS
      + "]";

  /** XML for EVENT_ELEMENT */
  public static final String EVENT_ELEMENT_XML = EVENT_ELEMENT;
  /** XML for EVENT_LATITUDE */
  public static final String EVENT_LATITUDE_XML = EVENT_ELEMENT + "[" + EVENT_LATITUDE + "]";
  /** XML for EVENT_LONGITUDE */
  public static final String EVENT_LONGITUDE_XML = EVENT_ELEMENT + "[" + EVENT_LONGITUDE + "]";
  /** XML for EVENT_MAGNITUDE */
  public static final String EVENT_MAGNITUDE_XML = EVENT_ELEMENT + "[" + EVENT_MAGNITUDE + "]";
  /** XML for EVENT_TIMESTAMP */
  public static final String EVENT_TIMESTAMP_XML = EVENT_ELEMENT + "[" + EVENT_TIMESTAMP + "]";
  /** XML for EVENT_DESCRIPTION */
  public static final String EVENT_DESCRIPTION_XML = EVENT_ELEMENT + "[" + EVENT_DESCRIPTION + "]";
  /** XML for EVENT_DEPTH */
  public static final String EVENT_DEPTH_XML = EVENT_ELEMENT + "[" + EVENT_DEPTH + "]";
  /** XML for EVENT_NETWORK */
  public static final String EVENT_NETWORK_XML = EVENT_ELEMENT + "[" + EVENT_NETWORK + "]";
  /** XML for EVENT_ID */
  public static final String EVENT_ID_XML = EVENT_ELEMENT + "[" + EVENT_ID + "]";

  /** XML for GRIDSPEC_ELEMENT */
  public static final String GRIDSPEC_ELEMENT_XML = GRIDSPEC_ELEMENT;
  /** XML for GRIDSPEC_LONMIN */
  public static final String GRIDSPEC_LONMIN_XML = GRIDSPEC_ELEMENT + "[" + GRIDSPEC_LONMIN + "]";
  /** XML for GRIDSPEC_LONMAX */
  public static final String GRIDSPEC_LONMAX_XML = GRIDSPEC_ELEMENT + "[" + GRIDSPEC_LONMAX + "]";
  /** XML for GRIDSPEC_LATMIN */
  public static final String GRIDSPEC_LATMIN_XML = GRIDSPEC_ELEMENT + "[" + GRIDSPEC_LATMIN + "]";
  /** XML for GRIDSPEC_LATMAX */
  public static final String GRIDSPEC_LATMAX_XML = GRIDSPEC_ELEMENT + "[" + GRIDSPEC_LATMAX + "]";

  // ShakeMap griddata parameters
  /** Element for Shakemap griddata */
  public static final String GRIDDATA_ELEMENT = "grid_data";
  /** Shakemap griddata parameter to stop parsing before */
  public static final String STOP_PARSING_BEFORE_GRIDDATA = "Stop parsing before grid data.";

  private HashMap<String, String> grid = new HashMap<String, String>();

  /**
   * Construct a new SAX Handler for an grid.xml document.
   */
  public GridXMLHandler() {
  }

  /**
   * @param in - the file or stream to parse
   * @return the ShakeMap associated with this XML handler
   * @throws Exception if error occurs
   */
  public HashMap<String, String> parse(final Object in) throws Exception {
    try {
      XmlUtils.parse(in, this);
    } catch (Exception se) {
      if (!se.getMessage().equals(STOP_PARSING_BEFORE_GRIDDATA)) {
        throw se;
      }
    }
    return this.grid;
  }

  /**
   * @return the parsed info.
   */
  public HashMap<String, String> getInfo() {
    return this.grid;
  }

  /**
   * Read grid, event, and gridspec element attributes.
   *
   * @param uri        namespace of element.
   * @param localName  name of element.
   * @param qName      qualified name of element.
   * @param attributes element attributes.
   * @throws SAXException when griddata element is reached, to stop parsing.
   */
  public final void startElement(final String uri, final String localName, final String qName,
      final Attributes attributes) throws SAXException {

    if (localName != null && GRIDDATA_ELEMENT.equals(localName)) {
      // don't read the whole grid
      throw new SAXException(STOP_PARSING_BEFORE_GRIDDATA);
    }

    if (localName.equals(SHAKEMAPGRID_ELEMENT)) {
      this.grid.put(SHAKEMAPGRID_ORIGINATOR_XML, attributes.getValue(SHAKEMAPGRID_ORIGINATOR));
      this.grid.put(SHAKEMAPGRID_ID_XML, attributes.getValue(SHAKEMAPGRID_ID));
      this.grid.put(SHAKEMAPGRID_TIMESTAMP_XML, attributes.getValue(SHAKEMAPGRID_TIMESTAMP));
      this.grid.put(SHAKEMAPGRID_VERSION_XML, attributes.getValue(SHAKEMAPGRID_VERSION));
      this.grid.put(SHAKEMAPGRID_EVENT_TYPE_XML, attributes.getValue(SHAKEMAPGRID_EVENT_TYPE));
      this.grid.put(SHAKEMAPGRID_EVENT_STATUS_XML, attributes.getValue(SHAKEMAPGRID_EVENT_STATUS));
    } else if (localName.equals(EVENT_ELEMENT)) {
      this.grid.put(EVENT_LATITUDE_XML, attributes.getValue(EVENT_LATITUDE));
      this.grid.put(EVENT_LONGITUDE_XML, attributes.getValue(EVENT_LONGITUDE));
      this.grid.put(EVENT_MAGNITUDE_XML, attributes.getValue(EVENT_MAGNITUDE));
      this.grid.put(EVENT_DEPTH_XML, attributes.getValue(EVENT_DEPTH));
      this.grid.put(EVENT_TIMESTAMP_XML, attributes.getValue(EVENT_TIMESTAMP));
      this.grid.put(EVENT_DESCRIPTION_XML, attributes.getValue(EVENT_DESCRIPTION));
      this.grid.put(EVENT_NETWORK_XML, attributes.getValue(EVENT_NETWORK));
      this.grid.put(EVENT_ID_XML, attributes.getValue(EVENT_ID));
    } else if (localName.equals(GRIDSPEC_ELEMENT)) {
      this.grid.put(GRIDSPEC_LONMIN_XML, attributes.getValue(GRIDSPEC_LONMIN));
      this.grid.put(GRIDSPEC_LATMIN_XML, attributes.getValue(GRIDSPEC_LATMIN));
      this.grid.put(GRIDSPEC_LONMAX_XML, attributes.getValue(GRIDSPEC_LONMAX));
      this.grid.put(GRIDSPEC_LATMAX_XML, attributes.getValue(GRIDSPEC_LATMAX));
    }
  }
}