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