package io.lumify.core.model.workspace.diff; import com.fasterxml.jackson.databind.JsonNode; import com.google.inject.Inject; import io.lumify.core.formula.FormulaEvaluator; import io.lumify.core.model.properties.LumifyProperties; import io.lumify.core.model.user.UserRepository; import io.lumify.core.model.workspace.Workspace; import io.lumify.core.model.workspace.WorkspaceEntity; import io.lumify.core.model.workspace.WorkspaceRepository; import io.lumify.core.user.User; import io.lumify.core.util.GraphUtil; import io.lumify.core.util.JSONUtil; import io.lumify.core.util.JsonSerializer; import io.lumify.web.clientapi.model.ClientApiWorkspaceDiff; import io.lumify.web.clientapi.model.SandboxStatus; import org.securegraph.*; import java.util.ArrayList; import java.util.List; import static org.securegraph.util.IterableUtils.toList; public class WorkspaceDiffHelper { private final Graph graph; private final UserRepository userRepository; private final FormulaEvaluator formulaEvaluator; @Inject public WorkspaceDiffHelper( final Graph graph, final UserRepository userRepository, final FormulaEvaluator formulaEvaluator ) { this.graph = graph; this.userRepository = userRepository; this.formulaEvaluator = formulaEvaluator; } public ClientApiWorkspaceDiff diff(Workspace workspace, List<WorkspaceEntity> workspaceEntities, List<Edge> workspaceEdges, FormulaEvaluator.UserContext userContext, User user) { Authorizations authorizations = userRepository.getAuthorizations(user, WorkspaceRepository.VISIBILITY_STRING, workspace.getWorkspaceId()); ClientApiWorkspaceDiff result = new ClientApiWorkspaceDiff(); for (WorkspaceEntity workspaceEntity : workspaceEntities) { List<ClientApiWorkspaceDiff.Item> entityDiffs = diffWorkspaceEntity(workspace, workspaceEntity, userContext, authorizations); if (entityDiffs != null) { result.addAll(entityDiffs); } } for (Edge workspaceEdge : workspaceEdges) { List<ClientApiWorkspaceDiff.Item> entityDiffs = diffEdge(workspace, workspaceEdge, authorizations); if (entityDiffs != null) { result.addAll(entityDiffs); } } return result; } private List<ClientApiWorkspaceDiff.Item> diffEdge(Workspace workspace, Edge edge, Authorizations hiddenAuthorizations) { List<ClientApiWorkspaceDiff.Item> result = new ArrayList<>(); SandboxStatus sandboxStatus = GraphUtil.getSandboxStatus(edge, workspace.getWorkspaceId()); boolean isPrivateChange = sandboxStatus != SandboxStatus.PUBLIC; boolean isPublicDelete = WorkspaceDiffHelper.isPublicDelete(edge, hiddenAuthorizations); if (isPrivateChange || isPublicDelete) { result.add(createWorkspaceDiffEdgeItem(edge, sandboxStatus, isPublicDelete)); } diffProperties(workspace, edge, result, hiddenAuthorizations); return result; } public static boolean isPublicDelete(Edge edge, Authorizations authorizations) { return edge.isHidden(authorizations); } public static boolean isPublicDelete(Vertex vertex, Authorizations authorizations) { return vertex.isHidden(authorizations); } public static boolean isPublicDelete(Property property, Authorizations authorizations) { return property.isHidden(authorizations); } private ClientApiWorkspaceDiff.EdgeItem createWorkspaceDiffEdgeItem(Edge edge, SandboxStatus sandboxStatus, boolean deleted) { Property visibilityJsonProperty = LumifyProperties.VISIBILITY_JSON.getProperty(edge); JsonNode visibilityJson = visibilityJsonProperty == null ? null : JSONUtil.toJsonNode(JsonSerializer.toJsonProperty(visibilityJsonProperty)); return new ClientApiWorkspaceDiff.EdgeItem( edge.getId(), edge.getLabel(), edge.getVertexId(Direction.OUT), edge.getVertexId(Direction.IN), visibilityJson, sandboxStatus, deleted ); } public List<ClientApiWorkspaceDiff.Item> diffWorkspaceEntity(Workspace workspace, WorkspaceEntity workspaceEntity, FormulaEvaluator.UserContext userContext, Authorizations authorizations) { List<ClientApiWorkspaceDiff.Item> result = new ArrayList<>(); Vertex entityVertex = this.graph.getVertex(workspaceEntity.getEntityVertexId(), FetchHint.ALL_INCLUDING_HIDDEN, authorizations); // vertex can be null if the user doesn't have access to the entity if (entityVertex == null) { return null; } SandboxStatus sandboxStatus = GraphUtil.getSandboxStatus(entityVertex, workspace.getWorkspaceId()); boolean isPrivateChange = sandboxStatus != SandboxStatus.PUBLIC; boolean isPublicDelete = WorkspaceDiffHelper.isPublicDelete(entityVertex, authorizations); if (isPrivateChange || isPublicDelete) { result.add(createWorkspaceDiffVertexItem(entityVertex, sandboxStatus, userContext, workspaceEntity.isVisible(), isPublicDelete)); } diffProperties(workspace, entityVertex, result, authorizations); return result; } private ClientApiWorkspaceDiff.VertexItem createWorkspaceDiffVertexItem(Vertex vertex, SandboxStatus sandboxStatus, FormulaEvaluator.UserContext userContext, boolean visible, boolean deleted) { String vertexId = vertex.getId(); String title = formulaEvaluator.evaluateTitleFormula(vertex, userContext, null); String conceptType = LumifyProperties.CONCEPT_TYPE.getPropertyValue(vertex); Property visibilityJsonProperty = LumifyProperties.VISIBILITY_JSON.getProperty(vertex); JsonNode visibilityJson = visibilityJsonProperty == null ? null : JSONUtil.toJsonNode(JsonSerializer.toJsonProperty(visibilityJsonProperty)); return new ClientApiWorkspaceDiff.VertexItem( vertexId, title, conceptType, visibilityJson, sandboxStatus, deleted, visible ); } private void diffProperties(Workspace workspace, Element element, List<ClientApiWorkspaceDiff.Item> result, Authorizations hiddenAuthorizations) { List<Property> properties = toList(element.getProperties()); SandboxStatus[] propertyStatuses = GraphUtil.getPropertySandboxStatuses(properties, workspace.getWorkspaceId()); for (int i = 0; i < properties.size(); i++) { Property property = properties.get(i); boolean isPrivateChange = propertyStatuses[i] != SandboxStatus.PUBLIC; boolean isPublicDelete = WorkspaceDiffHelper.isPublicDelete(property, hiddenAuthorizations); if (isPrivateChange || isPublicDelete) { Property existingProperty = null; if (isPrivateChange) { existingProperty = findExistingProperty(properties, propertyStatuses, property); } result.add(createWorkspaceDiffPropertyItem(element, property, existingProperty, propertyStatuses[i], isPublicDelete)); } } } private ClientApiWorkspaceDiff.PropertyItem createWorkspaceDiffPropertyItem(Element element, Property workspaceProperty, Property existingProperty, SandboxStatus sandboxStatus, boolean deleted) { JsonNode oldData = null; if (existingProperty != null) { oldData = JSONUtil.toJsonNode(JsonSerializer.toJsonProperty(existingProperty)); } JsonNode newData = JSONUtil.toJsonNode(JsonSerializer.toJsonProperty(workspaceProperty)); return new ClientApiWorkspaceDiff.PropertyItem( element instanceof Edge ? "edge" : "vertex", element.getId(), workspaceProperty.getName(), workspaceProperty.getKey(), oldData, newData, sandboxStatus, deleted, workspaceProperty.getVisibility().getVisibilityString() ); } private Property findExistingProperty(List<Property> properties, SandboxStatus[] propertyStatuses, Property workspaceProperty) { for (int i = 0; i < properties.size(); i++) { Property property = properties.get(i); if (property.getName().equals(workspaceProperty.getName()) && property.getKey().equals(workspaceProperty.getKey()) && propertyStatuses[i] == SandboxStatus.PUBLIC) { return property; } } return null; } }