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