/*- * ============LICENSE_START======================================================= * SDC * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= */ package org.openecomp.sdc.be.dao.janusgraph; import fj.data.Either; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import javax.validation.constraints.NotNull; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.ImmutableTriple; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Element; import org.apache.tinkerpop.gremlin.structure.Property; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.util.ElementHelper; import org.janusgraph.core.JanusGraph; import org.janusgraph.core.JanusGraphEdge; import org.janusgraph.core.JanusGraphQuery; import org.janusgraph.core.JanusGraphVertex; import org.janusgraph.core.JanusGraphVertexQuery; import org.janusgraph.core.PropertyKey; import org.janusgraph.graphdb.query.JanusGraphPredicate; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.exception.JanusGraphException; import org.openecomp.sdc.be.dao.graph.GraphElementFactory; import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge; import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum; import org.openecomp.sdc.be.dao.graph.datatype.GraphNode; import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation; import org.openecomp.sdc.be.dao.graph.datatype.RelationEndPoint; import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels; import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.resources.data.GraphNodeLock; import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode; import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.beans.factory.annotation.Qualifier; public class JanusGraphGenericDao { private static final String LOCK_NODE_PREFIX = "lock_"; private static Logger log = Logger.getLogger(JanusGraphGenericDao.class.getName()); private JanusGraphClient janusGraphClient; public JanusGraphGenericDao(@Qualifier("janusgraph-client") JanusGraphClient janusGraphClient) { this.janusGraphClient = janusGraphClient; log.info("** JanusGraphGenericDao created"); } public JanusGraphOperationStatus commit() { log.debug("doing commit."); return janusGraphClient.commit(); } public JanusGraphOperationStatus rollback() { log.error("Going to execute rollback on graph."); return janusGraphClient.rollback(); } public void handleTransactionCommitRollback(boolean inTransaction, Either result) { if (!inTransaction) { if (result == null || result.isRight()) { rollback(); } else { commit(); } } } public Either getGraph() { return janusGraphClient.getGraph(); } // For healthCheck public boolean isGraphOpen() { return janusGraphClient.getHealth(); } /** * @param node * @param clazz * @return */ public Either createNode(T node, Class clazz) { log.debug("try to create node for ID [{}]", node.getKeyValueIdForLog()); Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { T newNode; try { JanusGraph tGraph = graph.left().value(); Vertex vertex = tGraph.addVertex(); vertex.property(GraphPropertiesDictionary.LABEL.getProperty(), node.getLabel()); Map properties = node.toGraphMap(); if (properties != null) { setProperties(vertex, properties); } Map newProps = getProperties(vertex); newNode = GraphElementFactory.createElement(node.getLabel(), GraphElementTypeEnum.Node, newProps, clazz); log.debug("created node for props : {}", newProps); log.debug("Node was created for ID [{}]", node.getKeyValueIdForLog()); return Either.left(newNode); } catch (Exception e) { log.debug("Failed to create Node for ID [{}]", node.getKeyValueId(), e); return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { log.debug("Failed to create Node for ID [{}] {}", node.getKeyValueIdForLog(), graph.right().value()); return Either.right(graph.right().value()); } } public Either createNode(GraphNode node) { log.debug("try to create node for ID [{}]", node.getKeyValueId()); Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { try { JanusGraph tGraph = graph.left().value(); JanusGraphVertex vertex = tGraph.addVertex(); vertex.property(GraphPropertiesDictionary.LABEL.getProperty(), node.getLabel()); Map properties = node.toGraphMap(); if (properties != null) { setProperties(vertex, properties); } log.debug("Node was created for ID [{}]", node.getKeyValueId()); return Either.left(vertex); } catch (Exception e) { log.debug("Failed to create Node for ID [{}]", node.getKeyValueId(), e); return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { log.debug("Failed to create Node for ID [{}] {}", node.getKeyValueId(), graph.right().value()); return Either.right(graph.right().value()); } } /** * @param relation * @return */ public Either createRelation(GraphRelation relation) { log.debug("try to create relation from [{}] to [{}] ", relation.getFrom(), relation.getTo()); RelationEndPoint from = relation.getFrom(); RelationEndPoint to = relation.getTo(); ImmutablePair fromKeyId = new ImmutablePair<>(from.getIdName(), from.getIdValue()); ImmutablePair toKeyId = new ImmutablePair<>(to.getIdName(), to.getIdValue()); return createEdge(relation.getType(), fromKeyId, toKeyId, from.getLabel().getName(), to.getLabel().getName(), relation.toGraphMap()); } private Either createEdge(String type, ImmutablePair from, ImmutablePair to, String fromLabel, String toLabel, Map properties) { Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { try { Either fromV = getVertexByPropertyAndLabel(from.getKey(), from.getValue(), fromLabel); if (fromV.isRight()) { JanusGraphOperationStatus error = fromV.right().value(); if (JanusGraphOperationStatus.NOT_FOUND.equals(error)) { return Either.right(JanusGraphOperationStatus.INVALID_ID); } else { return Either.right(error); } } Either toV = getVertexByPropertyAndLabel(to.getKey(), to.getValue(), toLabel); if (toV.isRight()) { JanusGraphOperationStatus error = toV.right().value(); if (JanusGraphOperationStatus.NOT_FOUND.equals(error)) { return Either.right(JanusGraphOperationStatus.INVALID_ID); } else { return Either.right(error); } } Vertex fromVertex = fromV.left().value(); Vertex toVertex = toV.left().value(); Edge edge = fromVertex.addEdge(type, toVertex); if (properties != null) { setProperties(edge, properties); } Vertex vertexOut = edge.outVertex(); Vertex vertexIn = edge.inVertex(); GraphNode nodeOut = GraphElementFactory .createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class); GraphNode nodeIn = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class); GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn); return Either.left(newRelation); } catch (Exception e) { log.debug("Failed to create edge from [{}] to [{}]", from, to, e); return Either.right(janusGraphClient.handleJanusGraphException(e)); } } else { log.debug("Failed to create edge from [{}] to [{}] {}", from, to, graph.right().value()); return Either.right(graph.right().value()); } } public JanusGraphOperationStatus createEdge(Vertex vertexOut, Vertex vertexIn, GraphEdgeLabels type, Map properties) { try { Edge edge = addEdge(vertexOut, vertexIn, type, properties); } catch (Exception e) { log.debug("Failed to create edge from [{}] to [{}]", vertexOut, vertexIn, e); return janusGraphClient.handleJanusGraphException(e); } return JanusGraphOperationStatus.OK; } private Edge addEdge(Vertex vertexOut, Vertex vertexIn, GraphEdgeLabels type, Map properties) { Edge edge = vertexOut.addEdge(type.getProperty(), vertexIn); if (properties != null) { setProperties(edge, properties); } return edge; } /** * creates an identical edge in the graph * * @param edge * @return the copy operation status */ public Either copyEdge(Vertex out, Vertex in, Edge edge) { GraphEdgeLabels byName = GraphEdgeLabels.getByName(edge.label()); return this.saveEdge(out, in, byName, edgePropertiesToMap(edge)); } private Map edgePropertiesToMap(Edge edge) { Iterable> propertiesIterable = edge::properties; return StreamSupport.stream(propertiesIterable.spliterator(), false).collect(Collectors.toMap(Property::key, Property::value)); } public Either saveEdge(Vertex vertexOut, Vertex vertexIn, GraphEdgeLabels type, Map properties) { try { Edge edge = addEdge(vertexOut, vertexIn, type, properties); return Either.left(edge); } catch (Exception e) { log.debug("Failed to create edge from [{}] to [{}]", vertexOut, vertexIn, e); return Either.right(janusGraphClient.handleJanusGraphException(e)); } } public JanusGraphOperationStatus createEdge(JanusGraphVertex vertexOut, GraphNode to, GraphEdgeLabels type, Map properties) { JanusGraphVertex vertexIn; Either toV = getVertexByPropertyAndLabel(to.getUniqueIdKey(), to.getUniqueId(), to.getLabel()); if (toV.isRight()) { JanusGraphOperationStatus error = toV.right().value(); if (JanusGraphOperationStatus.NOT_FOUND.equals(error)) { return JanusGraphOperationStatus.INVALID_ID; } else { return error; } } vertexIn = (JanusGraphVertex) toV.left().value(); return createEdge(vertexOut, vertexIn, type, properties); } /** * @param from * @param to * @param label * @param properties * @return */ public Either createRelation(GraphNode from, GraphNode to, GraphEdgeLabels label, Map properties) { log.debug("try to create relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId()); return createEdge(label.getProperty(), from.getKeyValueId(), to.getKeyValueId(), from.getLabel(), to.getLabel(), properties); } public Either replaceRelationLabel(GraphNode from, GraphNode to, GraphEdgeLabels label, GraphEdgeLabels newLabel) { log.debug("try to replace relation {} to {} from [{}] to [{}]", label.name(), newLabel.name(), from.getKeyValueId(), to.getKeyValueId()); Either getRelationResult = getRelation(from, to, label); if (getRelationResult.isRight()) { return getRelationResult; } GraphRelation origRelation = getRelationResult.left().value(); Either createRelationResult = createRelation(from, to, newLabel, origRelation.toGraphMap()); if (createRelationResult.isRight()) { return createRelationResult; } Either deleteRelationResult = deleteRelation(origRelation); if (deleteRelationResult.isRight()) { return deleteRelationResult; } return Either.left(createRelationResult.left().value()); } /** * @param keyName * @param keyValue * @param clazz * @return */ public Either getNode(String keyName, Object keyValue, Class clazz) { log.debug("Try to get node for key [{}] with value [{}] ", keyName, keyValue); Either vertexByProperty = getVertexByProperty(keyName, keyValue); if (vertexByProperty.isLeft()) { try { Vertex vertex = vertexByProperty.left().value(); Map properties = getProperties(vertex); T node = GraphElementFactory .createElement((String) properties.get(GraphPropertiesDictionary.LABEL.getProperty()), GraphElementTypeEnum.Node, properties, clazz); return Either.left(node); } catch (Exception e) { log.debug("Failed to get node for key [{}] with value [{}] ", keyName, keyValue, e); return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { log.debug("Failed to get node for key [{}] with value [{}] ", keyName, keyValue, vertexByProperty.right().value()); return Either.right(vertexByProperty.right().value()); } } public Either getNode(final String keyName, final Object keyValue, final Class clazz, final String model) { log.debug("Try to get node for key [{}] with value [{}] ", keyName, keyValue); final Either vertexByProperty = getVertexByPropertyForModel(keyName, keyValue, model); if (vertexByProperty.isLeft()) { try { final Vertex vertex = vertexByProperty.left().value(); final Map properties = getProperties(vertex); final T node = GraphElementFactory .createElement((String) properties.get(GraphPropertiesDictionary.LABEL.getProperty()), GraphElementTypeEnum.Node, properties, clazz); return Either.left(node); } catch (final Exception e) { log.debug("Failed to get node for key [{}] with value [{}] ", keyName, keyValue, e); return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { log.debug("Failed to get node for key [{}] with value [{}] ", keyName, keyValue, vertexByProperty.right().value()); return Either.right(vertexByProperty.right().value()); } } /** * @param from * @param to * @param label * @return */ public Either getRelation(GraphNode from, GraphNode to, GraphEdgeLabels label) { log.debug("try to get relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId()); Either edge = getEdgeByNodes(from, to, label); if (edge.isLeft()) { try { Map properties = getProperties(edge.left().value()); GraphRelation relation = GraphElementFactory.createRelation(label.getProperty(), properties, from, to); return Either.left(relation); } catch (Exception e) { log.debug("Failed to get get relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId(), e); return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { log.debug("Failed to get get relation from [{}] to [{}] {}", from.getKeyValueId(), to.getKeyValueId(), edge.right().value()); return Either.right(edge.right().value()); } } public Either getEdgeByNodes(GraphNode from, GraphNode to, GraphEdgeLabels label) { ImmutablePair keyValueIdFrom = from.getKeyValueId(); ImmutablePair keyValueIdTo = to.getKeyValueId(); return getEdgeByVerticies(keyValueIdFrom.getKey(), keyValueIdFrom.getValue(), keyValueIdTo.getKey(), keyValueIdTo.getValue(), label.getProperty()); } public Either deleteIncomingRelationByCriteria(GraphNode to, GraphEdgeLabels label, Map props) { Either edgeByCriteria = getIncomingEdgeByCriteria(to, label, props); if (edgeByCriteria.isLeft()) { Either graph = getGraph(); if (graph.isLeft()) { Edge edge = edgeByCriteria.left().value(); log.debug("delete edge {} to {} ", label.getProperty(), to.getUniqueId()); edge.remove(); Map properties = getProperties(edge); Vertex fromVertex = edge.outVertex(); String fromLabel = fromVertex.value(GraphPropertiesDictionary.LABEL.getProperty()); GraphNode nodeFrom = GraphElementFactory .createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(fromVertex), GraphNode.class); GraphRelation relation = GraphElementFactory.createRelation(label.getProperty(), properties, nodeFrom, to); return Either.left(relation); } else { log.debug("failed to get graph"); return Either.right(graph.right().value()); } } else { log.debug("failed to find edge {} to {}", label.getProperty(), to.getUniqueId()); return Either.right(edgeByCriteria.right().value()); } } public Either getIncomingRelationByCriteria(GraphNode to, GraphEdgeLabels label, Map props) { Either edgeByCriteria = getIncomingEdgeByCriteria(to, label, props); if (edgeByCriteria.isLeft()) { Either graph = getGraph(); if (graph.isLeft()) { Edge edge = edgeByCriteria.left().value(); Map properties = getProperties(edge); Vertex fromVertex = edge.outVertex(); String fromLabel = fromVertex.value(GraphPropertiesDictionary.LABEL.getProperty()); GraphNode nodeFrom = GraphElementFactory .createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(fromVertex), GraphNode.class); GraphRelation relation = GraphElementFactory.createRelation(label.getProperty(), properties, nodeFrom, to); return Either.left(relation); } else { log.debug("failed to get graph"); return Either.right(graph.right().value()); } } else { log.debug("failed to find edge {} to {}", label.getProperty(), to.getUniqueId()); return Either.right(edgeByCriteria.right().value()); } } public Either getIncomingEdgeByCriteria(GraphNode to, GraphEdgeLabels label, Map props) { ImmutablePair keyValueIdTo = to.getKeyValueId(); Either vertexFrom = getVertexByProperty(keyValueIdTo.getKey(), keyValueIdTo.getValue()); if (vertexFrom.isRight()) { return Either.right(vertexFrom.right().value()); } Vertex vertex = vertexFrom.left().value(); JanusGraphVertex janusGraphVertex = (JanusGraphVertex) vertex; JanusGraphVertexQuery query = janusGraphVertex.query(); query = query.labels(label.getProperty()); if (props != null && !props.isEmpty()) { for (Map.Entry entry : props.entrySet()) { query = query.has(entry.getKey(), entry.getValue()); } } Edge matchingEdge = null; Iterable edges = query.edges(); if (edges == null) { log.debug("No edges in graph for criteria"); return Either.right(JanusGraphOperationStatus.NOT_FOUND); } Iterator eIter = edges.iterator(); if (eIter.hasNext()) { matchingEdge = eIter.next(); } if (matchingEdge == null) { log.debug("No edges in graph for criteria"); return Either.right(JanusGraphOperationStatus.NOT_FOUND); } return Either.left(matchingEdge); } public Either getEdgeByVerticies(String keyNameFrom, Object keyValueFrom, String keyNameTo, Object keyValueTo, String label) { Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { try { Either vertexFrom = getVertexByProperty(keyNameFrom, keyValueFrom); if (vertexFrom.isRight()) { return Either.right(vertexFrom.right().value()); } Iterable edges = ((JanusGraphVertex) vertexFrom.left().value()).query().labels(label).edges(); Iterator eIter = edges.iterator(); while (eIter.hasNext()) { Edge edge = eIter.next(); Vertex vertexIn = edge.inVertex(); if (vertexIn.value(keyNameTo) != null && vertexIn.value(keyNameTo).equals(keyValueTo) && label.equals(edge.label())) { return Either.left(edge); } } log.debug("No relation in graph from [{}={}] to [{}={}]", keyNameFrom, keyValueFrom, keyNameTo, keyValueTo); return Either.right(JanusGraphOperationStatus.NOT_FOUND); } catch (Exception e) { log.debug("Failed to get get relation from [{}={}] to [{}={}]", keyNameFrom, keyValueFrom, keyNameTo, keyValueTo, e); return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { return Either.right(graph.right().value()); } } public Either, JanusGraphOperationStatus> getEdgesForNode(GraphNode node, Direction requestedDirection) { Either, JanusGraphOperationStatus> result; ImmutablePair keyValueId = node.getKeyValueId(); Either eitherVertex = getVertexByProperty(keyValueId.getKey(), keyValueId.getValue()); if (eitherVertex.isLeft()) { List edges = prepareEdgesList(eitherVertex.left().value(), requestedDirection); result = Either.left(edges); } else { result = Either.right(eitherVertex.right().value()); } return result; } private List prepareEdgesList(Vertex vertex, Direction requestedDirection) { List edges = new ArrayList<>(); Iterator edgesItr = ((JanusGraphVertex) vertex).query().edges().iterator(); while (edgesItr.hasNext()) { Edge edge = edgesItr.next(); Direction currEdgeDirection = getEdgeDirection(vertex, edge); if (currEdgeDirection == requestedDirection || requestedDirection == Direction.BOTH) { edges.add(edge); } } return edges; } private Direction getEdgeDirection(Vertex vertex, Edge edge) { Direction result; Vertex vertexOut = edge.outVertex(); if (vertexOut.equals(vertex)) { result = Direction.OUT; } else { result = Direction.IN; } return result; } /** * @param from * @param to * @param label * @param properties * @return */ public Either updateRelation(GraphNode from, GraphNode to, GraphEdgeLabels label, Map properties) { log.debug("try to update relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId()); return updateEdge(label.getProperty(), from.getKeyValueId(), to.getKeyValueId(), from.getLabel(), to.getLabel(), properties); } private Either updateEdge(String type, ImmutablePair from, ImmutablePair to, String fromLabel, String toLabel, Map properties) { Either edgeS = getEdgeByVerticies(from.getKey(), from.getValue(), to.getKey(), to.getValue(), type); if (edgeS.isLeft()) { try { Edge edge = edgeS.left().value(); if (properties != null) { setProperties(edge, properties); } Vertex vertexOut = edge.outVertex(); Vertex vertexIn = edge.inVertex(); GraphNode nodeOut = GraphElementFactory .createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class); GraphNode nodeIn = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class); GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn); if (log.isDebugEnabled()) { log.debug("Relation was updated from [{}] to [{}] ", from, to); } return Either.left(newRelation); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Failed to update relation from [{}] to [{}] ", from, to, e); } return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { if (log.isDebugEnabled()) { log.debug("Failed to update relation from [{}] to [{}] {}", from, to, edgeS.right().value()); } return Either.right(edgeS.right().value()); } } /** * @param relation * @return */ public Either updateRelation(GraphRelation relation) { log.debug("try to update relation from [{}] to [{}]", relation.getFrom(), relation.getTo()); RelationEndPoint from = relation.getFrom(); RelationEndPoint to = relation.getTo(); ImmutablePair fromKeyId = new ImmutablePair<>(from.getIdName(), from.getIdValue()); ImmutablePair toKeyId = new ImmutablePair<>(to.getIdName(), to.getIdValue()); return updateEdge(relation.getType(), fromKeyId, toKeyId, from.getLabel().getName(), to.getLabel().getName(), relation.toGraphMap()); } private Either getVertexByPropertyAndLabel(String name, Object value, String label) { Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { try { JanusGraph tGraph = graph.left().value(); @SuppressWarnings("unchecked") Iterable vertecies = tGraph.query().has(name, value) .has(GraphPropertiesDictionary.LABEL.getProperty(), label).vertices(); java.util.Iterator iterator = vertecies.iterator(); if (iterator.hasNext()) { Vertex vertex = iterator.next(); return Either.left(vertex); } if (log.isDebugEnabled()) { log.debug("No vertex in graph for key =" + name + " and value = " + value + " label = " + label); } return Either.right(JanusGraphOperationStatus.NOT_FOUND); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Failed to get vertex in graph for key ={} and value = {} label = {}", name, value, label); } return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { if (log.isDebugEnabled()) { log.debug("No vertex in graph for key ={} and value = {} label = {} error : {}", name, value, label, graph.right().value()); } return Either.right(graph.right().value()); } } public Either getVertexByPropertyForModel(final String name, final Object value, final String model) { final Either, JanusGraphOperationStatus> vertices = getVerticesByProperty(name, value); if (vertices.isLeft()) { final Predicate filterPredicate = StringUtils.isEmpty(model) ? this::vertexNotConnectedToAnyModel : vertex -> vertexValidForModel(vertex, model); final List verticesForModel = StreamSupport.stream(vertices.left().value().spliterator(), false).filter(filterPredicate).collect(Collectors.toList()); if (CollectionUtils.isEmpty(verticesForModel)) { if (log.isDebugEnabled()) { log.debug("No vertex in graph for key ={} and value = {}", name, value); } return Either.right(JanusGraphOperationStatus.NOT_FOUND); } return Either.left(verticesForModel.get(0)); } return Either.right(vertices.right().value()); } public Either getVertexByProperty(final String name, final Object value) { final Either, JanusGraphOperationStatus> vertices = getVerticesByProperty(name, value); if (vertices.isLeft()) { return Either.left(vertices.left().value().iterator().next()); } return Either.right(vertices.right().value()); } public Either, JanusGraphOperationStatus> getVerticesByProperty(final String name, final Object value) { final Either graph = janusGraphClient.getGraph(); if (value == null) { if (log.isDebugEnabled()) { log.debug("No vertex in graph for key = {} and value = {}", name, value); } return Either.right(JanusGraphOperationStatus.NOT_FOUND); } if (graph.isLeft()) { try { final JanusGraph tGraph = graph.left().value(); @SuppressWarnings("unchecked") Iterable vertices = tGraph.query().has(name, value).vertices(); if (vertices.iterator().hasNext()) { return Either.left(vertices); } else { if (log.isDebugEnabled()) { log.debug("No vertex in graph for key ={} and value = {}", name, value); } return Either.right(JanusGraphOperationStatus.NOT_FOUND); } } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Failed to get vertex in graph for key = {} and value = ", name, value); } return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { if (log.isDebugEnabled()) { log.debug("No vertex in graph for key = {} and value = {} error : {}", name, value, graph.right().value()); } return Either.right(graph.right().value()); } } private boolean vertexValidForModel(final JanusGraphVertex vertex, final String model) { final Either>, JanusGraphOperationStatus> modelVertices = getParentVerticies(vertex, GraphEdgeLabels.MODEL_ELEMENT); if (modelVertices.isLeft()) { for (ImmutablePair vertexPair : modelVertices.left().value()) { if (modelVertexMatchesModel(vertexPair.getLeft(), model)) { return true; } } } return false; } private boolean modelVertexMatchesModel(final JanusGraphVertex modelVertex, final String model) { if (model.equals((String)modelVertex.property("name").value())) { return true; } final Either>, JanusGraphOperationStatus> derivedModels = getParentVerticies(modelVertex, GraphEdgeLabels.DERIVED_FROM); if (derivedModels.isLeft()) { for (final ImmutablePair derivedModel : derivedModels.left().value()) { if (modelVertexMatchesModel(derivedModel.left, model)) { return true; } } } return false; } private boolean vertexNotConnectedToAnyModel(final JanusGraphVertex vertex) { return !vertex.edges(Direction.IN, EdgeLabelEnum.MODEL_ELEMENT.name()).hasNext(); } public Either, JanusGraphOperationStatus> getByCriteria(NodeTypeEnum type, Map hasProps, Map hasNotProps, Class clazz) { Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { try { JanusGraph tGraph = graph.left().value(); JanusGraphQuery query = tGraph.query(); query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName()); if (hasProps != null && !hasProps.isEmpty()) { for (Map.Entry entry : hasProps.entrySet()) { query = query.has(entry.getKey(), entry.getValue()); } } if (hasNotProps != null && !hasNotProps.isEmpty()) { for (Map.Entry entry : hasNotProps.entrySet()) { query = query.hasNot(entry.getKey(), entry.getValue()); } } Iterable vertices = query.vertices(); if (vertices == null) { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } Iterator iterator = vertices.iterator(); List result = new ArrayList<>(); while (iterator.hasNext()) { Vertex vertex = iterator.next(); Map newProp = getProperties(vertex); T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz); result.add(element); } if (log.isDebugEnabled()) { log.debug("Number of fetced nodes in graph for criteria : from type = {} and properties has = {}, properties hasNot = {} is {}", type, hasProps, hasNotProps, result.size()); } if (result.size() == 0) { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } return Either.left(result); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Failed get by criteria for type = {}", type, e); } return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { if (log.isDebugEnabled()) { log.debug("Failed get by criteria for type ={} error : {}", type, graph.right().value()); } return Either.right(graph.right().value()); } } public Either, JanusGraphOperationStatus> getByCriteria(NodeTypeEnum type, Class clazz, List> props) { Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { try { JanusGraph tGraph = graph.left().value(); JanusGraphQuery query = tGraph.query(); query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName()); for (ImmutableTriple prop : props) { if (QueryType.HAS.equals(prop.getLeft())) { query = query.has(prop.getMiddle(), prop.getRight()); } else { query = query.hasNot(prop.getMiddle(), prop.getRight()); } } Iterable vertices = query.vertices(); if (vertices == null) { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } Iterator iterator = vertices.iterator(); List result = new ArrayList<>(); while (iterator.hasNext()) { Vertex vertex = iterator.next(); Map newProp = getProperties(vertex); T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz); result.add(element); } if (result.size() == 0) { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } return Either.left(result); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Failed get by criteria for type = {}", type, e); } return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { if (log.isDebugEnabled()) { log.debug("Failed get by criteria for type ={} error : {}", type, graph.right().value()); } return Either.right(graph.right().value()); } } public Either, JanusGraphOperationStatus> getByCriteria(NodeTypeEnum type, Map props, Class clazz) { return getByCriteriaForModel(type, props, null, clazz); } public Either, JanusGraphOperationStatus> getByCriteriaForModel(final NodeTypeEnum type, final Map props, final String model, final Class clazz) { try { final Either, JanusGraphOperationStatus> vertices = getVerticesByCriteria(type, props); if (vertices.isLeft()) { final Predicate filterPredicate = StringUtils.isEmpty(model) ? this::vertexNotConnectedToAnyModel : vertex -> vertexValidForModel(vertex, model); final List verticesForModel = StreamSupport.stream(vertices.left().value().spliterator(), false).filter(filterPredicate).collect(Collectors.toList()); if (CollectionUtils.isEmpty(verticesForModel)) { log.debug("No vertex in graph for props ={} ", props); return Either.right(JanusGraphOperationStatus.NOT_FOUND); } final Iterator iterator = verticesForModel.iterator(); final List result = new ArrayList<>(); while (iterator.hasNext()) { Vertex vertex = iterator.next(); Map newProp = getProperties(vertex); T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz); result.add(element); } log.debug("Number of fetced nodes in graph for criteria : from type = {} and properties = {} is {}", type, props, result.size()); return Either.left(result); } return Either.right(vertices.right().value()); } catch (Exception e) { log.debug("Failed get by criteria for type = {} and properties = {}", type, props, e); return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } private Either, JanusGraphOperationStatus> getVerticesByCriteria(final NodeTypeEnum type, final Map props) { final Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { try { final JanusGraph tGraph = graph.left().value(); JanusGraphQuery query = tGraph.query(); query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName()); if (props != null && !props.isEmpty()) { for (Map.Entry entry : props.entrySet()) { query = query.has(entry.getKey(), entry.getValue()); } } final Iterable vertices = query.vertices(); if (vertices == null || !vertices.iterator().hasNext()) { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } return Either.left(vertices); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Failed get by criteria for type = {} and properties = {}", type, props, e); } return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { if (log.isDebugEnabled()) { log.debug("Failed get by criteria for type ={} and properties = {} error : {}", type, props, graph.right().value()); } return Either.right(graph.right().value()); } } public Either, JanusGraphOperationStatus> getByCriteriaWithPredicate(NodeTypeEnum type, Map> props, Class clazz, String modelName) { Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { try { JanusGraph tGraph = graph.left().value(); JanusGraphQuery query = tGraph.query(); query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName()); if (props != null && !props.isEmpty()) { JanusGraphPredicate predicate = null; Object object = null; for (Map.Entry> entry : props.entrySet()) { predicate = entry.getValue().getKey(); object = entry.getValue().getValue(); query = query.has(entry.getKey(), predicate, object); } } Iterable vertices = query.vertices(); if (vertices == null) { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } final Predicate filterPredicate = StringUtils.isEmpty(modelName) ? this::vertexNotConnectedToAnyModel : vertex -> vertexValidForModel(vertex, modelName); final List verticesForModel = StreamSupport.stream(vertices.spliterator(), false).filter(filterPredicate) .collect(Collectors.toList()); Iterator iterator = verticesForModel.iterator(); List result = new ArrayList<>(); while (iterator.hasNext()) { Vertex vertex = iterator.next(); Map newProp = getProperties(vertex); T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz); result.add(element); } if (result.size() == 0) { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } if (log.isDebugEnabled()) { log.debug("No nodes in graph for criteria : from type = {} and properties = {}", type, props); } return Either.left(result); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Failed get by criteria for type = {} and properties = {}", type, props, e); } return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { if (log.isDebugEnabled()) { log.debug("Failed get by criteria for type = {} and properties = {} error : {}", type, props, graph.right().value()); } return Either.right(graph.right().value()); } } public Either, JanusGraphOperationStatus> getAll(NodeTypeEnum type, Class clazz) { return getByCriteria(type, null, clazz); } /** * @param node * @param clazz * @return */ public Either updateNode(GraphNode node, Class clazz) { log.debug("Try to update node for {}", node.getKeyValueIdForLog()); ImmutablePair keyValueId = node.getKeyValueId(); Either vertexByProperty = getVertexByPropertyAndLabel(keyValueId.getKey(), keyValueId.getValue(), node.getLabel()); if (vertexByProperty.isLeft()) { try { Vertex vertex = vertexByProperty.left().value(); Map mapProps = node.toGraphMap(); for (Map.Entry entry : mapProps.entrySet()) { if (!entry.getKey().equals(node.getUniqueIdKey())) { vertex.property(entry.getKey(), entry.getValue()); } } Either vertexByPropertyAndLabel = getVertexByPropertyAndLabel(keyValueId.getKey(), keyValueId.getValue(), node.getLabel()); if (vertexByPropertyAndLabel.isRight()) { return Either.right(vertexByPropertyAndLabel.right().value()); } else { Map newProp = getProperties(vertexByPropertyAndLabel.left().value()); T updateNode = GraphElementFactory.createElement(node.getLabel(), GraphElementTypeEnum.Node, newProp, clazz); return Either.left(updateNode); } } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Failed to update node for {}", node.getKeyValueId(), e); } return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { if (log.isDebugEnabled()) { log.debug("Failed to update node for {} error :{}", node.getKeyValueIdForLog(), vertexByProperty.right().value()); } return Either.right(vertexByProperty.right().value()); } } public JanusGraphOperationStatus updateVertex(GraphNode node, Vertex vertex) { log.debug("Try to update node for {}", node.getKeyValueId()); try { Map mapProps = node.toGraphMap(); for (Map.Entry entry : mapProps.entrySet()) { if (!entry.getKey().equals(node.getUniqueIdKey())) { vertex.property(entry.getKey(), entry.getValue()); } } } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Failed to update node for {}", node.getKeyValueId(), e); } return JanusGraphClient.handleJanusGraphException(e); } return JanusGraphOperationStatus.OK; } /** * @param node * @param clazz * @return */ public Either deleteNode(GraphNode node, Class clazz) { log.debug("Try to delete node for {}", node.getKeyValueId()); ImmutablePair keyValueId = node.getKeyValueId(); return deleteNode(keyValueId.getKey(), keyValueId.getValue(), clazz); } /** * @param keyName * @param keyValue * @param clazz * @return */ public Either deleteNode(String keyName, Object keyValue, Class clazz) { Either vertexByProperty = getVertexByProperty(keyName, keyValue); if (vertexByProperty.isLeft()) { try { Vertex vertex = vertexByProperty.left().value(); Map properties = getProperties(vertex); if (properties != null) { String label = (String) properties.get(GraphPropertiesDictionary.LABEL.getProperty()); T node = GraphElementFactory.createElement(label, GraphElementTypeEnum.Node, properties, clazz); if (node != null) { Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { JanusGraph tGraph = graph.left().value(); vertex.remove(); } else { return Either.right(graph.right().value()); } return Either.left(node); } else { if (log.isDebugEnabled()) { log.debug("Failed to delete node for {} = {} Missing label property on node", keyName, keyValue); } return Either.right(JanusGraphOperationStatus.MISSING_NODE_LABEL); } } else { if (log.isDebugEnabled()) { log.debug("Failed to delete node for {} = {} Missing label property on node", keyName, keyValue); } return Either.right(JanusGraphOperationStatus.MISSING_NODE_LABEL); } } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Failed to delete node for {} = {}", keyName, keyValue, e); } return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { return Either.right(vertexByProperty.right().value()); } } public Either deleteRelation(GraphRelation relation) { log.debug("try to delete relation from [{}] to [{}]", relation.getFrom(), relation.getTo()); RelationEndPoint from = relation.getFrom(); RelationEndPoint to = relation.getTo(); ImmutablePair fromKeyId = new ImmutablePair<>(from.getIdName(), from.getIdValue()); ImmutablePair toKeyId = new ImmutablePair<>(to.getIdName(), to.getIdValue()); return deleteEdge(relation.getType(), fromKeyId, toKeyId, from.getLabel().getName(), to.getLabel().getName()); } public Either isRelationExist(GraphNode from, GraphNode to, GraphEdgeLabels edgeLabel) { return getEdgeByNodes(from, to, edgeLabel).left().map(edge -> true).right() .bind(err -> err == JanusGraphOperationStatus.NOT_FOUND ? Either.left(false) : Either.right(err)); } public Either deleteRelation(GraphNode from, GraphNode to, GraphEdgeLabels label) { log.debug("try to delete relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId()); return deleteEdge(label.getProperty(), from.getKeyValueId(), to.getKeyValueId(), from.getLabel(), to.getLabel()); } private Either deleteEdge(String type, ImmutablePair fromKeyId, ImmutablePair toKeyId, String fromLabel, String toLabel) { Either edgeS = getEdgeByVerticies(fromKeyId.getKey(), fromKeyId.getValue(), toKeyId.getKey(), toKeyId.getValue(), type); if (edgeS.isLeft()) { try { Edge edge = edgeS.left().value(); Vertex vertexOut = edge.outVertex(); Vertex vertexIn = edge.inVertex(); GraphNode nodeOut = GraphElementFactory .createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class); GraphNode nodeIn = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class); GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn); Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { edge.remove(); ; } else { if (log.isDebugEnabled()) { log.debug("Failed to delete relation {} from {} to {} error : {}", type, fromKeyId, toKeyId, graph.right().value()); } return Either.right(graph.right().value()); } return Either.left(newRelation); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Failed to delete relation {} from {} to {}", type, fromKeyId, toKeyId, e); } return Either.right(JanusGraphClient.handleJanusGraphException(e)); } } else { if (log.isDebugEnabled()) { log.debug("Failed to delete relation {} from {} to {} error : {}", type, fromKeyId, toKeyId, edgeS.right().value()); } return Either.right(edgeS.right().value()); } } public void setJanusGraphClient(JanusGraphClient janusGraphClient) { this.janusGraphClient = janusGraphClient; } public Either deleteIncomingRelation(GraphRelation relation) { RelationEndPoint to = relation.getTo(); ImmutablePair toKeyId = new ImmutablePair<>(to.getIdName(), to.getIdValue()); return deleteIncomingEdge(relation.getType(), toKeyId); } private Either deleteIncomingEdge(String type, ImmutablePair toKeyId) { Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { Either rootVertexResult = getVertexByProperty(toKeyId.getKey(), toKeyId.getValue()); if (rootVertexResult.isLeft()) { Vertex rootVertex = rootVertexResult.left().value(); Iterator edgesIterator = rootVertex.edges(Direction.IN, type); if (edgesIterator != null) { Edge edge = null; if (edgesIterator.hasNext()) { edge = edgesIterator.next(); if (edgesIterator.hasNext()) { return Either.right(JanusGraphOperationStatus.MULTIPLE_EDGES_WITH_SAME_LABEL); } } else { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } log.debug("Find the tail vertex of the edge of type {} to vertex {}", type, toKeyId); Vertex vertexOut = edge.outVertex(); String fromLabel = vertexOut.value(GraphPropertiesDictionary.LABEL.getProperty()); String toLabel = rootVertex.value(GraphPropertiesDictionary.LABEL.getProperty()); log.debug("The label of the outgoing vertex is {}", fromLabel); GraphNode nodeOut = GraphElementFactory .createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class); GraphNode nodeIn = GraphElementFactory .createElement(toLabel, GraphElementTypeEnum.Node, getProperties(rootVertex), GraphNode.class); GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn); edge.remove(); return Either.left(newRelation); } else { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } } else { return Either.right(graph.right().value()); } } else { return Either.right(graph.right().value()); } } public Either deleteOutgoingRelation(GraphRelation relation) { RelationEndPoint from = relation.getFrom(); ImmutablePair fromKeyId = new ImmutablePair<>(from.getIdName(), from.getIdValue()); return deleteOutgoingEdge(relation.getType(), fromKeyId); } private Either deleteOutgoingEdge(String type, ImmutablePair toKeyId) { Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { Either rootVertexResult = getVertexByProperty(toKeyId.getKey(), toKeyId.getValue()); if (rootVertexResult.isLeft()) { Vertex rootVertex = rootVertexResult.left().value(); Iterator edgesIterator = rootVertex.edges(Direction.OUT, type); if (edgesIterator != null) { Edge edge = null; if (edgesIterator.hasNext()) { edge = edgesIterator.next(); if (edgesIterator.hasNext()) { return Either.right(JanusGraphOperationStatus.MULTIPLE_EDGES_WITH_SAME_LABEL); } } else { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } log.debug("Find the tail vertex of the edge of type {} to vertex ", type, toKeyId); Vertex vertexIn = edge.inVertex(); String toLabel = vertexIn.value(GraphPropertiesDictionary.LABEL.getProperty()); String fromLabel = rootVertex.value(GraphPropertiesDictionary.LABEL.getProperty()); log.debug("The label of the tail vertex is {}", toLabel); GraphNode nodeFrom = GraphElementFactory .createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(rootVertex), GraphNode.class); GraphNode nodeTo = GraphElementFactory .createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class); GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeFrom, nodeTo); edge.remove(); return Either.left(newRelation); } else { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } } else { return Either.right(graph.right().value()); } } else { return Either.right(graph.right().value()); } } /** * @param id * @return */ public JanusGraphOperationStatus lockElement(String id, NodeTypeEnum type) { StringBuilder lockId = new StringBuilder(LOCK_NODE_PREFIX); lockId.append(type.getName()).append("_").append(id); return lockNode(lockId.toString()); } public JanusGraphOperationStatus lockElement(GraphNode node) { String lockId = createLockElementId(node); return lockNode(lockId); } private JanusGraphOperationStatus lockNode(String lockId) { GraphNodeLock lockNode = new GraphNodeLock(lockId); Either lockNodeNew = createNode(lockNode, GraphNodeLock.class); if (lockNodeNew.isLeft()) { log.debug("before commit, Lock node created for {}", lockId); return janusGraphClient.commit(); } else { Either graph = janusGraphClient.getGraph(); if (graph.isLeft()) { JanusGraph tGraph = graph.left().value(); Either vertex = getVertexByProperty(lockNode.getUniqueIdKey(), lockNode.getUniqueId()); if (vertex.isLeft()) { return relockNode(lockNode, lockNodeNew, tGraph, vertex); } else { return vertex.right().value(); } } else { return graph.right().value(); } } } private JanusGraphOperationStatus relockNode(GraphNodeLock lockNode, Either lockNodeNew, JanusGraph tGraph, Either vertex) { Long time = vertex.left().value().value(GraphPropertiesDictionary.CREATION_DATE.getProperty()); Long lockTimeout = ConfigurationManager.getConfigurationManager().getConfiguration().getJanusGraphLockTimeout(); if (time + lockTimeout * 1000 < System.currentTimeMillis()) { log.debug("Found not released lock node with id {}", lockNode.getUniqueId()); vertex.left().value().remove(); lockNodeNew = createNode(lockNode, GraphNodeLock.class); if (lockNodeNew.isLeft()) { log.debug("Lock node created for {}", lockNode.getUniqueIdKey()); return janusGraphClient.commit(); } else { log.debug("Failed Lock node for {} . Commit transacton for deleted previous vertex .", lockNode.getUniqueIdKey()); janusGraphClient.commit(); return checkLockError(lockNode.getUniqueIdKey(), lockNodeNew); } } else { log.debug("Failed Lock node for {} rollback transacton", lockNode.getUniqueIdKey()); janusGraphClient.rollback(); return checkLockError(lockNode.getUniqueIdKey(), lockNodeNew); } } public Either>, JanusGraphOperationStatus> getChildrenNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class clazz, boolean withEdges) { List> immutablePairs = new ArrayList<>(); Either graphRes = janusGraphClient.getGraph(); if (graphRes.isRight()) { log.error("Failed to retrieve graph. status is {}", graphRes); return Either.right(graphRes.right().value()); } JanusGraph janusGraph = graphRes.left().value(); @SuppressWarnings("unchecked") Iterable vertices = janusGraph.query().has(key, uniqueId).vertices(); if (vertices == null || !vertices.iterator().hasNext()) { return Either.right(JanusGraphOperationStatus.INVALID_ID); } Vertex rootVertex = vertices.iterator().next(); Iterator edgesCreatorIterator = rootVertex.edges(Direction.OUT, edgeType.getProperty()); if (edgesCreatorIterator != null) { while (edgesCreatorIterator.hasNext()) { Edge edge = edgesCreatorIterator.next(); GraphEdge graphEdge = null; if (withEdges) { Map edgeProps = getProperties(edge); GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label()); graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps); } Vertex outgoingVertex = edge.inVertex(); Map properties = getProperties(outgoingVertex); T data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz); ImmutablePair immutablePair = new ImmutablePair<>(clazz.cast(data), graphEdge); immutablePairs.add(immutablePair); } } if (immutablePairs.isEmpty()) { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } return Either.left(immutablePairs); } public JanusGraphOperationStatus deleteAllChildrenNodes(String key, String uniqueId, GraphEdgeLabels edgeType) { final JanusGraph janusGraph = getJanusGraph(); final Iterable vertices = janusGraph.query().has(key, uniqueId).vertices(); if (vertices == null || !vertices.iterator().hasNext()) { return JanusGraphOperationStatus.NOT_FOUND; } final Vertex rootVertex = vertices.iterator().next(); final Iterator outEdges = rootVertex.edges(Direction.OUT, edgeType.getProperty()); while (outEdges.hasNext()) { final Edge edge = outEdges.next(); final Vertex vertexIn = edge.inVertex(); final Iterator outSubEdges = vertexIn.edges(Direction.OUT); while (outSubEdges.hasNext()) { Edge subEdge = outSubEdges.next(); Vertex vertex = subEdge.inVertex(); Map properties = getProperties(vertex); if (properties != null) { String label = (String) properties.get(GraphPropertiesDictionary.LABEL.getProperty()); if (label.equals("property")) { vertex.remove(); } } } Map properties = getProperties(vertexIn); if (properties != null) { String label = (String) properties.get(GraphPropertiesDictionary.LABEL.getProperty()); GraphNode node = GraphElementFactory .createElement(label, GraphElementTypeEnum.Node, properties, GraphNode.class); if (node != null) { vertexIn.remove(); } } } return JanusGraphOperationStatus.OK; } /** * Gets the JanusGraph instance. * * @return the JanusGraph instance * @throws JanusGraphException when the graph was not created */ public JanusGraph getJanusGraph() { final Either graphRes = janusGraphClient.getGraph(); if (graphRes.isRight()) { final var errorMsg = String.format("Failed to retrieve graph. Status was '%s'", graphRes.right().value()); log.error(EcompLoggerErrorCode.SCHEMA_ERROR, JanusGraphGenericDao.class.getName(), errorMsg); throw new JanusGraphException(graphRes.right().value(), errorMsg); } return graphRes.left().value(); } public Either>, JanusGraphOperationStatus> getChildrenVertecies(String key, String uniqueId, GraphEdgeLabels edgeType) { List> immutablePairs = new ArrayList<>(); Either graphRes = janusGraphClient.getGraph(); if (graphRes.isRight()) { log.error("Failed to retrieve graph. status is {}", graphRes); return Either.right(graphRes.right().value()); } JanusGraph janusGraph = graphRes.left().value(); @SuppressWarnings("unchecked") Iterable vertices = janusGraph.query().has(key, uniqueId).vertices(); if (vertices == null || !vertices.iterator().hasNext()) { return Either.right(JanusGraphOperationStatus.INVALID_ID); } return getChildrenVerticies(vertices.iterator().next(), edgeType); } public Either>, JanusGraphOperationStatus> getChildrenVerticies( final JanusGraphVertex rootVertex, final GraphEdgeLabels edgeType) { return getEdgeVerticies(rootVertex, Direction.OUT, edgeType); } public Either>, JanusGraphOperationStatus> getParentVerticies( final JanusGraphVertex rootVertex, final GraphEdgeLabels edgeType) { return getEdgeVerticies(rootVertex, Direction.IN, edgeType); } public Either>, JanusGraphOperationStatus> getEdgeVerticies( final JanusGraphVertex rootVertex, final Direction direction, final GraphEdgeLabels edgeType) { final List> immutablePairs = new ArrayList<>(); final Iterator edgesCreatorIterator = rootVertex.edges(direction, edgeType.getProperty()); if (edgesCreatorIterator != null) { while (edgesCreatorIterator.hasNext()) { Edge edge = edgesCreatorIterator.next(); JanusGraphVertex vertex = Direction.OUT.equals(direction)? (JanusGraphVertex) edge.inVertex() : (JanusGraphVertex) edge.outVertex(); ImmutablePair immutablePair = new ImmutablePair<>(vertex, edge); immutablePairs.add(immutablePair); } } if (immutablePairs.isEmpty()) { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } return Either.left(immutablePairs); } public Either>, JanusGraphOperationStatus> getChildrenNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class clazz) { return this.getChildrenNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz, true); } private JanusGraphOperationStatus checkLockError(String lockId, Either lockNodeNew) { JanusGraphOperationStatus status; JanusGraphOperationStatus error = lockNodeNew.right().value(); log.debug("Failed to Lock node for {} error = {}", lockId, error); if (error.equals(JanusGraphOperationStatus.JANUSGRAPH_SCHEMA_VIOLATION) || error.equals(JanusGraphOperationStatus.ILLEGAL_ARGUMENT)) { status = JanusGraphOperationStatus.ALREADY_LOCKED; } else { status = error; } return status; } /** * @param node * @return */ public JanusGraphOperationStatus releaseElement(GraphNode node) { String lockId = createLockElementId(node); return unlockNode(lockId); } private JanusGraphOperationStatus unlockNode(String lockId) { GraphNodeLock lockNode = new GraphNodeLock(lockId.toString()); Either lockNodeNew = deleteNode(lockNode, GraphNodeLock.class); if (lockNodeNew.isLeft()) { log.debug("Lock node released for lock id = {}", lockId); return janusGraphClient.commit(); } else { janusGraphClient.rollback(); JanusGraphOperationStatus error = lockNodeNew.right().value(); log.debug("Failed to Release node for lock id {} error = {}", lockId, error); return error; } } public JanusGraphOperationStatus releaseElement(String id, NodeTypeEnum type) { StringBuilder lockId = new StringBuilder(LOCK_NODE_PREFIX); lockId.append(type.getName()).append("_").append(id); return unlockNode(lockId.toString()); } private String createLockElementId(GraphNode node) { StringBuilder lockId = new StringBuilder(LOCK_NODE_PREFIX); lockId.append(node.getLabel()).append("_").append(node.getUniqueId()); return lockId.toString(); } public Either, JanusGraphOperationStatus> getChild(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class clazz) { Either>, JanusGraphOperationStatus> childrenNodes = getChildrenNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz); if (childrenNodes.isRight()) { return Either.right(childrenNodes.right().value()); } List> value = childrenNodes.left().value(); if (value.size() > 1) { return Either.right(JanusGraphOperationStatus.MULTIPLE_CHILDS_WITH_SAME_EDGE); } return Either.left(value.get(0)); } public ImmutablePair getChildVertex(JanusGraphVertex vertex, GraphEdgeLabels edgeType) { ImmutablePair pair = null; Iterator edges = vertex.edges(Direction.OUT, edgeType.getProperty()); if (edges.hasNext()) { // get only first edge Edge edge = edges.next(); pair = new ImmutablePair<>((JanusGraphVertex) edge.inVertex(), edge); } return pair; } public Either>, JanusGraphOperationStatus> getParentNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class clazz) { List> immutablePairs = new ArrayList<>(); T data = null; GraphEdge graphEdge = null; Either graphRes = janusGraphClient.getGraph(); if (graphRes.isRight()) { log.error("Failed to retrieve graph. status is {}", graphRes); return Either.right(graphRes.right().value()); } JanusGraph janusGraph = graphRes.left().value(); @SuppressWarnings("unchecked") Iterable vertices = janusGraph.query().has(key, uniqueId).vertices(); if (vertices == null || !vertices.iterator().hasNext()) { return Either.right(JanusGraphOperationStatus.INVALID_ID); } Vertex rootVertex = vertices.iterator().next(); Iterator edgesCreatorIterator = rootVertex.edges(Direction.IN, edgeType.name()); if (edgesCreatorIterator != null) { while (edgesCreatorIterator.hasNext()) { Edge edge = edgesCreatorIterator.next(); Map edgeProps = getProperties(edge); GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label()); graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps); Vertex outgoingVertex = edge.outVertex(); Map properties = getProperties(outgoingVertex); data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz); ImmutablePair immutablePair = new ImmutablePair<>(clazz.cast(data), graphEdge); immutablePairs.add(immutablePair); } } if (immutablePairs.isEmpty()) { return Either.right(JanusGraphOperationStatus.NOT_FOUND); } return Either.left(immutablePairs); } public Either, JanusGraphOperationStatus> getParentNode(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class clazz) { Either>, JanusGraphOperationStatus> parentNodesRes = this .getParentNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz); if (parentNodesRes.isRight()) { log.debug("failed to get edge key:{} uniqueId:{} edgeType {} nodeTypeEnum: {}, reason:{}", key, uniqueId, edgeType, nodeTypeEnum, parentNodesRes.right().value()); return Either.right(parentNodesRes.right().value()); } List> value = parentNodesRes.left().value(); if (value.size() > 1) { return Either.right(JanusGraphOperationStatus.MULTIPLE_CHILDS_WITH_SAME_EDGE); } return Either.left(value.get(0)); } public Either, JanusGraphOperationStatus> getChildByEdgeCriteria(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class clazz, Map edgeProperties) { Either outgoingEdgeByCriteria = getOutgoingEdgeByCriteria(key, uniqueId, edgeType, edgeProperties); if (outgoingEdgeByCriteria.isRight()) { JanusGraphOperationStatus status = outgoingEdgeByCriteria.right().value(); log.debug("Cannot find outgoing edge from vertex {} with label {} and properties {}" + uniqueId, edgeType, edgeProperties); return Either.right(status); } Edge edge = outgoingEdgeByCriteria.left().value(); Map edgeProps = getProperties(edge); GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label()); GraphEdge graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps); Vertex outgoingVertex = edge.inVertex(); Map properties = getProperties(outgoingVertex); T data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz); ImmutablePair immutablePair = new ImmutablePair<>(clazz.cast(data), graphEdge); return Either.left(immutablePair); } public Either, JanusGraphOperationStatus> getChildByEdgeCriteria(JanusGraphVertex vertex, GraphEdgeLabels edgeType, Map edgeProperties) { Either outgoingEdgeByCriteria = getOutgoingEdgeByCriteria(vertex, edgeType, edgeProperties); if (outgoingEdgeByCriteria.isRight()) { JanusGraphOperationStatus status = outgoingEdgeByCriteria.right().value(); log.debug("Cannot find outgoing edge from vertex {} with label {} and properties {}", vertex, edgeType, edgeProperties); return Either.right(status); } Edge edge = outgoingEdgeByCriteria.left().value(); JanusGraphVertex outgoingVertex = (JanusGraphVertex) edge.inVertex(); ImmutablePair immutablePair = new ImmutablePair<>(outgoingVertex, edge); return Either.left(immutablePair); } public Either getOutgoingEdgeByCriteria(String key, String value, GraphEdgeLabels label, Map props) { Either vertexFrom = getVertexByProperty(key, value); if (vertexFrom.isRight()) { JanusGraphOperationStatus status = vertexFrom.right().value(); if (status == JanusGraphOperationStatus.NOT_FOUND) { return Either.right(JanusGraphOperationStatus.INVALID_ID); } return Either.right(status); } return getOutgoingEdgeByCriteria(vertexFrom.left().value(), label, props); } public Either getOutgoingEdgeByCriteria(JanusGraphVertex vertex, GraphEdgeLabels label, Map props) { JanusGraphVertexQuery query = vertex.query(); query = query.direction(Direction.OUT).labels(label.getProperty()); if (props != null && !props.isEmpty()) { for (Map.Entry entry : props.entrySet()) { query = query.has(entry.getKey(), entry.getValue()); } } Edge matchingEdge = null; Iterable edges = query.edges(); if (edges == null) { log.debug("No edges in graph for criteria"); return Either.right(JanusGraphOperationStatus.NOT_FOUND); } Iterator eIter = edges.iterator(); if (eIter.hasNext()) { matchingEdge = eIter.next(); } if (matchingEdge == null) { log.debug("No edges in graph for criteria"); return Either.right(JanusGraphOperationStatus.NOT_FOUND); } return Either.left(matchingEdge); } public Either>, JanusGraphOperationStatus> deleteChildrenNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class clazz) { List> result = new ArrayList<>(); Either>, JanusGraphOperationStatus> childrenNodesRes = getChildrenNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz); if (childrenNodesRes.isRight()) { JanusGraphOperationStatus status = childrenNodesRes.right().value(); return Either.right(status); } List> list = childrenNodesRes.left().value(); for (ImmutablePair pair : list) { T node = pair.getKey(); Either deleteNodeRes = this.deleteNode(node, clazz); if (deleteNodeRes.isRight()) { JanusGraphOperationStatus status = deleteNodeRes.right().value(); log.error("Failed to delete node {} . status is {}", node, status); return Either.right(status); } ImmutablePair deletedPair = new ImmutablePair<>(node, pair.getValue()); result.add(deletedPair); } return Either.left(result); } public void setProperties(Element element, Map properties) { if (properties != null && !properties.isEmpty()) { Object[] propertyKeyValues = new Object[properties.size() * 2]; int i = 0; for (Entry entry : properties.entrySet()) { propertyKeyValues[i++] = entry.getKey(); propertyKeyValues[i++] = entry.getValue(); } ElementHelper.attachProperties(element, propertyKeyValues); } } public Map getProperties(Element element) { Map result = new HashMap<>(); if (element != null && element.keys() != null && element.keys().size() > 0) { Map propertyMap = ElementHelper.propertyMap(element, element.keys().toArray(new String[element.keys().size()])); for (Entry entry : propertyMap.entrySet()) { String key = entry.getKey(); Object value = entry.getValue().value(); result.put(key, value); } } return result; } public Object getProperty(JanusGraphVertex vertex, String key) { PropertyKey propertyKey = janusGraphClient.getGraph().left().value().getPropertyKey(key); return vertex.valueOrNull(propertyKey); } public Object getProperty(Edge edge, String key) { Object value = null; Property property = edge.property(key); if (property != null) { return property.orElse(null); } return value; } public Either>, JanusGraphOperationStatus> getChildrenByEdgeCriteria(Vertex vertex, String vertexUniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class clazz, Map edgeProperties) { List> result = new ArrayList<>(); Either, JanusGraphOperationStatus> outgoingEdgeByCriteria = getOutgoingEdgesByCriteria(vertex, edgeType, edgeProperties); if (outgoingEdgeByCriteria.isRight()) { JanusGraphOperationStatus status = outgoingEdgeByCriteria.right().value(); log.debug("Cannot find outgoing edge from vertex {} with label {} and properties {}", vertexUniqueId, edgeType, edgeProperties); return Either.right(status); } List edges = outgoingEdgeByCriteria.left().value(); if (edges != null) { for (Edge edge : edges) { Map edgeProps = getProperties(edge); GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label()); GraphEdge graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps); Vertex outgoingVertex = edge.inVertex(); Map properties = getProperties(outgoingVertex); T data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz); ImmutablePair immutablePair = new ImmutablePair<>(clazz.cast(data), graphEdge); result.add(immutablePair); } } return Either.left(result); } public @NotNull Either, JanusGraphOperationStatus> getOutgoingEdgesByCriteria(Vertex vertexFrom, GraphEdgeLabels label, Map props) { List edgesResult = new ArrayList<>(); JanusGraphVertex janusGraphVertex = (JanusGraphVertex) vertexFrom; JanusGraphVertexQuery query = janusGraphVertex.query(); query = query.direction(Direction.OUT).labels(label.getProperty()); if (props != null && !props.isEmpty()) { for (Map.Entry entry : props.entrySet()) { query = query.has(entry.getKey(), entry.getValue()); } } Iterable edges = query.edges(); Iterator eIter = edges.iterator(); if (!eIter.hasNext()) { log.debug("No edges found in graph for criteria (label = {} properties={})", label.getProperty(), props); return Either.left(edgesResult); } while (eIter.hasNext()) { Edge edge = eIter.next(); edgesResult.add(edge); } if (edgesResult.isEmpty()) { log.debug("No edges found in graph for criteria (label = {} properties={})", label.getProperty(), props); return Either.right(JanusGraphOperationStatus.NOT_FOUND); } return Either.left(edgesResult); } }