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