ShakeMap.java
package gov.usgs.earthquake.shakemap;
import gov.usgs.earthquake.product.Content;
import gov.usgs.earthquake.product.Product;
import gov.usgs.util.StreamUtils;
import gov.usgs.util.XmlUtils;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* ShakeMap object to add additional Product properties based on contents.
*
* This subclass of Product provides access to additional ShakeMap-specific
* attributes and loads these attributes, as well as additional Product
* attributes from ShakeMap source XML files.
*/
public class ShakeMap extends Product {
/** Property for event description */
public static final String EVENT_DESCRIPTION_PROPERTY = "event-description";
/** Property for event type */
public static final String EVENT_TYPE_PROPERTY = "event-type";
/** Property for map status */
public static final String MAP_STATUS_PROPERTY = "map-status";
/** Property for max latitude */
public static final String MAXIMUM_LATITUDE_PROPERTY = "maximum-latitude";
/** Property for max longitude */
public static final String MAXIMUM_LONGITUDE_PROPERTY = "maximum-longitude";
/** Property for min latitude */
public static final String MINIMUM_LATITUDE_PROPERTY = "minimum-latitude";
/** Property for min longitude */
public static final String MINIMUM_LONGITUDE_PROPERTY = "minimum-longitude";
/** Property for process timestamp */
public static final String PROCESS_TIMESTAMP_PROPERTY = "process-timestamp";
private static final Logger LOGGER = Logger.getLogger(ShakeMap.class
.getName());
/** References to file content in the Product */
public static final String GRID_XML_ATTACHMENT = "download/grid.xml";
/** References to file content in the Product */
public static final String INFO_XML_ATTACHMENT = "download/info.xml";
// The files below have been decided to be unsupported at this time to
// encourage
// adoption of grid.xml by all networks.
// public static final String GRID_XYZ_ATTACHMENT = "download/grid.xyz.zip";
// public static final String STATIONLIST_XML_ATTACHMENT =
// "download/stationlist.xml";
/** Invisible attachment */
public static final String INVISIBLE_ATTACHMENT = ".invisible";
/** A suffix added to all event codes for scenarios */
public static final String SCENARIO_ID_SUFFIX = "_se";
// Map types
/** Map type - actual */
public static final String ACTUAL = "ACTUAL";
/** Map type - scenario */
public static final String SCENARIO = "SCENARIO";
/** Map type - test */
public static final String TEST = "TEST";
/** key in info.xml for maximum mmi */
public static final String MAXIMUM_MMI_INFO_KEY = "mi_max";
/** Property for max MMI */
public static final String MAXIMUM_MMI_PROPERTY = "maxmmi";
/**
* @param product
* the base product to be converted to a ShakeMap product
*/
public ShakeMap(final Product product) {
super(product);
// prefer grid attachment
Content gridxml = product.getContents().get(GRID_XML_ATTACHMENT);
if (gridxml != null) {
InputStream gridXmlIn = null;
try {
// parse grid.xml
GridXMLHandler gridxmlHandler = new GridXMLHandler();
gridXmlIn = gridxml.getInputStream();
HashMap<String, String> grid = gridxmlHandler.parse(gridXmlIn);
// parse through hash maps to set shakemap properties
this.setGridXMLProperties(grid);
} catch (Exception e) {
// error parsing grid
LOGGER.log(Level.WARNING, "error parsing grid.xml", e);
} finally {
StreamUtils.closeStream(gridXmlIn);
}
}
Content infoxml = product.getContents().get(INFO_XML_ATTACHMENT);
if (infoxml != null) {
InputStream infoXmlIn = null;
try {
// parse info.xml
InfoXMLHandler infoxmlHandler = new InfoXMLHandler();
infoXmlIn = infoxml.getInputStream();
HashMap<String, String> info = infoxmlHandler.parse(infoXmlIn);
// parse through hash maps to set shakemap properties
this.setInfoXMLProperties(info);
} catch (Exception e) {
LOGGER.log(Level.WARNING, "error parsing info.xml", e);
} finally {
StreamUtils.closeStream(infoXmlIn);
}
}
/*
* else { // At this time we are disabling all non-grid.xml
* functionality // as all shakemaps sent in should have a grid.xml
* file.
*
* //otherwise try gridXYZ (has most) + stationlist (has depth) source =
* product.getContents().get(GRID_XYZ_ATTACHMENT); if (source != null) {
* GridXYZHandler handler = new GridXYZHandler(this); try {
* handler.parse(source.getInputStream()); } catch (Exception e) {
* //error parsing gridxyz throw new IllegalArgumentException(e); } }
*
* source = product.getContents().get(STATIONLIST_XML_ATTACHMENT); if
* (source != null) { StationlistXMLHandler handler = new
* StationlistXMLHandler(this); try {
* handler.parse(source.getInputStream()); } catch (Exception e) {
* //error parsing stationlist throw new IllegalArgumentException(e); }
* } }
*/
}
/**
* @param gridXML
* shakemap properties hash keyed by grid.xml attribute name
*/
public void setGridXMLProperties (HashMap<String, String> gridXML) {
String depth;
String eventDescription;
String eventId;
String eventSource;
String eventSourceCode;
String eventTime;
String eventType;
String latitude;
String longitude;
String magnitude;
String mapStatus;
String maximumLatitude;
String maximumLongitude;
String minimumLatitude;
String minimumLongitude;
String processTimestamp;
String version;
// eventId
eventSource = gridXML.get(GridXMLHandler.EVENT_NETWORK_XML);
eventSourceCode = gridXML.get(GridXMLHandler.EVENT_ID_XML);
eventId = eventSource + eventSourceCode;
if (valueIsEmpty(getEventId(), eventId)) {
setEventId(eventSource, eventSourceCode);
}
// less preferred eventId (if not already set)
eventSource = gridXML.get(GridXMLHandler.SHAKEMAPGRID_ORIGINATOR_XML);
eventSourceCode = gridXML.get(GridXMLHandler.SHAKEMAPGRID_ID_XML);
eventId = eventSource + eventSourceCode;
if (valueIsEmpty(getEventId(), eventId)) {
setEventId(eventSource, eventSourceCode);
}
// ShakeMap Metadata
processTimestamp = gridXML.get(GridXMLHandler.SHAKEMAPGRID_TIMESTAMP_XML);
if (valueIsEmpty(XmlUtils.formatDate(getProcessTimestamp()), processTimestamp)) {
setProcessTimestamp(XmlUtils.getDate(processTimestamp));
}
version = gridXML.get(GridXMLHandler.SHAKEMAPGRID_VERSION_XML);
if (valueIsEmpty(getVersion(), version)) {
setVersion(version);
}
eventType = gridXML.get(GridXMLHandler.SHAKEMAPGRID_EVENT_TYPE_XML);
if (valueIsEmpty(getEventType(), eventType)) {
setEventType(eventType);
}
mapStatus = gridXML.get(GridXMLHandler.SHAKEMAPGRID_EVENT_STATUS_XML);
if (valueIsEmpty(getMapStatus(), mapStatus)) {
setMapStatus(mapStatus);
}
// ShakeMap Grid
minimumLongitude = gridXML.get(GridXMLHandler.GRIDSPEC_LONMIN_XML);
if (valueIsEmpty(getString(getMinimumLongitude()), minimumLongitude)) {
setMinimumLongitude(getBigDecimal(minimumLongitude));
}
maximumLongitude = gridXML.get(GridXMLHandler.GRIDSPEC_LONMAX_XML);
if (valueIsEmpty(getString(getMaximumLongitude()), maximumLongitude)) {
setMaximumLongitude(getBigDecimal(maximumLongitude));
}
minimumLatitude = gridXML.get(GridXMLHandler.GRIDSPEC_LATMIN_XML);
if (valueIsEmpty(getString(getMinimumLatitude()), minimumLatitude)) {
setMinimumLatitude(getBigDecimal(minimumLatitude));
}
maximumLatitude = gridXML.get(GridXMLHandler.GRIDSPEC_LATMAX_XML);
if (valueIsEmpty(getString(getMaximumLatitude()), maximumLatitude)) {
setMaximumLatitude(getBigDecimal(maximumLatitude));
}
// Event
latitude = gridXML.get(GridXMLHandler.EVENT_LATITUDE_XML);
if (valueIsEmpty(getString(getLatitude()), latitude)) {
setLatitude(getBigDecimal(latitude));
}
longitude = gridXML.get(GridXMLHandler.EVENT_LONGITUDE_XML);
if (valueIsEmpty(getString(getLongitude()), longitude)) {
setLongitude(getBigDecimal(longitude));
}
magnitude = gridXML.get(GridXMLHandler.EVENT_MAGNITUDE_XML);
if (valueIsEmpty(getString(getMagnitude()), magnitude)) {
setMagnitude(getBigDecimal(magnitude));
}
depth = gridXML.get(GridXMLHandler.EVENT_DEPTH_XML);
if (valueIsEmpty(getString(getDepth()), depth)) {
setDepth(getBigDecimal(depth));
}
eventTime = gridXML.get(GridXMLHandler.EVENT_TIMESTAMP_XML)
.replace("GMT", "Z")
.replace("UTC","Z");
if (valueIsEmpty(XmlUtils.formatDate(getEventTime()), eventTime)) {
setEventTime(XmlUtils.getDate(eventTime));
}
eventDescription = gridXML.get(GridXMLHandler.EVENT_DESCRIPTION_XML);
if (valueIsEmpty(getEventDescription(), eventDescription)) {
setEventDescription(eventDescription);
}
};
/**
* @param infoXML
* shakemap properties hash keyed by info.xml attribute name
*/
public void setInfoXMLProperties (HashMap<String, String> infoXML) {
// read maxmmi from info.xml
if (infoXML.containsKey(MAXIMUM_MMI_INFO_KEY)) {
this.getProperties().put(MAXIMUM_MMI_PROPERTY,
infoXML.get(MAXIMUM_MMI_INFO_KEY));
}
};
/**
* @param productValue
* the value from the PDL object
* @param xmlValue
* the value from the XML document
* @return if the shakemap property is already set
*/
public boolean valueIsEmpty (String productValue, String xmlValue) {
// nothing to be set
if (xmlValue == null) {
return false;
}
// no value has been set
if (productValue == null) {
return true;
}
// value is set and values are different, log warning
if (!productValue.equals(xmlValue)) {
LOGGER.log(Level.FINE,
"The ShakeMap property value: \"" + xmlValue + "\"" +
" does not match the product value: \"" + productValue + "\".");
}
return false;
}
/**
* @param mapStatus
* the map status to set
*/
public void setMapStatus(String mapStatus) {
getProperties().put(MAP_STATUS_PROPERTY, mapStatus);
}
/**
* @return the status of this map
*/
public String getMapStatus() {
return getProperties().get(MAP_STATUS_PROPERTY);
}
/**
* @param eventType
* the event type to set
*/
public void setEventType(String eventType) {
getProperties().put(EVENT_TYPE_PROPERTY, eventType);
}
/**
* @return the event type of this product as defined in ShakeMap
*/
public String getEventType() {
return getProperties().get(EVENT_TYPE_PROPERTY);
}
/**
* @param processTimestamp
* the process timestamp to set
*/
public void setProcessTimestamp(Date processTimestamp) {
getProperties().put(PROCESS_TIMESTAMP_PROPERTY,
XmlUtils.formatDate(processTimestamp));
}
/**
* @return the process timestamp of this ShakeMap
*/
public Date getProcessTimestamp() {
return XmlUtils
.getDate(getProperties().get(PROCESS_TIMESTAMP_PROPERTY));
}
/**
* @return the event description text for this ShakeMap
*/
public String getEventDescription() {
return getProperties().get(EVENT_DESCRIPTION_PROPERTY);
}
/**
* @param eventDescription
* the event description to set
*/
public void setEventDescription(String eventDescription) {
getProperties().put(EVENT_DESCRIPTION_PROPERTY, eventDescription);
}
/**
* @return the minimum longitude boundary of this ShakeMap
*/
public BigDecimal getMinimumLongitude() {
return getBigDecimal(getProperties().get(MINIMUM_LONGITUDE_PROPERTY));
}
/**
* @param minimumLongitude
* the minimum longitude to set
*/
public void setMinimumLongitude(BigDecimal minimumLongitude) {
getProperties().put(MINIMUM_LONGITUDE_PROPERTY,
minimumLongitude.toPlainString());
}
/**
* @return the maximum longitude boundary of this ShakeMap
*/
public BigDecimal getMaximumLongitude() {
return getBigDecimal(getProperties().get(MAXIMUM_LONGITUDE_PROPERTY));
}
/**
* @param maximumLongitude
* the maximum longitude to set
*/
public void setMaximumLongitude(BigDecimal maximumLongitude) {
getProperties().put(MAXIMUM_LONGITUDE_PROPERTY,
maximumLongitude.toPlainString());
}
/**
* @return the minimum latitude boundary of this ShakeMap
*/
public BigDecimal getMinimumLatitude() {
return getBigDecimal(getProperties().get(MINIMUM_LATITUDE_PROPERTY));
}
/**
* @param minimumLatitude
* the minimum latitude to set
*/
public void setMinimumLatitude(BigDecimal minimumLatitude) {
getProperties().put(MINIMUM_LATITUDE_PROPERTY,
minimumLatitude.toPlainString());
}
/**
* @return the maximum latitude boundary of this ShakeMap
*/
public BigDecimal getMaximumLatitude() {
return getBigDecimal(getProperties().get(MAXIMUM_LATITUDE_PROPERTY));
}
/**
* @param maximumLatitude
* the maximum latitude to set
*/
public void setMaximumLatitude(BigDecimal maximumLatitude) {
getProperties().put(MAXIMUM_LATITUDE_PROPERTY,
maximumLatitude.toPlainString());
}
/**
* Returns String value as BigDecimal
* @param value to return as BigDecimal
* @return a BigDecimal
*/
protected BigDecimal getBigDecimal (String value) {
if (value == null) {
return null;
}
return new BigDecimal(value);
}
/**
* Returns BigDecimal value as String
* @param value a BigDecimal
* @return a string
*/
protected String getString (BigDecimal value) {
if (value == null) {
return null;
}
return value.toString();
}
}