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