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