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