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