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