JsonProduct.java
package gov.usgs.earthquake.product.io;
import gov.usgs.earthquake.product.AbstractContent;
import gov.usgs.earthquake.product.Content;
import gov.usgs.earthquake.product.InvalidProductIdException;
import gov.usgs.earthquake.product.Product;
import gov.usgs.earthquake.product.ProductId;
import gov.usgs.earthquake.product.ProductSignature;
import gov.usgs.earthquake.product.URLContent;
import gov.usgs.util.CryptoUtils.Version;
import gov.usgs.util.protocolhandlers.data.Handler;
import gov.usgs.util.CryptoUtils;
import gov.usgs.util.StreamUtils;
import gov.usgs.util.XmlUtils;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonValue;
/**
* Product format conversion tools to and from json
*/
public class JsonProduct {
static {
// make sure data protocol handler registered
Handler.register();
}
/**
* Convert product object to json.
*
* @param product a product
* @return a json object
* @throws Exception if error occurs
*/
public JsonObject getJsonObject(final Product product) throws Exception {
JsonObjectBuilder json = Json.createObjectBuilder();
json.add("contents", getContentsJson(product.getContents()));
JsonObjectBuilder geometry = getGeometryJson(product);
if (geometry == null) {
json.addNull("geometry");
} else {
json.add("geometry", geometry);
}
final ProductId id = product.getId();
json.add("id", getIdJson(id));
json.add("links", getLinksJson(product.getLinks()));
json.add("properties", getPropertiesJson(product.getProperties()));
if (product.getSignature() == null) {
json.addNull("signature");
} else {
json.add("signature", product.getSignature());
}
json.add("signatureVersion", product.getSignatureVersion().toString());
if (product.getSignatureHistory().isEmpty()) {
// add empty array
JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
json.add("signatureHistory", arrayBuilder);
} else {
json.add("signatureHistory", getHistoryJson(product.getSignatureHistory()));
}
json.add("status", product.getStatus());
json.add("type", "Feature");
return json.build();
}
/**
* Convert json object to product.
*
* @param json a json object
* @return a product
* @throws Exception if error occurs
*/
public Product getProduct(final JsonObject json) throws Exception {
Product product = new Product(getId(json.getJsonObject("id")));
product.setContents(getContents(json.get("contents")));
product.setLinks(getLinks(json.getJsonArray("links")));
product.setProperties(getProperties(json.getJsonObject("properties")));
product.setStatus(json.getString("status"));
try {
product.setSignature(json.getString("signature"));
} catch (Exception e) {
product.setSignature(null);
}
product.setSignatureVersion(Version.fromString(json.getString("signatureVersion")));
try {
product.setSignatureHistory(getHistory(json.getJsonArray("signatureHistory")));
} catch (Exception e) {
product.setSignatureHistory(new ArrayList<>());
}
return product;
}
/**
* Convert contents map to json.
*
* @param contents contents map
* @return JSOnArrayBuilder
* @throws Exception if error occurs
*/
public JsonObjectBuilder getContentsJson(final Map<String, Content> contents) throws Exception {
final JsonObjectBuilder builder = Json.createObjectBuilder();
for (final String path : contents.keySet()) {
final Content content = contents.get(path);
final JsonObjectBuilder jsonContent = Json.createObjectBuilder().add("length", content.getLength())
.add("modified", XmlUtils.formatDate(content.getLastModified())).add("path", path)
.add("sha256", content.getSha256()).add("type", content.getContentType());
if (content instanceof URLContent) {
jsonContent.add("url", ((URLContent) content).getURL().toString());
} else if ("".equals(path)) {
jsonContent.add("url", "data:" + content.getContentType() + ";base64,"
+ Base64.getEncoder().encodeToString(StreamUtils.readStream(content.getInputStream())));
} else {
// no url, will throw parse error
// this is used to get upload urls, and returned object includes urls...
jsonContent.addNull("url");
}
builder.add(path, jsonContent);
}
return builder;
}
/**
* Convert contents json to map.
*
* @param json JsonArray
* @return Contents map
* @throws Exception if error occurs
*/
public Map<String, Content> getContents(final JsonValue json) throws Exception {
Map<String, Content> contents = new HashMap<String, Content>();
if (json instanceof JsonArray) {
for (JsonValue value : json.asJsonArray()) {
JsonObject object = value.asJsonObject();
String path = object.getString("path");
AbstractContent content = getUrlContent(object);
contents.put(path, content);
}
} else {
for (String key : json.asJsonObject().keySet()) {
JsonObject object = json.asJsonObject().getJsonObject(key);
AbstractContent content = getUrlContent(object);
contents.put(key, content);
}
}
return contents;
}
/**
* Create json geometry from product properties.
*
* @param product a product
* @return JSON geometry via JsonObjectBuilder
* @throws Exception if error occurs
*/
public JsonObjectBuilder getGeometryJson(final Product product) throws Exception {
final BigDecimal latitude = product.getLatitude();
final BigDecimal longitude = product.getLongitude();
final BigDecimal depth = product.getDepth();
if (latitude != null || longitude != null || depth != null) {
final JsonArrayBuilder coordinates = Json.createArrayBuilder();
if (latitude != null) {
coordinates.add(latitude);
} else {
coordinates.addNull();
}
if (longitude != null) {
coordinates.add(longitude);
} else {
coordinates.addNull();
}
if (depth != null) {
coordinates.add(depth);
} else {
coordinates.addNull();
}
return Json.createObjectBuilder().add("type", "Point").add("coordinates", coordinates);
}
return null;
}
/**
* Convert json id to ProductId object.
*
* @param json A JsonObject ID
* @return a productId
* @throws InvalidProductIdException if error occurs
*/
public ProductId getId(final JsonObject json) throws InvalidProductIdException {
return ProductId.fromJson(json);
}
/**
* Convert ProductId to json object.
*
* @param id A ProductId
* @return JsonObjectBuilder
* @throws Exception if error occurs
*/
public JsonObjectBuilder getIdJson(final ProductId id) throws Exception {
return Json.createObjectBuilder().add("code", id.getCode()).add("source", id.getSource()).add("type", id.getType())
.add("updateTime", XmlUtils.formatDate(id.getUpdateTime()));
}
/**
* Convert json links to map.
*
* @param json a Jsonarray
* @return a Map of links
* @throws Exception if error occurs
*/
public Map<String, List<URI>> getLinks(final JsonArray json) throws Exception {
final Map<String, List<URI>> links = new HashMap<String, List<URI>>();
for (final JsonValue value : json) {
final JsonObject link = value.asJsonObject();
final String relation = link.getString("relation");
final URI uri = new URI(link.getString("uri"));
List<URI> relationLinks = links.get(relation);
if (relationLinks == null) {
relationLinks = new ArrayList<URI>();
links.put(relation, relationLinks);
}
relationLinks.add(uri);
}
return links;
}
/**
* Convert links map to json.
*
* @param links map
* @return JsonArray of JsonArrayBuilder
* @throws Exception if error occurs
*/
public JsonArrayBuilder getLinksJson(final Map<String, List<URI>> links) throws Exception {
final JsonArrayBuilder builder = Json.createArrayBuilder();
for (final String relation : links.keySet()) {
final List<URI> relationLinks = links.get(relation);
for (final URI uri : relationLinks) {
builder.add(Json.createObjectBuilder().add("relation", relation).add("uri", uri.toString()));
}
}
return builder;
}
/**
* Convert list of type signature history to Json.
*
* @param list signature history list
* @return a JsonArrayBuilder
* @throws Exception if error occurs
*/
public JsonArrayBuilder getHistoryJson(final List<ProductSignature> list) throws Exception {
JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
for (ProductSignature entry : list) {
JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
jsonObjectBuilder.add("signature", entry.getSignature());
jsonObjectBuilder.add("signatureVersion", entry.getSignatureVersion().toString());
jsonArrayBuilder.add(jsonObjectBuilder);
}
return jsonArrayBuilder;
}
/**
* Converts a Json list of objects to signature history list.
*
* @param jsonArray JsonArray
* @return List of ProductSignature
* @throws Exception if error occurs
*/
public static List<ProductSignature> getHistory(JsonArray jsonArray) throws Exception {
List<ProductSignature> result = new ArrayList<>();
for (final JsonValue jsonValue : jsonArray) {
JsonObject jsonObject = jsonValue.asJsonObject();
String signature = jsonObject.getString("signature");
Version version = Version.fromString(jsonObject.getString("signatureVersion"));
ProductSignature entry = new ProductSignature(signature, version);
result.add(entry);
}
return result;
}
/**
* Convert properties json to map.
*
* @param json JsonObject properties
* @return A map
* @throws Exception if error occurs
*/
public Map<String, String> getProperties(final JsonObject json) throws Exception {
final Map<String, String> properties = new HashMap<String, String>();
for (final String name : json.keySet()) {
properties.put(name, json.getString(name));
}
return properties;
}
/**
* Convert properties map to json.
*
* @param properties Map of properties
* @return JsonObjectBuilder
* @throws Exception if error occurs
*/
public JsonObjectBuilder getPropertiesJson(final Map<String, String> properties) throws Exception {
final JsonObjectBuilder builder = Json.createObjectBuilder();
for (final String name : properties.keySet()) {
builder.add(name, properties.get(name));
}
return builder;
}
private AbstractContent getUrlContent(JsonObject object) throws MalformedURLException, URISyntaxException {
Long length = object.getJsonNumber("length").longValue();
Date modified = XmlUtils.getDate(object.getString("modified"));
String sha256 = object.getString("sha256");
String type = object.getString("type");
String url = object.getString("url");
AbstractContent content = new URLContent(new URL(url));
content.setContentType(type);
content.setLastModified(modified);
content.setLength(length);
content.setSha256(sha256);
return content;
}
}