EQMessageProductCreator.java
- package gov.usgs.earthquake.eids;
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.math.BigDecimal;
- import java.util.Date;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Map;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- //Does it make sense to import objects from quakeml when we're parsing eqxml?
- //import org.quakeml.FocalMechanism;
- //import org.quakeml.NodalPlane;
- //import org.quakeml.NodalPlanes;
- import gov.usgs.ansseqmsg.Action;
- import gov.usgs.ansseqmsg.Comment;
- import gov.usgs.ansseqmsg.EQMessage;
- import gov.usgs.ansseqmsg.EventAction;
- import gov.usgs.ansseqmsg.EventScope;
- import gov.usgs.ansseqmsg.EventType;
- import gov.usgs.ansseqmsg.EventUsage;
- import gov.usgs.ansseqmsg.Fault;
- import gov.usgs.ansseqmsg.Magnitude;
- import gov.usgs.ansseqmsg.Method;
- import gov.usgs.ansseqmsg.MomentTensor;
- import gov.usgs.ansseqmsg.NodalPlanes;
- import gov.usgs.ansseqmsg.Origin;
- import gov.usgs.ansseqmsg.Event;
- import gov.usgs.ansseqmsg.ProductLink;
- import gov.usgs.ansseqmsg.Tensor;
- import gov.usgs.earthquake.cube.CubeAddon;
- import gov.usgs.earthquake.cube.CubeDelete;
- import gov.usgs.earthquake.cube.CubeEvent;
- import gov.usgs.earthquake.cube.CubeMessage;
- import gov.usgs.earthquake.eqxml.EQMessageParser;
- import gov.usgs.earthquake.event.Converter;
- import gov.usgs.earthquake.product.ByteContent;
- import gov.usgs.earthquake.product.Content;
- import gov.usgs.earthquake.product.Product;
- import gov.usgs.earthquake.product.ProductId;
- import gov.usgs.util.FileUtils;
- import gov.usgs.util.StreamUtils;
- import gov.usgs.util.XmlUtils;
- /**
- * Convert EQXML messages to Products.
- *
- * <p>
- * Product source is EQMessage/Source.
- * </p>
- * <p>
- * Product type is "origin", "magnitude", or "addon". Types may be prefixed by
- * non-Public Event/Scope, and suffixed by non-Actual Event/Usage
- * (internal-magnitude-scenario).
- * </p>
- * <p>
- * Product code is Event/DataSource + Event/EventId. When an addon product,
- * either ProductLink/Code or Comment/TypeKey is appended to code.
- * </p>
- * <p>
- * Product updateTime is EQMessage/Sent.
- * </p>
- *
- * <p>
- * Origin properties appear only on origin type products. Magnitude properties
- * appear on both magnitude and origin products.
- * </p>
- */
- public class EQMessageProductCreator implements ProductCreator {
- private static final Logger LOGGER = Logger
- .getLogger(EQMessageProductCreator.class.getName());
- /** Static var for the xml content type */
- public static final String XML_CONTENT_TYPE = "application/xml";
- /** Path to content where source message is stored in created product. */
- public static final String EQMESSAGE_CONTENT_PATH = "eqxml.xml";
- /** Path to contests xml */
- public static final String CONTENTS_XML_PATH = "contents.xml";
- /**
- * When phases exist is is a "phase" type product. When this flag is set to
- * true, a lightweight, origin-only type product is also sent.
- */
- private boolean sendOriginWhenPhasesExist = false;
- /**
- * Whether to validate when parsing and serializing. When validating, only
- * native EQXML is supported via the ProductCreator interface.
- */
- private boolean validate = false;
- // the eqmessage currently being processed.
- private EQMessage eqmessage;
- // xml for the eqmessage currently being processed
- private String eqmessageXML;
- private String eqmessageSource;
- private Date eqmessageSent;
- private String eventDataSource;
- private String eventEventId;
- private String eventVersion;
- private EventAction eventAction;
- private EventUsage eventUsage;
- private EventScope eventScope;
- private BigDecimal originLatitude;
- private BigDecimal originLongitude;
- private BigDecimal originDepth;
- private Date originEventTime;
- private BigDecimal magnitude;
- /**
- * Default, empty constructor.
- */
- public EQMessageProductCreator() {
- }
- /**
- * Get all the products contained in an EQMessage.
- *
- * Same as getEQMessageProducts(message, null).
- *
- * @param message
- * the EQMessage containing products.
- * @return a list of created products.
- * @throws Exception if error occurs
- */
- public synchronized List<Product> getEQMessageProducts(
- final EQMessage message) throws Exception {
- return getEQMessageProducts(message, null);
- }
- /**
- * Get all the products contained in an EQMessage.
- *
- * Parses rawEqxml string into an EQMessage, but preserves raw eqxml in
- * created products.
- *
- * Same as getEQMessageProducts(EQMessageParser.parse(rawEqxml), rawEqxml);
- *
- * @param rawEqxml
- * the raw EQXML message.
- * @return a list of created products.
- * @throws Exception if error occurs
- */
- public synchronized List<Product> getEQMessageProducts(final String rawEqxml)
- throws Exception {
- EQMessage message = EQMessageParser.parse(rawEqxml, validate);
- return getEQMessageProducts(message, rawEqxml);
- }
- /**
- * Get all the products contained in an EQMessage.
- *
- * @param message
- * the EQMessage containing products.
- * @param rawEqxml
- * the raw EQXML message. When null, an EQXML message is
- * serialized from the object.
- * @return a list of created products.
- * @throws Exception if error occurs
- */
- public synchronized List<Product> getEQMessageProducts(
- final EQMessage message, final String rawEqxml) throws Exception {
- List<Product> products = new LinkedList<Product>();
- if (message == null) {
- return products;
- }
- this.eqmessage = message;
- this.eqmessageSource = message.getSource();
- this.eqmessageSent = message.getSent();
- if (this.eqmessageSent == null) {
- this.eqmessageSent = new Date();
- }
- // convert to xml
- if (rawEqxml != null) {
- this.eqmessageXML = rawEqxml;
- } else {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- EQMessageParser.serialize(message, baos, validate);
- this.eqmessageXML = baos.toString();
- }
- // process each event
- List<Event> events = message.getEvent();
- if (events != null) {
- Iterator<Event> iter = events.iterator();
- while (iter.hasNext()) {
- products.addAll(getEventProducts(iter.next()));
- }
- }
- this.eqmessageSource = null;
- this.eqmessageSent = null;
- this.eqmessageXML = null;
- return products;
- }
- /**
- * Get products from an event.
- *
- * @param event
- * the event containing products.
- * @return a list of created products.
- * @throws Exception if error occurs
- */
- protected synchronized List<Product> getEventProducts(final Event event)
- throws Exception {
- List<Product> products = new LinkedList<Product>();
- if (event == null) {
- return products;
- }
- eventDataSource = event.getDataSource();
- eventEventId = event.getEventID();
- eventVersion = event.getVersion();
- eventAction = event.getAction();
- eventUsage = event.getUsage();
- eventScope = event.getScope();
- // default values
- if (eventAction == null) {
- eventAction = EventAction.UPDATE;
- }
- if (eventUsage == null) {
- eventUsage = EventUsage.ACTUAL;
- }
- if (eventScope == null) {
- eventScope = EventScope.PUBLIC;
- }
- if (eventAction == EventAction.DELETE) {
- // delete origin product (only product with location)
- Product deleteProduct = getProduct("origin", eventAction.toString());
- products.add(deleteProduct);
- } else {
- // update origin product
- products.addAll(getOriginProducts(event.getOrigin(), event));
- }
- for (ProductLink eventLink : event.getProductLink()) {
- products.addAll(getProductLinkProducts(eventLink));
- }
- for (Comment eventComment : event.getComment()) {
- products.addAll(getCommentProducts(eventComment));
- }
- eventDataSource = null;
- eventEventId = null;
- eventVersion = null;
- eventAction = null;
- eventUsage = null;
- eventScope = null;
- return products;
- }
- /**
- * Get origin product(s).
- *
- * This implementation only creates one origin (the first one) regardless of
- * how many origins are provided.
- *
- * @param origins
- * the list of origins.
- * @param event
- * A specific event
- * @return a list of created products.
- * @throws Exception if error occurs
- */
- protected synchronized List<Product> getOriginProducts(
- final List<Origin> origins, final Event event) throws Exception {
- List<Product> products = new LinkedList<Product>();
- if (origins == null || origins.size() == 0) {
- return products;
- }
- // only process first origin
- Origin origin = origins.get(0);
- // get sub-products
- products.addAll(getFocalMechanismProducts(origin.getMomentTensor()));
- this.originLatitude = origin.getLatitude();
- this.originLongitude = origin.getLongitude();
- this.originDepth = origin.getDepth();
- this.originEventTime = origin.getTime();
- boolean preferred = (origin.getPreferredFlag() == null || origin
- .getPreferredFlag());
- // only process "preferred" origins
- // this is how hydra differentiates between origins as input parameters
- // to focal mechanisms, and origins as origins
- if (preferred && this.originLatitude != null
- && this.originLongitude != null && this.originEventTime != null) {
- // create an origin/magnitude product only if origin has
- // lat+lon+time
- List<Product> magnitudeProducts = getMagnitudeProducts(origin
- .getMagnitude());
- // now build origin product
- Action originAction = origin.getAction();
- Product originProduct = getProduct("origin",
- originAction == null ? null : originAction.toString());
- // origin specific properties
- Map<String, String> properties = originProduct.getProperties();
- // set event type
- properties.put(
- "event-type",
- (event.getType() == null ? EventType.EARTHQUAKE : event
- .getType()).value().toLowerCase());
- if (magnitudeProducts.size() > 0) {
- // transfer magnitude product properties to origin
- properties.putAll(magnitudeProducts.get(0).getProperties());
- }
- if (origin.getSourceKey() != null) {
- properties.put("origin-source", origin.getSourceKey());
- }
- if (origin.getAzimGap() != null) {
- properties.put("azimuthal-gap", origin.getAzimGap().toString());
- }
- if (origin.getDepthError() != null) {
- properties
- .put("depth-error", origin.getDepthError().toString());
- }
- if (origin.getDepthMethod() != null) {
- properties.put("depth-method", origin.getDepthMethod());
- }
- if (origin.getErrh() != null) {
- properties.put("horizontal-error", origin.getErrh().toString());
- }
- if (origin.getErrz() != null) {
- properties.put("vertical-error", origin.getErrz().toString());
- }
- if (origin.getLatError() != null) {
- properties.put("latitude-error", origin.getLatError()
- .toString());
- }
- if (origin.getLonError() != null) {
- properties.put("longitude-error", origin.getLonError()
- .toString());
- }
- if (origin.getMinDist() != null) {
- properties.put("minimum-distance", origin.getMinDist()
- .toString());
- }
- if (origin.getNumPhaUsed() != null) {
- properties.put("num-phases-used", origin.getNumPhaUsed()
- .toString());
- }
- if (origin.getNumStaUsed() != null) {
- properties.put("num-stations-used", origin.getNumStaUsed()
- .toString());
- }
- if (origin.getRegion() != null) {
- properties.put("region", origin.getRegion());
- }
- if (origin.getStatus() != null) {
- properties.put("review-status", origin.getStatus().toString());
- }
- if (origin.getStdError() != null) {
- properties.put("standard-error", origin.getStdError()
- .toString());
- }
- // origin method
- Iterator<Method> methods = origin.getMethod().iterator();
- if (methods.hasNext()) {
- Method method = methods.next();
- if (method.getClazz() != null) {
- properties.put("location-method-class", method.getClazz());
- }
- if (method.getAlgorithm() != null) {
- properties.put("location-method-algorithm",
- method.getAlgorithm());
- }
- if (method.getModel() != null) {
- properties.put("location-method-model", method.getModel());
- }
- String cubeLocationMethod = getCubeCode(method.getComment());
- if (cubeLocationMethod != null) {
- properties.put("cube-location-method", cubeLocationMethod);
- }
- }
- if (origin.getPhase() != null && origin.getPhase().size() > 0) {
- originProduct.getId().setType("phase-data");
- products.add(originProduct);
- if (sendOriginWhenPhasesExist) {
- // create lightweight origin product
- Product lightweightOrigin = new Product(originProduct);
- lightweightOrigin.getId().setType("origin");
- lightweightOrigin.getContents().remove(
- EQMESSAGE_CONTENT_PATH);
- // seek and destroy phases
- Iterator<Origin> iter = origins.iterator();
- while (iter.hasNext()) {
- Origin next = iter.next();
- if (next.getPhase() != null) {
- next.getPhase().clear();
- }
- }
- // serialize xml without phase data
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- EQMessageParser.serialize(this.eqmessage, baos, validate);
- lightweightOrigin.getContents().put(EQMESSAGE_CONTENT_PATH,
- new ByteContent(baos.toByteArray()));
- products.add(0, lightweightOrigin);
- }
- } else {
- // insert origin at start of list
- products.add(0, originProduct);
- }
- }
- this.originDepth = null;
- this.originEventTime = null;
- this.originLatitude = null;
- this.originLongitude = null;
- this.magnitude = null;
- for (Comment originComment : origin.getComment()) {
- products.addAll(getCommentProducts(originComment));
- }
- return products;
- }
- /**
- * Build magnitude products.
- *
- * This implementation builds at most one magnitude product (the first).
- *
- * @param magnitudes
- * a list of candidate magsnitude objects.
- * @return a list of built magnitude products, which may be empty.
- */
- protected synchronized List<Product> getMagnitudeProducts(
- final List<Magnitude> magnitudes) {
- List<Product> products = new LinkedList<Product>();
- if (magnitudes == null || magnitudes.size() == 0) {
- return products;
- }
- // build product based on the first magnitude
- Magnitude magnitude = magnitudes.get(0);
- // set "globalish" property before getProduct()
- this.magnitude = magnitude.getValue();
- Action magnitudeAction = magnitude.getAction();
- // build magnitude product
- Product product = getProduct("magnitude",
- magnitudeAction == null ? null : magnitudeAction.toString());
- Map<String, String> properties = product.getProperties();
- if (magnitude.getSourceKey() != null) {
- properties.put("magnitude-source", magnitude.getSourceKey());
- }
- if (magnitude.getTypeKey() != null) {
- properties.put("magnitude-type", magnitude.getTypeKey());
- }
- if (magnitude.getAzimGap() != null) {
- properties.put("magnitude-azimuthal-gap", magnitude.getAzimGap()
- .toString());
- }
- if (magnitude.getError() != null) {
- properties.put("magnitude-error", magnitude.getError().toString());
- }
- if (magnitude.getNumStations() != null) {
- properties.put("magnitude-num-stations-used", magnitude
- .getNumStations().toString());
- }
- String cubeMagnitudeType = getCubeCode(magnitude.getComment());
- if (cubeMagnitudeType != null) {
- properties.put("cube-magnitude-type", cubeMagnitudeType);
- }
- // don't clear property here, so origin can borrow magnitude property
- // this.magnitude = null;
- products.add(product);
- return products;
- }
- /**
- * Gets a list of Focal Mechanism products from momentTensors
- * @param momentTensors List of Moment Tensors
- * @return a list of products
- */
- protected synchronized List<Product> getFocalMechanismProducts(
- final List<MomentTensor> momentTensors) {
- List<Product> products = new LinkedList<Product>();
- if (momentTensors == null || momentTensors.size() == 0) {
- return products;
- }
- // build moment tensors
- Iterator<MomentTensor> iter = momentTensors.iterator();
- while (iter.hasNext()) {
- MomentTensor mt = iter.next();
- Action mtAction = mt.getAction();
- // may be set to "moment-tensor" below
- Product product = getProduct("focal-mechanism",
- mtAction == null ? null : mtAction.toString());
- Map<String, String> properties = product.getProperties();
- // fill in product properties
- if (mt.getSourceKey() != null) {
- properties.put("beachball-source", mt.getSourceKey());
- }
- if (mt.getTypeKey() != null) {
- properties.put("beachball-type", mt.getTypeKey());
- // append source+type to code
- ProductId productId = product.getId();
- productId.setCode((productId.getCode() + "-"
- + mt.getSourceKey() + "-" + mt.getTypeKey())
- .toLowerCase());
- }
- if (mt.getMagMw() != null) {
- product.setMagnitude(mt.getMagMw());
- }
- if (mt.getM0() != null) {
- properties.put("scalar-moment", mt.getM0().toString());
- }
- if (mt.getTensor() != null) {
- // if the tensor is included, it is a "moment-tensor" instead of
- // a "focal-mechanism"
- product.getId().setType("moment-tensor");
- Tensor t = mt.getTensor();
- if (t.getMtt() != null) {
- properties.put("tensor-mtt", t.getMtt().toString());
- }
- if (t.getMpp() != null) {
- properties.put("tensor-mpp", t.getMpp().toString());
- }
- if (t.getMrr() != null) {
- properties.put("tensor-mrr", t.getMrr().toString());
- }
- if (t.getMtp() != null) {
- properties.put("tensor-mtp", t.getMtp().toString());
- }
- if (t.getMrp() != null) {
- properties.put("tensor-mrp", t.getMrp().toString());
- }
- if (t.getMrt() != null) {
- properties.put("tensor-mrt", t.getMrt().toString());
- }
- }
- if (mt.getNodalPlanes() != null) {
- NodalPlanes np = mt.getNodalPlanes();
- List<Fault> faults = np.getFault();
- if (faults.size() == 2) {
- Fault fault1 = faults.get(0);
- if (fault1.getDip() != null) {
- properties.put("nodal-plane-1-dip", fault1.getDip()
- .toString());
- }
- if (fault1.getSlip() != null) {
- properties.put("nodal-plane-1-slip", fault1.getSlip()
- .toString());
- }
- if (fault1.getStrike() != null) {
- properties.put("nodal-plane-1-strike", fault1
- .getStrike().toString());
- }
- Fault fault2 = faults.get(1);
- if (fault2.getDip() != null) {
- properties.put("nodal-plane-2-dip", fault2.getDip()
- .toString());
- }
- if (fault2.getSlip() != null) {
- properties.put("nodal-plane-2-slip", fault2.getSlip()
- .toString());
- }
- if (fault2.getStrike() != null) {
- properties.put("nodal-plane-2-strike", fault2
- .getStrike().toString());
- }
- }
- }
- if (mt.getDerivedOriginTime() != null) {
- properties.put("derived-eventtime",
- XmlUtils.formatDate(mt.getDerivedOriginTime()));
- }
- if (mt.getDerivedLatitude() != null) {
- properties.put("derived-latitude", mt.getDerivedLatitude()
- .toString());
- }
- if (mt.getDerivedLongitude() != null) {
- properties.put("derived-longitude", mt.getDerivedLongitude()
- .toString());
- }
- if (mt.getDerivedDepth() != null) {
- properties
- .put("derived-depth", mt.getDerivedDepth().toString());
- }
- if (mt.getPerDblCpl() != null) {
- properties.put("percent-double-couple", mt.getPerDblCpl()
- .toString());
- }
- if (mt.getNumObs() != null) {
- properties.put("num-stations-used", mt.getNumObs().toString());
- }
- // attach original message as product content
- ByteContent xml = new ByteContent(eqmessageXML.getBytes());
- xml.setLastModified(eqmessageSent);
- xml.setContentType("application/xml");
- product.getContents().put(EQMESSAGE_CONTENT_PATH, xml);
- // add to list of built products
- products.add(product);
- }
- return products;
- }
- /**
- * Get product(s) from a ProductLink object.
- *
- * @param link
- * the link object.
- * @return a list of found products.
- * @throws Exception if error occurs
- */
- protected synchronized List<Product> getProductLinkProducts(
- final ProductLink link) throws Exception {
- List<Product> products = new LinkedList<Product>();
- String linkType = getLinkAddonProductType(link.getCode());
- if (linkType == null) {
- LOGGER.finer("No product type found for productlink with code '"
- + link.getCode() + "', skipping");
- return products;
- }
- Action linkAction = link.getAction();
- Product linkProduct = getProduct(linkType, linkAction == null ? null
- : linkAction.toString());
- // remove the EQXML, only send product link attributes with link
- // products
- linkProduct.getContents().clear();
- // add addon code to product code
- ProductId id = linkProduct.getId();
- id.setCode(id.getCode() + "-" + link.getCode().toLowerCase());
- if (link.getVersion() != null) {
- linkProduct.setVersion(link.getVersion());
- }
- Map<String, String> properties = linkProduct.getProperties();
- if (link.getLink() != null) {
- properties.put("url", link.getLink());
- }
- if (link.getNote() != null) {
- properties.put("text", link.getNote());
- }
- if (link.getCode() != null) {
- properties.put("addon-code", link.getCode());
- }
- properties.put("addon-type", link.getTypeKey());
- products.add(linkProduct);
- return products;
- }
- /**
- * Get product(s) from a Comment object.
- *
- * @param comment
- * the comment object.
- * @return a list of found products.
- * @throws Exception if error occurs
- */
- protected synchronized List<Product> getCommentProducts(
- final Comment comment) throws Exception {
- List<Product> products = new LinkedList<Product>();
- // CUBE_Codes are attributes of the containing product.
- String typeKey = comment.getTypeKey();
- if (typeKey != null && !typeKey.equals("CUBE_Code")) {
- String commentType = getTextAddonProductType(typeKey);
- if (commentType == null) {
- LOGGER.finer("No product type found for comment with type '"
- + comment.getTypeKey() + "'");
- return products;
- }
- Action commentAction = comment.getAction();
- Product commentProduct = getProduct(commentType,
- commentAction == null ? null : commentAction.toString());
- // remove the EQXML, only send comment text with comment products
- commentProduct.getContents().clear();
- // one product per comment type
- ProductId id = commentProduct.getId();
- id.setCode(id.getCode() + "_" + comment.getTypeKey().toLowerCase());
- Map<String, String> properties = commentProduct.getProperties();
- properties.put("addon-type", "comment");
- if (comment.getTypeKey() != null) {
- properties.put("code", comment.getTypeKey());
- }
- // store the comment text as content instead of a property, it may
- // contain newlines
- commentProduct.getContents().put("",
- new ByteContent(comment.getText().getBytes()));
- products.add(commentProduct);
- }
- return products;
- }
- /**
- * Build a product skeleton based on the current state.
- *
- * Product type is : [internal-](origin,magnitude,addon)[-(scenario|test)]
- * where the optional scope is not "Public", and the optional usage is not
- * "Actual".
- *
- * @param type
- * short product type, like "origin", "magnitude".
- * @param action
- * override the global message action.
- * @return a Product so that properties and content can be added.
- */
- protected synchronized Product getProduct(final String type,
- final String action) {
- String productType = type;
- // prepend type with non Public scopes (Internal)
- if (eventScope != EventScope.PUBLIC) {
- productType = eventScope.toString() + "-" + productType;
- }
- // append to type with non Actual usages
- if (eventUsage != EventUsage.ACTUAL) {
- productType = productType + "-" + eventUsage.toString();
- }
- // make it all lower case
- productType = productType.toLowerCase();
- // use event id
- String productCode = eventDataSource + eventEventId;
- productCode = productCode.toLowerCase();
- ProductId id = new ProductId(eqmessageSource.toLowerCase(),
- productType, productCode, eqmessageSent);
- Product product = new Product(id);
- // figure out whether this is a delete
- String productAction = action;
- if (productAction == null) {
- productAction = eventAction.toString();
- if (productAction == null) {
- productAction = "Update";
- }
- }
- String productStatus;
- if (productAction.equalsIgnoreCase("Delete")) {
- productStatus = Product.STATUS_DELETE;
- } else {
- productStatus = Product.STATUS_UPDATE;
- }
- product.setStatus(productStatus);
- if (eventDataSource != null && eventEventId != null) {
- product.setEventId(eventDataSource, eventEventId);
- }
- if (originEventTime != null) {
- product.setEventTime(originEventTime);
- }
- if (originLongitude != null) {
- product.setLongitude(originLongitude);
- }
- if (originLatitude != null) {
- product.setLatitude(originLatitude);
- }
- if (originDepth != null) {
- product.setDepth(originDepth);
- }
- if (magnitude != null) {
- product.setMagnitude(magnitude);
- }
- if (eventVersion != null) {
- product.setVersion(eventVersion);
- }
- /*
- * Map<String, String> properties = product.getProperties(); if
- * (eventUsage != null) { properties.put("eqxml-usage",
- * eventUsage.toString()); } if (eventScope != null) {
- * properties.put("eqxml-scope", eventScope.toString()); } if
- * (eventAction != null) { properties.put("eqxml-action",
- * eventAction.toString()); }
- */
- ByteContent xml = new ByteContent(eqmessageXML.getBytes());
- xml.setLastModified(eqmessageSent);
- product.getContents().put(EQMESSAGE_CONTENT_PATH, xml);
- // add contents.xml to product to describe above content
- product.getContents().put(CONTENTS_XML_PATH, getContentsXML());
- return product;
- }
- /**
- * @return a buffer of XML content
- */
- protected Content getContentsXML() {
- StringBuffer buf = new StringBuffer();
- buf.append("<?xml version=\"1.0\"?>\n");
- buf.append("<contents xmlns=\"http://earthquake.usgs.gov/earthquakes/event/contents\">\n");
- buf.append("<file title=\"Earthquake XML (EQXML)\" id=\"eqxml\">\n");
- buf.append("<format type=\"xml\" href=\"")
- .append(EQMESSAGE_CONTENT_PATH).append("\"/>\n");
- buf.append("</file>\n");
- buf.append("<page title=\"Location\" slug=\"location\">\n");
- buf.append("<file refid=\"eqxml\"/>\n");
- buf.append("</page>\n");
- buf.append("</contents>\n");
- ByteContent content = new ByteContent(buf.toString().getBytes());
- content.setLastModified(eqmessageSent);
- // this breaks things
- // content.setContentType("application/xml");
- return content;
- }
- /**
- * Extract a CUBE_Code from a Comment.
- *
- * This is the ISTI convention for preserving CUBE information in EQXML
- * messages. Checks a list of Comment objects for one with
- * TypeKey="CUBE_Code" and Text="CUBE_Code X", where X is the returned cube
- * code.
- *
- * @param comments
- * the list of comments.
- * @return the cube code, or null if not found.
- */
- protected synchronized String getCubeCode(final List<Comment> comments) {
- String cubeCode = null;
- if (comments != null) {
- Iterator<Comment> iter = comments.iterator();
- while (iter.hasNext()) {
- Comment comment = iter.next();
- if (comment.getTypeKey().equals("CUBE_Code")) {
- cubeCode = comment.getText().replace("CUBE_Code ", "");
- break;
- }
- }
- }
- return cubeCode;
- }
- /**
- * @return boolean sendOriginWhenPhasesExist
- */
- public boolean isSendOriginWhenPhasesExist() {
- return sendOriginWhenPhasesExist;
- }
- /** @param sendOriginWhenPhasesExist boolean to set */
- public void setSendOriginWhenPhasesExist(boolean sendOriginWhenPhasesExist) {
- this.sendOriginWhenPhasesExist = sendOriginWhenPhasesExist;
- }
- @Override
- public boolean isValidate() {
- return validate;
- }
- @Override
- public void setValidate(boolean validate) {
- this.validate = validate;
- }
- @Override
- public List<Product> getProducts(File file) throws Exception {
- EQMessage eqxml = null;
- String content = new String(FileUtils.readFile(file));
- String rawEqxml = null;
- // try to read eqxml
- try {
- eqxml = EQMessageParser.parse(
- StreamUtils.getInputStream(content.getBytes()), validate);
- rawEqxml = content;
- } catch (Exception e) {
- if (validate) {
- throw e;
- }
- // try to read cube
- try {
- Converter converter = new Converter();
- CubeMessage cube = converter.getCubeMessage(content);
- eqxml = converter.getEQMessage(cube);
- } catch (Exception e2) {
- if (content.startsWith(CubeEvent.TYPE) ||
- content.startsWith(CubeDelete.TYPE) ||
- content.startsWith(CubeAddon.TYPE)) {
- // throw cube parsing exception
- throw e2;
- } else {
- // log cube parsing exception
- LOGGER.log(Level.FINE, "Unable to parse cube message", e2);
- }
- // try to read eventaddon xml
- try {
- EventAddonParser parser = new EventAddonParser();
- parser.parse(content);
- eqxml = parser.getAddon().getEQMessage();
- } catch (Exception e3) {
- // log eventaddon parsing exception
- LOGGER.log(Level.FINE, "Unable to parse eventaddon", e3);
- // throw original exception
- throw e;
- }
- }
- }
- return this.getEQMessageProducts(eqxml, rawEqxml);
- }
- /** Type for general text */
- public static final String GENERAL_TEXT_TYPE = "general-text";
- /** Empty string array for general text addons */
- public static final String[] GENERAL_TEXT_ADDONS = new String[] {};
- /** Type for scitech text */
- public static final String SCITECH_TEXT_TYPE = "scitech-text";
- /** Empty string array for scitech text addons */
- public static final String[] SCITECH_TEXT_ADDONS = new String[] {};
- /** Type for impact text */
- public static final String IMPACT_TEXT_TYPE = "impact-text";
- /** String array for impact text addons */
- public static final String[] IMPACT_TEXT_ADDONS = new String[] { "feltreports" };
- /** Selected link type products have a mapping. */
- public static final String GENERAL_LINK_TYPE = "general-link";
- /** String array for general link addons */
- public static final String[] GENERAL_LINK_ADDONS = new String[] {
- "aftershock", "afterwarn", "asw", "generalmisc" };
- /** Type for scitech link */
- public static final String SCITECH_LINK_TYPE = "scitech-link";
- /** String array for scitech link */
- public static final String[] SCITECH_LINK_ADDONS = new String[] { "energy",
- "focalmech", "ncfm", "histmomenttensor", "finitefault",
- "momenttensor", "mtensor", "phase", "seiscrosssec", "seisrecsec",
- "traveltimes", "waveform", "seismograms", "scitechmisc" };
- /** Type for impact link */
- public static final String IMPACT_LINK_TYPE = "impact-link";
- /** String array for impact link */
- public static final String[] IMPACT_LINK_ADDONS = new String[] {
- "tsunamilinks", "impactmisc" };
- /**
- * Map from cube style link addon to product type.
- *
- * @param addonType String to find correct link type
- * @return null if link should not be converted to a product.
- */
- public String getLinkAddonProductType(final String addonType) {
- String c = addonType.toLowerCase();
- for (String general : GENERAL_LINK_ADDONS) {
- if (c.startsWith(general)) {
- return GENERAL_LINK_TYPE;
- }
- }
- for (String scitech : SCITECH_LINK_ADDONS) {
- if (c.startsWith(scitech)) {
- return SCITECH_LINK_TYPE;
- }
- }
- for (String impact : IMPACT_LINK_ADDONS) {
- if (c.startsWith(impact)) {
- return IMPACT_LINK_TYPE;
- }
- }
- return null;
- }
- /**
- * Map from cube style text addon to product type.
- *
- * @param addonType to find correct addon type
- * @return null if comment should not be converted to a product.
- */
- public String getTextAddonProductType(final String addonType) {
- String c = addonType.toLowerCase();
- for (String general : GENERAL_TEXT_ADDONS) {
- if (c.startsWith(general)) {
- return GENERAL_TEXT_TYPE;
- }
- }
- for (String impact : IMPACT_TEXT_ADDONS) {
- if (c.startsWith(impact)) {
- return IMPACT_TEXT_TYPE;
- }
- }
- for (String scitech : SCITECH_TEXT_ADDONS) {
- if (c.startsWith(scitech)) {
- return SCITECH_TEXT_TYPE;
- }
- }
- return null;
- }
- }