2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
20 package org.openecomp.sdc.be.dao.jsongraph;
22 import static org.apache.commons.collections.CollectionUtils.isEmpty;
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;
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;
64 public class JanusGraphDao {
66 private static Logger logger = Logger.getLogger(JanusGraphDao.class.getName());
67 JanusGraphClient janusGraphClient;
69 public JanusGraphDao(@Qualifier("janusgraph-client") JanusGraphClient janusGraphClient) {
70 this.janusGraphClient = janusGraphClient;
71 logger.info("** JanusGraphDao created");
74 public JanusGraphOperationStatus commit() {
75 logger.debug("#commit - The operation succeeded. Doing commit...");
76 return janusGraphClient.commit();
79 public JanusGraphOperationStatus rollback() {
80 logger.debug("#rollback - The operation failed. Doing rollback...");
81 return janusGraphClient.rollback();
84 public Either<JanusGraph, JanusGraphOperationStatus> getGraph() {
85 return janusGraphClient.getGraph();
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();
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) {
104 .error(EcompLoggerErrorCode.DATA_ERROR, "JanusGraphDao", "Failed to create Node for ID '{}'", (Object) graphVertex.getUniqueId(),
106 return Either.right(JanusGraphClient.handleJanusGraphException(e));
109 logger.debug("Failed to create vertex for ID '{}' {}", graphVertex.getUniqueId(), graph.right().value());
110 return Either.right(graph.right().value());
120 public Either<GraphVertex, JanusGraphOperationStatus> getVertexByPropertyAndLabel(GraphPropertyEnum name, Object value, VertexTypeEnum label) {
121 return getVertexByPropertyAndLabel(name, value, label, JsonParseFlagEnum.ParseAll);
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));
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);
136 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
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()) {
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);
160 if (logger.isDebugEnabled()) {
161 logger.debug("No vertex in graph for key = {} and value = {} label = {}", name, value, label);
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);
168 return Either.right(JanusGraphClient.handleJanusGraphException(e));
171 if (logger.isDebugEnabled()) {
172 logger.debug("No vertex in graph for key ={} and value = {} label = {} error :{}", name, value, label, graph.right().value());
174 return Either.right(graph.right().value());
182 public Either<GraphVertex, JanusGraphOperationStatus> getVertexById(String id) {
183 return getVertexById(id, JsonParseFlagEnum.ParseAll);
191 public Either<GraphVertex, JanusGraphOperationStatus> getVertexById(String id, JsonParseFlagEnum parseFlag) {
192 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
194 if (logger.isDebugEnabled()) {
195 logger.debug("No vertex in graph for id = {} ", id);
197 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
199 if (graph.isLeft()) {
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);
210 if (logger.isDebugEnabled()) {
211 logger.debug("No vertex in graph for id = {}", id);
213 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
215 } catch (Exception e) {
216 if (logger.isDebugEnabled()) {
217 logger.debug("Failed to get vertex in graph for id {} ", id);
219 return Either.right(JanusGraphClient.handleJanusGraphException(e));
222 if (logger.isDebugEnabled()) {
223 logger.debug("No vertex in graph for id {} error : {}", id, graph.right().value());
225 return Either.right(graph.right().value());
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());
237 vertex.property(GraphPropertyEnum.LABEL.getProperty(), graphVertex.getLabel().getName());
238 Map<String, ? extends ToscaDataDefinition> json = graphVertex.getJson();
240 String jsonStr = JsonParserUtils.toJson(json);
241 vertex.property(GraphPropertyEnum.JSON.getProperty(), jsonStr);
243 Map<String, Object> jsonMetadata = graphVertex.getMetadataJson();
244 if (jsonMetadata != null) {
245 String jsonMetadataStr = JsonParserUtils.toJson(jsonMetadata);
246 vertex.property(GraphPropertyEnum.METADATA.getProperty(), jsonMetadataStr);
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());
258 private GraphVertex createAndFill(JanusGraphVertex vertex, JsonParseFlagEnum parseFlag) {
259 GraphVertex graphVertex = new GraphVertex();
260 graphVertex.setVertex(vertex);
261 parseVertexProperties(graphVertex, parseFlag);
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();
273 graphVertex.setUniqueId((String) entry.getValue());
276 graphVertex.setLabel(VertexTypeEnum.getByName((String) entry.getValue()));
279 String type = (String) entry.getValue();
281 graphVertex.setType(ComponentTypeEnum.valueOf(type));
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);
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);
299 graphVertex.addMetadataProperty(key, entry.getValue());
305 public JanusGraphOperationStatus createEdge(GraphVertex from, GraphVertex to, EdgeLabelEnum label, Map<EdgePropertyEnum, Object> properties) {
306 return createEdge(from.getVertex(), to.getVertex(), label, properties);
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);
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;
321 Edge edge = from.addEdge(label.name(), to);
322 JanusGraphOperationStatus status;
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;
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);
345 // add print to properties that can't be converted by enum
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);
363 result.put(valueOf, value);
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];
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;
382 propertyKeyValues[i++] = entry.getValue();
385 ElementHelper.attachProperties(element, propertyKeyValues);
389 public Either<List<GraphVertex>, JanusGraphOperationStatus> getByCriteria(VertexTypeEnum type, Map<GraphPropertyEnum, Object> props) {
390 return getByCriteria(type, props, JsonParseFlagEnum.ParseAll);
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()) {
398 JanusGraph tGraph = graph.left().value();
399 JanusGraphQuery<? extends JanusGraphQuery> query = tGraph.query();
401 query = query.has(GraphPropertyEnum.LABEL.getProperty(), type.getName());
403 if (props != null && !props.isEmpty()) {
404 for (Map.Entry<GraphPropertyEnum, Object> entry : props.entrySet()) {
405 query = query.has(entry.getKey().getProperty(), entry.getValue());
408 Iterable<JanusGraphVertex> vertices = query.vertices();
409 if (vertices == null) {
410 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
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);
420 if (logger.isDebugEnabled()) {
422 .debug("Number of fetced nodes in graph for criteria : from type = {} and properties = {} is {}", type, props, result.size());
424 if (result.size() == 0) {
425 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
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);
432 return Either.right(JanusGraphClient.handleJanusGraphException(e));
435 if (logger.isDebugEnabled()) {
436 logger.debug("Failed get by criteria for type ={} and properties = {} error : {}", type, props, graph.right().value());
438 return Either.right(graph.right().value());
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);
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()) {
456 JanusGraph tGraph = graph.left().value();
457 JanusGraphQuery<? extends JanusGraphQuery> query = tGraph.query();
459 query = query.has(GraphPropertyEnum.LABEL.getProperty(), type.getName());
461 if (hasProps != null && !hasProps.isEmpty()) {
462 for (Map.Entry<GraphPropertyEnum, Object> entry : hasProps.entrySet()) {
463 query = query.has(entry.getKey().getProperty(), entry.getValue());
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);
471 query = query.hasNot(entry.getKey().getProperty(), entry.getValue());
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);
482 Iterable<JanusGraphVertex> vertices = query.vertices();
483 if (vertices == null || !vertices.iterator().hasNext()) {
484 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
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,
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);
497 return Either.right(JanusGraphClient.handleJanusGraphException(e));
500 if (logger.isDebugEnabled()) {
501 logger.debug("Failed to get by criteria for type '{}' and properties '{}'. Error : '{}'", type, hasProps, graph.right().value());
503 return Either.right(graph.right().value());
507 public Either<Iterator<Vertex>, JanusGraphOperationStatus> getCatalogOrArchiveVerticies(boolean isCatalog) {
508 Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphClient.getGraph();
509 if (graph.isLeft()) {
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);
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);
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);
530 return Either.right(JanusGraphClient.handleJanusGraphException(e));
533 if (logger.isDebugEnabled()) {
534 logger.debug("Failed get by criteria : ", graph.right().value());
536 return Either.right(graph.right().value());
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);
548 * @param parentVertex
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());
559 return Either.left(childrenVertecies.left().value().get(0));
563 * @param parentVertex
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());
573 return Either.left(childrenVertecies.left().value().get(0));
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());
582 if (isEmpty(childrenVertecies.left().value())) {
583 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
585 return Either.left(childrenVertecies.left().value().get(0));
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());
593 if (isEmpty(childrenVertecies.left().value())) {
594 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
596 return Either.left(childrenVertecies.left().value().get(0));
600 * @param parentVertex
605 public Either<List<GraphVertex>, JanusGraphOperationStatus> getChildrenVertices(GraphVertex parentVertex, EdgeLabelEnum edgeLabel,
606 JsonParseFlagEnum parseFlag) {
607 return getAdjacentVertices(parentVertex, edgeLabel, parseFlag, Direction.OUT);
610 public Either<List<GraphVertex>, JanusGraphOperationStatus> getParentVertices(GraphVertex parentVertex, EdgeLabelEnum edgeLabel,
611 JsonParseFlagEnum parseFlag) {
612 return getAdjacentVertices(parentVertex, edgeLabel, parseFlag, Direction.IN);
615 public Either<List<Vertex>, JanusGraphOperationStatus> getParentVertices(Vertex parentVertex, EdgeLabelEnum edgeLabel,
616 JsonParseFlagEnum parseFlag) {
617 return getAdjacentVertices(parentVertex, edgeLabel, parseFlag, Direction.IN);
620 private Either<List<Vertex>, JanusGraphOperationStatus> getAdjacentVertices(Vertex parentVertex, EdgeLabelEnum edgeLabel,
621 JsonParseFlagEnum parseFlag, Direction direction) {
622 List<Vertex> list = new ArrayList<>();
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());
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();
637 vertex = (JanusGraphVertex) edge.inVertex();
639 // GraphVertex graphVertex = createAndFill(vertex, parseFlag);
643 if (list.isEmpty()) {
644 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
646 } catch (Exception e) {
647 logger.error("Failed to perform graph operation ", e);
648 Either.right(JanusGraphClient.handleJanusGraphException(e));
650 return Either.left(list);
654 * @param parentVertex
659 public Either<List<Vertex>, JanusGraphOperationStatus> getChildrenVertices(Vertex parentVertex, EdgeLabelEnum edgeLabel,
660 JsonParseFlagEnum parseFlag) {
661 return getAdjacentVertices(parentVertex, edgeLabel, parseFlag, Direction.OUT);
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,
669 if (adjacentVerticies.isRight()) {
670 return Either.right(adjacentVerticies.right().value());
672 adjacentVerticies.left().value().stream().forEach(vertex -> {
673 list.add(createAndFill((JanusGraphVertex) vertex, parseFlag));
675 return Either.left(list);
679 * Searches Edge by received label and criteria
684 * @return found edge or JanusGraphOperationStatus
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";
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());
698 Iterable<JanusGraphEdge> edges = query.edges();
700 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, notFoundMsg);
701 result = Either.right(JanusGraphOperationStatus.NOT_FOUND);
703 Iterator<JanusGraphEdge> eIter = edges.iterator();
704 if (eIter.hasNext()) {
705 matchingEdge = eIter.next();
707 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, notFoundMsg);
708 result = Either.right(JanusGraphOperationStatus.NOT_FOUND);
711 if (result == null) {
712 result = Either.left(matchingEdge);
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));
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";
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);
739 if (result == null) {
741 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, notFoundMsg);
742 result = Either.right(JanusGraphOperationStatus.NOT_FOUND);
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));
753 * Deletes Edge by received label and criteria
760 public Either<Edge, JanusGraphOperationStatus> deleteBelongingEdgeByCriteria(GraphVertex vertex, EdgeLabelEnum label,
761 Map<GraphPropertyEnum, Object> properties) {
762 Either<Edge, JanusGraphOperationStatus> result = null;
764 result = getBelongingEdgeByCriteria(vertex, label, properties);
765 if (result.isLeft()) {
766 Edge edge = result.left().value();
768 .addRecordToLog(logger, LogLevelEnum.TRACE, "Going to delete an edge with the label {} belonging to the vertex {} ", label.name(),
769 vertex.getUniqueId());
771 result = Either.left(edge);
774 .addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to find an edge with the label {} belonging to the vertex {} ", label.name(),
775 vertex.getUniqueId());
777 } catch (Exception e) {
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));
786 @SuppressWarnings("unchecked")
788 * Deletes an edge between vertices fromVertex and toVertex according to received label
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);
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);
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;
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;
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());
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());
834 } catch (Exception e1) {
835 logger.debug("failed to remove problematic edge. {}", e1);
839 } catch (Exception e2) {
840 logger.debug("failed to remove problematic vertex . {}", e2);
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);
849 result = Either.left(edge);
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);
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,
864 return Either.right(JanusGraphClient.handleJanusGraphException(e));
869 public JanusGraphOperationStatus deleteEdgeByDirection(GraphVertex fromVertex, Direction direction, EdgeLabelEnum label) {
871 Iterator<Edge> edges = fromVertex.getVertex().edges(direction, label.name());
872 while (edges.hasNext()) {
873 Edge edge = edges.next();
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);
880 return JanusGraphOperationStatus.OK;
884 * Updates vertex properties. Note that graphVertex argument should contain updated data
889 public Either<GraphVertex, JanusGraphOperationStatus> updateVertex(GraphVertex graphVertex) {
890 CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "Going to update metadata of vertex with uniqueId {}. ", graphVertex.getUniqueId());
892 graphVertex.updateMetadataJsonWithCurrentMetadataProperties();
893 setVertexProperties(graphVertex.getVertex(), graphVertex);
894 } catch (Exception e) {
896 .addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to update metadata of vertex with uniqueId {}. ", graphVertex.getUniqueId(), e);
897 return Either.right(JanusGraphClient.handleJanusGraphException(e));
899 return Either.left(graphVertex);
903 * Fetches vertices by uniqueId according to received parse flag
905 * @param verticesToGet
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());
921 if (getVertexRes == null) {
922 titatStatus = JanusGraphOperationStatus.ILLEGAL_ARGUMENT;
924 .addRecordToLog(logger, LogLevelEnum.DEBUG, "Invalid vertex type label {} has been received. ", entry.getValue().getKey(),
926 return Either.right(titatStatus);
928 if (getVertexRes.isRight()) {
929 titatStatus = getVertexRes.right().value();
931 .addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to get vertex by id {} . Status is {}. ", entry.getKey(), titatStatus);
932 result = Either.right(titatStatus);
935 vertices.put(entry.getKey(), getVertexRes.left().value());
938 if (result == null) {
939 result = Either.left(vertices);
945 * Creates edge between "from" and "to" vertices with specified label and properties extracted from received edge
953 public JanusGraphOperationStatus createEdge(Vertex from, Vertex to, EdgeLabelEnum label, Edge edgeToCopy) {
954 return createEdge(from, to, label, getEdgeProperties(edgeToCopy));
957 public JanusGraphOperationStatus replaceEdgeLabel(Vertex fromVertex, Vertex toVertex, Edge prevEdge, EdgeLabelEnum prevLabel,
958 EdgeLabelEnum newLabel) {
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) {
971 * Replaces previous label of edge with new label
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()) {
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;
988 return replaceEdgeLabel(fromVertex, toVertex, prevEdgeIter.next(), prevLabel, newLabel);
993 * Updates metadata properties of vertex on graph. Json metadata property of the vertex will be updated with received properties too.
999 public JanusGraphOperationStatus updateVertexMetadataPropertiesWithJson(Vertex vertex, Map<GraphPropertyEnum, Object> properties) {
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());
1008 vertex.property(GraphPropertyEnum.METADATA.getProperty(), JsonParserUtils.toJson(jsonMetadataMap));
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);
1015 return JanusGraphOperationStatus.OK;
1018 public JanusGraphOperationStatus disassociateAndDeleteLast(GraphVertex vertex, Direction direction, EdgeLabelEnum label) {
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;
1029 secondVertex = edge.inVertex();
1030 reverseDirection = Direction.IN;
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());
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);
1047 return JanusGraphOperationStatus.OK;
1050 public Object getProperty(JanusGraphVertex vertex, String key) {
1051 PropertyKey propertyKey = janusGraphClient.getGraph().left().value().getPropertyKey(key);
1052 return vertex.valueOrNull(propertyKey);
1055 public Object getProperty(Edge edge, EdgePropertyEnum key) {
1056 Object value = null;
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);
1066 } catch (Exception e) {
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);
1084 JanusGraphOperationStatus createRelation;
1085 if (direction == Direction.IN) {
1086 createRelation = createEdge(vertexB, vertexA, label, null);
1088 createRelation = createEdge(vertexA, vertexB, label, null);
1090 if (createRelation != JanusGraphOperationStatus.OK) {
1091 return createRelation;
1093 return JanusGraphOperationStatus.OK;
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());
1102 return getBelongingEdgeByCriteria(getVertexRes.left().value(), label, properties);