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