package io.lumify.core.util;
import io.lumify.core.ingest.video.VideoFrameInfo;
import io.lumify.core.ingest.video.VideoPropertyHelper;
import io.lumify.core.ingest.video.VideoTranscript;
import io.lumify.core.model.PropertyJustificationMetadata;
import io.lumify.core.model.properties.LumifyProperties;
import io.lumify.core.model.properties.MediaLumifyProperties;
import io.lumify.web.clientapi.model.SandboxStatus;
import io.lumify.web.clientapi.model.VisibilityJson;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.securegraph.*;
import org.securegraph.property.StreamingPropertyValue;
import org.securegraph.type.GeoPoint;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.securegraph.util.IterableUtils.toList;
public class JsonSerializer {
public static JSONArray toJson(Iterable<? extends Element> elements, String workspaceId, Authorizations authorizations) {
JSONArray result = new JSONArray();
for (Element element : elements) {
result.put(toJson(element, workspaceId, authorizations));
}
return result;
}
public static JSONObject toJson(Element element, String workspaceId, Authorizations authorizations) {
checkNotNull(element, "element cannot be null");
if (element instanceof Vertex) {
return toJsonVertex((Vertex) element, workspaceId, authorizations);
}
if (element instanceof Edge) {
return toJsonEdge((Edge) element, workspaceId);
}
throw new RuntimeException("Unexpected element type: " + element.getClass().getName());
}
public static JSONObject toJsonVertex(Vertex vertex, String workspaceId, Authorizations authorizations) {
try {
JSONObject json = toJsonElement(vertex, workspaceId);
JSONArray vertexEdgeLabelsJson = getVertexEdgeLabelsJson(vertex, authorizations);
if (vertexEdgeLabelsJson != null) {
json.put("edgeLabels", vertexEdgeLabelsJson);
}
return json;
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
private static JSONArray getVertexEdgeLabelsJson(Vertex vertex, Authorizations authorizations) {
if (authorizations == null) {
return null;
}
Iterable<String> edgeLabels = vertex.getEdgeLabels(Direction.BOTH, authorizations);
JSONArray result = new JSONArray();
for (String edgeLabel : edgeLabels) {
result.put(edgeLabel);
}
return result;
}
public static JSONObject toJsonEdge(Edge edge, String workspaceId) {
try {
JSONObject json = toJsonElement(edge, workspaceId);
json.put("label", edge.getLabel());
json.put("sourceVertexId", edge.getVertexId(Direction.OUT));
json.put("destVertexId", edge.getVertexId(Direction.IN));
return json;
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
public static JSONObject toJsonElement(Element element, String workspaceId) {
JSONObject json = new JSONObject();
json.put("id", element.getId());
json.put("properties", toJsonProperties(element.getProperties(), workspaceId));
json.put("sandboxStatus", GraphUtil.getSandboxStatus(element, workspaceId).toString());
VisibilityJson visibilityJson = LumifyProperties.VISIBILITY_JSON.getPropertyValue(element);
if (visibilityJson != null) {
json.put("visibilitySource", visibilityJson.getSource());
}
return json;
}
public static JSONArray toJsonProperties(Iterable<Property> properties, String workspaceId) {
JSONArray resultsJson = new JSONArray();
List<Property> propertiesList = toList(properties);
Collections.sort(propertiesList, new ConfidencePropertyComparator());
SandboxStatus[] sandboxStatuses = GraphUtil.getPropertySandboxStatuses(propertiesList, workspaceId);
for (int i = 0; i < propertiesList.size(); i++) {
Property property = propertiesList.get(i);
String sandboxStatus = sandboxStatuses[i].toString();
VideoFrameInfo videoFrameInfo;
if ((videoFrameInfo = VideoPropertyHelper.getVideoFrameInfoFromProperty(property)) != null) {
String textDescription = LumifyProperties.META_DATA_TEXT_DESCRIPTION.getMetadataValueOrDefault(property.getMetadata(), null);
addVideoFramePropertyToResults(resultsJson, videoFrameInfo.getPropertyKey(), textDescription, sandboxStatus);
} else {
JSONObject propertyJson = toJsonProperty(property);
propertyJson.put("sandboxStatus", sandboxStatus);
resultsJson.put(propertyJson);
}
}
return resultsJson;
}
public static VideoTranscript getSynthesisedVideoTranscription(Vertex artifactVertex, String propertyKey) throws IOException {
VideoTranscript videoTranscript = new VideoTranscript();
for (Property property : artifactVertex.getProperties()) {
VideoFrameInfo videoFrameInfo = VideoPropertyHelper.getVideoFrameInfoFromProperty(property);
if (videoFrameInfo == null) {
continue;
}
if (videoFrameInfo.getPropertyKey().equals(propertyKey)) {
Object value = property.getValue();
String text;
if (value instanceof StreamingPropertyValue) {
text = IOUtils.toString(((StreamingPropertyValue) value).getInputStream());
} else {
text = value.toString();
}
videoTranscript.add(new VideoTranscript.Time(videoFrameInfo.getFrameStartTime(), videoFrameInfo.getFrameEndTime()), text);
}
}
if (videoTranscript.getEntries().size() > 0) {
return videoTranscript;
}
return null;
}
private static void addVideoFramePropertyToResults(JSONArray resultsJson, String propertyKey, String textDescription, String sandboxStatus) {
JSONObject json = findProperty(resultsJson, MediaLumifyProperties.VIDEO_TRANSCRIPT.getPropertyName(), propertyKey);
if (json == null) {
json = new JSONObject();
json.put("key", propertyKey);
json.put("name", MediaLumifyProperties.VIDEO_TRANSCRIPT.getPropertyName());
json.put("sandboxStatus", sandboxStatus);
json.put(LumifyProperties.META_DATA_TEXT_DESCRIPTION.getPropertyName(), textDescription);
json.put("streamingPropertyValue", true);
resultsJson.put(json);
}
}
private static JSONObject findProperty(JSONArray resultsJson, String propertyName, String propertyKey) {
for (int i = 0; i < resultsJson.length(); i++) {
JSONObject json = resultsJson.getJSONObject(i);
if (json.getString("name").equals(propertyName)
&& json.getString("key").equals(propertyKey)) {
return json;
}
}
return null;
}
public static JSONObject toJsonProperty(Property property) {
checkNotNull(property, "property cannot be null");
JSONObject result = new JSONObject();
result.put("key", property.getKey());
result.put("name", property.getName());
Object propertyValue = property.getValue();
if (propertyValue instanceof StreamingPropertyValue) {
result.put("streamingPropertyValue", true);
} else {
result.put("value", toJsonValue(propertyValue));
}
for (Metadata.Entry metadataEntry : property.getMetadata().entrySet()) {
result.put(metadataEntry.getKey(), toJsonValue(metadataEntry.getValue()));
}
return result;
}
private static Object toJsonValue(Object value) {
if (value instanceof GeoPoint) {
GeoPoint geoPoint = (GeoPoint) value;
JSONObject result = new JSONObject();
result.put("latitude", geoPoint.getLatitude());
result.put("longitude", geoPoint.getLongitude());
if (geoPoint.getAltitude() != null) {
result.put("altitude", geoPoint.getAltitude());
}
if (geoPoint.getDescription() != null) {
result.put("description", geoPoint.getDescription());
}
return result;
} else if (value instanceof Date) {
return ((Date) value).getTime();
} else if (value instanceof PropertyJustificationMetadata) {
return ((PropertyJustificationMetadata) value).toJson();
} else if (value instanceof String) {
try {
String valueString = (String) value;
valueString = valueString.trim();
if (valueString.startsWith("{") && valueString.endsWith("}")) {
return new JSONObject(valueString);
}
} catch (Exception ex) {
// ignore this exception it just mean the string wasn't really json
}
}
return value;
}
}