re base code
[sdc.git] / catalog-dao / src / main / java / org / openecomp / sdc / be / dao / jsongraph / TitanDao.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.jsongraph;
22
23 import com.thinkaurelius.titan.core.*;
24 import fj.data.Either;
25 import org.apache.commons.collections.MapUtils;
26 import org.apache.commons.lang3.tuple.ImmutablePair;
27 import org.apache.tinkerpop.gremlin.structure.*;
28 import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
29 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
30 import org.openecomp.sdc.be.dao.jsongraph.types.EdgePropertyEnum;
31 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
32 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
33 import org.openecomp.sdc.be.dao.jsongraph.utils.JsonParserUtils;
34 import org.openecomp.sdc.be.dao.titan.TitanGraphClient;
35 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
36 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
37 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
38 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
39 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
40 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
41 import org.openecomp.sdc.common.log.wrappers.Logger;
42 import org.springframework.beans.factory.annotation.Qualifier;
43 import org.springframework.stereotype.Component;
44
45 import java.io.IOException;
46 import java.util.*;
47 import java.util.Map.Entry;
48
49 import static org.apache.commons.collections.CollectionUtils.isEmpty;
50
51 @Component("titan-dao")
52 public class TitanDao {
53     TitanGraphClient titanClient;
54
55     private static Logger logger = Logger.getLogger(TitanDao.class.getName());
56
57     public TitanDao(@Qualifier("titan-client") TitanGraphClient titanClient) {
58         this.titanClient = titanClient;
59         logger.info("** TitanDao created");
60     }
61
62     public TitanOperationStatus commit() {
63         logger.debug("#commit - The operation succeeded. Doing commit...");
64         return titanClient.commit();
65     }
66
67     public TitanOperationStatus rollback() {
68         logger.debug("#rollback - The operation failed. Doing rollback...");
69         return titanClient.rollback();
70     }
71
72     public Either<TitanGraph, TitanOperationStatus> getGraph() {
73         return titanClient.getGraph();
74     }
75
76     /**
77      * 
78      * @param graphVertex
79      * @return
80      */
81     public Either<GraphVertex, TitanOperationStatus> createVertex(GraphVertex graphVertex) {
82         logger.trace("try to create vertex for ID [{}]", graphVertex.getUniqueId());
83         Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
84         if (graph.isLeft()) {
85             try {
86                 TitanGraph tGraph = graph.left().value();
87
88                 TitanVertex vertex = tGraph.addVertex();
89
90                 setVertexProperties(vertex, graphVertex);
91
92                 graphVertex.setVertex(vertex);
93
94                 return Either.left(graphVertex);
95
96             } catch (Exception e) {
97                 logger.debug("Failed to create Node for ID [{}]", graphVertex.getUniqueId(), e);
98                 return Either.right(TitanGraphClient.handleTitanException(e));
99             }
100         } else {
101             logger.debug("Failed to create vertex for ID [{}]  {}", graphVertex.getUniqueId(), graph.right().value());
102             return Either.right(graph.right().value());
103         }
104     }
105
106     /**
107      * 
108      * @param name
109      * @param value
110      * @param label
111      * @return
112      */
113     public Either<GraphVertex, TitanOperationStatus> getVertexByPropertyAndLabel(GraphPropertyEnum name, Object value, VertexTypeEnum label) {
114         return getVertexByPropertyAndLabel(name, value, label, JsonParseFlagEnum.ParseAll);
115     }
116
117     public Either<GraphVertex, TitanOperationStatus> getVertexByLabel(VertexTypeEnum label) {
118         return titanClient.getGraph().left().map(graph -> graph.query().has(GraphPropertyEnum.LABEL.getProperty(), label.getName()).vertices()).left().bind(titanVertices -> getFirstFoundVertex(JsonParseFlagEnum.NoParse, titanVertices));
119     }
120
121     private Either<GraphVertex, TitanOperationStatus> getFirstFoundVertex(JsonParseFlagEnum parseFlag, Iterable<TitanVertex> vertices) {
122         Iterator<TitanVertex> iterator = vertices.iterator();
123         if (iterator.hasNext()) {
124             TitanVertex vertex = iterator.next();
125             GraphVertex graphVertex = createAndFill(vertex, parseFlag);
126
127             return Either.left(graphVertex);
128         }
129         return Either.right(TitanOperationStatus.NOT_FOUND);
130     }
131
132     /**
133      * 
134      * @param name
135      * @param value
136      * @param label
137      * @param parseFlag
138      * @return
139      */
140     public Either<GraphVertex, TitanOperationStatus> getVertexByPropertyAndLabel(GraphPropertyEnum name, Object value, VertexTypeEnum label, JsonParseFlagEnum parseFlag) {
141
142         Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
143         if (graph.isLeft()) {
144             try {
145                 TitanGraph tGraph = graph.left().value();
146
147                 @SuppressWarnings("unchecked")
148                 Iterable<TitanVertex> vertecies = tGraph.query().has(name.getProperty(), value).has(GraphPropertyEnum.LABEL.getProperty(), label.getName()).vertices();
149
150                 java.util.Iterator<TitanVertex> iterator = vertecies.iterator();
151                 if (iterator.hasNext()) {
152                     TitanVertex vertex = iterator.next();
153                     GraphVertex graphVertex = createAndFill(vertex, parseFlag);
154
155                     return Either.left(graphVertex);
156                 }
157                 if (logger.isDebugEnabled()) {
158                     logger.debug("No vertex in graph for key = {}  and value = {}   label = {}" + name, value, label);
159                 }
160                 return Either.right(TitanOperationStatus.NOT_FOUND);
161             } catch (Exception e) {
162                 if (logger.isDebugEnabled()) {
163                     logger.debug("Failed to get vertex in graph for key ={} and value = {}  label = {}", name, value, label);
164                 }
165                 return Either.right(TitanGraphClient.handleTitanException(e));
166             }
167
168         } else {
169             if (logger.isDebugEnabled()) {
170                 logger.debug("No vertex in graph for key ={} and value = {}  label = {} error :{}", name, value, label, graph.right().value());
171             }
172             return Either.right(graph.right().value());
173         }
174     }
175
176     /**
177      * 
178      * @param id
179      * @return
180      */
181     public Either<GraphVertex, TitanOperationStatus> getVertexById(String id) {
182         return getVertexById(id, JsonParseFlagEnum.ParseAll);
183     }
184
185     /**
186      * 
187      * @param id
188      * @param parseFlag
189      * @return
190      */
191     public Either<GraphVertex, TitanOperationStatus> getVertexById(String id, JsonParseFlagEnum parseFlag) {
192
193         Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
194         if (id == null) {
195             if (logger.isDebugEnabled()) {
196                 logger.debug("No vertex in graph for id = {} ", id);
197             }
198             return Either.right(TitanOperationStatus.NOT_FOUND);
199         }
200         if (graph.isLeft()) {
201             try {
202                 TitanGraph tGraph = graph.left().value();
203
204                 @SuppressWarnings("unchecked")
205                 Iterable<TitanVertex> vertecies = tGraph.query().has(GraphPropertyEnum.UNIQUE_ID.getProperty(), id).vertices();
206
207                 java.util.Iterator<TitanVertex> iterator = vertecies.iterator();
208                 if (iterator.hasNext()) {
209                     TitanVertex vertex = iterator.next();
210                     GraphVertex graphVertex = createAndFill(vertex, parseFlag);
211                     return Either.left(graphVertex);
212                 } else {
213                     if (logger.isDebugEnabled()) {
214                         logger.debug("No vertex in graph for id = {}", id);
215                     }
216                     return Either.right(TitanOperationStatus.NOT_FOUND);
217                 }
218             } catch (Exception e) {
219                 if (logger.isDebugEnabled()) {
220                     logger.debug("Failed to get vertex in graph for id {} ", id);
221                 }
222                 return Either.right(TitanGraphClient.handleTitanException(e));
223             }
224         } else {
225             if (logger.isDebugEnabled()) {
226                 logger.debug("No vertex in graph for id {} error : {}", id, graph.right().value());
227             }
228             return Either.right(graph.right().value());
229         }
230     }
231
232     private void setVertexProperties(TitanVertex vertex, GraphVertex graphVertex) throws IOException {
233
234         if (graphVertex.getMetadataProperties() != null) {
235             for (Map.Entry<GraphPropertyEnum, Object> entry : graphVertex.getMetadataProperties().entrySet()) {
236                 if (entry.getValue() != null) {
237                     vertex.property(entry.getKey().getProperty(), entry.getValue());
238                 }
239             }
240         }
241         vertex.property(GraphPropertyEnum.LABEL.getProperty(), graphVertex.getLabel().getName());
242
243         Map<String, ? extends ToscaDataDefinition> json = graphVertex.getJson();
244         if (json != null) {
245             String jsonStr = JsonParserUtils.toJson(json);
246             vertex.property(GraphPropertyEnum.JSON.getProperty(), jsonStr);
247
248         }
249         Map<String, Object> jsonMetadata = graphVertex.getMetadataJson();
250         if (jsonMetadata != null) {
251             String jsonMetadataStr = JsonParserUtils.toJson(jsonMetadata);
252             vertex.property(GraphPropertyEnum.METADATA.getProperty(), jsonMetadataStr);
253         }
254     }
255
256     public void setVertexProperties(Vertex vertex, Map<String, Object> properties) throws IOException {
257         for (Map.Entry<String, Object> entry : properties.entrySet()) {
258             if (entry.getValue() != null) {
259                 vertex.property(entry.getKey(), entry.getValue());
260             }
261         }
262     }
263
264     private GraphVertex createAndFill(TitanVertex vertex, JsonParseFlagEnum parseFlag) {
265         GraphVertex graphVertex = new GraphVertex();
266         graphVertex.setVertex(vertex);
267         parseVertexProperties(graphVertex, parseFlag);
268         return graphVertex;
269     }
270
271     public void parseVertexProperties(GraphVertex graphVertex, JsonParseFlagEnum parseFlag) {
272         TitanVertex vertex = graphVertex.getVertex();
273         Map<GraphPropertyEnum, Object> properties = getVertexProperties(vertex);
274         VertexTypeEnum label = VertexTypeEnum.getByName((String) (properties.get(GraphPropertyEnum.LABEL)));
275         for (Map.Entry<GraphPropertyEnum, Object> entry : properties.entrySet()) {
276             GraphPropertyEnum key = entry.getKey();
277             switch (key) {
278             case UNIQUE_ID:
279                 graphVertex.setUniqueId((String) entry.getValue());
280                 break;
281             case LABEL:
282                 graphVertex.setLabel(VertexTypeEnum.getByName((String) entry.getValue()));
283                 break;
284             case COMPONENT_TYPE:
285                 String type = (String) entry.getValue();
286                 if (type != null) {
287                     graphVertex.setType(ComponentTypeEnum.valueOf(type));
288                 }
289                 break;
290             case JSON:
291                 if (parseFlag == JsonParseFlagEnum.ParseAll || parseFlag == JsonParseFlagEnum.ParseJson) {
292                     String json = (String) entry.getValue();
293                     Map<String, ? extends ToscaDataDefinition> jsonObj = JsonParserUtils.toMap(json, label.getClassOfJson());
294                     graphVertex.setJson(jsonObj);
295                 }
296                 break;
297             case METADATA:
298                 if (parseFlag == JsonParseFlagEnum.ParseAll || parseFlag == JsonParseFlagEnum.ParseMetadata) {
299                     String json = (String) entry.getValue();
300                     Map<String, Object> metadatObj = JsonParserUtils.toMap(json);
301                     graphVertex.setMetadataJson(metadatObj);
302                 }
303                 break;
304             default:
305                 graphVertex.addMetadataProperty(key, entry.getValue());
306                 break;
307             }
308         }
309     }
310
311     public TitanOperationStatus createEdge(GraphVertex from, GraphVertex to, EdgeLabelEnum label, Map<EdgePropertyEnum, Object> properties) {
312         return createEdge(from.getVertex(), to.getVertex(), label, properties);
313     }
314
315     public TitanOperationStatus createEdge(Vertex from, Vertex to, EdgeLabelEnum label, Map<EdgePropertyEnum, Object> properties) {
316         if (logger.isTraceEnabled()) {
317             logger.trace("Try to connect {} with {} label {} properties {}",
318                     from == null ? "NULL" : from.property(GraphPropertyEnum.UNIQUE_ID.getProperty()),
319                     to == null ? "NULL" : to.property(GraphPropertyEnum.UNIQUE_ID.getProperty()), label, properties);
320         }
321         if (from == null || to == null) {
322             logger.trace("No Titan vertex for id from {} or id to {}",
323                     from == null ? "NULL" : from.property(GraphPropertyEnum.UNIQUE_ID.getProperty()),
324                     to == null ? "NULL" : to.property(GraphPropertyEnum.UNIQUE_ID.getProperty()));
325             return TitanOperationStatus.NOT_FOUND;
326         }
327         Edge edge = from.addEdge(label.name(), to);
328         TitanOperationStatus status;
329         try {
330             setEdgeProperties(edge, properties);
331             status = TitanOperationStatus.OK;
332         } catch (IOException e) {
333             logger.debug("Failed to set properties on edge  properties [{}]", properties, e);
334             status = TitanOperationStatus.GENERAL_ERROR;
335         }
336         return status;
337     }
338
339     public Map<GraphPropertyEnum, Object> getVertexProperties(Element element) {
340
341         Map<GraphPropertyEnum, Object> result = new HashMap<>();
342
343         if (element != null && element.keys() != null && element.keys().size() > 0) {
344             Map<String, Property> propertyMap = ElementHelper.propertyMap(element, element.keys().toArray(new String[element.keys().size()]));
345
346             for (Entry<String, Property> entry : propertyMap.entrySet()) {
347                 String key = entry.getKey();
348                 Object value = entry.getValue().value();
349
350                 GraphPropertyEnum valueOf = GraphPropertyEnum.getByProperty(key);
351                 if (valueOf != null) {
352                     result.put(valueOf, value);
353                 }
354             }
355         }
356         return result;
357     }
358
359     public Map<EdgePropertyEnum, Object> getEdgeProperties(Element element) {
360
361         Map<EdgePropertyEnum, Object> result = new HashMap<>();
362
363         if (element != null && element.keys() != null && element.keys().size() > 0) {
364             Map<String, Property> propertyMap = ElementHelper.propertyMap(element, element.keys().toArray(new String[element.keys().size()]));
365
366             for (Entry<String, Property> entry : propertyMap.entrySet()) {
367                 String key = entry.getKey();
368                 Object value = entry.getValue().value();
369
370                 EdgePropertyEnum valueOf = EdgePropertyEnum.getByProperty(key);
371                 if (valueOf != null) {
372                     if (valueOf == EdgePropertyEnum.INSTANCES) {
373                         List<String> list = JsonParserUtils.toList((String) value, String.class);
374                         result.put(valueOf, list);
375                     } else {
376                         result.put(valueOf, value);
377                     }
378                 }
379             }
380         }
381         return result;
382     }
383
384     public void setEdgeProperties(Element element, Map<EdgePropertyEnum, Object> properties) throws IOException {
385
386         if (properties != null && !properties.isEmpty()) {
387
388             Object[] propertyKeyValues = new Object[properties.size() * 2];
389             int i = 0;
390             for (Entry<EdgePropertyEnum, Object> entry : properties.entrySet()) {
391                 propertyKeyValues[i++] = entry.getKey().getProperty();
392                 Object value = entry.getValue();
393                 if (entry.getKey() == EdgePropertyEnum.INSTANCES) {
394                     String jsonStr = JsonParserUtils.toJson(value);
395                     propertyKeyValues[i++] = jsonStr;
396                 } else {
397                     propertyKeyValues[i++] = entry.getValue();
398                 }
399             }
400             ElementHelper.attachProperties(element, propertyKeyValues);
401         }
402     }
403
404     public Either<List<GraphVertex>, TitanOperationStatus> getByCriteria(VertexTypeEnum type, Map<GraphPropertyEnum, Object> props) {
405         return getByCriteria(type, props, JsonParseFlagEnum.ParseAll);
406     }
407
408     public Either<List<GraphVertex>, TitanOperationStatus> getByCriteria(VertexTypeEnum type, Map<GraphPropertyEnum, Object> props, JsonParseFlagEnum parseFlag) {
409         Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
410         if (graph.isLeft()) {
411             try {
412                 TitanGraph tGraph = graph.left().value();
413
414                 TitanGraphQuery<? extends TitanGraphQuery> query = tGraph.query();
415                 if (type != null) {
416                     query = query.has(GraphPropertyEnum.LABEL.getProperty(), type.getName());
417                 }
418
419                 if (props != null && !props.isEmpty()) {
420                     for (Map.Entry<GraphPropertyEnum, Object> entry : props.entrySet()) {
421                         query = query.has(entry.getKey().getProperty(), entry.getValue());
422                     }
423                 }
424                 Iterable<TitanVertex> vertices = query.vertices();
425                 if (vertices == null) {
426                     return Either.right(TitanOperationStatus.NOT_FOUND);
427                 }
428
429                 Iterator<TitanVertex> iterator = vertices.iterator();
430                 List<GraphVertex> result = new ArrayList<>();
431
432                 while (iterator.hasNext()) {
433                     TitanVertex vertex = iterator.next();
434
435                     Map<GraphPropertyEnum, Object> newProp = getVertexProperties(vertex);
436                     GraphVertex graphVertex = createAndFill(vertex, parseFlag);
437
438                     result.add(graphVertex);
439                 }
440                 if (logger.isDebugEnabled()) {
441                     logger.debug("Number of fetced nodes in graph for criteria : from type = {} and properties = {} is {}", type, props, result.size());
442                 }
443                 if (result.size() == 0) {
444                     return Either.right(TitanOperationStatus.NOT_FOUND);
445                 }
446
447                 return Either.left(result);
448             } catch (Exception e) {
449                 if (logger.isDebugEnabled()) {
450                     logger.debug("Failed  get by  criteria for type = {} and properties = {}", type, props, e);
451                 }
452                 return Either.right(TitanGraphClient.handleTitanException(e));
453             }
454
455         } else {
456             if (logger.isDebugEnabled()) {
457                 logger.debug("Failed  get by  criteria for type ={} and properties = {} error : {}", type, props, graph.right().value());
458             }
459             return Either.right(graph.right().value());
460         }
461     }
462
463     public Either<List<GraphVertex>, TitanOperationStatus> getByCriteria(VertexTypeEnum type, Map<GraphPropertyEnum, Object> props, Map<GraphPropertyEnum, Object> hasNotProps, JsonParseFlagEnum parseFlag) {
464         Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
465         if (graph.isLeft()) {
466             try {
467                 TitanGraph tGraph = graph.left().value();
468
469                 TitanGraphQuery<? extends TitanGraphQuery> query = tGraph.query();
470                 if (type != null) {
471                     query = query.has(GraphPropertyEnum.LABEL.getProperty(), type.getName());
472                 }
473
474                 if (props != null && !props.isEmpty()) {
475                     for (Map.Entry<GraphPropertyEnum, Object> entry : props.entrySet()) {
476                         query = query.has(entry.getKey().getProperty(), entry.getValue());
477                     }
478                 }
479                 if (hasNotProps != null && !hasNotProps.isEmpty()) {
480                     for (Map.Entry<GraphPropertyEnum, Object> entry : hasNotProps.entrySet()) {
481                         if (entry.getValue() instanceof List) {
482                             buildMultipleNegateQueryFromList(entry, query);
483                         } else {
484                             query = query.hasNot(entry.getKey().getProperty(), entry.getValue());
485                         }
486                     }
487                 }
488                 Iterable<TitanVertex> vertices = query.vertices();
489                 if (vertices == null) {
490                     return Either.right(TitanOperationStatus.NOT_FOUND);
491                 }
492
493                 Iterator<TitanVertex> iterator = vertices.iterator();
494                 List<GraphVertex> result = new ArrayList<>();
495
496                 while (iterator.hasNext()) {
497                     TitanVertex vertex = iterator.next();
498
499                     Map<GraphPropertyEnum, Object> newProp = getVertexProperties(vertex);
500                     GraphVertex graphVertex = createAndFill(vertex, parseFlag);
501
502                     result.add(graphVertex);
503                 }
504                 if (logger.isDebugEnabled()) {
505                     logger.debug("Number of fetced nodes in graph for criteria : from type = {} and properties = {} is {}", type, props, result.size());
506                 }
507                 if (result.size() == 0) {
508                     return Either.right(TitanOperationStatus.NOT_FOUND);
509                 }
510
511                 return Either.left(result);
512             } catch (Exception e) {
513                 if (logger.isDebugEnabled()) {
514                     logger.debug("Failed  get by  criteria for type = {} and properties = {}", type, props, e);
515                 }
516                 return Either.right(TitanGraphClient.handleTitanException(e));
517             }
518
519         } else {
520             if (logger.isDebugEnabled()) {
521                 logger.debug("Failed  get by  criteria for type ={} and properties = {} error : {}", type, props, graph.right().value());
522             }
523             return Either.right(graph.right().value());
524         }
525     }
526
527     public Either<Iterator<Vertex>, TitanOperationStatus> getCatalogOrArchiveVerticies(boolean isCatalog) {
528         Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
529         if (graph.isLeft()) {
530             try {
531                 TitanGraph tGraph = graph.left().value();
532
533                 String name = isCatalog ? VertexTypeEnum.CATALOG_ROOT.getName() : VertexTypeEnum.ARCHIVE_ROOT.getName();
534                 Iterable<TitanVertex> vCatalogIter = tGraph.query().has(GraphPropertyEnum.LABEL.getProperty(), name).vertices();
535                 if (vCatalogIter == null) {
536                     logger.debug("Failed to fetch catalog vertex");
537                     return Either.right(TitanOperationStatus.GENERAL_ERROR);
538                 }
539                 TitanVertex catalogV = vCatalogIter.iterator().next();
540                 if (catalogV == null) {
541                     logger.debug("Failed to fetch catalog vertex");
542                     return Either.right(TitanOperationStatus.GENERAL_ERROR);
543                 }
544                 String edgeLabel = isCatalog ? EdgeLabelEnum.CATALOG_ELEMENT.name() : EdgeLabelEnum.ARCHIVE_ELEMENT.name();
545                 Iterator<Vertex> vertices = catalogV.vertices(Direction.OUT, edgeLabel);
546
547                 return Either.left(vertices);
548             } catch (Exception e) {
549                 if (logger.isDebugEnabled()) {
550                     logger.debug("Failed  get by  criteria: ", e);
551                 }
552                 return Either.right(TitanGraphClient.handleTitanException(e));
553             }
554
555         } else {
556             if (logger.isDebugEnabled()) {
557                 logger.debug("Failed  get by  criteria : ", graph.right().value());
558             }
559             return Either.right(graph.right().value());
560         }
561     }
562
563     private void buildMultipleNegateQueryFromList(Map.Entry<GraphPropertyEnum, Object> entry, TitanGraphQuery query) {
564         List<Object> negateList = (List<Object>) entry.getValue();
565         for (Object listItem : negateList) {
566             query.hasNot(entry.getKey().getProperty(), listItem);
567         }
568     }
569
570     /**
571      * 
572      * @param parentVertex
573      * @param edgeLabel
574      * @param parseFlag
575      * @return
576      */
577     public Either<GraphVertex, TitanOperationStatus> getChildVertex(GraphVertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
578         Either<List<GraphVertex>, TitanOperationStatus> childrenVertecies = getChildrenVertecies(parentVertex, edgeLabel, parseFlag);
579         if (childrenVertecies.isRight()) {
580             return Either.right(childrenVertecies.right().value());
581         }
582         return Either.left(childrenVertecies.left().value().get(0));
583     }
584
585     /**
586      *
587      * @param parentVertex
588      * @param edgeLabel
589      * @param parseFlag
590      * @return
591      */
592     public Either<Vertex, TitanOperationStatus> getChildVertex(Vertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
593         Either<List<Vertex>, TitanOperationStatus> childrenVertecies = getChildrenVertecies(parentVertex, edgeLabel, parseFlag);
594         if (childrenVertecies.isRight()) {
595             return Either.right(childrenVertecies.right().value());
596         }
597         return Either.left(childrenVertecies.left().value().get(0));
598     }
599
600     public Either<GraphVertex, TitanOperationStatus> getParentVertex(GraphVertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
601         Either<List<GraphVertex>, TitanOperationStatus> childrenVertecies = getParentVertecies(parentVertex, edgeLabel, parseFlag);
602         if (childrenVertecies.isRight()) {
603             return Either.right(childrenVertecies.right().value());
604         }
605         if (isEmpty(childrenVertecies.left().value())){
606             return Either.right(TitanOperationStatus.NOT_FOUND);
607         }
608         return Either.left(childrenVertecies.left().value().get(0));
609     }
610
611     public Either<Vertex, TitanOperationStatus> getParentVertex(Vertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
612         Either<List<Vertex>, TitanOperationStatus> childrenVertecies = getParentVertecies(parentVertex, edgeLabel, parseFlag);
613         if (childrenVertecies.isRight() ) {
614             return Either.right(childrenVertecies.right().value());
615         }
616         if (isEmpty(childrenVertecies.left().value())){
617             return Either.right(TitanOperationStatus.NOT_FOUND);
618         }
619         return Either.left(childrenVertecies.left().value().get(0));
620     }
621
622     /**
623      * 
624      * @param parentVertex
625      * @param edgeLabel
626      * @param parseFlag
627      * @return
628      */
629     public Either<List<GraphVertex>, TitanOperationStatus> getChildrenVertecies(GraphVertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
630         return getAdjacentVerticies(parentVertex, edgeLabel, parseFlag, Direction.OUT);
631     }
632
633     public Either<List<GraphVertex>, TitanOperationStatus> getParentVertecies(GraphVertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
634         return getAdjacentVerticies(parentVertex, edgeLabel, parseFlag, Direction.IN);
635     }
636
637     public Either<List<Vertex>, TitanOperationStatus> getParentVertecies(Vertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
638         return getAdjacentVerticies(parentVertex, edgeLabel, parseFlag, Direction.IN);
639     }
640
641     private Either<List<Vertex>, TitanOperationStatus> getAdjacentVerticies(Vertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag, Direction direction) {
642         List<Vertex> list = new ArrayList<>();
643         try {
644             Either<TitanGraph, TitanOperationStatus> graphRes = titanClient.getGraph();
645             if (graphRes.isRight()) {
646                 logger.error("Failed to retrieve graph. status is {}", graphRes);
647                 return Either.right(graphRes.right().value());
648             }
649             Iterator<Edge> edgesCreatorIterator = parentVertex.edges(direction, edgeLabel.name());
650             if (edgesCreatorIterator != null) {
651                 while (edgesCreatorIterator.hasNext()) {
652                     Edge edge = edgesCreatorIterator.next();
653                     TitanVertex vertex;
654                     if (direction == Direction.IN) {
655                         vertex = (TitanVertex) edge.outVertex();
656                     } else {
657                         vertex = (TitanVertex) edge.inVertex();
658                     }
659                     // GraphVertex graphVertex = createAndFill(vertex, parseFlag);
660
661                     list.add(vertex);
662                 }
663             }
664             if (list.isEmpty()) {
665                 return Either.right(TitanOperationStatus.NOT_FOUND);
666             }
667         } catch (Exception e) {
668             logger.error("Failed to perform graph operation ", e);
669             Either.right(TitanGraphClient.handleTitanException(e));
670         }
671
672         return Either.left(list);
673     }
674
675     /**
676      *
677      * @param parentVertex
678      * @param edgeLabel
679      * @param parseFlag
680      * @return
681      */
682     public Either<List<Vertex>, TitanOperationStatus> getChildrenVertecies(Vertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
683         return getAdjacentVerticies(parentVertex, edgeLabel, parseFlag, Direction.OUT);
684     }
685
686     private Either<List<GraphVertex>, TitanOperationStatus> getAdjacentVerticies(GraphVertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag, Direction direction) {
687         List<GraphVertex> list = new ArrayList<>();
688
689         Either<List<Vertex>, TitanOperationStatus> adjacentVerticies = getAdjacentVerticies(parentVertex.getVertex(), edgeLabel, parseFlag, direction);
690         if (adjacentVerticies.isRight()) {
691             return Either.right(adjacentVerticies.right().value());
692         }
693         adjacentVerticies.left().value().stream().forEach(vertex -> {
694             list.add(createAndFill((TitanVertex) vertex, parseFlag));
695         });
696
697         return Either.left(list);
698     }
699
700     /**
701      * Searches Edge by received label and criteria
702      * 
703      * @param vertex
704      * @param label
705      * @param properties
706      * @return found edge or TitanOperationStatus
707      */
708     public Either<Edge, TitanOperationStatus> getBelongingEdgeByCriteria(GraphVertex vertex, EdgeLabelEnum label, Map<GraphPropertyEnum, Object> properties) {
709
710         Either<Edge, TitanOperationStatus> result = null;
711         Edge matchingEdge = null;
712         String notFoundMsg = "No edges in graph for criteria";
713         try {
714             TitanVertexQuery<?> query = vertex.getVertex().query().labels(label.name());
715
716             if (properties != null && !properties.isEmpty()) {
717                 for (Map.Entry<GraphPropertyEnum, Object> entry : properties.entrySet()) {
718                     query = query.has(entry.getKey().getProperty(), entry.getValue());
719                 }
720             }
721
722             Iterable<TitanEdge> edges = query.edges();
723             if (edges == null) {
724                 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, notFoundMsg);
725                 result = Either.right(TitanOperationStatus.NOT_FOUND);
726             } else {
727                 Iterator<TitanEdge> eIter = edges.iterator();
728                 if (eIter.hasNext()) {
729                     matchingEdge = eIter.next();
730                 } else {
731                     CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, notFoundMsg);
732                     result = Either.right(TitanOperationStatus.NOT_FOUND);
733                 }
734             }
735             if (result == null) {
736                 result = Either.left(matchingEdge);
737             }
738         } catch (Exception e) {
739             CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occured during getting edge by criteria for component with id {}. {}", vertex.getUniqueId(), e);
740             return Either.right(TitanGraphClient.handleTitanException(e));
741         }
742         return result;
743     }
744
745     public Either<Edge, TitanOperationStatus> getEdgeByChildrenVertexProperties(GraphVertex vertex, EdgeLabelEnum label, Map<GraphPropertyEnum, Object> properties) {
746         Either<Edge, TitanOperationStatus> result = null;
747         Edge matchingEdge = null;
748         String notFoundMsg = "No edges in graph for criteria";
749         try {
750
751             Iterator<Edge> edges = vertex.getVertex().edges(Direction.OUT, label.name());
752             while (edges.hasNext()) {
753                 matchingEdge = edges.next();
754                 Vertex childV = matchingEdge.inVertex();
755                 Map<GraphPropertyEnum, Object> vertexProperties = getVertexProperties(childV);
756                 Optional<Entry<GraphPropertyEnum, Object>> findNotMatch = properties.entrySet().stream().filter(e -> vertexProperties.get(e.getKey()) == null || !vertexProperties.get(e.getKey()).equals(e.getValue())).findFirst();
757                 if (!findNotMatch.isPresent()) {
758                     result = Either.left(matchingEdge);
759                 }
760             }
761             if (result == null) {
762                 //no match 
763                 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, notFoundMsg);
764                 result = Either.right(TitanOperationStatus.NOT_FOUND);
765             }
766         } catch (Exception e) {
767             CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occured during getting edge by criteria for component with id {}. {}", vertex.getUniqueId(), e);
768             return Either.right(TitanGraphClient.handleTitanException(e));
769         }
770         return result;
771     }
772
773     /**
774      * Deletes Edge by received label and criteria
775      * 
776      * @param vertex
777      * @param label
778      * @param properties
779      * @return
780      */
781     public Either<Edge, TitanOperationStatus> deleteBelongingEdgeByCriteria(GraphVertex vertex, EdgeLabelEnum label, Map<GraphPropertyEnum, Object> properties) {
782         Either<Edge, TitanOperationStatus> result = null;
783         try {
784             result = getBelongingEdgeByCriteria(vertex, label, properties);
785             if (result.isLeft()) {
786                 Edge edge = result.left().value();
787                 CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "Going to delete an edge with the label {} belonging to the vertex {} ", label.name(), vertex.getUniqueId());
788                 edge.remove();
789                 result = Either.left(edge);
790             } else {
791                 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to find an edge with the label {} belonging to the vertex {} ", label.name(), vertex.getUniqueId());
792             }
793         } catch (Exception e) {
794             CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occured during deleting an edge by criteria for the component with id {}. {}", vertex == null ? "NULL" : vertex.getUniqueId(), e);
795             return Either.right(TitanGraphClient.handleTitanException(e));
796         }
797         return result;
798     }
799
800     @SuppressWarnings("unchecked")
801     /**
802      * Deletes an edge between vertices fromVertex and toVertex according to received label
803      * 
804      * @param fromVertex
805      * @param toVertex
806      * @param label
807      * @return
808      */
809
810     public Either<Edge, TitanOperationStatus> deleteEdge(GraphVertex fromVertex, GraphVertex toVertex, EdgeLabelEnum label) {
811         return deleteEdge(fromVertex.getVertex(), toVertex.getVertex(), label, fromVertex.getUniqueId(), toVertex.getUniqueId(), false);
812     }
813
814     public Either<Edge, TitanOperationStatus> deleteAllEdges(GraphVertex fromVertex, GraphVertex toVertex, EdgeLabelEnum label) {
815         return deleteEdge(fromVertex.getVertex(), toVertex.getVertex(), label, fromVertex.getUniqueId(), toVertex.getUniqueId(), true);
816     }
817
818     public Either<Edge, TitanOperationStatus> deleteEdge(TitanVertex fromVertex, TitanVertex toVertex, EdgeLabelEnum label, String uniqueIdFrom, String uniqueIdTo, boolean deleteAll) {
819         Either<Edge, TitanOperationStatus> result = null;
820         try {
821             Iterable<TitanEdge> edges = fromVertex.query().labels(label.name()).edges();
822             Iterator<TitanEdge> eIter = edges.iterator();
823             while (eIter.hasNext()) {
824                 Edge edge = eIter.next();
825                 String currVertexUniqueId = edge.inVertex().value(GraphPropertyEnum.UNIQUE_ID.getProperty());
826                 if (currVertexUniqueId != null && currVertexUniqueId.equals(uniqueIdTo)) {
827                     CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "Going to delete an edge with the label {} between vertices {} and {}. ", label.name(), uniqueIdFrom, uniqueIdTo);
828                     edge.remove();
829                     result = Either.left(edge);
830                     if (!deleteAll) {
831                         break;
832                     }
833                 }
834             }
835             if (result == null) {
836                 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to delete an edge with the label {} between vertices {} and {}. ", label.name(), uniqueIdFrom, uniqueIdTo);
837                 result = Either.right(TitanOperationStatus.NOT_FOUND);
838             }
839         } catch (Exception e) {
840             CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occured during deleting an edge with the label {} between vertices {} and {}. {}", label.name(), uniqueIdFrom, uniqueIdTo, e);
841             return Either.right(TitanGraphClient.handleTitanException(e));
842         }
843         return result;
844     }
845
846     public TitanOperationStatus deleteEdgeByDirection(GraphVertex fromVertex, Direction direction, EdgeLabelEnum label) {
847         try {
848             Iterator<Edge> edges = fromVertex.getVertex().edges(direction, label.name());
849
850             while (edges.hasNext()) {
851                 Edge edge = edges.next();
852                 edge.remove();
853             }
854         } catch (Exception e) {
855             logger.debug("Failed to remove from vertex {} edges {} by direction {} ", fromVertex.getUniqueId(), label, direction, e);
856             return TitanGraphClient.handleTitanException(e);
857         }
858         return TitanOperationStatus.OK;
859     }
860
861     /**
862      * Updates vertex properties. Note that graphVertex argument should contain updated data
863      * 
864      * @param graphVertex
865      * @return
866      */
867     public Either<GraphVertex, TitanOperationStatus> updateVertex(GraphVertex graphVertex) {
868         CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "Going to update metadata of vertex with uniqueId {}. ", graphVertex.getUniqueId());
869         try {
870             graphVertex.updateMetadataJsonWithCurrentMetadataProperties();
871             setVertexProperties(graphVertex.getVertex(), graphVertex);
872
873         } catch (Exception e) {
874             CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to update metadata of vertex with uniqueId {}. ", graphVertex.getUniqueId(), e);
875             return Either.right(TitanGraphClient.handleTitanException(e));
876         }
877         return Either.left(graphVertex);
878     }
879
880     /**
881      * Fetches vertices by uniqueId according to received parse flag
882      * 
883      * @param verticesToGet
884      * @return
885      */
886     public Either<Map<String, GraphVertex>, TitanOperationStatus> getVerticesByUniqueIdAndParseFlag(Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> verticesToGet) {
887
888         Either<Map<String, GraphVertex>, TitanOperationStatus> result = null;
889         Map<String, GraphVertex> vertices = new HashMap<>();
890         TitanOperationStatus titatStatus;
891         Either<GraphVertex, TitanOperationStatus> getVertexRes = null;
892         for (Map.Entry<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> entry : verticesToGet.entrySet()) {
893             if (entry.getValue().getKey() == GraphPropertyEnum.UNIQUE_ID) {
894                 getVertexRes = getVertexById(entry.getKey(), entry.getValue().getValue());
895             } else if (entry.getValue().getKey() == GraphPropertyEnum.USERID) {
896                 getVertexRes = getVertexByPropertyAndLabel(entry.getValue().getKey(), entry.getKey(), VertexTypeEnum.USER, entry.getValue().getValue());
897             }
898             if (getVertexRes == null) {
899                 titatStatus = TitanOperationStatus.ILLEGAL_ARGUMENT;
900                 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Invalid vertex type label {} has been received. ", entry.getValue().getKey(), titatStatus);
901                 return Either.right(titatStatus);
902             }
903             if (getVertexRes.isRight()) {
904                 titatStatus = getVertexRes.right().value();
905                 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to get vertex by id {} . Status is {}. ", entry.getKey(), titatStatus);
906                 result = Either.right(titatStatus);
907                 break;
908             } else {
909                 vertices.put(entry.getKey(), getVertexRes.left().value());
910             }
911         }
912         if (result == null) {
913             result = Either.left(vertices);
914         }
915         return result;
916     }
917
918     /**
919      * Creates edge between "from" and "to" vertices with specified label and properties extracted from received edge
920      * 
921      * @param from
922      * @param to
923      * @param label
924      * @param edgeToCopy
925      * @return
926      */
927     public TitanOperationStatus createEdge(Vertex from, Vertex to, EdgeLabelEnum label, Edge edgeToCopy) {
928         return createEdge(from, to, label, getEdgeProperties(edgeToCopy));
929     }
930
931     public TitanOperationStatus replaceEdgeLabel(Vertex fromVertex, Vertex toVertex, Edge prevEdge, EdgeLabelEnum prevLabel, EdgeLabelEnum newLabel) {
932         CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "Going to replace edge with label {} to {} between vertices {} and {}", prevLabel, newLabel, fromVertex!=null ? fromVertex.property(GraphPropertyEnum.UNIQUE_ID.getProperty()) : "NULL",
933                 toVertex!=null ? toVertex.property(GraphPropertyEnum.UNIQUE_ID.getProperty()) : "NULL");
934
935         TitanOperationStatus result = createEdge(fromVertex, toVertex, newLabel, prevEdge);
936         if (result == TitanOperationStatus.OK) {
937             prevEdge.remove();
938         }
939         return result;
940     }
941
942     /**
943      * Replaces previous label of edge with new label
944      * 
945      * @param fromVertex
946      * @param toVertex
947      * @param prevLabel
948      * @param newLabel
949      * @return
950      */
951     public TitanOperationStatus replaceEdgeLabel(Vertex fromVertex, Vertex toVertex, EdgeLabelEnum prevLabel, EdgeLabelEnum newLabel) {
952
953         TitanOperationStatus result = null;
954         Iterator<Edge> prevEdgeIter = toVertex.edges(Direction.IN, prevLabel.name());
955         if (prevEdgeIter == null || !prevEdgeIter.hasNext()) {
956             CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to replace edge with label {} to {} between vertices {} and {}", prevLabel, newLabel, fromVertex.property(GraphPropertyEnum.UNIQUE_ID.getProperty()),
957                     toVertex.property(GraphPropertyEnum.UNIQUE_ID.getProperty()));
958             result = TitanOperationStatus.NOT_FOUND;
959         }
960         if (result == null) {
961             result = replaceEdgeLabel(fromVertex, toVertex, prevEdgeIter.next(), prevLabel, newLabel);
962         }
963         return result;
964     }
965
966     /**
967      * Updates metadata properties of vertex on graph. Json metadata property of the vertex will be updated with received properties too.
968      * 
969      * 
970      * @param vertex
971      * @param properties
972      * @return
973      */
974     public TitanOperationStatus updateVertexMetadataPropertiesWithJson(Vertex vertex, Map<GraphPropertyEnum, Object> properties) {
975         try {
976             if (!MapUtils.isEmpty(properties)) {
977                 String jsonMetadataStr = (String) vertex.property(GraphPropertyEnum.METADATA.getProperty()).value();
978                 Map<String, Object> jsonMetadataMap = JsonParserUtils.toMap(jsonMetadataStr);
979                 for (Map.Entry<GraphPropertyEnum, Object> property : properties.entrySet()) {
980                     vertex.property(property.getKey().getProperty(), property.getValue());
981                     jsonMetadataMap.put(property.getKey().getProperty(), property.getValue());
982                 }
983                 vertex.property(GraphPropertyEnum.METADATA.getProperty(), JsonParserUtils.toJson(jsonMetadataMap));
984             }
985         } catch (Exception e) {
986             CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occurred during update vertex metadata properties with json{}. {}", vertex.property(GraphPropertyEnum.UNIQUE_ID.getProperty()), e.getMessage());
987             return TitanGraphClient.handleTitanException(e);
988         }
989         return TitanOperationStatus.OK;
990     }
991
992     public TitanOperationStatus disassociateAndDeleteLast(GraphVertex vertex, Direction direction, EdgeLabelEnum label) {
993         try {
994             Iterator<Edge> edges = vertex.getVertex().edges(direction, label.name());
995
996             while (edges.hasNext()) {
997                 Edge edge = edges.next();
998                 Vertex secondVertex;
999                 Direction reverseDirection;
1000                 if (direction == Direction.IN) {
1001                     secondVertex = edge.outVertex();
1002                     reverseDirection = Direction.OUT;
1003                 } else {
1004                     secondVertex = edge.inVertex();
1005                     reverseDirection = Direction.IN;
1006                 }
1007                 edge.remove();
1008                 CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "Edge  {} with direction {} was removed from {}", label.name(), direction, vertex.getVertex());
1009
1010                 Iterator<Edge> restOfEdges = secondVertex.edges(reverseDirection, label.name());
1011                 if (!restOfEdges.hasNext()) {
1012                     secondVertex.remove();
1013                     CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "This was last edge . Vertex  {} was removed ", vertex.getUniqueId());
1014                 }
1015             }
1016         } catch (Exception e) {
1017             CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occured during deleting an edge with the label {} direction {} from vertex {}. {}", label.name(), direction, vertex.getUniqueId(), e);
1018             return TitanGraphClient.handleTitanException(e);
1019         }
1020         return TitanOperationStatus.OK;
1021     }
1022
1023     public Object getProperty(TitanVertex vertex, String key) {
1024         PropertyKey propertyKey = titanClient.getGraph().left().value().getPropertyKey(key);
1025         return vertex.valueOrNull(propertyKey);
1026     }
1027
1028     public Object getProperty(Edge edge, EdgePropertyEnum key) {
1029         Object value = null;
1030         try {
1031             Property<Object> property = edge.property(key.getProperty());
1032             if (property != null) {
1033                 value = property.orElse(null);
1034                 if (value != null && key == EdgePropertyEnum.INSTANCES) {
1035                     return JsonParserUtils.toList((String) value, String.class);
1036                 }
1037                 return value;
1038             }
1039         } catch (Exception e) {
1040
1041         }
1042         return value;
1043     }
1044
1045     /**
1046      * 
1047      * @param vertexA
1048      * @param vertexB
1049      * @param label
1050      * @param direction
1051      * @return
1052      */
1053     public TitanOperationStatus moveEdge(GraphVertex vertexA, GraphVertex vertexB, EdgeLabelEnum label, Direction direction) {
1054         TitanOperationStatus result = deleteEdgeByDirection(vertexA, direction, label);
1055         if (result != TitanOperationStatus.OK) {
1056             logger.error("Failed to diassociate {} from element {}. error {} ", label, vertexA.getUniqueId(), result);
1057             return result;
1058         }
1059         TitanOperationStatus createRelation;
1060         if (direction == Direction.IN) {
1061             createRelation = createEdge(vertexB, vertexA, label, null);
1062         } else {
1063             createRelation = createEdge(vertexA, vertexB, label, null);
1064         }
1065         if (createRelation != TitanOperationStatus.OK) {
1066             return createRelation;
1067         }
1068         return TitanOperationStatus.OK;
1069     }
1070
1071     public Either<Edge, TitanOperationStatus> getBelongingEdgeByCriteria(String parentId, EdgeLabelEnum label, Map<GraphPropertyEnum, Object> properties) {
1072         Either<GraphVertex, TitanOperationStatus> getVertexRes = getVertexById(parentId, JsonParseFlagEnum.NoParse);
1073         if (getVertexRes.isRight()) {
1074             return Either.right(getVertexRes.right().value());
1075         }
1076         return getBelongingEdgeByCriteria(getVertexRes.left().value(), label, properties);
1077     }
1078 }