package io.lumify.core.util;
import io.lumify.core.exception.LumifyException;
import io.lumify.core.model.PropertyJustificationMetadata;
import io.lumify.core.model.SourceInfo;
import io.lumify.core.model.ontology.OntologyRepository;
import io.lumify.core.model.properties.LumifyProperties;
import io.lumify.core.model.termMention.TermMentionFor;
import io.lumify.core.model.termMention.TermMentionRepository;
import io.lumify.core.security.LumifyVisibility;
import io.lumify.core.security.VisibilityTranslator;
import io.lumify.core.user.User;
import io.lumify.web.clientapi.model.SandboxStatus;
import io.lumify.web.clientapi.model.VisibilityJson;
import org.json.JSONObject;
import org.securegraph.*;
import org.securegraph.mutation.ExistingElementMutation;
import java.util.Date;
import java.util.List;
import java.util.Set;
public class GraphUtil {
private static final LumifyLogger LOGGER = LumifyLoggerFactory.getLogger(GraphUtil.class);
public static final String LUMIFY_VERSION_KEY = "lumify.version";
public static final int LUMIFY_VERSION = 3;
public static final double SET_PROPERTY_CONFIDENCE = 0.5;
public static void verifyVersion(Graph graph) {
verifyVersion(graph, LUMIFY_VERSION);
}
public static void verifyVersion(Graph graph, int requiredVersion) {
Object version = graph.getMetadata(LUMIFY_VERSION_KEY);
if (version == null) {
writeVersion(graph);
return;
}
if (!(version instanceof Integer)) {
throw new LumifyException("Invalid " + LUMIFY_VERSION_KEY + " found. Expected Integer, found " + version.getClass().getName());
}
Integer versionInt = (Integer) version;
if (versionInt != requiredVersion) {
throw new LumifyException("Invalid " + LUMIFY_VERSION_KEY + " found. Expected " + requiredVersion + ", found " + versionInt);
}
LOGGER.info("Lumify graph version verified: %d", versionInt);
}
public static void writeVersion(Graph graph) {
writeVersion(graph, LUMIFY_VERSION);
}
public static void writeVersion(Graph graph, int version) {
graph.setMetadata(LUMIFY_VERSION_KEY, version);
LOGGER.info("Wrote %s: %d", LUMIFY_VERSION_KEY, version);
}
public static SandboxStatus getSandboxStatus(Element element, String workspaceId) {
VisibilityJson visibilityJson = LumifyProperties.VISIBILITY_JSON.getPropertyValue(element);
return getSandboxStatusFromVisibilityJsonString(visibilityJson, workspaceId);
}
public static SandboxStatus getSandboxStatusFromVisibilityString(String visibility, String workspaceId) {
if (visibility == null) {
return SandboxStatus.PUBLIC;
}
if (!visibility.contains(workspaceId)) {
return SandboxStatus.PUBLIC;
}
return SandboxStatus.PRIVATE;
}
public static SandboxStatus getSandboxStatusFromVisibilityJsonString(VisibilityJson visibilityJson, String workspaceId) {
if (visibilityJson == null) {
return SandboxStatus.PUBLIC;
}
Set<String> workspacesList = visibilityJson.getWorkspaces();
if (workspacesList == null || workspacesList.size() == 0) {
return SandboxStatus.PUBLIC;
}
if (!workspacesList.contains(workspaceId)) {
return SandboxStatus.PUBLIC;
}
return SandboxStatus.PRIVATE;
}
public static SandboxStatus[] getPropertySandboxStatuses(List<Property> properties, String workspaceId) {
SandboxStatus[] sandboxStatuses = new SandboxStatus[properties.size()];
for (int i = 0; i < properties.size(); i++) {
Property property = properties.get(i);
VisibilityJson visibilityJson = LumifyProperties.VISIBILITY_JSON.getMetadataValue(property.getMetadata());
sandboxStatuses[i] = getSandboxStatusFromVisibilityJsonString(visibilityJson, workspaceId);
}
for (int i = 0; i < properties.size(); i++) {
Property property = properties.get(i);
if (sandboxStatuses[i] != SandboxStatus.PRIVATE) {
continue;
}
VisibilityJson propertyVisibilityJson = LumifyProperties.VISIBILITY_JSON.getMetadataValue(property.getMetadata());
for (int j = 0; j < properties.size(); j++) {
Property p = properties.get(j);
VisibilityJson pVisibilityJson = LumifyProperties.VISIBILITY_JSON.getMetadataValue(p.getMetadata());
if (i == j) {
continue;
}
if (sandboxStatuses[j] == SandboxStatus.PUBLIC &&
property.getName().equals(p.getName()) &&
property.getKey().equals(p.getKey()) &&
(propertyVisibilityJson == null || pVisibilityJson == null || (propertyVisibilityJson.getSource().equals(pVisibilityJson.getSource())))) {
sandboxStatuses[i] = SandboxStatus.PUBLIC_CHANGED;
}
}
}
return sandboxStatuses;
}
public static Metadata metadataStringToMap(String metadataString, Visibility visibility) {
Metadata metadata = new Metadata();
if (metadataString != null && metadataString.length() > 0) {
JSONObject metadataJson = new JSONObject(metadataString);
for (Object keyObj : metadataJson.keySet()) {
String key = "" + keyObj;
metadata.add(key, metadataJson.get(key), visibility);
}
}
return metadata;
}
public static class VisibilityAndElementMutation<T extends Element> {
public final ExistingElementMutation<T> elementMutation;
public final LumifyVisibility visibility;
public VisibilityAndElementMutation(LumifyVisibility visibility, ExistingElementMutation<T> elementMutation) {
this.visibility = visibility;
this.elementMutation = elementMutation;
}
}
public static <T extends Element> VisibilityAndElementMutation<T> updateElementVisibilitySource(
VisibilityTranslator visibilityTranslator,
Element element,
SandboxStatus sandboxStatus,
String visibilitySource,
String workspaceId,
Authorizations authorizations
) {
VisibilityJson visibilityJson = LumifyProperties.VISIBILITY_JSON.getPropertyValue(element);
visibilityJson = sandboxStatus != SandboxStatus.PUBLIC ? updateVisibilitySourceAndAddWorkspaceId(visibilityJson, visibilitySource, workspaceId) : updateVisibilitySource(visibilityJson, visibilitySource);
LumifyVisibility lumifyVisibility = visibilityTranslator.toVisibility(visibilityJson);
ExistingElementMutation<T> m = element.<T>prepareMutation().alterElementVisibility(lumifyVisibility.getVisibility());
if (LumifyProperties.VISIBILITY_JSON.getPropertyValue(element) != null) {
Property visibilityJsonProperty = LumifyProperties.VISIBILITY_JSON.getProperty(element);
m.alterPropertyVisibility(visibilityJsonProperty.getKey(), LumifyProperties.VISIBILITY_JSON.getPropertyName(), visibilityTranslator.getDefaultVisibility());
}
Metadata metadata = new Metadata();
metadata.add(LumifyProperties.VISIBILITY_JSON.getPropertyName(), visibilityJson.toString(), visibilityTranslator.getDefaultVisibility());
LumifyProperties.VISIBILITY_JSON.setProperty(m, visibilityJson, metadata, visibilityTranslator.getDefaultVisibility());
m.save(authorizations);
return new VisibilityAndElementMutation<>(lumifyVisibility, m);
}
public static <T extends Element> VisibilityAndElementMutation<T> setProperty(
Graph graph,
T element,
String propertyName,
String propertyKey,
Object value,
Metadata metadata,
String visibilitySource,
String workspaceId,
VisibilityTranslator visibilityTranslator,
String justificationText,
SourceInfo sourceInfo,
TermMentionRepository termMentionRepository,
User user,
Authorizations authorizations) {
VisibilityJson visibilityJson = new VisibilityJson();
visibilityJson.setSource(visibilitySource);
visibilityJson.addWorkspace(workspaceId);
LumifyVisibility lumifyVisibility = visibilityTranslator.toVisibility(visibilityJson);
Visibility propertyVisibility = lumifyVisibility.getVisibility();
Property oldProperty = element.getProperty(propertyKey, propertyName, propertyVisibility);
Metadata propertyMetadata;
if (oldProperty != null) {
propertyMetadata = oldProperty.getMetadata();
if (oldProperty.getName().equals(propertyName) && oldProperty.getKey().equals(propertyKey)) {
element.removeProperty(propertyKey, propertyName, authorizations);
graph.flush();
}
} else {
propertyMetadata = new Metadata();
}
mergeMetadata(propertyMetadata, metadata);
ExistingElementMutation<T> elementMutation = element.prepareMutation();
visibilityJson = updateVisibilitySourceAndAddWorkspaceId(visibilityJson, visibilitySource, workspaceId);
Date now = new Date();
if (LumifyProperties.CREATE_DATE.getMetadataValue(propertyMetadata, null) == null) {
LumifyProperties.CREATE_DATE.setMetadata(propertyMetadata, now, visibilityTranslator.getDefaultVisibility());
}
if (LumifyProperties.CREATED_BY.getMetadataValue(propertyMetadata, null) == null) {
LumifyProperties.CREATED_BY.setMetadata(propertyMetadata, user.getUserId(), visibilityTranslator.getDefaultVisibility());
}
LumifyProperties.VISIBILITY_JSON.setMetadata(propertyMetadata, visibilityJson, visibilityTranslator.getDefaultVisibility());
LumifyProperties.MODIFIED_DATE.setMetadata(propertyMetadata, now, visibilityTranslator.getDefaultVisibility());
LumifyProperties.MODIFIED_BY.setMetadata(propertyMetadata, user.getUserId(), visibilityTranslator.getDefaultVisibility());
LumifyProperties.CONFIDENCE.setMetadata(propertyMetadata, SET_PROPERTY_CONFIDENCE, visibilityTranslator.getDefaultVisibility());
lumifyVisibility = visibilityTranslator.toVisibility(visibilityJson);
if (justificationText != null) {
PropertyJustificationMetadata propertyJustificationMetadata = new PropertyJustificationMetadata(justificationText);
termMentionRepository.removeSourceInfoEdge(element, propertyKey, propertyName, lumifyVisibility, authorizations);
LumifyProperties.JUSTIFICATION.setMetadata(propertyMetadata, propertyJustificationMetadata, lumifyVisibility.getVisibility());
} else if (sourceInfo != null) {
Vertex sourceVertex = graph.getVertex(sourceInfo.getVertexId(), authorizations);
LumifyProperties.JUSTIFICATION.removeMetadata(propertyMetadata);
termMentionRepository.addSourceInfo(
element,
element.getId(),
TermMentionFor.PROPERTY,
propertyKey,
propertyName,
propertyVisibility,
sourceInfo.getSnippet(),
sourceInfo.getTextPropertyKey(),
sourceInfo.getStartOffset(),
sourceInfo.getEndOffset(),
sourceVertex,
lumifyVisibility.getVisibility(),
authorizations
);
}
elementMutation.addPropertyValue(propertyKey, propertyName, value, propertyMetadata, lumifyVisibility.getVisibility());
return new VisibilityAndElementMutation<>(lumifyVisibility, elementMutation);
}
private static void mergeMetadata(Metadata metadata, Metadata additionalMetadata) {
if (additionalMetadata == null) {
return;
}
for (Metadata.Entry entry : additionalMetadata.entrySet()) {
metadata.add(entry.getKey(), entry.getValue(), entry.getVisibility());
}
}
public static Vertex addVertex(
Graph graph,
String conceptType,
String visibilitySource,
String workspaceId,
String justificationText,
SourceInfo sourceInfo,
VisibilityTranslator visibilityTranslator,
TermMentionRepository termMentionRepository,
Authorizations authorizations
) {
VisibilityJson visibilityJson = updateVisibilitySourceAndAddWorkspaceId(null, visibilitySource, workspaceId);
LumifyVisibility lumifyVisibility = visibilityTranslator.toVisibility(visibilityJson);
VertexBuilder vertexBuilder = graph.prepareVertex(lumifyVisibility.getVisibility());
LumifyProperties.VISIBILITY_JSON.setProperty(vertexBuilder, visibilityJson, lumifyVisibility.getVisibility());
Metadata propertyMetadata = new Metadata();
LumifyProperties.VISIBILITY_JSON.setMetadata(propertyMetadata, visibilityJson, visibilityTranslator.getDefaultVisibility());
LumifyProperties.CONCEPT_TYPE.setProperty(vertexBuilder, conceptType, propertyMetadata, lumifyVisibility.getVisibility());
if (justificationText != null) {
PropertyJustificationMetadata propertyJustificationMetadata = new PropertyJustificationMetadata(justificationText);
LumifyProperties.JUSTIFICATION.setProperty(vertexBuilder, propertyJustificationMetadata, lumifyVisibility.getVisibility());
} else if (sourceInfo != null) {
LumifyProperties.JUSTIFICATION.removeProperty(vertexBuilder, lumifyVisibility.getVisibility());
}
Vertex vertex = vertexBuilder.save(authorizations);
graph.flush();
if (justificationText != null) {
termMentionRepository.removeSourceInfoEdgeFromVertex(vertex.getId(), vertex.getId(), null, null, lumifyVisibility, authorizations);
} else if (sourceInfo != null) {
Vertex sourceDataVertex = graph.getVertex(sourceInfo.getVertexId(), authorizations);
termMentionRepository.addSourceInfoToVertex(
vertex,
vertex.getId(),
TermMentionFor.VERTEX,
null,
null,
null,
sourceInfo.getSnippet(),
sourceInfo.getTextPropertyKey(),
sourceInfo.getStartOffset(),
sourceInfo.getEndOffset(),
sourceDataVertex,
lumifyVisibility.getVisibility(),
authorizations
);
}
return vertex;
}
public static Edge addEdge(
Graph graph,
Vertex sourceVertex,
Vertex destVertex,
String predicateLabel,
String justificationText,
SourceInfo sourceInfo,
String visibilitySource,
String workspaceId,
VisibilityTranslator visibilityTranslator,
TermMentionRepository termMentionRepository,
User user,
Authorizations authorizations) {
Date now = new Date();
VisibilityJson visibilityJson = updateVisibilitySourceAndAddWorkspaceId(null, visibilitySource, workspaceId);
LumifyVisibility lumifyVisibility = visibilityTranslator.toVisibility(visibilityJson);
ElementBuilder<Edge> edgeBuilder = graph.prepareEdge(sourceVertex, destVertex, predicateLabel, lumifyVisibility.getVisibility());
LumifyProperties.VISIBILITY_JSON.setProperty(edgeBuilder, visibilityJson, lumifyVisibility.getVisibility());
LumifyProperties.CONCEPT_TYPE.setProperty(edgeBuilder, OntologyRepository.TYPE_RELATIONSHIP, lumifyVisibility.getVisibility());
LumifyProperties.CREATE_DATE.setProperty(edgeBuilder, now, lumifyVisibility.getVisibility());
LumifyProperties.CREATED_BY.setProperty(edgeBuilder, user.getUserId(), lumifyVisibility.getVisibility());
LumifyProperties.MODIFIED_DATE.setProperty(edgeBuilder, now, lumifyVisibility.getVisibility());
LumifyProperties.MODIFIED_BY.setProperty(edgeBuilder, user.getUserId(), lumifyVisibility.getVisibility());
if (justificationText != null) {
PropertyJustificationMetadata propertyJustificationMetadata = new PropertyJustificationMetadata(justificationText);
LumifyProperties.JUSTIFICATION.setProperty(edgeBuilder, propertyJustificationMetadata, lumifyVisibility.getVisibility());
} else if (sourceInfo != null) {
LumifyProperties.JUSTIFICATION.removeProperty(edgeBuilder, lumifyVisibility.getVisibility());
}
Edge edge = edgeBuilder.save(authorizations);
if (justificationText != null) {
termMentionRepository.removeSourceInfoEdgeFromEdge(edge, null, null, lumifyVisibility, authorizations);
} else if (sourceInfo != null) {
Vertex sourceDataVertex = graph.getVertex(sourceInfo.getVertexId(), authorizations);
termMentionRepository.addSourceInfoEdgeToEdge(
edge,
edge.getId(),
TermMentionFor.EDGE,
null,
null,
null,
sourceInfo.getSnippet(),
sourceInfo.getTextPropertyKey(),
sourceInfo.getStartOffset(),
sourceInfo.getEndOffset(),
sourceDataVertex,
lumifyVisibility.getVisibility(),
authorizations
);
}
return edge;
}
// TODO remove me?
public static VisibilityJson updateVisibilitySource(VisibilityJson visibilityJson, String visibilitySource) {
if (visibilityJson == null) {
visibilityJson = new VisibilityJson();
}
visibilityJson.setSource(visibilitySource);
return visibilityJson;
}
// TODO remove me?
public static VisibilityJson updateVisibilitySourceAndAddWorkspaceId(VisibilityJson visibilityJson, String visibilitySource, String workspaceId) {
if (visibilityJson == null) {
visibilityJson = new VisibilityJson();
}
visibilityJson.setSource(visibilitySource);
if (workspaceId != null) {
visibilityJson.addWorkspace(workspaceId);
}
return visibilityJson;
}
// TODO remove me?
public static VisibilityJson updateVisibilityJsonRemoveFromWorkspace(VisibilityJson json, String workspaceId) {
if (json == null) {
json = new VisibilityJson();
}
json.getWorkspaces().remove(workspaceId);
return json;
}
// TODO remove me?
public static VisibilityJson updateVisibilityJsonRemoveFromAllWorkspace(VisibilityJson json) {
if (json == null) {
json = new VisibilityJson();
}
json.getWorkspaces().clear();
return json;
}
}