Remove dead code
[sdc.git] / catalog-dao / src / main / java / org / openecomp / sdc / be / dao / janusgraph / JanusGraphGenericDao.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.sdc.be.dao.janusgraph;
22
23 import org.janusgraph.core.PropertyKey;
24 import org.janusgraph.core.JanusGraphEdge;
25 import org.janusgraph.core.JanusGraph;
26 import org.janusgraph.core.JanusGraphQuery;
27 import org.janusgraph.core.JanusGraphVertex;
28 import org.janusgraph.core.JanusGraphVertexQuery;
29 import org.janusgraph.graphdb.query.JanusGraphPredicate;
30 import fj.data.Either;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Map.Entry;
37 import java.util.stream.Collectors;
38 import java.util.stream.StreamSupport;
39 import org.apache.commons.lang3.tuple.ImmutablePair;
40 import org.apache.commons.lang3.tuple.ImmutableTriple;
41 import org.apache.tinkerpop.gremlin.structure.Direction;
42 import org.apache.tinkerpop.gremlin.structure.Edge;
43 import org.apache.tinkerpop.gremlin.structure.Element;
44 import org.apache.tinkerpop.gremlin.structure.Property;
45 import org.apache.tinkerpop.gremlin.structure.Vertex;
46 import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
47 import org.openecomp.sdc.be.config.ConfigurationManager;
48 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
49 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
50 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
51 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
52 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
53 import org.openecomp.sdc.be.dao.graph.datatype.RelationEndPoint;
54 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
55 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
56 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
57 import org.openecomp.sdc.be.resources.data.GraphNodeLock;
58 import org.openecomp.sdc.common.log.wrappers.Logger;
59 import org.springframework.beans.factory.annotation.Qualifier;
60
61 import javax.validation.constraints.NotNull;
62 public class JanusGraphGenericDao {
63
64         private JanusGraphClient janusGraphClient;
65         private static Logger log = Logger.getLogger(JanusGraphGenericDao.class.getName());
66         private static final String LOCK_NODE_PREFIX = "lock_";
67
68         public JanusGraphGenericDao(@Qualifier("janusgraph-client") JanusGraphClient janusGraphClient) {
69                 this.janusGraphClient = janusGraphClient;
70                 log.info("** JanusGraphGenericDao created");
71         }
72
73         public JanusGraphOperationStatus commit() {
74                 log.debug("doing commit.");
75                 return janusGraphClient.commit();
76         }
77
78         public JanusGraphOperationStatus rollback() {
79                 log.error("Going to execute rollback on graph.");
80                 return janusGraphClient.rollback();
81         }
82
83         public <T, TStatus> void handleTransactionCommitRollback(boolean inTransaction, Either<T, TStatus> result) {
84                 if (!inTransaction) {
85                         if (result == null || result.isRight()) {
86                                 rollback();
87                         } else {
88                                 commit();
89                         }
90                 }
91         }
92
93         public Either<JanusGraph, JanusGraphOperationStatus> getGraph() {
94                 return janusGraphClient.getGraph();
95         }
96
97         // For healthCheck
98         public boolean isGraphOpen() {
99                 return janusGraphClient.getHealth();
100         }
101
102         /**
103          * 
104          * @param node
105          * @param clazz
106          * @return
107          */
108         public <T extends GraphNode> Either<T, JanusGraphOperationStatus> createNode(T node, Class<T> clazz) {
109                 log.debug("try to create node for ID [{}]", node.getKeyValueIdForLog());
110                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
111                 if (graph.isLeft()) {
112                         T newNode;
113                         try {
114                                 JanusGraph tGraph = graph.left().value();
115
116                                 Vertex vertex = tGraph.addVertex();
117
118                                 vertex.property(GraphPropertiesDictionary.LABEL.getProperty(), node.getLabel());
119
120                                 Map<String, Object> properties = node.toGraphMap();
121                                 if (properties != null) {
122                                         setProperties(vertex, properties);
123                                 }
124                                 Map<String, Object> newProps = getProperties(vertex);
125                                 newNode = GraphElementFactory.createElement(node.getLabel(), GraphElementTypeEnum.Node, newProps, clazz);
126                                 log.debug("created node for props : {}", newProps);
127                                 log.debug("Node was created for ID [{}]", node.getKeyValueIdForLog());
128                                 return Either.left(newNode);
129
130                         } catch (Exception e) {
131                                 log.debug("Failed to create Node for ID [{}]", node.getKeyValueId(), e);
132                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
133                         }
134
135                 } else {
136                         log.debug("Failed to create Node for ID [{}]  {}", node.getKeyValueIdForLog(), graph.right().value());
137                         return Either.right(graph.right().value());
138                 }
139         }
140
141         public Either<JanusGraphVertex, JanusGraphOperationStatus> createNode(GraphNode node) {
142                 log.debug("try to create node for ID [{}]", node.getKeyValueId());
143                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
144                 if (graph.isLeft()) {
145                         try {
146                                 JanusGraph tGraph = graph.left().value();
147
148                                 JanusGraphVertex vertex = tGraph.addVertex();
149
150                                 vertex.property(GraphPropertiesDictionary.LABEL.getProperty(), node.getLabel());
151
152                                 Map<String, Object> properties = node.toGraphMap();
153                                 if (properties != null) {
154                                         setProperties(vertex, properties);
155                                 }
156                                 log.debug("Node was created for ID [{}]", node.getKeyValueId());
157                                 return Either.left(vertex);
158
159                         } catch (Exception e) {
160                                 log.debug("Failed to create Node for ID [{}]", node.getKeyValueId(), e);
161                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
162                         }
163
164                 } else {
165                         log.debug("Failed to create Node for ID [{}]  {}", node.getKeyValueId(), graph.right().value());
166                         return Either.right(graph.right().value());
167                 }
168         }
169
170         /**
171          * 
172          * @param relation
173          * @return
174          */
175         public Either<GraphRelation, JanusGraphOperationStatus> createRelation(GraphRelation relation) {
176                 log.debug("try to create relation from [{}] to [{}] ", relation.getFrom(), relation.getTo());
177
178                 RelationEndPoint from = relation.getFrom();
179                 RelationEndPoint to = relation.getTo();
180                 ImmutablePair<String, Object> fromKeyId = new ImmutablePair<>(from.getIdName(), from.getIdValue());
181                 ImmutablePair<String, Object> toKeyId = new ImmutablePair<>(to.getIdName(), to.getIdValue());
182
183                 return createEdge(relation.getType(), fromKeyId, toKeyId, from.getLabel().getName(), to.getLabel().getName(), relation.toGraphMap());
184
185         }
186
187         private Either<GraphRelation, JanusGraphOperationStatus> createEdge(String type, ImmutablePair<String, Object> from, ImmutablePair<String, Object> to, String fromLabel, String toLabel, Map<String, Object> properties) {
188                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
189
190                 if (graph.isLeft()) {
191                         try {
192                                 Either<Vertex, JanusGraphOperationStatus> fromV = getVertexByPropertyAndLabel(from.getKey(), from.getValue(), fromLabel);
193                                 if (fromV.isRight()) {
194                                         JanusGraphOperationStatus error = fromV.right().value();
195                                         if (JanusGraphOperationStatus.NOT_FOUND.equals(error)) {
196                                                 return Either.right(JanusGraphOperationStatus.INVALID_ID);
197                                         } else {
198                                                 return Either.right(error);
199                                         }
200                                 }
201                                 Either<Vertex, JanusGraphOperationStatus> toV = getVertexByPropertyAndLabel(to.getKey(), to.getValue(), toLabel);
202                                 if (toV.isRight()) {
203                                         JanusGraphOperationStatus error = toV.right().value();
204                                         if (JanusGraphOperationStatus.NOT_FOUND.equals(error)) {
205                                                 return Either.right(JanusGraphOperationStatus.INVALID_ID);
206                                         } else {
207                                                 return Either.right(error);
208                                         }
209                                 }
210
211                                 Vertex fromVertex = fromV.left().value();
212                                 Vertex toVertex = toV.left().value();
213                                 Edge edge = fromVertex.addEdge(type, toVertex);
214
215                                 if (properties != null) {
216
217                                         setProperties(edge, properties);
218                                 }
219
220                                 Vertex vertexOut = edge.outVertex();
221                                 Vertex vertexIn = edge.inVertex();
222
223                                 GraphNode nodeOut = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class);
224                                 GraphNode nodeIn = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class);
225
226                                 GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn);
227
228                                 return Either.left(newRelation);
229                         } catch (Exception e) {
230                                 log.debug("Failed to create edge from [{}] to [{}]", from, to, e);
231                                 return Either.right(janusGraphClient.handleJanusGraphException(e));
232                         }
233                 } else {
234                         log.debug("Failed to create edge from [{}] to [{}]   {}", from, to, graph.right().value());
235                         return Either.right(graph.right().value());
236                 }
237         }
238
239         public JanusGraphOperationStatus createEdge(Vertex vertexOut, Vertex vertexIn, GraphEdgeLabels type, Map<String, Object> properties) {
240                 try {
241                         Edge edge = addEdge(vertexOut, vertexIn, type, properties);
242                 } catch (Exception e) {
243                         log.debug("Failed to create edge from [{}] to [{}]", vertexOut, vertexIn, e);
244                         return janusGraphClient.handleJanusGraphException(e);
245                 }
246                 return JanusGraphOperationStatus.OK;
247
248         }
249         
250         private Edge addEdge(Vertex vertexOut, Vertex vertexIn, GraphEdgeLabels type, Map<String, Object> properties) {
251                 Edge edge = vertexOut.addEdge(type.getProperty(), vertexIn);
252
253                 if (properties != null) {
254
255             setProperties(edge, properties);
256         }
257                 return edge;
258         }
259
260         /**
261          * creates an identical edge in the graph
262          * @param edge
263          * @return the copy operation status
264          */
265         public Either<Edge, JanusGraphOperationStatus> copyEdge(Vertex out, Vertex in, Edge edge) {
266                 GraphEdgeLabels byName = GraphEdgeLabels.getByName(edge.label());
267                 return this.saveEdge(out, in, byName, edgePropertiesToMap(edge));
268         }
269
270         private <V> Map<String, Object> edgePropertiesToMap(Edge edge) {
271                 Iterable<Property<Object>> propertiesIterable = edge::properties;
272                 return StreamSupport.stream(propertiesIterable.spliterator(), false).collect(Collectors.toMap(Property::key, Property::value));
273         }
274
275         public Either<Edge, JanusGraphOperationStatus> saveEdge(Vertex vertexOut, Vertex vertexIn, GraphEdgeLabels type, Map<String, Object> properties) {
276                 try {
277                         Edge edge = addEdge(vertexOut, vertexIn, type, properties);
278                         return Either.left(edge);
279                 } catch (Exception e) {
280                         log.debug("Failed to create edge from [{}] to [{}]", vertexOut, vertexIn, e);
281                         return Either.right(janusGraphClient.handleJanusGraphException(e));
282                 }
283
284         }
285
286         public JanusGraphOperationStatus createEdge(JanusGraphVertex vertexOut, GraphNode to, GraphEdgeLabels type, Map<String, Object> properties) {
287
288                 JanusGraphVertex vertexIn;
289                 Either<Vertex, JanusGraphOperationStatus> toV = getVertexByPropertyAndLabel(to.getUniqueIdKey(), to.getUniqueId(), to.getLabel());
290                 if (toV.isRight()) {
291                         JanusGraphOperationStatus error = toV.right().value();
292                         if (JanusGraphOperationStatus.NOT_FOUND.equals(error)) {
293                                 return JanusGraphOperationStatus.INVALID_ID;
294                         } else {
295                                 return error;
296                         }
297                 }
298                 vertexIn = (JanusGraphVertex) toV.left().value();
299                 return createEdge(vertexOut, vertexIn, type, properties);
300         }
301
302         /**
303          * 
304          * @param from
305          * @param to
306          * @param label
307          * @param properties
308          * @return
309          */
310         public Either<GraphRelation, JanusGraphOperationStatus> createRelation(GraphNode from, GraphNode to, GraphEdgeLabels label, Map<String, Object> properties) {
311                 log.debug("try to create relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId());
312                 return createEdge(label.getProperty(), from.getKeyValueId(), to.getKeyValueId(), from.getLabel(), to.getLabel(), properties);
313         }
314
315         public Either<GraphRelation, JanusGraphOperationStatus> replaceRelationLabel(GraphNode from, GraphNode to, GraphEdgeLabels label, GraphEdgeLabels newLabel) {
316
317                 log.debug("try to replace relation {} to {} from [{}] to [{}]", label.name(), newLabel.name(), from.getKeyValueId(), to.getKeyValueId());
318                 Either<GraphRelation, JanusGraphOperationStatus> getRelationResult = getRelation(from, to, label);
319                 if (getRelationResult.isRight()) {
320                         return getRelationResult;
321                 }
322
323                 GraphRelation origRelation = getRelationResult.left().value();
324                 Either<GraphRelation, JanusGraphOperationStatus> createRelationResult = createRelation(from, to, newLabel, origRelation.toGraphMap());
325                 if (createRelationResult.isRight()) {
326                         return createRelationResult;
327                 }
328
329                 Either<GraphRelation, JanusGraphOperationStatus> deleteRelationResult = deleteRelation(origRelation);
330                 if (deleteRelationResult.isRight()) {
331                         return deleteRelationResult;
332                 }
333                 return Either.left(createRelationResult.left().value());
334         }
335
336         /**
337          * 
338          * @param keyName
339          * @param keyValue
340          * @param clazz
341          * @return
342          */
343         public <T extends GraphNode> Either<T, JanusGraphOperationStatus> getNode(String keyName, Object keyValue, Class<T> clazz) {
344
345                 log.debug("Try to get node for key [{}] with value [{}] ", keyName, keyValue);
346
347                 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexByProperty = getVertexByProperty(keyName, keyValue);
348
349                 if (vertexByProperty.isLeft()) {
350                         try {
351                                 Vertex vertex = vertexByProperty.left().value();
352                                 Map<String, Object> properties = getProperties(vertex);
353                                 T node = GraphElementFactory.createElement((String) properties.get(GraphPropertiesDictionary.LABEL.getProperty()), GraphElementTypeEnum.Node, properties, clazz);
354                                 return Either.left(node);
355                         } catch (Exception e) {
356                                 log.debug("Failed to get node for key [{}] with value [{}] ", keyName, keyValue, e);
357                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
358                         }
359                 } else {
360                         log.debug("Failed to get node for key [{}] with value [{}]  ", keyName, keyValue, vertexByProperty.right().value());
361                         return Either.right(vertexByProperty.right().value());
362                 }
363         }
364
365         /**
366          * 
367          * @param from
368          * @param to
369          * @param label
370          * @return
371          */
372         public Either<GraphRelation, JanusGraphOperationStatus> getRelation(GraphNode from, GraphNode to, GraphEdgeLabels label) {
373                 log.debug("try to get relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId());
374
375                 Either<Edge, JanusGraphOperationStatus> edge = getEdgeByNodes(from, to, label);
376
377                 if (edge.isLeft()) {
378                         try {
379                                 Map<String, Object> properties = getProperties(edge.left().value());
380                                 GraphRelation relation = GraphElementFactory.createRelation(label.getProperty(), properties, from, to);
381                                 return Either.left(relation);
382                         } catch (Exception e) {
383                                 log.debug("Failed to get  get relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId(), e);
384                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
385                         }
386                 } else {
387                         log.debug("Failed to get  get relation from [{}] to [{}]   {}", from.getKeyValueId(), to.getKeyValueId(), edge.right().value());
388                         return Either.right(edge.right().value());
389                 }
390         }
391
392         public Either<Edge, JanusGraphOperationStatus> getEdgeByNodes(GraphNode from, GraphNode to, GraphEdgeLabels label) {
393                 ImmutablePair<String, Object> keyValueIdFrom = from.getKeyValueId();
394                 ImmutablePair<String, Object> keyValueIdTo = to.getKeyValueId();
395
396                 return getEdgeByVerticies(keyValueIdFrom.getKey(), keyValueIdFrom.getValue(), keyValueIdTo.getKey(), keyValueIdTo.getValue(), label.getProperty());
397         }
398
399         public Either<GraphRelation, JanusGraphOperationStatus> deleteIncomingRelationByCriteria(GraphNode to, GraphEdgeLabels label, Map<String, Object> props) {
400
401                 Either<Edge, JanusGraphOperationStatus> edgeByCriteria = getIncomingEdgeByCriteria(to, label, props);
402                 if (edgeByCriteria.isLeft()) {
403                         Either<JanusGraph, JanusGraphOperationStatus> graph = getGraph();
404                         if (graph.isLeft()) {
405                                 Edge edge = edgeByCriteria.left().value();
406                                 log.debug("delete edge {} to {} ", label.getProperty(), to.getUniqueId());
407                                 edge.remove();
408                                 Map<String, Object> properties = getProperties(edge);
409                                 Vertex fromVertex = edge.outVertex();
410                                 String fromLabel = fromVertex.value(GraphPropertiesDictionary.LABEL.getProperty());
411                                 GraphNode nodeFrom = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(fromVertex), GraphNode.class);
412                                 GraphRelation relation = GraphElementFactory.createRelation(label.getProperty(), properties, nodeFrom, to);
413                                 return Either.left(relation);
414                         } else {
415                                 log.debug("failed to get graph");
416                                 return Either.right(graph.right().value());
417                         }
418
419                 } else {
420                         log.debug("failed to find edge {} to {}", label.getProperty(), to.getUniqueId());
421                         return Either.right(edgeByCriteria.right().value());
422                 }
423
424         }
425
426         public Either<GraphRelation, JanusGraphOperationStatus> getIncomingRelationByCriteria(GraphNode to, GraphEdgeLabels label, Map<String, Object> props) {
427
428                 Either<Edge, JanusGraphOperationStatus> edgeByCriteria = getIncomingEdgeByCriteria(to, label, props);
429                 if (edgeByCriteria.isLeft()) {
430                         Either<JanusGraph, JanusGraphOperationStatus> graph = getGraph();
431                         if (graph.isLeft()) {
432                                 Edge edge = edgeByCriteria.left().value();
433                                 Map<String, Object> properties = getProperties(edge);
434                                 Vertex fromVertex = edge.outVertex();
435                                 String fromLabel = fromVertex.value(GraphPropertiesDictionary.LABEL.getProperty());
436                                 GraphNode nodeFrom = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(fromVertex), GraphNode.class);
437                                 GraphRelation relation = GraphElementFactory.createRelation(label.getProperty(), properties, nodeFrom, to);
438                                 return Either.left(relation);
439                         } else {
440                                 log.debug("failed to get graph");
441                                 return Either.right(graph.right().value());
442                         }
443
444                 } else {
445                         log.debug("failed to find edge {} to {}", label.getProperty(), to.getUniqueId());
446                         return Either.right(edgeByCriteria.right().value());
447                 }
448
449         }
450
451         public Either<Edge, JanusGraphOperationStatus> getIncomingEdgeByCriteria(GraphNode to, GraphEdgeLabels label, Map<String, Object> props) {
452
453                 ImmutablePair<String, Object> keyValueIdTo = to.getKeyValueId();
454
455                 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexFrom = getVertexByProperty(keyValueIdTo.getKey(), keyValueIdTo.getValue());
456                 if (vertexFrom.isRight()) {
457                         return Either.right(vertexFrom.right().value());
458                 }
459                 Vertex vertex = vertexFrom.left().value();
460                 JanusGraphVertex janusGraphVertex = (JanusGraphVertex) vertex;
461                 JanusGraphVertexQuery<?> query = janusGraphVertex.query();
462                 query = query.labels(label.getProperty());
463
464                 if (props != null && !props.isEmpty()) {
465                         for (Map.Entry<String, Object> entry : props.entrySet()) {
466                                 query = query.has(entry.getKey(), entry.getValue());
467                         }
468                 }
469                 Edge matchingEdge = null;
470                 Iterable<JanusGraphEdge> edges = query.edges();
471                 if (edges == null) {
472                         log.debug("No edges in graph for criteria");
473                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
474                 }
475                 Iterator<JanusGraphEdge> eIter = edges.iterator();
476                 if (eIter.hasNext()) {
477             matchingEdge = eIter.next();
478                 }
479
480                 if (matchingEdge == null) {
481                         log.debug("No edges in graph for criteria");
482                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
483                 }
484                 return Either.left(matchingEdge);
485         }
486
487         public Either<Edge, JanusGraphOperationStatus> getEdgeByVerticies(String keyNameFrom, Object keyValueFrom, String keyNameTo, Object keyValueTo, String label) {
488                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
489
490                 if (graph.isLeft()) {
491                         try {
492                                 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexFrom = getVertexByProperty(keyNameFrom, keyValueFrom);
493                                 if (vertexFrom.isRight()) {
494                                         return Either.right(vertexFrom.right().value());
495                                 }
496                                 Iterable<JanusGraphEdge> edges = ((JanusGraphVertex) vertexFrom.left().value()).query().labels(label).edges();
497                                 Iterator<JanusGraphEdge> eIter = edges.iterator();
498                                 while (eIter.hasNext()) {
499                                         Edge edge = eIter.next();
500                                         Vertex vertexIn = edge.inVertex();
501                                         if (vertexIn.value(keyNameTo) != null && vertexIn.value(keyNameTo).equals(keyValueTo) && label.equals(edge.label())) {
502                                                 return Either.left(edge);
503                                         }
504                                 }
505                                 log.debug("No relation in graph from [{}={}] to [{}={}]", keyNameFrom, keyValueFrom, keyNameTo, keyValueTo);
506                                 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
507                         } catch (Exception e) {
508                                 log.debug("Failed to get  get relation from [{}={}] to [{}={}]", keyNameFrom, keyValueFrom, keyNameTo, keyValueTo, e);
509                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
510                         }
511                 } else {
512                         return Either.right(graph.right().value());
513                 }
514         }
515
516         public Either<List<Edge>, JanusGraphOperationStatus> getEdgesForNode(GraphNode node, Direction requestedDirection) {
517
518                 Either<List<Edge>, JanusGraphOperationStatus> result;
519
520                 ImmutablePair<String, Object> keyValueId = node.getKeyValueId();
521                 Either<JanusGraphVertex, JanusGraphOperationStatus> eitherVertex = getVertexByProperty(keyValueId.getKey(), keyValueId.getValue());
522
523                 if (eitherVertex.isLeft()) {
524                         List<Edge> edges = prepareEdgesList(eitherVertex.left().value(), requestedDirection);
525
526                         result = Either.left(edges);
527                 } else {
528                         result = Either.right(eitherVertex.right().value());
529                 }
530                 return result;
531         }
532
533         private List<Edge> prepareEdgesList(Vertex vertex, Direction requestedDirection) {
534                 List<Edge> edges = new ArrayList<>();
535                 Iterator<JanusGraphEdge> edgesItr = ((JanusGraphVertex) vertex).query().edges().iterator();
536                 while (edgesItr.hasNext()) {
537                         Edge edge = edgesItr.next();
538                         Direction currEdgeDirection = getEdgeDirection(vertex, edge);
539                         if (currEdgeDirection == requestedDirection || requestedDirection == Direction.BOTH) {
540                                 edges.add(edge);
541                         }
542
543                 }
544                 return edges;
545         }
546
547         private Direction getEdgeDirection(Vertex vertex, Edge edge) {
548                 Direction result;
549                 Vertex vertexOut = edge.outVertex();
550                 if (vertexOut.equals(vertex)) {
551                         result = Direction.OUT;
552                 } else {
553                         result = Direction.IN;
554
555                 }
556                 return result;
557         }
558
559         /**
560          * 
561          * @param from
562          * @param to
563          * @param label
564          * @param properties
565          * @return
566          */
567         public Either<GraphRelation, JanusGraphOperationStatus> updateRelation(GraphNode from, GraphNode to, GraphEdgeLabels label, Map<String, Object> properties) {
568                 log.debug("try to update relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId());
569                 return updateEdge(label.getProperty(), from.getKeyValueId(), to.getKeyValueId(), from.getLabel(), to.getLabel(), properties);
570         }
571
572         private Either<GraphRelation, JanusGraphOperationStatus> updateEdge(String type, ImmutablePair<String, Object> from, ImmutablePair<String, Object> to, String fromLabel, String toLabel, Map<String, Object> properties) {
573
574                 Either<Edge, JanusGraphOperationStatus> edgeS = getEdgeByVerticies(from.getKey(), from.getValue(), to.getKey(), to.getValue(), type);
575                 if (edgeS.isLeft()) {
576
577                         try {
578                                 Edge edge = edgeS.left().value();
579                                 if (properties != null) {
580                                         setProperties(edge, properties);
581                                 }
582
583                                 Vertex vertexOut = edge.outVertex();
584                                 Vertex vertexIn = edge.inVertex();
585
586                                 GraphNode nodeOut = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class);
587                                 GraphNode nodeIn = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class);
588
589                                 GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn);
590                                 if (log.isDebugEnabled()) {
591                                         log.debug("Relation was updated from [{}] to [{}] ", from, to);
592                                 }
593                                 return Either.left(newRelation);
594                         } catch (Exception e) {
595                                 if (log.isDebugEnabled()) {
596                                         log.debug("Failed to update relation from [{}] to [{}] ", from, to, e);
597                                 }
598                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
599                         }
600                 } else {
601                         if (log.isDebugEnabled()) {
602                                 log.debug("Failed to update relation from [{}] to [{}] {}", from, to, edgeS.right().value());
603                         }
604                         return Either.right(edgeS.right().value());
605                 }
606         }
607
608         /**
609          * 
610          * @param relation
611          * @return
612          */
613         public Either<GraphRelation, JanusGraphOperationStatus> updateRelation(GraphRelation relation) {
614                 log.debug("try to update relation from [{}] to [{}]", relation.getFrom(), relation.getTo());
615                 RelationEndPoint from = relation.getFrom();
616                 RelationEndPoint to = relation.getTo();
617                 ImmutablePair<String, Object> fromKeyId = new ImmutablePair<>(from.getIdName(), from.getIdValue());
618                 ImmutablePair<String, Object> toKeyId = new ImmutablePair<>(to.getIdName(), to.getIdValue());
619
620                 return updateEdge(relation.getType(), fromKeyId, toKeyId, from.getLabel().getName(), to.getLabel().getName(), relation.toGraphMap());
621
622         }
623
624         private Either<Vertex, JanusGraphOperationStatus> getVertexByPropertyAndLabel(String name, Object value, String label) {
625
626                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
627                 if (graph.isLeft()) {
628                         try {
629                                 JanusGraph tGraph = graph.left().value();
630
631                                 @SuppressWarnings("unchecked")
632                                 Iterable<JanusGraphVertex> vertecies = tGraph.query().has(name, value).has(GraphPropertiesDictionary.LABEL.getProperty(), label).vertices();
633
634                                 java.util.Iterator<JanusGraphVertex> iterator = vertecies.iterator();
635                                 if (iterator.hasNext()) {
636                                         Vertex vertex = iterator.next();
637                                         return Either.left(vertex);
638                                 }
639                                 if (log.isDebugEnabled()) {
640                                         log.debug("No vertex in graph for key =" + name + " and value = " + value + "  label = " + label);
641                                 }
642                                 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
643                         } catch (Exception e) {
644                                 if (log.isDebugEnabled()) {
645                                         log.debug("Failed to get vertex in graph for key ={} and value = {} label = {}",name,value,label);
646                                 }
647                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
648                         }
649
650                 } else {
651                         if (log.isDebugEnabled()) {
652                                 log.debug("No vertex in graph for key ={} and value = {}  label = {} error : {}",name,value,label,graph.right().value());
653                         }
654                         return Either.right(graph.right().value());
655                 }
656         }
657
658         public Either<JanusGraphVertex, JanusGraphOperationStatus> getVertexByProperty(String name, Object value) {
659
660                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
661                 if (value == null) {
662                         if (log.isDebugEnabled()) {
663                                 log.debug("No vertex in graph for key = {} and value = {}", name, value);
664                         }
665                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
666                 }
667                 if (graph.isLeft()) {
668                         try {
669                                 JanusGraph tGraph = graph.left().value();
670
671                                 @SuppressWarnings("unchecked")
672                                 Iterable<JanusGraphVertex> vertecies = tGraph.query().has(name, value).vertices();
673
674                                 java.util.Iterator<JanusGraphVertex> iterator = vertecies.iterator();
675                                 if (iterator.hasNext()) {
676                                         JanusGraphVertex vertex = iterator.next();
677                                         return Either.left(vertex);
678                                 } else {
679                                         if (log.isDebugEnabled()) {
680                                                 log.debug("No vertex in graph for key ={} and value = {}", name, value);
681                                         }
682                                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
683                                 }
684                         } catch (Exception e) {
685                                 if (log.isDebugEnabled()) {
686                                         log.debug("Failed to get vertex in graph for key = {} and value = ", name, value);
687                                 }
688                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
689                         }
690                 } else {
691                         if (log.isDebugEnabled()) {
692                                 log.debug("No vertex in graph for key = {} and value = {} error : {}", name, value, graph.right().value());
693                         }
694                         return Either.right(graph.right().value());
695                 }
696         }
697
698         public <T extends GraphNode> Either<List<T>, JanusGraphOperationStatus> getByCriteria(NodeTypeEnum type, Map<String, Object> hasProps, Map<String, Object> hasNotProps, Class<T> clazz) {
699                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
700                 if (graph.isLeft()) {
701                         try {
702                                 JanusGraph tGraph = graph.left().value();
703
704                                 JanusGraphQuery<? extends JanusGraphQuery> query = tGraph.query();
705                                 query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName());
706
707                                 if (hasProps != null && !hasProps.isEmpty()) {
708                                         for (Map.Entry<String, Object> entry : hasProps.entrySet()) {
709                                                 query = query.has(entry.getKey(), entry.getValue());
710                                         }
711                                 }
712                                 if (hasNotProps != null && !hasNotProps.isEmpty()) {
713                                         for (Map.Entry<String, Object> entry : hasNotProps.entrySet()) {
714                                                 query = query.hasNot(entry.getKey(), entry.getValue());
715                                         }
716                                 }
717                                 Iterable<JanusGraphVertex> vertices = query.vertices();
718                                 if (vertices == null) {
719                                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
720                                 }
721
722                                 Iterator<JanusGraphVertex> iterator = vertices.iterator();
723                                 List<T> result = new ArrayList<>();
724
725                                 while (iterator.hasNext()) {
726                                         Vertex vertex = iterator.next();
727
728                                         Map<String, Object> newProp = getProperties(vertex);
729
730                                         T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz);
731                                         result.add(element);
732                                 }
733                                 if (log.isDebugEnabled()) {
734                                         log.debug("Number of fetced nodes in graph for criteria : from type = {} and properties has = {}, properties hasNot = {}  is {}", type, hasProps, hasNotProps, result.size());
735                                 }
736                                 if (result.size() == 0) {
737                                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
738                                 }
739
740                                 return Either.left(result);
741                         } catch (Exception e) {
742                                 if (log.isDebugEnabled()) {
743                                         log.debug("Failed  get by  criteria for type = {}", type, e);
744                                 }
745                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
746                         }
747
748                 } else {
749                         if (log.isDebugEnabled()) {
750                                 log.debug("Failed  get by  criteria for type ={}  error : {}", type, graph.right().value());
751                         }
752                         return Either.right(graph.right().value());
753                 }
754         }
755
756         public <T extends GraphNode> Either<List<T>, JanusGraphOperationStatus> getByCriteria(NodeTypeEnum type, Class<T> clazz, List<ImmutableTriple<QueryType, String, Object>> props) {
757                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
758                 if (graph.isLeft()) {
759                         try {
760                                 JanusGraph tGraph = graph.left().value();
761
762                                 JanusGraphQuery<? extends JanusGraphQuery> query = tGraph.query();
763                                 query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName());
764                                 for (ImmutableTriple<QueryType, String, Object> prop : props) {
765                                         if (QueryType.HAS.equals(prop.getLeft())) {
766                                                 query = query.has(prop.getMiddle(), prop.getRight());
767                                         } else {
768                                                 query = query.hasNot(prop.getMiddle(), prop.getRight());
769                                         }
770                                 }
771                                 Iterable<JanusGraphVertex> vertices = query.vertices();
772                                 if (vertices == null) {
773                                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
774                                 }
775
776                                 Iterator<JanusGraphVertex> iterator = vertices.iterator();
777                                 List<T> result = new ArrayList<>();
778
779                                 while (iterator.hasNext()) {
780                                         Vertex vertex = iterator.next();
781
782                                         Map<String, Object> newProp = getProperties(vertex);
783
784                                         T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz);
785                                         result.add(element);
786                                 }
787                                 if (result.size() == 0) {
788                                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
789                                 }
790
791                                 return Either.left(result);
792                         } catch (Exception e) {
793                                 if (log.isDebugEnabled()) {
794                                         log.debug("Failed  get by  criteria for type = {}", type, e);
795                                 }
796                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
797                         }
798
799                 } else {
800                         if (log.isDebugEnabled()) {
801                                 log.debug("Failed  get by  criteria for type ={}  error : {}", type, graph.right().value());
802                         }
803                         return Either.right(graph.right().value());
804                 }
805         }
806
807         public <T extends GraphNode> Either<List<T>, JanusGraphOperationStatus> getByCriteria(NodeTypeEnum type, Map<String, Object> props, Class<T> clazz) {
808                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
809                 if (graph.isLeft()) {
810                         try {
811                                 JanusGraph tGraph = graph.left().value();
812
813                                 JanusGraphQuery<? extends JanusGraphQuery> query = tGraph.query();
814                                 query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName());
815
816                                 if (props != null && !props.isEmpty()) {
817                                         for (Map.Entry<String, Object> entry : props.entrySet()) {
818                                                 query = query.has(entry.getKey(), entry.getValue());
819                                         }
820                                 }
821                                 Iterable<JanusGraphVertex> vertices = query.vertices();
822                                 if (vertices == null) {
823                                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
824                                 }
825
826                                 Iterator<JanusGraphVertex> iterator = vertices.iterator();
827                                 List<T> result = new ArrayList<>();
828
829                                 while (iterator.hasNext()) {
830                                         Vertex vertex = iterator.next();
831
832                                         Map<String, Object> newProp = getProperties(vertex);
833
834                                         T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz);
835                                         result.add(element);
836                                 }
837                                 if (log.isDebugEnabled()) {
838                                         log.debug("Number of fetced nodes in graph for criteria : from type = {} and properties = {} is {}", type, props, result.size());
839                                 }
840                                 if (result.size() == 0) {
841                                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
842                                 }
843
844                                 return Either.left(result);
845                         } catch (Exception e) {
846                                 if (log.isDebugEnabled()) {
847                                         log.debug("Failed  get by  criteria for type = {} and properties = {}", type, props, e);
848                                 }
849                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
850                         }
851
852                 } else {
853                         if (log.isDebugEnabled()) {
854                                 log.debug("Failed  get by  criteria for type ={} and properties = {} error : {}", type, props, graph.right().value());
855                         }
856                         return Either.right(graph.right().value());
857                 }
858         }
859
860         public <T extends GraphNode> Either<List<T>, JanusGraphOperationStatus> getByCriteriaWithPredicate(NodeTypeEnum type, Map<String, Entry<JanusGraphPredicate, Object>> props, Class<T> clazz) {
861                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
862                 if (graph.isLeft()) {
863                         try {
864                                 JanusGraph tGraph = graph.left().value();
865
866                                 JanusGraphQuery<? extends JanusGraphQuery> query = tGraph.query();
867                                 query = query.has(GraphPropertiesDictionary.LABEL.getProperty(), type.getName());
868
869                                 if (props != null && !props.isEmpty()) {
870                                         JanusGraphPredicate predicate = null;
871                                         Object object = null;
872                                         for (Map.Entry<String, Entry<JanusGraphPredicate, Object>> entry : props.entrySet()) {
873                                                 predicate = entry.getValue().getKey();
874                                                 object = entry.getValue().getValue();
875                                                 query = query.has(entry.getKey(), predicate, object);
876                                         }
877                                 }
878                                 Iterable<JanusGraphVertex> vertices = query.vertices();
879                                 if (vertices == null) {
880                                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
881                                 }
882
883                                 Iterator<JanusGraphVertex> iterator = vertices.iterator();
884                                 List<T> result = new ArrayList<>();
885
886                                 while (iterator.hasNext()) {
887                                         Vertex vertex = iterator.next();
888
889                                         Map<String, Object> newProp = getProperties(vertex);
890                                         T element = GraphElementFactory.createElement(type.getName(), GraphElementTypeEnum.Node, newProp, clazz);
891                                         result.add(element);
892                                 }
893                                 if (result.size() == 0) {
894                                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
895                                 }
896                                 if (log.isDebugEnabled()) {
897                                         log.debug("No nodes in graph for criteria : from type = {} and properties = {}", type, props);
898                                 }
899                                 return Either.left(result);
900                         } catch (Exception e) {
901                                 if (log.isDebugEnabled()) {
902                                         log.debug("Failed  get by  criteria for type = {} and properties = {}", type, props, e);
903                                 }
904                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
905                         }
906
907                 } else {
908                         if (log.isDebugEnabled()) {
909                                 log.debug("Failed  get by  criteria for type = {} and properties = {} error : {}", type, props, graph.right().value());
910                         }
911                         return Either.right(graph.right().value());
912                 }
913         }
914
915         public <T extends GraphNode> Either<List<T>, JanusGraphOperationStatus> getAll(NodeTypeEnum type, Class<T> clazz) {
916                 return getByCriteria(type, null, clazz);
917         }
918
919         /**
920          * 
921          * @param node
922          * @param clazz
923          * @return
924          */
925         public <T extends GraphNode> Either<T, JanusGraphOperationStatus> updateNode(GraphNode node, Class<T> clazz) {
926                 log.debug("Try to update node for {}", node.getKeyValueIdForLog());
927
928                 ImmutablePair<String, Object> keyValueId = node.getKeyValueId();
929                 Either<Vertex, JanusGraphOperationStatus> vertexByProperty = getVertexByPropertyAndLabel(keyValueId.getKey(), keyValueId.getValue(), node.getLabel());
930
931                 if (vertexByProperty.isLeft()) {
932                         try {
933                                 Vertex vertex = vertexByProperty.left().value();
934
935                                 Map<String, Object> mapProps = node.toGraphMap();
936
937                                 for (Map.Entry<String, Object> entry : mapProps.entrySet()) {
938                                         if (!entry.getKey().equals(node.getUniqueIdKey())) {
939                                                 vertex.property(entry.getKey(), entry.getValue());
940                                         }
941                                 }
942
943                                 Either<Vertex, JanusGraphOperationStatus> vertexByPropertyAndLabel = getVertexByPropertyAndLabel(keyValueId.getKey(), keyValueId.getValue(), node.getLabel());
944                                 if (vertexByPropertyAndLabel.isRight()) {
945                                         return Either.right(vertexByPropertyAndLabel.right().value());
946                                 } else {
947                                         Map<String, Object> newProp = getProperties(vertexByPropertyAndLabel.left().value());
948                                         T updateNode = GraphElementFactory.createElement(node.getLabel(), GraphElementTypeEnum.Node, newProp, clazz);
949                                         return Either.left(updateNode);
950                                 }
951                         } catch (Exception e) {
952                                 if (log.isDebugEnabled()) {
953                                         log.debug("Failed to update node for {}", node.getKeyValueId(), e);
954                                 }
955                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
956                         }
957                 } else {
958                         if (log.isDebugEnabled()) {
959                                 log.debug("Failed to update node for {} error :{}", node.getKeyValueIdForLog(), vertexByProperty.right().value());
960                         }
961                         return Either.right(vertexByProperty.right().value());
962                 }
963
964         }
965
966         public JanusGraphOperationStatus updateVertex(GraphNode node, Vertex vertex) {
967                 log.debug("Try to update node for {}", node.getKeyValueId());
968                 try {
969
970                         Map<String, Object> mapProps = node.toGraphMap();
971
972                         for (Map.Entry<String, Object> entry : mapProps.entrySet()) {
973                                 if (!entry.getKey().equals(node.getUniqueIdKey())) {
974                                         vertex.property(entry.getKey(), entry.getValue());
975                                 }
976                         }
977
978                 } catch (Exception e) {
979                         if (log.isDebugEnabled()) {
980                                 log.debug("Failed to update node for {}", node.getKeyValueId(), e);
981                         }
982                         return JanusGraphClient.handleJanusGraphException(e);
983                 }
984                 return JanusGraphOperationStatus.OK;
985
986         }
987
988         /**
989          * 
990          * @param node
991          * @param clazz
992          * @return
993          */
994         public <T extends GraphNode> Either<T, JanusGraphOperationStatus> deleteNode(GraphNode node, Class<T> clazz) {
995                 log.debug("Try to delete node for {}", node.getKeyValueId());
996                 ImmutablePair<String, Object> keyValueId = node.getKeyValueId();
997                 return deleteNode(keyValueId.getKey(), keyValueId.getValue(), clazz);
998         }
999
1000         /**
1001          * 
1002          * @param keyName
1003          * @param keyValue
1004          * @param clazz
1005          * @return
1006          */
1007         public <T extends GraphNode> Either<T, JanusGraphOperationStatus> deleteNode(String keyName, Object keyValue, Class<T> clazz) {
1008                 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexByProperty = getVertexByProperty(keyName, keyValue);
1009
1010                 if (vertexByProperty.isLeft()) {
1011                         try {
1012                                 Vertex vertex = vertexByProperty.left().value();
1013
1014                                 Map<String, Object> properties = getProperties(vertex);
1015                                 if (properties != null) {
1016                                         String label = (String) properties.get(GraphPropertiesDictionary.LABEL.getProperty());
1017
1018                                         T node = GraphElementFactory.createElement(label, GraphElementTypeEnum.Node, properties, clazz);
1019                                         if (node != null) {
1020                                                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
1021                                                 if (graph.isLeft()) {
1022                                                         JanusGraph tGraph = graph.left().value();
1023                                                         vertex.remove();
1024                                                 } else {
1025                                                         return Either.right(graph.right().value());
1026                                                 }
1027                                                 return Either.left(node);
1028                                         } else {
1029                                                 if (log.isDebugEnabled()) {
1030                                                         log.debug("Failed to delete node for {} = {} Missing label property on node", keyName, keyValue);
1031                                                 }
1032                                                 return Either.right(JanusGraphOperationStatus.MISSING_NODE_LABEL);
1033                                         }
1034                                 } else {
1035                                         if (log.isDebugEnabled()) {
1036                                                 log.debug("Failed to delete node for {} = {} Missing label property on node", keyName, keyValue);
1037                                         }
1038                                         return Either.right(JanusGraphOperationStatus.MISSING_NODE_LABEL);
1039                                 }
1040                         } catch (Exception e) {
1041                                 if (log.isDebugEnabled()) {
1042                                         log.debug("Failed to delete node for {} = {}", keyName, keyValue, e);
1043                                 }
1044                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
1045                         }
1046
1047                 } else {
1048                         return Either.right(vertexByProperty.right().value());
1049                 }
1050         }
1051
1052         public Either<GraphRelation, JanusGraphOperationStatus> deleteRelation(GraphRelation relation) {
1053                 log.debug("try to delete relation from [{}] to [{}]", relation.getFrom(), relation.getTo());
1054                 RelationEndPoint from = relation.getFrom();
1055                 RelationEndPoint to = relation.getTo();
1056                 ImmutablePair<String, Object> fromKeyId = new ImmutablePair<>(from.getIdName(), from.getIdValue());
1057                 ImmutablePair<String, Object> toKeyId = new ImmutablePair<>(to.getIdName(), to.getIdValue());
1058
1059                 return deleteEdge(relation.getType(), fromKeyId, toKeyId, from.getLabel().getName(), to.getLabel().getName());
1060
1061         }
1062
1063         public Either<Boolean, JanusGraphOperationStatus> isRelationExist(GraphNode from, GraphNode to, GraphEdgeLabels edgeLabel) {
1064                 return getEdgeByNodes(from, to, edgeLabel)
1065                                 .left()
1066                                 .map(edge -> true)
1067                                 .right()
1068                                 .bind(err -> err == JanusGraphOperationStatus.NOT_FOUND ? Either.left(false): Either.right(err));
1069         }
1070
1071         public Either<GraphRelation, JanusGraphOperationStatus> deleteRelation(GraphNode from, GraphNode to, GraphEdgeLabels label) {
1072                 log.debug("try to delete relation from [{}] to [{}]", from.getKeyValueId(), to.getKeyValueId());
1073                 return deleteEdge(label.getProperty(), from.getKeyValueId(), to.getKeyValueId(), from.getLabel(), to.getLabel());
1074         }
1075
1076         private Either<GraphRelation, JanusGraphOperationStatus> deleteEdge(String type, ImmutablePair<String, Object> fromKeyId, ImmutablePair<String, Object> toKeyId, String fromLabel, String toLabel) {
1077                 Either<Edge, JanusGraphOperationStatus> edgeS = getEdgeByVerticies(fromKeyId.getKey(), fromKeyId.getValue(), toKeyId.getKey(), toKeyId.getValue(), type);
1078                 if (edgeS.isLeft()) {
1079                         try {
1080                                 Edge edge = edgeS.left().value();
1081
1082                                 Vertex vertexOut = edge.outVertex();
1083                                 Vertex vertexIn = edge.inVertex();
1084
1085                                 GraphNode nodeOut = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class);
1086                                 GraphNode nodeIn = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class);
1087
1088                                 GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn);
1089
1090                                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
1091
1092                                 if (graph.isLeft()) {
1093                                         edge.remove();
1094                                         ;
1095                                 } else {
1096                                         if (log.isDebugEnabled()) {
1097                                                 log.debug("Failed to delete relation {} from {}  to {} error : {}",type,fromKeyId,toKeyId,graph.right().value());
1098                                         }
1099                                         return Either.right(graph.right().value());
1100                                 }
1101                                 return Either.left(newRelation);
1102                         } catch (Exception e) {
1103                                 if (log.isDebugEnabled()) {
1104                                         log.debug("Failed to delete relation {} from {}  to {}", type, fromKeyId, toKeyId, e);
1105                                 }
1106                                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
1107                         }
1108                 } else {
1109                         if (log.isDebugEnabled()) {
1110                                 log.debug("Failed to delete relation {} from {}  to {} error : {}", type, fromKeyId, toKeyId, edgeS.right().value());
1111                         }
1112                         return Either.right(edgeS.right().value());
1113                 }
1114         }
1115
1116         public void setJanusGraphClient(JanusGraphClient janusGraphClient) {
1117                 this.janusGraphClient = janusGraphClient;
1118         }
1119
1120         public Either<GraphRelation, JanusGraphOperationStatus> deleteIncomingRelation(GraphRelation relation) {
1121
1122                 RelationEndPoint to = relation.getTo();
1123                 ImmutablePair<String, Object> toKeyId = new ImmutablePair<>(to.getIdName(), to.getIdValue());
1124
1125                 return deleteIncomingEdge(relation.getType(), toKeyId);
1126
1127         }
1128
1129         private Either<GraphRelation, JanusGraphOperationStatus> deleteIncomingEdge(String type, ImmutablePair<String, Object> toKeyId) {
1130
1131                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
1132
1133                 if (graph.isLeft()) {
1134                         Either<JanusGraphVertex, JanusGraphOperationStatus> rootVertexResult = getVertexByProperty(toKeyId.getKey(), toKeyId.getValue());
1135                         if (rootVertexResult.isLeft()) {
1136                                 Vertex rootVertex = rootVertexResult.left().value();
1137                                 Iterator<Edge> edgesIterator = rootVertex.edges(Direction.IN, type);
1138                                 if (edgesIterator != null) {
1139
1140                                         Edge edge = null;
1141
1142                                         if (edgesIterator.hasNext()) {
1143                                                 edge = edgesIterator.next();
1144                                                 if (edgesIterator.hasNext()) {
1145                                                         return Either.right(JanusGraphOperationStatus.MULTIPLE_EDGES_WITH_SAME_LABEL);
1146                                                 }
1147                                         } else {
1148                                                 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1149                                         }
1150
1151                                         log.debug("Find the tail vertex of the edge of type {} to vertex {}", type, toKeyId);
1152                                         Vertex vertexOut = edge.outVertex();
1153                                         String fromLabel = vertexOut.value(GraphPropertiesDictionary.LABEL.getProperty());
1154                                         String toLabel = rootVertex.value(GraphPropertiesDictionary.LABEL.getProperty());
1155                                         log.debug("The label of the outgoing vertex is {}", fromLabel);
1156                                         GraphNode nodeOut = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(vertexOut), GraphNode.class);
1157
1158                                         GraphNode nodeIn = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(rootVertex), GraphNode.class);
1159
1160                                         GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeOut, nodeIn);
1161
1162                                         edge.remove();
1163
1164                                         return Either.left(newRelation);
1165
1166                                 } else {
1167                                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1168                                 }
1169
1170                         } else {
1171                                 return Either.right(graph.right().value());
1172                         }
1173
1174                 } else {
1175                         return Either.right(graph.right().value());
1176                 }
1177
1178         }
1179
1180         public Either<GraphRelation, JanusGraphOperationStatus> deleteOutgoingRelation(GraphRelation relation) {
1181
1182                 RelationEndPoint from = relation.getFrom();
1183                 ImmutablePair<String, Object> fromKeyId = new ImmutablePair<>(from.getIdName(), from.getIdValue());
1184
1185                 return deleteOutgoingEdge(relation.getType(), fromKeyId);
1186
1187         }
1188
1189         private Either<GraphRelation, JanusGraphOperationStatus> deleteOutgoingEdge(String type, ImmutablePair<String, Object> toKeyId) {
1190
1191                 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
1192
1193                 if (graph.isLeft()) {
1194                         Either<JanusGraphVertex, JanusGraphOperationStatus> rootVertexResult = getVertexByProperty(toKeyId.getKey(), toKeyId.getValue());
1195                         if (rootVertexResult.isLeft()) {
1196                                 Vertex rootVertex = rootVertexResult.left().value();
1197                                 Iterator<Edge> edgesIterator = rootVertex.edges(Direction.OUT, type);
1198                                 if (edgesIterator != null) {
1199
1200                                         Edge edge = null;
1201
1202                                         if (edgesIterator.hasNext()) {
1203                                                 edge = edgesIterator.next();
1204                                                 if (edgesIterator.hasNext()) {
1205                                                         return Either.right(JanusGraphOperationStatus.MULTIPLE_EDGES_WITH_SAME_LABEL);
1206                                                 }
1207                                         } else {
1208                                                 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1209                                         }
1210
1211                                         log.debug("Find the tail vertex of the edge of type {}  to vertex ", type, toKeyId);
1212                                         Vertex vertexIn = edge.inVertex();
1213                                         String toLabel = vertexIn.value(GraphPropertiesDictionary.LABEL.getProperty());
1214                                         String fromLabel = rootVertex.value(GraphPropertiesDictionary.LABEL.getProperty());
1215                                         log.debug("The label of the tail vertex is {}", toLabel);
1216                                         GraphNode nodeFrom = GraphElementFactory.createElement(fromLabel, GraphElementTypeEnum.Node, getProperties(rootVertex), GraphNode.class);
1217
1218                                         GraphNode nodeTo = GraphElementFactory.createElement(toLabel, GraphElementTypeEnum.Node, getProperties(vertexIn), GraphNode.class);
1219
1220                                         GraphRelation newRelation = GraphElementFactory.createRelation(edge.label(), getProperties(edge), nodeFrom, nodeTo);
1221
1222                                         edge.remove();
1223
1224                                         return Either.left(newRelation);
1225
1226                                 } else {
1227                                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1228                                 }
1229
1230                         } else {
1231                                 return Either.right(graph.right().value());
1232                         }
1233
1234                 } else {
1235                         return Either.right(graph.right().value());
1236                 }
1237         }
1238
1239         /**
1240          * 
1241          * @param id
1242          * @return
1243          */
1244
1245         public JanusGraphOperationStatus lockElement(String id, NodeTypeEnum type) {
1246
1247                 StringBuilder lockId = new StringBuilder(LOCK_NODE_PREFIX);
1248                 lockId.append(type.getName()).append("_").append(id);
1249                 return lockNode(lockId.toString());
1250         }
1251
1252         public JanusGraphOperationStatus lockElement(GraphNode node) {
1253
1254                 String lockId = createLockElementId(node);
1255
1256                 return lockNode(lockId);
1257         }
1258
1259         private JanusGraphOperationStatus lockNode(String lockId) {
1260                 GraphNodeLock lockNode = new GraphNodeLock(lockId);
1261
1262                 Either<GraphNodeLock, JanusGraphOperationStatus> lockNodeNew = createNode(lockNode, GraphNodeLock.class);
1263                 if (lockNodeNew.isLeft()) {
1264                         log.debug("before commit, Lock node created for {}", lockId);
1265                         return janusGraphClient.commit();
1266                 } else {
1267                         Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
1268                         if (graph.isLeft()) {
1269                                 JanusGraph tGraph = graph.left().value();
1270                                 Either<JanusGraphVertex, JanusGraphOperationStatus> vertex = getVertexByProperty(lockNode.getUniqueIdKey(), lockNode.getUniqueId());
1271                                 if (vertex.isLeft()) {
1272                                         return relockNode(lockNode, lockNodeNew, tGraph, vertex);
1273                                 } else {
1274                                         return vertex.right().value();
1275                                 }
1276                         } else {
1277                                 return graph.right().value();
1278                         }
1279                 }
1280         }
1281
1282         private JanusGraphOperationStatus relockNode(GraphNodeLock lockNode, Either<GraphNodeLock, JanusGraphOperationStatus> lockNodeNew, JanusGraph tGraph, Either<JanusGraphVertex, JanusGraphOperationStatus> vertex) {
1283                 Long time = vertex.left().value().value(GraphPropertiesDictionary.CREATION_DATE.getProperty());
1284                 Long lockTimeout = ConfigurationManager.getConfigurationManager().getConfiguration().getJanusGraphLockTimeout();
1285                 if (time + lockTimeout * 1000 < System.currentTimeMillis()) {
1286                         log.debug("Found not released lock node with id {}", lockNode.getUniqueId());
1287                         vertex.left().value().remove();
1288                         lockNodeNew = createNode(lockNode, GraphNodeLock.class);
1289                         if (lockNodeNew.isLeft()) {
1290                                 log.debug("Lock node created for {}", lockNode.getUniqueIdKey());
1291                                 return janusGraphClient.commit();
1292                         } else {
1293                                 log.debug("Failed Lock node for {} .  Commit transacton for deleted previous vertex .", lockNode.getUniqueIdKey());
1294                                 janusGraphClient.commit();
1295                                 return checkLockError(lockNode.getUniqueIdKey(), lockNodeNew);
1296                         }
1297                 } else {
1298                         log.debug("Failed Lock node for {}  rollback transacton", lockNode.getUniqueIdKey());
1299                         janusGraphClient.rollback();
1300                         return checkLockError(lockNode.getUniqueIdKey(), lockNodeNew);
1301                 }
1302         }
1303
1304         public <T extends GraphNode> Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> getChildrenNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz, boolean withEdges) {
1305
1306                 List<ImmutablePair<T, GraphEdge>> immutablePairs = new ArrayList<>();
1307
1308                 Either<JanusGraph, JanusGraphOperationStatus> graphRes = janusGraphClient.getGraph();
1309                 if (graphRes.isRight()) {
1310                         log.error("Failed to retrieve graph. status is {}", graphRes);
1311                         return Either.right(graphRes.right().value());
1312                 }
1313
1314                 JanusGraph janusGraph = graphRes.left().value();
1315                 @SuppressWarnings("unchecked")
1316                 Iterable<JanusGraphVertex> vertices = janusGraph.query().has(key, uniqueId).vertices();
1317                 if (vertices == null || !vertices.iterator().hasNext()) {
1318                         return Either.right(JanusGraphOperationStatus.INVALID_ID);
1319                 }
1320
1321                 Vertex rootVertex = vertices.iterator().next();
1322
1323                 Iterator<Edge> edgesCreatorIterator = rootVertex.edges(Direction.OUT, edgeType.getProperty());
1324                 if (edgesCreatorIterator != null) {
1325                         while (edgesCreatorIterator.hasNext()) {
1326                                 Edge edge = edgesCreatorIterator.next();
1327                                 GraphEdge graphEdge = null;
1328
1329                                 if (withEdges) {
1330                                         Map<String, Object> edgeProps = getProperties(edge);
1331                                         GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label());
1332                                         graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps);
1333                                 }
1334
1335                                 Vertex outgoingVertex = edge.inVertex();
1336                                 Map<String, Object> properties = getProperties(outgoingVertex);
1337                                 T data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz);
1338
1339                                 ImmutablePair<T, GraphEdge> immutablePair = new ImmutablePair<>(clazz.cast(data), graphEdge);
1340                                 immutablePairs.add(immutablePair);
1341                         }
1342                 }
1343
1344                 if (immutablePairs.isEmpty()) {
1345                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1346                 }
1347
1348                 return Either.left(immutablePairs);
1349
1350         }
1351
1352         public Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> getChildrenVertecies(String key, String uniqueId, GraphEdgeLabels edgeType) {
1353
1354                 List<ImmutablePair<JanusGraphVertex, Edge>> immutablePairs = new ArrayList<>();
1355
1356                 Either<JanusGraph, JanusGraphOperationStatus> graphRes = janusGraphClient.getGraph();
1357                 if (graphRes.isRight()) {
1358                         log.error("Failed to retrieve graph. status is {}", graphRes);
1359                         return Either.right(graphRes.right().value());
1360                 }
1361
1362                 JanusGraph janusGraph = graphRes.left().value();
1363                 @SuppressWarnings("unchecked")
1364                 Iterable<JanusGraphVertex> vertices = janusGraph.query().has(key, uniqueId).vertices();
1365                 if (vertices == null || !vertices.iterator().hasNext()) {
1366                         return Either.right(JanusGraphOperationStatus.INVALID_ID);
1367                 }
1368
1369                 Vertex rootVertex = vertices.iterator().next();
1370
1371                 Iterator<Edge> edgesCreatorIterator = rootVertex.edges(Direction.OUT, edgeType.getProperty());
1372                 if (edgesCreatorIterator != null) {
1373                         while (edgesCreatorIterator.hasNext()) {
1374                                 Edge edge = edgesCreatorIterator.next();
1375                                 JanusGraphVertex vertex = (JanusGraphVertex) edge.inVertex();
1376
1377                                 ImmutablePair<JanusGraphVertex, Edge> immutablePair = new ImmutablePair<>(vertex, edge);
1378                                 immutablePairs.add(immutablePair);
1379                         }
1380                 }
1381                 if (immutablePairs.isEmpty()) {
1382                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1383                 }
1384
1385                 return Either.left(immutablePairs);
1386
1387         }
1388
1389         public <T extends GraphNode> Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> getChildrenNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz) {
1390                 return this.getChildrenNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz, true);
1391         }
1392
1393         private JanusGraphOperationStatus checkLockError(String lockId, Either<GraphNodeLock, JanusGraphOperationStatus> lockNodeNew) {
1394                 JanusGraphOperationStatus status;
1395                 JanusGraphOperationStatus error = lockNodeNew.right().value();
1396                 log.debug("Failed to Lock node for {}  error = {}", lockId, error);
1397                 if (error.equals(JanusGraphOperationStatus.JANUSGRAPH_SCHEMA_VIOLATION) || error.equals(
1398                                 JanusGraphOperationStatus.ILLEGAL_ARGUMENT)) {
1399                         status = JanusGraphOperationStatus.ALREADY_LOCKED;
1400                 } else {
1401                         status = error;
1402                 }
1403                 return status;
1404         }
1405
1406         /**
1407          * 
1408          * @param node
1409          * @return
1410          */
1411         public JanusGraphOperationStatus releaseElement(GraphNode node) {
1412                 String lockId = createLockElementId(node);
1413
1414                 return unlockNode(lockId);
1415         }
1416
1417         private JanusGraphOperationStatus unlockNode(String lockId) {
1418                 GraphNodeLock lockNode = new GraphNodeLock(lockId.toString());
1419
1420                 Either<GraphNodeLock, JanusGraphOperationStatus> lockNodeNew = deleteNode(lockNode, GraphNodeLock.class);
1421                 if (lockNodeNew.isLeft()) {
1422                         log.debug("Lock node released for lock id = {}", lockId);
1423                         return janusGraphClient.commit();
1424                 } else {
1425                         janusGraphClient.rollback();
1426                         JanusGraphOperationStatus error = lockNodeNew.right().value();
1427                         log.debug("Failed to Release node for lock id {} error = {}", lockId, error);
1428                         return error;
1429                 }
1430         }
1431
1432         public JanusGraphOperationStatus releaseElement(String id, NodeTypeEnum type) {
1433                 StringBuilder lockId = new StringBuilder(LOCK_NODE_PREFIX);
1434                 lockId.append(type.getName()).append("_").append(id);
1435                 return unlockNode(lockId.toString());
1436         }
1437
1438         private String createLockElementId(GraphNode node) {
1439                 StringBuilder lockId = new StringBuilder(LOCK_NODE_PREFIX);
1440                 lockId.append(node.getLabel()).append("_").append(node.getUniqueId());
1441                 return lockId.toString();
1442         }
1443
1444         public <T extends GraphNode> Either<ImmutablePair<T, GraphEdge>, JanusGraphOperationStatus> getChild(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz) {
1445
1446                 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = getChildrenNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz);
1447
1448                 if (childrenNodes.isRight()) {
1449                         return Either.right(childrenNodes.right().value());
1450                 }
1451
1452                 List<ImmutablePair<T, GraphEdge>> value = childrenNodes.left().value();
1453
1454                 if (value.size() > 1) {
1455                         return Either.right(JanusGraphOperationStatus.MULTIPLE_CHILDS_WITH_SAME_EDGE);
1456                 }
1457
1458                 return Either.left(value.get(0));
1459
1460         }
1461
1462         public ImmutablePair<JanusGraphVertex, Edge> getChildVertex(JanusGraphVertex vertex, GraphEdgeLabels edgeType) {
1463
1464                 ImmutablePair<JanusGraphVertex, Edge> pair = null;
1465                 Iterator<Edge> edges = vertex.edges(Direction.OUT, edgeType.getProperty());
1466                 if (edges.hasNext()) {
1467                         // get only first edge
1468                         Edge edge = edges.next();
1469                         pair = new ImmutablePair<>((JanusGraphVertex) edge.inVertex(), edge);
1470                 }
1471                 return pair;
1472         }
1473
1474         public <T extends GraphNode> Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> getParentNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz) {
1475
1476                 List<ImmutablePair<T, GraphEdge>> immutablePairs = new ArrayList<>();
1477
1478                 T data = null;
1479                 GraphEdge graphEdge = null;
1480
1481                 Either<JanusGraph, JanusGraphOperationStatus> graphRes = janusGraphClient.getGraph();
1482                 if (graphRes.isRight()) {
1483                         log.error("Failed to retrieve graph. status is {}", graphRes);
1484                         return Either.right(graphRes.right().value());
1485                 }
1486
1487                 JanusGraph janusGraph = graphRes.left().value();
1488                 @SuppressWarnings("unchecked")
1489                 Iterable<JanusGraphVertex> vertices = janusGraph.query().has(key, uniqueId).vertices();
1490                 if (vertices == null || !vertices.iterator().hasNext()) {
1491                         return Either.right(JanusGraphOperationStatus.INVALID_ID);
1492                 }
1493
1494                 Vertex rootVertex = vertices.iterator().next();
1495
1496                 Iterator<Edge> edgesCreatorIterator = rootVertex.edges(Direction.IN, edgeType.name());
1497                 if (edgesCreatorIterator != null) {
1498                         while (edgesCreatorIterator.hasNext()) {
1499                                 Edge edge = edgesCreatorIterator.next();
1500                                 Map<String, Object> edgeProps = getProperties(edge);
1501                                 GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label());
1502                                 graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps);
1503
1504                                 Vertex outgoingVertex = edge.outVertex();
1505                                 Map<String, Object> properties = getProperties(outgoingVertex);
1506                                 data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz);
1507
1508                                 ImmutablePair<T, GraphEdge> immutablePair = new ImmutablePair<>(clazz.cast(data), graphEdge);
1509                                 immutablePairs.add(immutablePair);
1510                         }
1511                 }
1512
1513                 if (immutablePairs.isEmpty()) {
1514                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1515                 }
1516
1517                 return Either.left(immutablePairs);
1518
1519         }
1520
1521         public <T extends GraphNode> Either<ImmutablePair<T, GraphEdge>, JanusGraphOperationStatus> getParentNode(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz) {
1522
1523                 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> parentNodesRes = this.getParentNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz);
1524
1525                 if (parentNodesRes.isRight()) {
1526                         log.debug("failed to get edge key:{} uniqueId:{} edgeType {} nodeTypeEnum: {}, reason:{}", key, uniqueId, edgeType, nodeTypeEnum, parentNodesRes.right().value());
1527                         return Either.right(parentNodesRes.right().value());
1528                 }
1529
1530                 List<ImmutablePair<T, GraphEdge>> value = parentNodesRes.left().value();
1531
1532                 if (value.size() > 1) {
1533                         return Either.right(JanusGraphOperationStatus.MULTIPLE_CHILDS_WITH_SAME_EDGE);
1534                 }
1535
1536                 return Either.left(value.get(0));
1537         }
1538
1539         public <T extends GraphNode> Either<ImmutablePair<T, GraphEdge>, JanusGraphOperationStatus> getChildByEdgeCriteria(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz, Map<String, Object> edgeProperties) {
1540
1541                 Either<Edge, JanusGraphOperationStatus> outgoingEdgeByCriteria = getOutgoingEdgeByCriteria(key, uniqueId, edgeType, edgeProperties);
1542                 if (outgoingEdgeByCriteria.isRight()) {
1543                         JanusGraphOperationStatus status = outgoingEdgeByCriteria.right().value();
1544                         log.debug("Cannot find outgoing edge from vertex {} with label {} and properties {}" + uniqueId, edgeType, edgeProperties);
1545                         return Either.right(status);
1546                 }
1547
1548                 Edge edge = outgoingEdgeByCriteria.left().value();
1549                 Map<String, Object> edgeProps = getProperties(edge);
1550                 GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label());
1551                 GraphEdge graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps);
1552
1553                 Vertex outgoingVertex = edge.inVertex();
1554                 Map<String, Object> properties = getProperties(outgoingVertex);
1555                 T data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz);
1556
1557                 ImmutablePair<T, GraphEdge> immutablePair = new ImmutablePair<>(clazz.cast(data), graphEdge);
1558
1559                 return Either.left(immutablePair);
1560         }
1561
1562         public Either<ImmutablePair<JanusGraphVertex, Edge>, JanusGraphOperationStatus> getChildByEdgeCriteria(JanusGraphVertex vertex, GraphEdgeLabels edgeType, Map<String, Object> edgeProperties) {
1563
1564                 Either<Edge, JanusGraphOperationStatus> outgoingEdgeByCriteria = getOutgoingEdgeByCriteria(vertex, edgeType, edgeProperties);
1565                 if (outgoingEdgeByCriteria.isRight()) {
1566                         JanusGraphOperationStatus status = outgoingEdgeByCriteria.right().value();
1567                         log.debug("Cannot find outgoing edge from vertex {} with label {} and properties {}", vertex, edgeType, edgeProperties);
1568                         return Either.right(status);
1569                 }
1570                 Edge edge = outgoingEdgeByCriteria.left().value();
1571
1572                 JanusGraphVertex outgoingVertex = (JanusGraphVertex) edge.inVertex();
1573
1574                 ImmutablePair<JanusGraphVertex, Edge> immutablePair = new ImmutablePair<>(outgoingVertex, edge);
1575
1576                 return Either.left(immutablePair);
1577         }
1578
1579         public Either<Edge, JanusGraphOperationStatus> getOutgoingEdgeByCriteria(String key, String value, GraphEdgeLabels label, Map<String, Object> props) {
1580
1581                 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexFrom = getVertexByProperty(key, value);
1582                 if (vertexFrom.isRight()) {
1583                         JanusGraphOperationStatus status = vertexFrom.right().value();
1584                         if (status == JanusGraphOperationStatus.NOT_FOUND) {
1585                                 return Either.right(JanusGraphOperationStatus.INVALID_ID);
1586                         }
1587                         return Either.right(status);
1588                 }
1589
1590                 return getOutgoingEdgeByCriteria(vertexFrom.left().value(), label, props);
1591         }
1592
1593         public Either<Edge, JanusGraphOperationStatus> getOutgoingEdgeByCriteria(JanusGraphVertex vertex, GraphEdgeLabels label, Map<String, Object> props) {
1594
1595                 JanusGraphVertexQuery<?> query = vertex.query();
1596                 query = query.direction(Direction.OUT).labels(label.getProperty());
1597
1598                 if (props != null && !props.isEmpty()) {
1599                         for (Map.Entry<String, Object> entry : props.entrySet()) {
1600                                 query = query.has(entry.getKey(), entry.getValue());
1601                         }
1602                 }
1603                 Edge matchingEdge = null;
1604                 Iterable<JanusGraphEdge> edges = query.edges();
1605                 if (edges == null) {
1606                         log.debug("No edges in graph for criteria");
1607                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1608                 }
1609                 Iterator<JanusGraphEdge> eIter = edges.iterator();
1610                 if (eIter.hasNext()) {
1611             matchingEdge = eIter.next();
1612                 }
1613
1614                 if (matchingEdge == null) {
1615                         log.debug("No edges in graph for criteria");
1616                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1617                 }
1618                 return Either.left(matchingEdge);
1619         }
1620
1621         public <T extends GraphNode> Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> deleteChildrenNodes(String key, String uniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz) {
1622
1623                 List<ImmutablePair<T, GraphEdge>> result = new ArrayList<>();
1624
1625                 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodesRes = getChildrenNodes(key, uniqueId, edgeType, nodeTypeEnum, clazz);
1626
1627                 if (childrenNodesRes.isRight()) {
1628                         JanusGraphOperationStatus status = childrenNodesRes.right().value();
1629                         return Either.right(status);
1630                 }
1631
1632                 List<ImmutablePair<T, GraphEdge>> list = childrenNodesRes.left().value();
1633                 for (ImmutablePair<T, GraphEdge> pair : list) {
1634                         T node = pair.getKey();
1635                         Either<T, JanusGraphOperationStatus> deleteNodeRes = this.deleteNode(node, clazz);
1636                         if (deleteNodeRes.isRight()) {
1637                                 JanusGraphOperationStatus status = deleteNodeRes.right().value();
1638                                 log.error("Failed to delete node {} . status is {}", node, status);
1639                                 return Either.right(status);
1640                         }
1641                         ImmutablePair<T, GraphEdge> deletedPair = new ImmutablePair<>(node, pair.getValue());
1642                         result.add(deletedPair);
1643                 }
1644
1645                 return Either.left(result);
1646
1647         }
1648
1649         public void setProperties(Element element, Map<String, Object> properties) {
1650
1651                 if (properties != null && !properties.isEmpty()) {
1652
1653                         Object[] propertyKeyValues = new Object[properties.size() * 2];
1654                         int i = 0;
1655                         for (Entry<String, Object> entry : properties.entrySet()) {
1656                                 propertyKeyValues[i++] = entry.getKey();
1657                                 propertyKeyValues[i++] = entry.getValue();
1658                         }
1659
1660                         ElementHelper.attachProperties(element, propertyKeyValues);
1661
1662                 }
1663
1664         }
1665
1666         public Map<String, Object> getProperties(Element element) {
1667
1668                 Map<String, Object> result = new HashMap<>();
1669
1670                 if (element != null && element.keys() != null && element.keys().size() > 0) {
1671                         Map<String, Property> propertyMap = ElementHelper.propertyMap(element, element.keys().toArray(new String[element.keys().size()]));
1672
1673                         for (Entry<String, Property> entry : propertyMap.entrySet()) {
1674                                 String key = entry.getKey();
1675                                 Object value = entry.getValue().value();
1676
1677                                 result.put(key, value);
1678                         }
1679                 }
1680                 return result;
1681         }
1682
1683         public Object getProperty(JanusGraphVertex vertex, String key) {
1684                 PropertyKey propertyKey = janusGraphClient.getGraph().left().value().getPropertyKey(key);
1685         return vertex.valueOrNull(propertyKey);
1686         }
1687
1688         public Object getProperty(Edge edge, String key) {
1689                 Object value = null;
1690                 Property<Object> property = edge.property(key);
1691                 if (property != null) {
1692                         return property.orElse(null);
1693                 }
1694                 return value;
1695         }
1696
1697         public <T extends GraphNode> Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> getChildrenByEdgeCriteria(Vertex vertex, String vertexUniqueId, GraphEdgeLabels edgeType, NodeTypeEnum nodeTypeEnum, Class<T> clazz,
1698                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         Map<String, Object> edgeProperties) {
1699
1700                 List<ImmutablePair<T, GraphEdge>> result = new ArrayList<>();
1701
1702                 Either<List<Edge>, JanusGraphOperationStatus> outgoingEdgeByCriteria = getOutgoingEdgesByCriteria(vertex, edgeType, edgeProperties);
1703                 if (outgoingEdgeByCriteria.isRight()) {
1704                         JanusGraphOperationStatus status = outgoingEdgeByCriteria.right().value();
1705                         log.debug("Cannot find outgoing edge from vertex {} with label {}  and properties {}", vertexUniqueId, edgeType, edgeProperties);
1706                         return Either.right(status);
1707                 }
1708
1709                 List<Edge> edges = outgoingEdgeByCriteria.left().value();
1710                 if (edges != null) {
1711                         for (Edge edge : edges) {
1712                                 Map<String, Object> edgeProps = getProperties(edge);
1713                                 GraphEdgeLabels edgeTypeFromGraph = GraphEdgeLabels.getByName(edge.label());
1714                                 GraphEdge graphEdge = new GraphEdge(edgeTypeFromGraph, edgeProps);
1715
1716                                 Vertex outgoingVertex = edge.inVertex();
1717                                 Map<String, Object> properties = getProperties(outgoingVertex);
1718                                 T data = GraphElementFactory.createElement(nodeTypeEnum.getName(), GraphElementTypeEnum.Node, properties, clazz);
1719
1720                                 ImmutablePair<T, GraphEdge> immutablePair = new ImmutablePair<>(clazz.cast(data), graphEdge);
1721                                 result.add(immutablePair);
1722                         }
1723                 }
1724
1725                 return Either.left(result);
1726         }
1727
1728         public @NotNull Either<List<Edge>, JanusGraphOperationStatus> getOutgoingEdgesByCriteria(Vertex vertexFrom, GraphEdgeLabels label, Map<String, Object> props) {
1729
1730                 List<Edge> edgesResult = new ArrayList<>();
1731
1732                 JanusGraphVertex janusGraphVertex = (JanusGraphVertex) vertexFrom;
1733                 JanusGraphVertexQuery<?> query = janusGraphVertex.query();
1734
1735                 query = query.direction(Direction.OUT).labels(label.getProperty());
1736
1737                 if (props != null && !props.isEmpty()) {
1738                         for (Map.Entry<String, Object> entry : props.entrySet()) {
1739                                 query = query.has(entry.getKey(), entry.getValue());
1740                         }
1741                 }
1742
1743                 Iterable<JanusGraphEdge> edges = query.edges();
1744                 Iterator<JanusGraphEdge> eIter = edges.iterator();
1745                 if (!eIter.hasNext()) {
1746                         log.debug("No edges found in graph for criteria (label = {} properties={})", label.getProperty(), props);
1747                         return Either.left(edgesResult);
1748                 }
1749
1750                 while (eIter.hasNext()) {
1751                         Edge edge = eIter.next();
1752                         edgesResult.add(edge);
1753                 }
1754
1755                 if (edgesResult.isEmpty()) {
1756                         log.debug("No edges found in graph for criteria (label = {} properties={})", label.getProperty(), props);
1757                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1758                 }
1759                 return Either.left(edgesResult);
1760
1761         }
1762
1763 }