2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.be.dao.titan;
23 import com.thinkaurelius.titan.core.PropertyKey;
24 import com.thinkaurelius.titan.core.TitanEdge;
25 import com.thinkaurelius.titan.core.TitanGraph;
26 import com.thinkaurelius.titan.core.TitanGraphQuery;
27 import com.thinkaurelius.titan.core.TitanVertex;
28 import com.thinkaurelius.titan.core.TitanVertexQuery;
29 import com.thinkaurelius.titan.graphdb.query.TitanPredicate;
30 import fj.data.Either;
31 import org.apache.commons.lang3.tuple.ImmutablePair;
32 import org.apache.commons.lang3.tuple.ImmutableTriple;
33 import org.apache.tinkerpop.gremlin.structure.Direction;
34 import org.apache.tinkerpop.gremlin.structure.Edge;
35 import org.apache.tinkerpop.gremlin.structure.Element;
36 import org.apache.tinkerpop.gremlin.structure.Property;
37 import org.apache.tinkerpop.gremlin.structure.Vertex;
38 import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
39 import org.openecomp.sdc.be.config.ConfigurationManager;
40 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
41 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
42 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
43 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
44 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
45 import org.openecomp.sdc.be.dao.graph.datatype.RelationEndPoint;
46 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
47 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
48 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
49 import org.openecomp.sdc.be.resources.data.GraphNodeLock;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52 import org.springframework.stereotype.Component;
54 import java.util.ArrayList;
55 import java.util.HashMap;
56 import java.util.Iterator;
57 import java.util.List;
59 import java.util.Map.Entry;
60 import java.util.stream.Collectors;
61 import java.util.stream.StreamSupport;
62 @Component("titan-generic-dao")
63 public class TitanGenericDao {
65 private TitanGraphClient titanClient;
67 private static Logger logger = LoggerFactory.getLogger(TitanGenericDao.class.getName());
68 private static final String LOCK_NODE_PREFIX = "lock_";
70 public TitanGenericDao(TitanGraphClient titanClient) {
71 this.titanClient = titanClient;
72 logger.info("** TitanGenericDao created");
75 public TitanOperationStatus commit() {
76 logger.debug("doing commit.");
77 return titanClient.commit();
80 public TitanOperationStatus rollback() {
81 return titanClient.rollback();
84 public Either<TitanGraph, TitanOperationStatus> getGraph() {
85 return titanClient.getGraph();
89 public boolean isGraphOpen() {
90 return titanClient.getHealth();
99 public <T extends GraphNode> Either<T, TitanOperationStatus> createNode(T node, Class<T> clazz) {
100 logger.debug("try to create node for ID [{}]", node.getKeyValueId());
101 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
102 if (graph.isLeft()) {
105 TitanGraph tGraph = graph.left().value();
107 Vertex vertex = tGraph.addVertex();
109 vertex.property(GraphPropertiesDictionary.LABEL.getProperty(), node.getLabel());
111 Map<String, Object> properties = node.toGraphMap();
112 if (properties != null) {
113 setProperties(vertex, properties);
115 Map<String, Object> newProps = getProperties(vertex);
116 newNode = GraphElementFactory.createElement(node.getLabel(), GraphElementTypeEnum.Node, newProps, clazz);
117 logger.debug("created node for props : {}", newProps);
118 logger.debug("Node was created for ID [{}]", node.getKeyValueId());
119 return Either.left(newNode);
121 } catch (Exception e) {
122 logger.debug("Failed to create Node for ID [{}]", node.getKeyValueId(), e);
123 return Either.right(TitanGraphClient.handleTitanException(e));
127 logger.debug("Failed to create Node for ID [{}] {}", node.getKeyValueId(), graph.right().value());
128 return Either.right(graph.right().value());
132 public Either<TitanVertex, TitanOperationStatus> createNode(GraphNode node) {
133 logger.debug("try to create node for ID [{}]", node.getKeyValueId());
134 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
135 if (graph.isLeft()) {
137 TitanGraph tGraph = graph.left().value();
139 TitanVertex vertex = tGraph.addVertex();
141 vertex.property(GraphPropertiesDictionary.LABEL.getProperty(), node.getLabel());
143 Map<String, Object> properties = node.toGraphMap();
144 if (properties != null) {
145 setProperties(vertex, properties);
147 logger.debug("Node was created for ID [{}]", node.getKeyValueId());
148 return Either.left(vertex);
150 } catch (Exception e) {
151 logger.debug("Failed to create Node for ID [{}]", node.getKeyValueId(), e);
152 return Either.right(TitanGraphClient.handleTitanException(e));
156 logger.debug("Failed to create Node for ID [{}] {}", node.getKeyValueId(), graph.right().value());
157 return Either.right(graph.right().value());
166 public Either<GraphRelation, TitanOperationStatus> createRelation(GraphRelation relation) {
167 logger.debug("try to create relation from [{}] to [{}] ", relation.getFrom(), relation.getTo());
169 RelationEndPoint from = relation.getFrom();
170 RelationEndPoint to = relation.getTo();
171 ImmutablePair<String, Object> fromKeyId = new ImmutablePair<String, Object>(from.getIdName(), from.getIdValue());
172 ImmutablePair<String, Object> toKeyId = new ImmutablePair<String, Object>(to.getIdName(), to.getIdValue());
174 return createEdge(relation.getType(), fromKeyId, toKeyId, from.getLabel().getName(), to.getLabel().getName(), relation.toGraphMap());
178 private Either<GraphRelation, TitanOperationStatus> createEdge(String type, ImmutablePair<String, Object> from, ImmutablePair<String, Object> to, String fromLabel, String toLabel, Map<String, Object> properties) {
179 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
181 if (graph.isLeft()) {
183 Either<Vertex, TitanOperationStatus> fromV = getVertexByPropertyAndLabel(from.getKey(), from.getValue(), fromLabel);
184 if (fromV.isRight()) {
185 TitanOperationStatus error = fromV.right().value();
186 if (TitanOperationStatus.NOT_FOUND.equals(error)) {
187 return Either.right(TitanOperationStatus.INVALID_ID);
189 return Either.right(error);
192 Either<Vertex, TitanOperationStatus> toV = getVertexByPropertyAndLabel(to.getKey(), to.getValue(), toLabel);
194 TitanOperationStatus error = toV.right().value();
195 if (TitanOperationStatus.NOT_FOUND.equals(error)) {
196 return Either.right(TitanOperationStatus.INVALID_ID);
198 return Either.right(error);
202 Vertex fromVertex = fromV.left().value();
203 Vertex toVertex = toV.left().value();
204 Edge edge = fromVertex.addEdge(type, toVertex);
206 if (properties != null) {
208 setProperties(edge, properties);
211 Vertex vertexOut = edge.outVertex();
212 Vertex vertexIn = edge.inVertex();
214 GraphNode nodeOut = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class);
215 GraphNode nodeIn = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class);
217 GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn);
219 return Either.left(newRelation);
220 } catch (Exception e) {
221 logger.debug("Failed to create edge from [{}] to [{}]", from, to, e);
222 return Either.right(TitanGraphClient.handleTitanException(e));
225 logger.debug("Failed to create edge from [{}] to [{}] {}", from, to, graph.right().value());
226 return Either.right(graph.right().value());
230 public TitanOperationStatus createEdge(Vertex vertexOut, Vertex vertexIn, GraphEdgeLabels type, Map<String, Object> properties) {
232 Edge edge = addEdge(vertexOut, vertexIn, type, properties);
233 } catch (Exception e) {
234 logger.debug("Failed to create edge from [{}] to [{}]", vertexOut, vertexIn, e);
235 return TitanGraphClient.handleTitanException(e);
237 return TitanOperationStatus.OK;
241 private Edge addEdge(Vertex vertexOut, Vertex vertexIn, GraphEdgeLabels type, Map<String, Object> properties) {
242 Edge edge = vertexOut.addEdge(type.getProperty(), vertexIn);
244 if (properties != null) {
246 setProperties(edge, properties);
252 * creates an identical edge in the graph
254 * @return the copy operation status
256 public Either<Edge, TitanOperationStatus> copyEdge(Vertex out, Vertex in, Edge edge) {
257 GraphEdgeLabels byName = GraphEdgeLabels.getByName(edge.label());
258 return this.saveEdge(out, in, byName, edgePropertiesToMap(edge));
261 private <V> Map<String, Object> edgePropertiesToMap(Edge edge) {
262 Iterable<Property<Object>> propertiesIterable = edge::properties;
263 return StreamSupport.stream(propertiesIterable.spliterator(), false).collect(Collectors.toMap(Property::key, Property::value));
266 public Either<Edge, TitanOperationStatus> saveEdge(Vertex vertexOut, Vertex vertexIn, GraphEdgeLabels type, Map<String, Object> properties) {
268 Edge edge = addEdge(vertexOut, vertexIn, type, properties);
269 return Either.left(edge);
270 } catch (Exception e) {
271 logger.debug("Failed to create edge from [{}] to [{}]", vertexOut, vertexIn, e);
272 return Either.right(TitanGraphClient.handleTitanException(e));
277 public TitanOperationStatus createEdge(TitanVertex vertexOut, GraphNode to, GraphEdgeLabels type, Map<String, Object> properties) {
279 TitanVertex vertexIn;
280 Either<Vertex, TitanOperationStatus> toV = getVertexByPropertyAndLabel(to.getUniqueIdKey(), to.getUniqueId(), to.getLabel());
282 TitanOperationStatus error = toV.right().value();
283 if (TitanOperationStatus.NOT_FOUND.equals(error)) {
284 return TitanOperationStatus.INVALID_ID;
289 vertexIn = (TitanVertex) toV.left().value();
290 return createEdge(vertexOut, vertexIn, type, properties);
301 public Either<GraphRelation, TitanOperationStatus> createRelation(GraphNode from, GraphNode to, GraphEdgeLabels label, Map<String, Object> properties) {
302 logger.debug("try to create relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId());
303 return createEdge(label.getProperty(), from.getKeyValueId(), to.getKeyValueId(), from.getLabel(), to.getLabel(), properties);
306 public Either<GraphRelation, TitanOperationStatus> replaceRelationLabel(GraphNode from, GraphNode to, GraphEdgeLabels label, GraphEdgeLabels newLabel) {
308 logger.debug("try to replace relation {} to {} from [{}] to [{}]", label.name(), newLabel.name(), from.getKeyValueId(), to.getKeyValueId());
309 Either<GraphRelation, TitanOperationStatus> getRelationResult = getRelation(from, to, label);
310 if (getRelationResult.isRight()) {
311 return getRelationResult;
314 GraphRelation origRelation = getRelationResult.left().value();
315 Either<GraphRelation, TitanOperationStatus> createRelationResult = createRelation(from, to, newLabel, origRelation.toGraphMap());
316 if (createRelationResult.isRight()) {
317 return createRelationResult;
320 Either<GraphRelation, TitanOperationStatus> deleteRelationResult = deleteRelation(origRelation);
321 if (deleteRelationResult.isRight()) {
322 return deleteRelationResult;
324 return Either.left(createRelationResult.left().value());
334 public <T extends GraphNode> Either<T, TitanOperationStatus> getNode(String keyName, Object keyValue, Class<T> clazz) {
336 logger.debug("Try to get node for key [{}] with value [{}] ", keyName, keyValue);
338 Either<TitanVertex, TitanOperationStatus> vertexByProperty = getVertexByProperty(keyName, keyValue);
340 if (vertexByProperty.isLeft()) {
342 Vertex vertex = vertexByProperty.left().value();
343 Map<String, Object> properties = getProperties(vertex);
344 T node = GraphElementFactory.createElement((String) properties.get(GraphPropertiesDictionary.LABEL.getProperty()), GraphElementTypeEnum.Node, properties, clazz);
345 return Either.left(node);
346 } catch (Exception e) {
347 logger.debug("Failed to get node for key [{}] with value [{}] ", keyName, keyValue, e);
348 return Either.right(TitanGraphClient.handleTitanException(e));
351 logger.debug("Failed to get node for key [{}] with value [{}] ", keyName, keyValue, vertexByProperty.right().value());
352 return Either.right(vertexByProperty.right().value());
363 public Either<GraphRelation, TitanOperationStatus> getRelation(GraphNode from, GraphNode to, GraphEdgeLabels label) {
364 logger.debug("try to get relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId());
366 Either<Edge, TitanOperationStatus> edge = getEdgeByNodes(from, to, label);
370 Map<String, Object> properties = getProperties(edge.left().value());
371 GraphRelation relation = GraphElementFactory.createRelation(label.getProperty(), properties, from, to);
372 return Either.left(relation);
373 } catch (Exception e) {
374 logger.debug("Failed to get get relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId(), e);
375 return Either.right(TitanGraphClient.handleTitanException(e));
378 logger.debug("Failed to get get relation from [{}] to [{}] {}", from.getKeyValueId(), to.getKeyValueId(), edge.right().value());
379 return Either.right(edge.right().value());
383 public Either<Edge, TitanOperationStatus> getEdgeByNodes(GraphNode from, GraphNode to, GraphEdgeLabels label) {
384 ImmutablePair<String, Object> keyValueIdFrom = from.getKeyValueId();
385 ImmutablePair<String, Object> keyValueIdTo = to.getKeyValueId();
387 return getEdgeByVerticies(keyValueIdFrom.getKey(), keyValueIdFrom.getValue(), keyValueIdTo.getKey(), keyValueIdTo.getValue(), label.getProperty());
390 public Either<GraphRelation, TitanOperationStatus> deleteIncomingRelationByCriteria(GraphNode to, GraphEdgeLabels label, Map<String, Object> props) {
392 Either<Edge, TitanOperationStatus> edgeByCriteria = getIncomingEdgeByCriteria(to, label, props);
393 if (edgeByCriteria.isLeft()) {
394 Either<TitanGraph, TitanOperationStatus> graph = getGraph();
395 if (graph.isLeft()) {
396 Edge edge = edgeByCriteria.left().value();
397 logger.debug("delete edge {} to {} ", label.getProperty(), to.getUniqueId());
399 Map<String, Object> properties = getProperties(edge);
400 Vertex fromVertex = edge.outVertex();
401 String fromLabel = fromVertex.value(GraphPropertiesDictionary.LABEL.getProperty());
402 GraphNode nodeFrom = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(fromVertex), GraphNode.class);
403 GraphRelation relation = GraphElementFactory.createRelation(label.getProperty(), properties, nodeFrom, to);
404 return Either.left(relation);
406 logger.debug("failed to get graph");
407 return Either.right(graph.right().value());
411 logger.debug("failed to find edge {} to {}", label.getProperty(), to.getUniqueId());
412 return Either.right(edgeByCriteria.right().value());
417 public Either<GraphRelation, TitanOperationStatus> getIncomingRelationByCriteria(GraphNode to, GraphEdgeLabels label, Map<String, Object> props) {
419 Either<Edge, TitanOperationStatus> edgeByCriteria = getIncomingEdgeByCriteria(to, label, props);
420 if (edgeByCriteria.isLeft()) {
421 Either<TitanGraph, TitanOperationStatus> graph = getGraph();
422 if (graph.isLeft()) {
423 Edge edge = edgeByCriteria.left().value();
424 Map<String, Object> properties = getProperties(edge);
425 Vertex fromVertex = edge.outVertex();
426 String fromLabel = fromVertex.value(GraphPropertiesDictionary.LABEL.getProperty());
427 GraphNode nodeFrom = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(fromVertex), GraphNode.class);
428 GraphRelation relation = GraphElementFactory.createRelation(label.getProperty(), properties, nodeFrom, to);
429 return Either.left(relation);
431 logger.debug("failed to get graph");
432 return Either.right(graph.right().value());
436 logger.debug("failed to find edge {} to {}", label.getProperty(), to.getUniqueId());
437 return Either.right(edgeByCriteria.right().value());
442 public Either<Edge, TitanOperationStatus> getIncomingEdgeByCriteria(GraphNode to, GraphEdgeLabels label, Map<String, Object> props) {
444 ImmutablePair<String, Object> keyValueIdTo = to.getKeyValueId();
446 Either<TitanVertex, TitanOperationStatus> vertexFrom = getVertexByProperty(keyValueIdTo.getKey(), keyValueIdTo.getValue());
447 if (vertexFrom.isRight()) {
448 return Either.right(vertexFrom.right().value());
450 Vertex vertex = vertexFrom.left().value();
451 TitanVertex titanVertex = (TitanVertex) vertex;
452 TitanVertexQuery<?> query = titanVertex.query();
453 query = query.labels(label.getProperty());
455 if (props != null && !props.isEmpty()) {
456 for (Map.Entry<String, Object> entry : props.entrySet()) {
457 query = query.has(entry.getKey(), entry.getValue());
460 Edge matchingEdge = null;
461 Iterable<TitanEdge> edges = query.edges();
463 logger.debug("No edges in graph for criteria");
464 return Either.right(TitanOperationStatus.NOT_FOUND);
466 Iterator<TitanEdge> eIter = edges.iterator();
467 if (eIter.hasNext()) {
468 TitanEdge edge = eIter.next();
472 if (matchingEdge == null) {
473 logger.debug("No edges in graph for criteria");
474 return Either.right(TitanOperationStatus.NOT_FOUND);
476 return Either.left(matchingEdge);
479 public Either<Edge, TitanOperationStatus> getEdgeByVerticies(String keyNameFrom, Object keyValueFrom, String keyNameTo, Object keyValueTo, String label) {
480 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
482 if (graph.isLeft()) {
484 Either<TitanVertex, TitanOperationStatus> vertexFrom = getVertexByProperty(keyNameFrom, keyValueFrom);
485 if (vertexFrom.isRight()) {
486 return Either.right(vertexFrom.right().value());
488 Iterable<TitanEdge> edges = ((TitanVertex) vertexFrom.left().value()).query().labels(label).edges();
489 Iterator<TitanEdge> eIter = edges.iterator();
490 while (eIter.hasNext()) {
491 Edge edge = eIter.next();
492 Vertex vertexIn = edge.inVertex();
493 if (vertexIn.value(keyNameTo) != null && vertexIn.value(keyNameTo).equals(keyValueTo) && label.equals(edge.label())) {
494 return Either.left(edge);
497 logger.debug("No relation in graph from [{}={}] to [{}={}]", keyNameFrom, keyValueFrom, keyNameTo, keyValueTo);
498 return Either.right(TitanOperationStatus.NOT_FOUND);
499 } catch (Exception e) {
500 logger.debug("Failed to get get relation from [{}={}] to [{}={}]", keyNameFrom, keyValueFrom, keyNameTo, keyValueTo, e);
501 return Either.right(TitanGraphClient.handleTitanException(e));
504 return Either.right(graph.right().value());
508 public Either<List<Edge>, TitanOperationStatus> getEdgesForNode(GraphNode node, Direction requestedDirection) {
510 Either<List<Edge>, TitanOperationStatus> result;
512 ImmutablePair<String, Object> keyValueId = node.getKeyValueId();
513 Either<TitanVertex, TitanOperationStatus> eitherVertex = getVertexByProperty(keyValueId.getKey(), keyValueId.getValue());
515 if (eitherVertex.isLeft()) {
516 List<Edge> edges = prepareEdgesList(eitherVertex.left().value(), requestedDirection);
518 result = Either.left(edges);
520 result = Either.right(eitherVertex.right().value());
525 private List<Edge> prepareEdgesList(Vertex vertex, Direction requestedDirection) {
526 List<Edge> edges = new ArrayList<>();
527 Iterator<TitanEdge> edgesItr = ((TitanVertex) vertex).query().edges().iterator();
528 while (edgesItr.hasNext()) {
529 Edge edge = edgesItr.next();
530 Direction currEdgeDirection = getEdgeDirection(vertex, edge);
531 if (currEdgeDirection == requestedDirection || requestedDirection == Direction.BOTH) {
539 private Direction getEdgeDirection(Vertex vertex, Edge edge) {
541 Vertex vertexOut = edge.outVertex();
542 if (vertexOut.equals(vertex)) {
543 result = Direction.OUT;
545 result = Direction.IN;
559 public Either<GraphRelation, TitanOperationStatus> updateRelation(GraphNode from, GraphNode to, GraphEdgeLabels label, Map<String, Object> properties) {
560 logger.debug("try to update relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId());
561 return updateEdge(label.getProperty(), from.getKeyValueId(), to.getKeyValueId(), from.getLabel(), to.getLabel(), properties);
564 private Either<GraphRelation, TitanOperationStatus> updateEdge(String type, ImmutablePair<String, Object> from, ImmutablePair<String, Object> to, String fromLabel, String toLabel, Map<String, Object> properties) {
566 Either<Edge, TitanOperationStatus> edgeS = getEdgeByVerticies(from.getKey(), from.getValue(), to.getKey(), to.getValue(), type);
567 if (edgeS.isLeft()) {
570 Edge edge = edgeS.left().value();
571 if (properties != null) {
572 setProperties(edge, properties);
575 Vertex vertexOut = edge.outVertex();
576 Vertex vertexIn = edge.inVertex();
578 GraphNode nodeOut = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class);
579 GraphNode nodeIn = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class);
581 GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn);
582 if (logger.isDebugEnabled()) {
583 logger.debug("Relation was updated from [{}] to [{}] ", from, to);
585 return Either.left(newRelation);
586 } catch (Exception e) {
587 if (logger.isDebugEnabled()) {
588 logger.debug("Failed to update relation from [{}] to [{}] ", from, to, e);
590 return Either.right(TitanGraphClient.handleTitanException(e));
593 if (logger.isDebugEnabled()) {
594 logger.debug("Failed to update relation from [{}] to [{}] {}", from, to, edgeS.right().value());
596 return Either.right(edgeS.right().value());
605 public Either<GraphRelation, TitanOperationStatus> updateRelation(GraphRelation relation) {
606 logger.debug("try to update relation from [{}] to [{}]", relation.getFrom(), relation.getTo());
607 RelationEndPoint from = relation.getFrom();
608 RelationEndPoint to = relation.getTo();
609 ImmutablePair<String, Object> fromKeyId = new ImmutablePair<String, Object>(from.getIdName(), from.getIdValue());
610 ImmutablePair<String, Object> toKeyId = new ImmutablePair<String, Object>(to.getIdName(), to.getIdValue());
612 return updateEdge(relation.getType(), fromKeyId, toKeyId, from.getLabel().getName(), to.getLabel().getName(), relation.toGraphMap());
616 private Either<Vertex, TitanOperationStatus> getVertexByPropertyAndLabel(String name, Object value, String label) {
618 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
619 if (graph.isLeft()) {
621 TitanGraph tGraph = graph.left().value();
623 @SuppressWarnings("unchecked")
624 Iterable<TitanVertex> vertecies = tGraph.query().has(name, value).has(GraphPropertiesDictionary.LABEL.getProperty(), label).vertices();
626 java.util.Iterator<TitanVertex> iterator = vertecies.iterator();
627 if (iterator.hasNext()) {
628 Vertex vertex = iterator.next();
629 return Either.left(vertex);
631 if (logger.isDebugEnabled()) {
632 logger.debug("No vertex in graph for key =" + name + " and value = " + value + " label = " + label);
634 return Either.right(TitanOperationStatus.NOT_FOUND);
635 } catch (Exception e) {
636 if (logger.isDebugEnabled()) {
637 logger.debug("Failed to get vertex in graph for key ={} and value = {} label = {}",name,value,label);
639 return Either.right(TitanGraphClient.handleTitanException(e));
643 if (logger.isDebugEnabled()) {
644 logger.debug("No vertex in graph for key ={} and value = {} label = {} error : {}",name,value,label,graph.right().value());
646 return Either.right(graph.right().value());
650 public Either<TitanVertex, TitanOperationStatus> getVertexByProperty(String name, Object value) {
652 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
654 if (logger.isDebugEnabled()) {
655 logger.debug("No vertex in graph for key = {} and value = {}", name, value);
657 return Either.right(TitanOperationStatus.NOT_FOUND);
659 if (graph.isLeft()) {
661 TitanGraph tGraph = graph.left().value();
663 @SuppressWarnings("unchecked")
664 Iterable<TitanVertex> vertecies = tGraph.query().has(name, value).vertices();
666 java.util.Iterator<TitanVertex> iterator = vertecies.iterator();
667 if (iterator.hasNext()) {
668 TitanVertex vertex = iterator.next();
669 return Either.left(vertex);
671 if (logger.isDebugEnabled()) {
672 logger.debug("No vertex in graph for key ={} and value = {}", name, value);
674 return Either.right(TitanOperationStatus.NOT_FOUND);
676 } catch (Exception e) {
677 if (logger.isDebugEnabled()) {
678 logger.debug("Failed to get vertex in graph for key = {} and value = ", name, value);
680 return Either.right(TitanGraphClient.handleTitanException(e));
683 if (logger.isDebugEnabled()) {
684 logger.debug("No vertex in graph for key = {} and value = {} error : {}", name, value, graph.right().value());
686 return Either.right(graph.right().value());
690 public <T extends GraphNode> Either<List<T>, TitanOperationStatus> getByCriteria(NodeTypeEnum type, Map<String, Object> hasProps, Map<String, Object> hasNotProps, Class<T> clazz) {
691 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
692 if (graph.isLeft()) {
694 TitanGraph tGraph = graph.left().value();
696 TitanGraphQuery<? extends TitanGraphQuery> query = tGraph.query();
697 query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName());
699 if (hasProps != null && !hasProps.isEmpty()) {
700 for (Map.Entry<String, Object> entry : hasProps.entrySet()) {
701 query = query.has(entry.getKey(), entry.getValue());
704 if (hasNotProps != null && !hasNotProps.isEmpty()) {
705 for (Map.Entry<String, Object> entry : hasNotProps.entrySet()) {
706 query = query.hasNot(entry.getKey(), entry.getValue());
709 Iterable<TitanVertex> vertices = query.vertices();
710 if (vertices == null) {
711 return Either.right(TitanOperationStatus.NOT_FOUND);
714 Iterator<TitanVertex> iterator = vertices.iterator();
715 List<T> result = new ArrayList<T>();
717 while (iterator.hasNext()) {
718 Vertex vertex = iterator.next();
720 Map<String, Object> newProp = getProperties(vertex);
722 T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz);
725 if (logger.isDebugEnabled()) {
726 logger.debug("Number of fetced nodes in graph for criteria : from type = {} and properties has = {}, properties hasNot = {} is {}", type, hasProps, hasNotProps, result.size());
728 if (result.size() == 0) {
729 return Either.right(TitanOperationStatus.NOT_FOUND);
732 return Either.left(result);
733 } catch (Exception e) {
734 if (logger.isDebugEnabled()) {
735 logger.debug("Failed get by criteria for type = {}", type, e);
737 return Either.right(TitanGraphClient.handleTitanException(e));
741 if (logger.isDebugEnabled()) {
742 logger.debug("Failed get by criteria for type ={} error : {}", type, graph.right().value());
744 return Either.right(graph.right().value());
748 public <T extends GraphNode> Either<List<T>, TitanOperationStatus> getByCriteria(NodeTypeEnum type, Class<T> clazz, List<ImmutableTriple<QueryType, String, Object>> props) {
749 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
750 if (graph.isLeft()) {
752 TitanGraph tGraph = graph.left().value();
754 TitanGraphQuery<? extends TitanGraphQuery> query = tGraph.query();
755 query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName());
756 for (ImmutableTriple<QueryType, String, Object> prop : props) {
757 if (QueryType.HAS.equals(prop.getLeft())) {
758 query = query.has(prop.getMiddle(), prop.getRight());
760 query = query.hasNot(prop.getMiddle(), prop.getRight());
763 Iterable<TitanVertex> vertices = query.vertices();
764 if (vertices == null) {
765 return Either.right(TitanOperationStatus.NOT_FOUND);
768 Iterator<TitanVertex> iterator = vertices.iterator();
769 List<T> result = new ArrayList<T>();
771 while (iterator.hasNext()) {
772 Vertex vertex = iterator.next();
774 Map<String, Object> newProp = getProperties(vertex);
776 T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz);
779 if (result.size() == 0) {
780 return Either.right(TitanOperationStatus.NOT_FOUND);
783 return Either.left(result);
784 } catch (Exception e) {
785 if (logger.isDebugEnabled()) {
786 logger.debug("Failed get by criteria for type = {}", type, e);
788 return Either.right(TitanGraphClient.handleTitanException(e));
792 if (logger.isDebugEnabled()) {
793 logger.debug("Failed get by criteria for type ={} error : {}", type, graph.right().value());
795 return Either.right(graph.right().value());
799 private boolean vertexLeftNotContainsAllRightProps(Map<String, Object> leftProps, Map<String, Object> rightProps) {
801 if (rightProps != null) {
803 for (Entry<String, Object> entry : rightProps.entrySet()) {
804 String key = entry.getKey();
805 Object leftValue = leftProps.get(key);
806 Object rightValue = entry.getValue();
808 if (leftValue == null) {
809 if (rightValue == null) {
816 if (true == leftValue.equals(rightValue)) {
817 logger.trace("The value of key {} is differnet between properties. {} vs {}", key, leftValue, rightValue);
828 public <T extends GraphNode> Either<List<T>, TitanOperationStatus> getByCriteria(NodeTypeEnum type, Map<String, Object> props, Class<T> clazz) {
829 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
830 if (graph.isLeft()) {
832 TitanGraph tGraph = graph.left().value();
834 TitanGraphQuery<? extends TitanGraphQuery> query = tGraph.query();
835 query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName());
837 if (props != null && !props.isEmpty()) {
838 for (Map.Entry<String, Object> entry : props.entrySet()) {
839 query = query.has(entry.getKey(), entry.getValue());
842 Iterable<TitanVertex> vertices = query.vertices();
843 if (vertices == null) {
844 return Either.right(TitanOperationStatus.NOT_FOUND);
847 Iterator<TitanVertex> iterator = vertices.iterator();
848 List<T> result = new ArrayList<T>();
850 while (iterator.hasNext()) {
851 Vertex vertex = iterator.next();
853 Map<String, Object> newProp = getProperties(vertex);
855 T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz);
858 if (logger.isDebugEnabled()) {
859 logger.debug("Number of fetced nodes in graph for criteria : from type = {} and properties = {} is {}", type, props, result.size());
861 if (result.size() == 0) {
862 return Either.right(TitanOperationStatus.NOT_FOUND);
865 return Either.left(result);
866 } catch (Exception e) {
867 if (logger.isDebugEnabled()) {
868 logger.debug("Failed get by criteria for type = {} and properties = {}", type, props, e);
870 return Either.right(TitanGraphClient.handleTitanException(e));
874 if (logger.isDebugEnabled()) {
875 logger.debug("Failed get by criteria for type ={} and properties = {} error : {}", type, props, graph.right().value());
877 return Either.right(graph.right().value());
881 private boolean vertexLeftContainsRightProps(Map<String, Object> leftProps, Map<String, Object> rightProps) {
883 if (rightProps != null) {
885 for (Entry<String, Object> entry : rightProps.entrySet()) {
886 String key = entry.getKey();
887 Object leftValue = leftProps.get(key);
888 Object rightValue = entry.getValue();
889 if (leftValue == null) {
890 if (rightValue == null) {
893 logger.debug("The key {} cannot be found in the properties {}", key, leftProps);
898 if (false == leftValue.equals(rightValue)) {
899 logger.trace("The value of key {} is differnet between properties. {} vs {} ", key, leftValue, rightValue);
909 public <T extends GraphNode> Either<List<T>, TitanOperationStatus> getByCriteriaWithPredicate(NodeTypeEnum type, Map<String, Entry<TitanPredicate, Object>> props, Class<T> clazz) {
910 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
911 if (graph.isLeft()) {
913 TitanGraph tGraph = graph.left().value();
915 TitanGraphQuery<? extends TitanGraphQuery> query = tGraph.query();
916 query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName());
918 if (props != null && !props.isEmpty()) {
919 TitanPredicate predicate = null;
920 Object object = null;
921 for (Map.Entry<String, Entry<TitanPredicate, Object>> entry : props.entrySet()) {
922 predicate = entry.getValue().getKey();
923 object = entry.getValue().getValue();
924 query = query.has(entry.getKey(), predicate, object);
927 Iterable<TitanVertex> vertices = query.vertices();
928 if (vertices == null) {
929 return Either.right(TitanOperationStatus.NOT_FOUND);
932 Iterator<TitanVertex> iterator = vertices.iterator();
933 List<T> result = new ArrayList<T>();
935 while (iterator.hasNext()) {
936 Vertex vertex = iterator.next();
938 Map<String, Object> newProp = getProperties(vertex);
939 T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz);
942 if (result.size() == 0) {
943 return Either.right(TitanOperationStatus.NOT_FOUND);
945 if (logger.isDebugEnabled()) {
946 logger.debug("No nodes in graph for criteria : from type = {} and properties = {}", type, props);
948 return Either.left(result);
949 } catch (Exception e) {
950 if (logger.isDebugEnabled()) {
951 logger.debug("Failed get by criteria for type = {} and properties = {}", type, props, e);
953 return Either.right(TitanGraphClient.handleTitanException(e));
957 if (logger.isDebugEnabled()) {
958 logger.debug("Failed get by criteria for type = {} and properties = {} error : {}", type, props, graph.right().value());
960 return Either.right(graph.right().value());
964 public <T extends GraphNode> Either<List<T>, TitanOperationStatus> getAll(NodeTypeEnum type, Class<T> clazz) {
965 return getByCriteria(type, null, clazz);
974 public <T extends GraphNode> Either<T, TitanOperationStatus> updateNode(GraphNode node, Class<T> clazz) {
975 logger.debug("Try to update node for {}", node.getKeyValueId());
977 ImmutablePair<String, Object> keyValueId = node.getKeyValueId();
978 Either<Vertex, TitanOperationStatus> vertexByProperty = getVertexByPropertyAndLabel(keyValueId.getKey(), keyValueId.getValue(), node.getLabel());
980 if (vertexByProperty.isLeft()) {
982 Vertex vertex = vertexByProperty.left().value();
984 Map<String, Object> mapProps = node.toGraphMap();
986 for (Map.Entry<String, Object> entry : mapProps.entrySet()) {
987 if (!entry.getKey().equals(node.getUniqueIdKey())) {
988 vertex.property(entry.getKey(), entry.getValue());
992 Either<Vertex, TitanOperationStatus> vertexByPropertyAndLabel = getVertexByPropertyAndLabel(keyValueId.getKey(), keyValueId.getValue(), node.getLabel());
993 if (vertexByPropertyAndLabel.isRight()) {
994 return Either.right(vertexByPropertyAndLabel.right().value());
996 Map<String, Object> newProp = getProperties(vertexByPropertyAndLabel.left().value());
997 T updateNode = GraphElementFactory.createElement(node.getLabel(), GraphElementTypeEnum.Node, newProp, clazz);
998 return Either.left(updateNode);
1000 } catch (Exception e) {
1001 if (logger.isDebugEnabled()) {
1002 logger.debug("Failed to update node for {}", node.getKeyValueId(), e);
1004 return Either.right(TitanGraphClient.handleTitanException(e));
1007 if (logger.isDebugEnabled()) {
1008 logger.debug("Failed to update node for {} error :{}", node.getKeyValueId(), vertexByProperty.right().value());
1010 return Either.right(vertexByProperty.right().value());
1015 public TitanOperationStatus updateVertex(GraphNode node, Vertex vertex) {
1016 logger.debug("Try to update node for {}", node.getKeyValueId());
1019 Map<String, Object> mapProps = node.toGraphMap();
1021 for (Map.Entry<String, Object> entry : mapProps.entrySet()) {
1022 if (!entry.getKey().equals(node.getUniqueIdKey())) {
1023 vertex.property(entry.getKey(), entry.getValue());
1027 } catch (Exception e) {
1028 if (logger.isDebugEnabled()) {
1029 logger.debug("Failed to update node for {}", node.getKeyValueId(), e);
1031 return TitanGraphClient.handleTitanException(e);
1033 return TitanOperationStatus.OK;
1043 public <T extends GraphNode> Either<T, TitanOperationStatus> deleteNode(GraphNode node, Class<T> clazz) {
1044 logger.debug("Try to delete node for {}", node.getKeyValueId());
1045 ImmutablePair<String, Object> keyValueId = node.getKeyValueId();
1046 return deleteNode(keyValueId.getKey(), keyValueId.getValue(), clazz);
1056 public <T extends GraphNode> Either<T, TitanOperationStatus> deleteNode(String keyName, Object keyValue, Class<T> clazz) {
1057 Either<TitanVertex, TitanOperationStatus> vertexByProperty = getVertexByProperty(keyName, keyValue);
1059 if (vertexByProperty.isLeft()) {
1061 Vertex vertex = vertexByProperty.left().value();
1063 Map<String, Object> properties = getProperties(vertex);
1064 if (properties != null) {
1065 String label = (String) properties.get(GraphPropertiesDictionary.LABEL.getProperty());
1067 T node = GraphElementFactory.createElement(label, GraphElementTypeEnum.Node, properties, clazz);
1069 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
1070 if (graph.isLeft()) {
1071 TitanGraph tGraph = graph.left().value();
1074 return Either.right(graph.right().value());
1076 return Either.left(node);
1078 if (logger.isDebugEnabled()) {
1079 logger.debug("Failed to delete node for {} = {} Missing label property on node", keyName, keyValue);
1081 return Either.right(TitanOperationStatus.MISSING_NODE_LABEL);
1084 if (logger.isDebugEnabled()) {
1085 logger.debug("Failed to delete node for {} = {} Missing label property on node", keyName, keyValue);
1087 return Either.right(TitanOperationStatus.MISSING_NODE_LABEL);
1089 } catch (Exception e) {
1090 if (logger.isDebugEnabled()) {
1091 logger.debug("Failed to delete node for {} = {}", keyName, keyValue, e);
1093 return Either.right(TitanGraphClient.handleTitanException(e));
1097 return Either.right(vertexByProperty.right().value());
1101 public Either<GraphRelation, TitanOperationStatus> deleteRelation(GraphRelation relation) {
1102 logger.debug("try to delete relation from [{}] to [{}]", relation.getFrom(), relation.getTo());
1103 RelationEndPoint from = relation.getFrom();
1104 RelationEndPoint to = relation.getTo();
1105 ImmutablePair<String, Object> fromKeyId = new ImmutablePair<String, Object>(from.getIdName(), from.getIdValue());
1106 ImmutablePair<String, Object> toKeyId = new ImmutablePair<String, Object>(to.getIdName(), to.getIdValue());
1108 return deleteEdge(relation.getType(), fromKeyId, toKeyId, from.getLabel().getName(), to.getLabel().getName());
1112 public Either<Boolean, TitanOperationStatus> isRelationExist(GraphNode from, GraphNode to, GraphEdgeLabels edgeLabel) {
1113 return getEdgeByNodes(from, to, edgeLabel)
1117 .bind(err -> err == TitanOperationStatus.NOT_FOUND ? Either.left(false): Either.right(err));
1120 public Either<GraphRelation, TitanOperationStatus> deleteRelation(GraphNode from, GraphNode to, GraphEdgeLabels label) {
1121 logger.debug("try to delete relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId());
1122 return deleteEdge(label.getProperty(), from.getKeyValueId(), to.getKeyValueId(), from.getLabel(), to.getLabel());
1125 private Either<GraphRelation, TitanOperationStatus> deleteEdge(String type, ImmutablePair<String, Object> fromKeyId, ImmutablePair<String, Object> toKeyId, String fromLabel, String toLabel) {
1126 Either<Edge, TitanOperationStatus> edgeS = getEdgeByVerticies(fromKeyId.getKey(), fromKeyId.getValue(), toKeyId.getKey(), toKeyId.getValue(), type);
1127 if (edgeS.isLeft()) {
1129 Edge edge = edgeS.left().value();
1131 Vertex vertexOut = edge.outVertex();
1132 Vertex vertexIn = edge.inVertex();
1134 GraphNode nodeOut = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class);
1135 GraphNode nodeIn = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class);
1137 GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn);
1139 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
1141 if (graph.isLeft()) {
1145 if (logger.isDebugEnabled()) {
1146 logger.debug("Failed to delete relation {} from {} to {} error : {}",type,fromKeyId,toKeyId,graph.right().value());
1148 return Either.right(graph.right().value());
1150 return Either.left(newRelation);
1151 } catch (Exception e) {
1152 if (logger.isDebugEnabled()) {
1153 logger.debug("Failed to delete relation {} from {} to {}", type, fromKeyId, toKeyId, e);
1155 return Either.right(TitanGraphClient.handleTitanException(e));
1158 if (logger.isDebugEnabled()) {
1159 logger.debug("Failed to delete relation {} from {} to {} error : {}", type, fromKeyId, toKeyId, edgeS.right().value());
1161 return Either.right(edgeS.right().value());
1165 public void setTitanGraphClient(TitanGraphClient titanGraphClient) {
1166 this.titanClient = titanGraphClient;
1169 public Either<GraphRelation, TitanOperationStatus> deleteIncomingRelation(GraphRelation relation) {
1171 RelationEndPoint to = relation.getTo();
1172 ImmutablePair<String, Object> toKeyId = new ImmutablePair<String, Object>(to.getIdName(), to.getIdValue());
1174 return deleteIncomingEdge(relation.getType(), toKeyId);
1178 private Either<GraphRelation, TitanOperationStatus> deleteIncomingEdge(String type, ImmutablePair<String, Object> toKeyId) {
1180 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
1182 if (graph.isLeft()) {
1183 Either<TitanVertex, TitanOperationStatus> rootVertexResult = getVertexByProperty(toKeyId.getKey(), toKeyId.getValue());
1184 if (rootVertexResult.isLeft()) {
1185 Vertex rootVertex = rootVertexResult.left().value();
1186 Iterator<Edge> edgesIterator = rootVertex.edges(Direction.IN, type);
1187 if (edgesIterator != null) {
1191 if (edgesIterator.hasNext()) {
1192 edge = edgesIterator.next();
1193 if (edgesIterator.hasNext()) {
1194 return Either.right(TitanOperationStatus.MULTIPLE_EDGES_WITH_SAME_LABEL);
1197 return Either.right(TitanOperationStatus.NOT_FOUND);
1200 logger.debug("Find the tail vertex of the edge of type {} to vertex {}", type, toKeyId);
1201 Vertex vertexOut = edge.outVertex();
1202 String fromLabel = vertexOut.value(GraphPropertiesDictionary.LABEL.getProperty());
1203 String toLabel = rootVertex.value(GraphPropertiesDictionary.LABEL.getProperty());
1204 logger.debug("The label of the outgoing vertex is {}", fromLabel);
1205 GraphNode nodeOut = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class);
1207 GraphNode nodeIn = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(rootVertex), GraphNode.class);
1209 GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn);
1213 return Either.left(newRelation);
1216 return Either.right(TitanOperationStatus.NOT_FOUND);
1220 return Either.right(graph.right().value());
1224 return Either.right(graph.right().value());
1229 public Either<GraphRelation, TitanOperationStatus> deleteOutgoingRelation(GraphRelation relation) {
1231 RelationEndPoint from = relation.getFrom();
1232 ImmutablePair<String, Object> fromKeyId = new ImmutablePair<String, Object>(from.getIdName(), from.getIdValue());
1234 return deleteOutgoingEdge(relation.getType(), fromKeyId);
1238 private Either<GraphRelation, TitanOperationStatus> deleteOutgoingEdge(String type, ImmutablePair<String, Object> toKeyId) {
1240 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
1242 if (graph.isLeft()) {
1243 Either<TitanVertex, TitanOperationStatus> rootVertexResult = getVertexByProperty(toKeyId.getKey(), toKeyId.getValue());
1244 if (rootVertexResult.isLeft()) {
1245 Vertex rootVertex = rootVertexResult.left().value();
1246 Iterator<Edge> edgesIterator = rootVertex.edges(Direction.OUT, type);
1247 if (edgesIterator != null) {
1251 if (edgesIterator.hasNext()) {
1252 edge = edgesIterator.next();
1253 if (edgesIterator.hasNext()) {
1254 return Either.right(TitanOperationStatus.MULTIPLE_EDGES_WITH_SAME_LABEL);
1257 return Either.right(TitanOperationStatus.NOT_FOUND);
1260 logger.debug("Find the tail vertex of the edge of type {} to vertex ", type, toKeyId);
1261 Vertex vertexIn = edge.inVertex();
1262 String toLabel = vertexIn.value(GraphPropertiesDictionary.LABEL.getProperty());
1263 String fromLabel = rootVertex.value(GraphPropertiesDictionary.LABEL.getProperty());
1264 logger.debug("The label of the tail vertex is {}", toLabel);
1265 GraphNode nodeFrom = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(rootVertex), GraphNode.class);
1267 GraphNode nodeTo = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class);
1269 GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeFrom, nodeTo);
1273 return Either.left(newRelation);
1276 return Either.right(TitanOperationStatus.NOT_FOUND);
1280 return Either.right(graph.right().value());
1284 return Either.right(graph.right().value());
1294 public TitanOperationStatus lockElement(String id, NodeTypeEnum type) {
1296 StringBuffer lockId = new StringBuffer(LOCK_NODE_PREFIX);
1297 lockId.append(type.getName()).append("_").append(id);
1298 return lockNode(lockId.toString());
1301 public TitanOperationStatus lockElement(GraphNode node) {
1303 StringBuffer lockId = createLockElementId(node);
1305 return lockNode(lockId.toString());
1308 private TitanOperationStatus lockNode(String lockId) {
1309 TitanOperationStatus status = TitanOperationStatus.OK;
1311 GraphNodeLock lockNode = new GraphNodeLock(lockId);
1313 Either<GraphNodeLock, TitanOperationStatus> lockNodeNew = createNode(lockNode, GraphNodeLock.class);
1314 if (lockNodeNew.isLeft()) {
1315 logger.debug("before commit, Lock node created for {}", lockId);
1316 return titanClient.commit();
1318 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
1319 if (graph.isLeft()) {
1320 TitanGraph tGraph = graph.left().value();
1321 Either<TitanVertex, TitanOperationStatus> vertex = getVertexByProperty(lockNode.getUniqueIdKey(), lockNode.getUniqueId());
1322 if (vertex.isLeft()) {
1323 status = relockNode(lockNode, lockNodeNew, tGraph, vertex);
1325 status = vertex.right().value();
1328 status = graph.right().value();
1334 private TitanOperationStatus relockNode(GraphNodeLock lockNode, Either<GraphNodeLock, TitanOperationStatus> lockNodeNew, TitanGraph tGraph, Either<TitanVertex, TitanOperationStatus> vertex) {
1335 TitanOperationStatus status = TitanOperationStatus.OK;
1336 Long time = vertex.left().value().value(GraphPropertiesDictionary.CREATION_DATE.getProperty());
1337 Long lockTimeout = ConfigurationManager.getConfigurationManager().getConfiguration().getTitanLockTimeout();
1338 if (time + lockTimeout * 1000 < System.currentTimeMillis()) {
1339 logger.debug("Found not released lock node with id {}", lockNode.getUniqueId());
1340 vertex.left().value().remove();
1341 lockNodeNew = createNode(lockNode, GraphNodeLock.class);
1342 if (lockNodeNew.isLeft()) {
1343 logger.debug("Lock node created for {}", lockNode.getUniqueIdKey());
1344 return titanClient.commit();
1346 logger.debug("Failed Lock node for {} . Commit transacton for deleted previous vertex .", lockNode.getUniqueIdKey());
1347 titanClient.commit();
1348 status = checkLockError(lockNode.getUniqueIdKey(), lockNodeNew);
1351 logger.debug("Failed Lock node for {} rollback transacton", lockNode.getUniqueIdKey());
1352 titanClient.rollback();
1353 status = checkLockError(lockNode.getUniqueIdKey(), lockNodeNew);
1358 public <T extends GraphNode> Either<List<ImmutablePair<T, GraphEdge>>, TitanOperationStatus> getChildrenNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz, boolean withEdges) {
1360 List<ImmutablePair<T, GraphEdge>> immutablePairs = new ArrayList<ImmutablePair<T, GraphEdge>>();
1362 Either<TitanGraph, TitanOperationStatus> graphRes = titanClient.getGraph();
1363 if (graphRes.isRight()) {
1364 logger.error("Failed to retrieve graph. status is {}", graphRes);
1365 return Either.right(graphRes.right().value());
1368 TitanGraph titanGraph = graphRes.left().value();
1369 @SuppressWarnings("unchecked")
1370 Iterable<TitanVertex> vertices = titanGraph.query().has(key, uniqueId).vertices();
1371 if (vertices == null || false == vertices.iterator().hasNext()) {
1372 return Either.right(TitanOperationStatus.INVALID_ID);
1375 Vertex rootVertex = vertices.iterator().next();
1377 Iterator<Edge> edgesCreatorIterator = rootVertex.edges(Direction.OUT, edgeType.getProperty());
1378 if (edgesCreatorIterator != null) {
1379 while (edgesCreatorIterator.hasNext()) {
1380 Edge edge = edgesCreatorIterator.next();
1381 GraphEdge graphEdge = null;
1384 Map<String, Object> edgeProps = getProperties(edge);
1385 GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label());
1386 graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps);
1389 Vertex outgoingVertex = edge.inVertex();
1390 Map<String, Object> properties = getProperties(outgoingVertex);
1391 T data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz);
1393 ImmutablePair<T, GraphEdge> immutablePair = new ImmutablePair<T, GraphEdge>(clazz.cast(data), graphEdge);
1394 immutablePairs.add(immutablePair);
1398 if (true == immutablePairs.isEmpty()) {
1399 return Either.right(TitanOperationStatus.NOT_FOUND);
1402 return Either.left(immutablePairs);
1406 public Either<List<ImmutablePair<TitanVertex, Edge>>, TitanOperationStatus> getChildrenVertecies(String key, String uniqueId, GraphEdgeLabels edgeType) {
1408 List<ImmutablePair<TitanVertex, Edge>> immutablePairs = new ArrayList<ImmutablePair<TitanVertex, Edge>>();
1410 Either<TitanGraph, TitanOperationStatus> graphRes = titanClient.getGraph();
1411 if (graphRes.isRight()) {
1412 logger.error("Failed to retrieve graph. status is {}", graphRes);
1413 return Either.right(graphRes.right().value());
1416 TitanGraph titanGraph = graphRes.left().value();
1417 @SuppressWarnings("unchecked")
1418 Iterable<TitanVertex> vertices = titanGraph.query().has(key, uniqueId).vertices();
1419 if (vertices == null || false == vertices.iterator().hasNext()) {
1420 return Either.right(TitanOperationStatus.INVALID_ID);
1423 Vertex rootVertex = vertices.iterator().next();
1425 Iterator<Edge> edgesCreatorIterator = rootVertex.edges(Direction.OUT, edgeType.getProperty());
1426 if (edgesCreatorIterator != null) {
1427 while (edgesCreatorIterator.hasNext()) {
1428 Edge edge = edgesCreatorIterator.next();
1429 TitanVertex vertex = (TitanVertex) edge.inVertex();
1431 ImmutablePair<TitanVertex, Edge> immutablePair = new ImmutablePair<TitanVertex, Edge>(vertex, edge);
1432 immutablePairs.add(immutablePair);
1435 if (true == immutablePairs.isEmpty()) {
1436 return Either.right(TitanOperationStatus.NOT_FOUND);
1439 return Either.left(immutablePairs);
1443 public <T extends GraphNode> Either<List<ImmutablePair<T, GraphEdge>>, TitanOperationStatus> getChildrenNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz) {
1444 return this.getChildrenNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz, true);
1447 private TitanOperationStatus checkLockError(String lockId, Either<GraphNodeLock, TitanOperationStatus> lockNodeNew) {
1448 TitanOperationStatus status;
1449 TitanOperationStatus error = lockNodeNew.right().value();
1450 logger.debug("Failed to Lock node for {} error = {}", lockId, error);
1451 if (error.equals(TitanOperationStatus.TITAN_SCHEMA_VIOLATION) || error.equals(TitanOperationStatus.ILLEGAL_ARGUMENT)) {
1452 status = TitanOperationStatus.ALREADY_LOCKED;
1464 public TitanOperationStatus releaseElement(GraphNode node) {
1465 StringBuffer lockId = createLockElementId(node);
1467 return unlockNode(lockId);
1470 private TitanOperationStatus unlockNode(StringBuffer lockId) {
1471 GraphNodeLock lockNode = new GraphNodeLock(lockId.toString());
1473 Either<GraphNodeLock, TitanOperationStatus> lockNodeNew = deleteNode(lockNode, GraphNodeLock.class);
1474 if (lockNodeNew.isLeft()) {
1475 logger.debug("Lock node released for lock id = {}", lockId);
1476 return titanClient.commit();
1478 titanClient.rollback();
1479 TitanOperationStatus error = lockNodeNew.right().value();
1480 logger.debug("Failed to Release node for lock id {} error = {}", lockId, error);
1485 public TitanOperationStatus releaseElement(String id, NodeTypeEnum type) {
1486 StringBuffer lockId = new StringBuffer(LOCK_NODE_PREFIX);
1487 lockId.append(type.getName()).append("_").append(id);
1488 return unlockNode(lockId);
1491 private StringBuffer createLockElementId(GraphNode node) {
1492 StringBuffer lockId = new StringBuffer(LOCK_NODE_PREFIX);
1493 lockId.append(node.getLabel()).append("_").append(node.getUniqueId());
1497 public <T extends GraphNode> Either<ImmutablePair<T, GraphEdge>, TitanOperationStatus> getChild(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz) {
1499 Either<List<ImmutablePair<T, GraphEdge>>, TitanOperationStatus> childrenNodes = getChildrenNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz);
1501 if (childrenNodes.isRight()) {
1502 return Either.right(childrenNodes.right().value());
1505 List<ImmutablePair<T, GraphEdge>> value = childrenNodes.left().value();
1507 if (value.size() > 1) {
1508 return Either.right(TitanOperationStatus.MULTIPLE_CHILDS_WITH_SAME_EDGE);
1511 return Either.left(value.get(0));
1515 public ImmutablePair<TitanVertex, Edge> getChildVertex(TitanVertex vertex, GraphEdgeLabels edgeType) {
1517 ImmutablePair<TitanVertex, Edge> pair = null;
1518 Iterator<Edge> edges = vertex.edges(Direction.OUT, edgeType.getProperty());
1519 if (edges.hasNext()) {
1520 // get only first edge
1521 Edge edge = edges.next();
1522 pair = new ImmutablePair<TitanVertex, Edge>((TitanVertex) edge.inVertex(), edge);
1527 public <T extends GraphNode> Either<List<ImmutablePair<T, GraphEdge>>, TitanOperationStatus> getParentNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz) {
1529 List<ImmutablePair<T, GraphEdge>> immutablePairs = new ArrayList<ImmutablePair<T, GraphEdge>>();
1532 GraphEdge graphEdge = null;
1534 Either<TitanGraph, TitanOperationStatus> graphRes = titanClient.getGraph();
1535 if (graphRes.isRight()) {
1536 logger.error("Failed to retrieve graph. status is {}", graphRes);
1537 return Either.right(graphRes.right().value());
1540 TitanGraph titanGraph = graphRes.left().value();
1541 @SuppressWarnings("unchecked")
1542 Iterable<TitanVertex> vertices = titanGraph.query().has(key, uniqueId).vertices();
1543 if (vertices == null || false == vertices.iterator().hasNext()) {
1544 return Either.right(TitanOperationStatus.INVALID_ID);
1547 Vertex rootVertex = vertices.iterator().next();
1549 Iterator<Edge> edgesCreatorIterator = rootVertex.edges(Direction.IN, edgeType.name());
1550 if (edgesCreatorIterator != null) {
1551 while (edgesCreatorIterator.hasNext()) {
1552 Edge edge = edgesCreatorIterator.next();
1553 Map<String, Object> edgeProps = getProperties(edge);
1554 GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label());
1555 graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps);
1557 Vertex outgoingVertex = edge.outVertex();
1558 Map<String, Object> properties = getProperties(outgoingVertex);
1559 data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz);
1561 ImmutablePair<T, GraphEdge> immutablePair = new ImmutablePair<T, GraphEdge>(clazz.cast(data), graphEdge);
1562 immutablePairs.add(immutablePair);
1566 if (true == immutablePairs.isEmpty()) {
1567 return Either.right(TitanOperationStatus.NOT_FOUND);
1570 return Either.left(immutablePairs);
1574 public <T extends GraphNode> Either<ImmutablePair<T, GraphEdge>, TitanOperationStatus> getParentNode(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz) {
1576 Either<List<ImmutablePair<T, GraphEdge>>, TitanOperationStatus> parentNodesRes = this.getParentNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz);
1578 if (parentNodesRes.isRight()) {
1579 logger.debug("failed to get edge key:{} uniqueId:{} edgeType {} nodeTypeEnum: {}, reason:{}", key, uniqueId, edgeType, nodeTypeEnum, parentNodesRes.right().value());
1580 return Either.right(parentNodesRes.right().value());
1583 List<ImmutablePair<T, GraphEdge>> value = parentNodesRes.left().value();
1585 if (value.size() > 1) {
1586 return Either.right(TitanOperationStatus.MULTIPLE_CHILDS_WITH_SAME_EDGE);
1589 return Either.left(value.get(0));
1592 public <T extends GraphNode> Either<ImmutablePair<T, GraphEdge>, TitanOperationStatus> getChildByEdgeCriteria(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz, Map<String, Object> edgeProperties) {
1594 Either<Edge, TitanOperationStatus> outgoingEdgeByCriteria = getOutgoingEdgeByCriteria(key, uniqueId, edgeType, edgeProperties);
1595 if (outgoingEdgeByCriteria.isRight()) {
1596 TitanOperationStatus status = outgoingEdgeByCriteria.right().value();
1597 logger.debug("Cannot find outgoing edge from vertex {} with label {} and properties {}" + uniqueId, edgeType, edgeProperties);
1598 return Either.right(status);
1601 Edge edge = outgoingEdgeByCriteria.left().value();
1602 Map<String, Object> edgeProps = getProperties(edge);
1603 GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label());
1604 GraphEdge graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps);
1606 Vertex outgoingVertex = edge.inVertex();
1607 Map<String, Object> properties = getProperties(outgoingVertex);
1608 T data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz);
1610 ImmutablePair<T, GraphEdge> immutablePair = new ImmutablePair<T, GraphEdge>(clazz.cast(data), graphEdge);
1612 return Either.left(immutablePair);
1615 public Either<ImmutablePair<TitanVertex, Edge>, TitanOperationStatus> getChildByEdgeCriteria(TitanVertex vertex, GraphEdgeLabels edgeType, Map<String, Object> edgeProperties) {
1617 Either<Edge, TitanOperationStatus> outgoingEdgeByCriteria = getOutgoingEdgeByCriteria(vertex, edgeType, edgeProperties);
1618 if (outgoingEdgeByCriteria.isRight()) {
1619 TitanOperationStatus status = outgoingEdgeByCriteria.right().value();
1620 logger.debug("Cannot find outgoing edge from vertex {} with label {} and properties {}", vertex, edgeType, edgeProperties);
1621 return Either.right(status);
1623 Edge edge = outgoingEdgeByCriteria.left().value();
1625 TitanVertex outgoingVertex = (TitanVertex) edge.inVertex();
1627 ImmutablePair<TitanVertex, Edge> immutablePair = new ImmutablePair<TitanVertex, Edge>(outgoingVertex, edge);
1629 return Either.left(immutablePair);
1632 public Either<Edge, TitanOperationStatus> getOutgoingEdgeByCriteria(String key, String value, GraphEdgeLabels label, Map<String, Object> props) {
1634 Either<TitanVertex, TitanOperationStatus> vertexFrom = getVertexByProperty(key, value);
1635 if (vertexFrom.isRight()) {
1636 TitanOperationStatus status = vertexFrom.right().value();
1637 if (status == TitanOperationStatus.NOT_FOUND) {
1638 return Either.right(TitanOperationStatus.INVALID_ID);
1640 return Either.right(status);
1643 return getOutgoingEdgeByCriteria(vertexFrom.left().value(), label, props);
1646 public Either<Edge, TitanOperationStatus> getOutgoingEdgeByCriteria(TitanVertex vertex, GraphEdgeLabels label, Map<String, Object> props) {
1648 TitanVertexQuery<?> query = vertex.query();
1649 query = query.direction(Direction.OUT).labels(label.getProperty());
1651 if (props != null && !props.isEmpty()) {
1652 for (Map.Entry<String, Object> entry : props.entrySet()) {
1653 query = query.has(entry.getKey(), entry.getValue());
1656 Edge matchingEdge = null;
1657 Iterable<TitanEdge> edges = query.edges();
1658 if (edges == null) {
1659 logger.debug("No edges in graph for criteria");
1660 return Either.right(TitanOperationStatus.NOT_FOUND);
1662 Iterator<TitanEdge> eIter = edges.iterator();
1663 if (eIter.hasNext()) {
1664 Edge edge = eIter.next();
1665 matchingEdge = edge;
1668 if (matchingEdge == null) {
1669 logger.debug("No edges in graph for criteria");
1670 return Either.right(TitanOperationStatus.NOT_FOUND);
1672 return Either.left(matchingEdge);
1675 public <T extends GraphNode> Either<List<ImmutablePair<T, GraphEdge>>, TitanOperationStatus> deleteChildrenNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz) {
1677 List<ImmutablePair<T, GraphEdge>> result = new ArrayList<ImmutablePair<T, GraphEdge>>();
1679 Either<List<ImmutablePair<T, GraphEdge>>, TitanOperationStatus> childrenNodesRes = getChildrenNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz);
1681 if (childrenNodesRes.isRight()) {
1682 TitanOperationStatus status = childrenNodesRes.right().value();
1683 return Either.right(status);
1686 List<ImmutablePair<T, GraphEdge>> list = childrenNodesRes.left().value();
1687 for (ImmutablePair<T, GraphEdge> pair : list) {
1688 T node = pair.getKey();
1689 Either<T, TitanOperationStatus> deleteNodeRes = this.deleteNode(node, clazz);
1690 if (deleteNodeRes.isRight()) {
1691 TitanOperationStatus status = deleteNodeRes.right().value();
1692 logger.error("Failed to delete node {} . status is {}", node, status);
1693 return Either.right(status);
1695 ImmutablePair<T, GraphEdge> deletedPair = new ImmutablePair<T, GraphEdge>(node, pair.getValue());
1696 result.add(deletedPair);
1699 return Either.left(result);
1703 public void setProperties(Element element, Map<String, Object> properties) {
1705 if (properties != null && false == properties.isEmpty()) {
1707 Object[] propertyKeyValues = new Object[properties.size() * 2];
1709 for (Entry<String, Object> entry : properties.entrySet()) {
1710 propertyKeyValues[i++] = entry.getKey();
1711 propertyKeyValues[i++] = entry.getValue();
1714 ElementHelper.attachProperties(element, propertyKeyValues);
1720 public Map<String, Object> getProperties(Element element) {
1722 Map<String, Object> result = new HashMap<String, Object>();
1724 if (element != null && element.keys() != null && element.keys().size() > 0) {
1725 Map<String, Property> propertyMap = ElementHelper.propertyMap(element, element.keys().toArray(new String[element.keys().size()]));
1727 for (Entry<String, Property> entry : propertyMap.entrySet()) {
1728 String key = entry.getKey();
1729 Object value = entry.getValue().value();
1731 result.put(key, value);
1737 public Object getProperty(TitanVertex vertex, String key) {
1738 PropertyKey propertyKey = titanClient.getGraph().left().value().getPropertyKey(key);
1739 Object value = vertex.valueOrNull(propertyKey);
1743 public Object getProperty(Edge edge, String key) {
1744 Object value = null;
1745 Property<Object> property = edge.property(key);
1746 if (property != null) {
1747 return property.orElse(null);
1752 public <T extends GraphNode> Either<List<ImmutablePair<T, GraphEdge>>, TitanOperationStatus> getChildrenByEdgeCriteria(Vertex vertex, String vertexUniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz,
1753 Map<String, Object> edgeProperties) {
1755 List<ImmutablePair<T, GraphEdge>> result = new ArrayList<>();
1757 Either<List<Edge>, TitanOperationStatus> outgoingEdgeByCriteria = getOutgoingEdgesByCriteria(vertex, edgeType, edgeProperties);
1758 if (outgoingEdgeByCriteria.isRight()) {
1759 TitanOperationStatus status = outgoingEdgeByCriteria.right().value();
1760 logger.debug("Cannot find outgoing edge from vertex {} with label {} and properties {}", vertexUniqueId, edgeType, edgeProperties);
1761 return Either.right(status);
1764 List<Edge> edges = outgoingEdgeByCriteria.left().value();
1765 if (edges != null) {
1766 for (Edge edge : edges) {
1767 Map<String, Object> edgeProps = getProperties(edge);
1768 GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label());
1769 GraphEdge graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps);
1771 Vertex outgoingVertex = edge.inVertex();
1772 Map<String, Object> properties = getProperties(outgoingVertex);
1773 T data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz);
1775 ImmutablePair<T, GraphEdge> immutablePair = new ImmutablePair<T, GraphEdge>(clazz.cast(data), graphEdge);
1776 result.add(immutablePair);
1780 return Either.left(result);
1783 public Either<List<Edge>, TitanOperationStatus> getOutgoingEdgesByCriteria(Vertex vertexFrom, GraphEdgeLabels label, Map<String, Object> props) {
1785 List<Edge> edgesResult = new ArrayList<>();
1787 TitanVertex titanVertex = (TitanVertex) vertexFrom;
1788 TitanVertexQuery<?> query = titanVertex.query();
1790 query = query.direction(Direction.OUT).labels(label.getProperty());
1792 if (props != null && !props.isEmpty()) {
1793 for (Map.Entry<String, Object> entry : props.entrySet()) {
1794 query = query.has(entry.getKey(), entry.getValue());
1798 Iterable<TitanEdge> edges = query.edges();
1799 Iterator<TitanEdge> eIter = edges.iterator();
1800 if (edges == null || false == eIter.hasNext()) {
1801 logger.debug("No edges found in graph for criteria (label = {} properties={})", label.getProperty(), props);
1802 return Either.right(TitanOperationStatus.NOT_FOUND);
1805 while (eIter.hasNext()) {
1806 Edge edge = eIter.next();
1807 edgesResult.add(edge);
1810 if (edgesResult.isEmpty()) {
1811 logger.debug("No edges found in graph for criteria (label = {} properties={})", label.getProperty(), props);
1812 return Either.right(TitanOperationStatus.NOT_FOUND);
1814 return Either.left(edgesResult);