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=========================================================
21 package org.openecomp.sdc.be.dao.jsongraph;
23 import com.thinkaurelius.titan.core.*;
24 import fj.data.Either;
25 import org.apache.commons.collections.MapUtils;
26 import org.apache.commons.lang3.tuple.ImmutablePair;
27 import org.apache.tinkerpop.gremlin.structure.*;
28 import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
29 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
30 import org.openecomp.sdc.be.dao.jsongraph.types.EdgePropertyEnum;
31 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
32 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
33 import org.openecomp.sdc.be.dao.jsongraph.utils.JsonParserUtils;
34 import org.openecomp.sdc.be.dao.titan.TitanGraphClient;
35 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
36 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
37 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
38 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
39 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
40 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
41 import org.openecomp.sdc.common.log.wrappers.Logger;
42 import org.springframework.beans.factory.annotation.Qualifier;
43 import org.springframework.stereotype.Component;
45 import java.io.IOException;
47 import java.util.Map.Entry;
49 import static org.apache.commons.collections.CollectionUtils.isEmpty;
52 public class TitanDao {
53 TitanGraphClient titanClient;
55 private static Logger logger = Logger.getLogger(TitanDao.class.getName());
57 public TitanDao(@Qualifier("titan-client") TitanGraphClient titanClient) {
58 this.titanClient = titanClient;
59 logger.info("** TitanDao created");
62 public TitanOperationStatus commit() {
63 logger.debug("#commit - The operation succeeded. Doing commit...");
64 return titanClient.commit();
67 public TitanOperationStatus rollback() {
68 logger.debug("#rollback - The operation failed. Doing rollback...");
69 return titanClient.rollback();
72 public Either<TitanGraph, TitanOperationStatus> getGraph() {
73 return titanClient.getGraph();
81 public Either<GraphVertex, TitanOperationStatus> createVertex(GraphVertex graphVertex) {
82 logger.trace("try to create vertex for ID [{}]", graphVertex.getUniqueId());
83 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
86 TitanGraph tGraph = graph.left().value();
88 TitanVertex vertex = tGraph.addVertex();
90 setVertexProperties(vertex, graphVertex);
92 graphVertex.setVertex(vertex);
94 return Either.left(graphVertex);
96 } catch (Exception e) {
97 logger.debug("Failed to create Node for ID [{}]", graphVertex.getUniqueId(), e);
98 return Either.right(TitanGraphClient.handleTitanException(e));
101 logger.debug("Failed to create vertex for ID [{}] {}", graphVertex.getUniqueId(), graph.right().value());
102 return Either.right(graph.right().value());
113 public Either<GraphVertex, TitanOperationStatus> getVertexByPropertyAndLabel(GraphPropertyEnum name, Object value, VertexTypeEnum label) {
114 return getVertexByPropertyAndLabel(name, value, label, JsonParseFlagEnum.ParseAll);
117 public Either<GraphVertex, TitanOperationStatus> getVertexByLabel(VertexTypeEnum label) {
118 return titanClient.getGraph().left().map(graph -> graph.query().has(GraphPropertyEnum.LABEL.getProperty(), label.getName()).vertices()).left().bind(titanVertices -> getFirstFoundVertex(JsonParseFlagEnum.NoParse, titanVertices));
121 private Either<GraphVertex, TitanOperationStatus> getFirstFoundVertex(JsonParseFlagEnum parseFlag, Iterable<TitanVertex> vertices) {
122 Iterator<TitanVertex> iterator = vertices.iterator();
123 if (iterator.hasNext()) {
124 TitanVertex vertex = iterator.next();
125 GraphVertex graphVertex = createAndFill(vertex, parseFlag);
127 return Either.left(graphVertex);
129 return Either.right(TitanOperationStatus.NOT_FOUND);
140 public Either<GraphVertex, TitanOperationStatus> getVertexByPropertyAndLabel(GraphPropertyEnum name, Object value, VertexTypeEnum label, JsonParseFlagEnum parseFlag) {
142 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
143 if (graph.isLeft()) {
145 TitanGraph tGraph = graph.left().value();
147 @SuppressWarnings("unchecked")
148 Iterable<TitanVertex> vertecies = tGraph.query().has(name.getProperty(), value).has(GraphPropertyEnum.LABEL.getProperty(), label.getName()).vertices();
150 java.util.Iterator<TitanVertex> iterator = vertecies.iterator();
151 if (iterator.hasNext()) {
152 TitanVertex vertex = iterator.next();
153 GraphVertex graphVertex = createAndFill(vertex, parseFlag);
155 return Either.left(graphVertex);
157 if (logger.isDebugEnabled()) {
158 logger.debug("No vertex in graph for key = {} and value = {} label = {}" + name, value, label);
160 return Either.right(TitanOperationStatus.NOT_FOUND);
161 } catch (Exception e) {
162 if (logger.isDebugEnabled()) {
163 logger.debug("Failed to get vertex in graph for key ={} and value = {} label = {}", name, value, label);
165 return Either.right(TitanGraphClient.handleTitanException(e));
169 if (logger.isDebugEnabled()) {
170 logger.debug("No vertex in graph for key ={} and value = {} label = {} error :{}", name, value, label, graph.right().value());
172 return Either.right(graph.right().value());
181 public Either<GraphVertex, TitanOperationStatus> getVertexById(String id) {
182 return getVertexById(id, JsonParseFlagEnum.ParseAll);
191 public Either<GraphVertex, TitanOperationStatus> getVertexById(String id, JsonParseFlagEnum parseFlag) {
193 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
195 if (logger.isDebugEnabled()) {
196 logger.debug("No vertex in graph for id = {} ", id);
198 return Either.right(TitanOperationStatus.NOT_FOUND);
200 if (graph.isLeft()) {
202 TitanGraph tGraph = graph.left().value();
204 @SuppressWarnings("unchecked")
205 Iterable<TitanVertex> vertecies = tGraph.query().has(GraphPropertyEnum.UNIQUE_ID.getProperty(), id).vertices();
207 java.util.Iterator<TitanVertex> iterator = vertecies.iterator();
208 if (iterator.hasNext()) {
209 TitanVertex vertex = iterator.next();
210 GraphVertex graphVertex = createAndFill(vertex, parseFlag);
211 return Either.left(graphVertex);
213 if (logger.isDebugEnabled()) {
214 logger.debug("No vertex in graph for id = {}", id);
216 return Either.right(TitanOperationStatus.NOT_FOUND);
218 } catch (Exception e) {
219 if (logger.isDebugEnabled()) {
220 logger.debug("Failed to get vertex in graph for id {} ", id);
222 return Either.right(TitanGraphClient.handleTitanException(e));
225 if (logger.isDebugEnabled()) {
226 logger.debug("No vertex in graph for id {} error : {}", id, graph.right().value());
228 return Either.right(graph.right().value());
232 private void setVertexProperties(TitanVertex vertex, GraphVertex graphVertex) throws IOException {
234 if (graphVertex.getMetadataProperties() != null) {
235 for (Map.Entry<GraphPropertyEnum, Object> entry : graphVertex.getMetadataProperties().entrySet()) {
236 if (entry.getValue() != null) {
237 vertex.property(entry.getKey().getProperty(), entry.getValue());
241 vertex.property(GraphPropertyEnum.LABEL.getProperty(), graphVertex.getLabel().getName());
243 Map<String, ? extends ToscaDataDefinition> json = graphVertex.getJson();
245 String jsonStr = JsonParserUtils.toJson(json);
246 vertex.property(GraphPropertyEnum.JSON.getProperty(), jsonStr);
249 Map<String, Object> jsonMetadata = graphVertex.getMetadataJson();
250 if (jsonMetadata != null) {
251 String jsonMetadataStr = JsonParserUtils.toJson(jsonMetadata);
252 vertex.property(GraphPropertyEnum.METADATA.getProperty(), jsonMetadataStr);
256 public void setVertexProperties(Vertex vertex, Map<String, Object> properties) {
257 for (Map.Entry<String, Object> entry : properties.entrySet()) {
258 if (entry.getValue() != null) {
259 vertex.property(entry.getKey(), entry.getValue());
264 private GraphVertex createAndFill(TitanVertex vertex, JsonParseFlagEnum parseFlag) {
265 GraphVertex graphVertex = new GraphVertex();
266 graphVertex.setVertex(vertex);
267 parseVertexProperties(graphVertex, parseFlag);
271 public void parseVertexProperties(GraphVertex graphVertex, JsonParseFlagEnum parseFlag) {
272 TitanVertex vertex = graphVertex.getVertex();
273 Map<GraphPropertyEnum, Object> properties = getVertexProperties(vertex);
274 VertexTypeEnum label = VertexTypeEnum.getByName((String) (properties.get(GraphPropertyEnum.LABEL)));
275 for (Map.Entry<GraphPropertyEnum, Object> entry : properties.entrySet()) {
276 GraphPropertyEnum key = entry.getKey();
279 graphVertex.setUniqueId((String) entry.getValue());
282 graphVertex.setLabel(VertexTypeEnum.getByName((String) entry.getValue()));
285 String type = (String) entry.getValue();
287 graphVertex.setType(ComponentTypeEnum.valueOf(type));
291 if (parseFlag == JsonParseFlagEnum.ParseAll || parseFlag == JsonParseFlagEnum.ParseJson) {
292 String json = (String) entry.getValue();
293 Map<String, ? extends ToscaDataDefinition> jsonObj = JsonParserUtils.toMap(json, label.getClassOfJson());
294 graphVertex.setJson(jsonObj);
298 if (parseFlag == JsonParseFlagEnum.ParseAll || parseFlag == JsonParseFlagEnum.ParseMetadata) {
299 String json = (String) entry.getValue();
300 Map<String, Object> metadatObj = JsonParserUtils.toMap(json);
301 graphVertex.setMetadataJson(metadatObj);
305 graphVertex.addMetadataProperty(key, entry.getValue());
311 public TitanOperationStatus createEdge(GraphVertex from, GraphVertex to, EdgeLabelEnum label, Map<EdgePropertyEnum, Object> properties) {
312 return createEdge(from.getVertex(), to.getVertex(), label, properties);
315 public TitanOperationStatus createEdge(Vertex from, Vertex to, EdgeLabelEnum label, Map<EdgePropertyEnum, Object> properties) {
316 if (logger.isTraceEnabled()) {
317 logger.trace("Try to connect {} with {} label {} properties {}",
318 from == null ? "NULL" : from.property(GraphPropertyEnum.UNIQUE_ID.getProperty()),
319 to == null ? "NULL" : to.property(GraphPropertyEnum.UNIQUE_ID.getProperty()), label, properties);
321 if (from == null || to == null) {
322 logger.trace("No Titan vertex for id from {} or id to {}",
323 from == null ? "NULL" : from.property(GraphPropertyEnum.UNIQUE_ID.getProperty()),
324 to == null ? "NULL" : to.property(GraphPropertyEnum.UNIQUE_ID.getProperty()));
325 return TitanOperationStatus.NOT_FOUND;
327 Edge edge = from.addEdge(label.name(), to);
328 TitanOperationStatus status;
330 setEdgeProperties(edge, properties);
331 status = TitanOperationStatus.OK;
332 } catch (IOException e) {
333 logger.debug("Failed to set properties on edge properties [{}]", properties, e);
334 status = TitanOperationStatus.GENERAL_ERROR;
339 public Map<GraphPropertyEnum, Object> getVertexProperties(Element element) {
341 Map<GraphPropertyEnum, Object> result = new HashMap<>();
343 if (element != null && element.keys() != null && element.keys().size() > 0) {
344 Map<String, Property> propertyMap = ElementHelper.propertyMap(element, element.keys().toArray(new String[element.keys().size()]));
346 for (Entry<String, Property> entry : propertyMap.entrySet()) {
347 String key = entry.getKey();
348 Object value = entry.getValue().value();
350 GraphPropertyEnum valueOf = GraphPropertyEnum.getByProperty(key);
351 if (valueOf != null) {
352 result.put(valueOf, value);
359 public Map<EdgePropertyEnum, Object> getEdgeProperties(Element element) {
361 Map<EdgePropertyEnum, Object> result = new HashMap<>();
363 if (element != null && element.keys() != null && element.keys().size() > 0) {
364 Map<String, Property> propertyMap = ElementHelper.propertyMap(element, element.keys().toArray(new String[element.keys().size()]));
366 for (Entry<String, Property> entry : propertyMap.entrySet()) {
367 String key = entry.getKey();
368 Object value = entry.getValue().value();
370 EdgePropertyEnum valueOf = EdgePropertyEnum.getByProperty(key);
371 if (valueOf != null) {
372 if (valueOf == EdgePropertyEnum.INSTANCES) {
373 List<String> list = JsonParserUtils.toList((String) value, String.class);
374 result.put(valueOf, list);
376 result.put(valueOf, value);
384 public void setEdgeProperties(Element element, Map<EdgePropertyEnum, Object> properties) throws IOException {
386 if (properties != null && !properties.isEmpty()) {
388 Object[] propertyKeyValues = new Object[properties.size() * 2];
390 for (Entry<EdgePropertyEnum, Object> entry : properties.entrySet()) {
391 propertyKeyValues[i++] = entry.getKey().getProperty();
392 Object value = entry.getValue();
393 if (entry.getKey() == EdgePropertyEnum.INSTANCES) {
394 String jsonStr = JsonParserUtils.toJson(value);
395 propertyKeyValues[i++] = jsonStr;
397 propertyKeyValues[i++] = entry.getValue();
400 ElementHelper.attachProperties(element, propertyKeyValues);
404 public Either<List<GraphVertex>, TitanOperationStatus> getByCriteria(VertexTypeEnum type, Map<GraphPropertyEnum, Object> props) {
405 return getByCriteria(type, props, JsonParseFlagEnum.ParseAll);
408 public Either<List<GraphVertex>, TitanOperationStatus> getByCriteria(VertexTypeEnum type, Map<GraphPropertyEnum, Object> props, JsonParseFlagEnum parseFlag) {
409 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
410 if (graph.isLeft()) {
412 TitanGraph tGraph = graph.left().value();
414 TitanGraphQuery<? extends TitanGraphQuery> query = tGraph.query();
416 query = query.has(GraphPropertyEnum.LABEL.getProperty(), type.getName());
419 if (props != null && !props.isEmpty()) {
420 for (Map.Entry<GraphPropertyEnum, Object> entry : props.entrySet()) {
421 query = query.has(entry.getKey().getProperty(), entry.getValue());
424 Iterable<TitanVertex> vertices = query.vertices();
425 if (vertices == null) {
426 return Either.right(TitanOperationStatus.NOT_FOUND);
429 Iterator<TitanVertex> iterator = vertices.iterator();
430 List<GraphVertex> result = new ArrayList<>();
432 while (iterator.hasNext()) {
433 TitanVertex vertex = iterator.next();
435 Map<GraphPropertyEnum, Object> newProp = getVertexProperties(vertex);
436 GraphVertex graphVertex = createAndFill(vertex, parseFlag);
438 result.add(graphVertex);
440 if (logger.isDebugEnabled()) {
441 logger.debug("Number of fetced nodes in graph for criteria : from type = {} and properties = {} is {}", type, props, result.size());
443 if (result.size() == 0) {
444 return Either.right(TitanOperationStatus.NOT_FOUND);
447 return Either.left(result);
448 } catch (Exception e) {
449 if (logger.isDebugEnabled()) {
450 logger.debug("Failed get by criteria for type = {} and properties = {}", type, props, e);
452 return Either.right(TitanGraphClient.handleTitanException(e));
456 if (logger.isDebugEnabled()) {
457 logger.debug("Failed get by criteria for type ={} and properties = {} error : {}", type, props, graph.right().value());
459 return Either.right(graph.right().value());
463 public Either<List<GraphVertex>, TitanOperationStatus> getByCriteria(VertexTypeEnum type, Map<GraphPropertyEnum, Object> props, Map<GraphPropertyEnum, Object> hasNotProps, JsonParseFlagEnum parseFlag) {
464 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
465 if (graph.isLeft()) {
467 TitanGraph tGraph = graph.left().value();
469 TitanGraphQuery<? extends TitanGraphQuery> query = tGraph.query();
471 query = query.has(GraphPropertyEnum.LABEL.getProperty(), type.getName());
474 if (props != null && !props.isEmpty()) {
475 for (Map.Entry<GraphPropertyEnum, Object> entry : props.entrySet()) {
476 query = query.has(entry.getKey().getProperty(), entry.getValue());
479 if (hasNotProps != null && !hasNotProps.isEmpty()) {
480 for (Map.Entry<GraphPropertyEnum, Object> entry : hasNotProps.entrySet()) {
481 if (entry.getValue() instanceof List) {
482 buildMultipleNegateQueryFromList(entry, query);
484 query = query.hasNot(entry.getKey().getProperty(), entry.getValue());
488 Iterable<TitanVertex> vertices = query.vertices();
489 if (vertices == null) {
490 return Either.right(TitanOperationStatus.NOT_FOUND);
493 Iterator<TitanVertex> iterator = vertices.iterator();
494 List<GraphVertex> result = new ArrayList<>();
496 while (iterator.hasNext()) {
497 TitanVertex vertex = iterator.next();
499 Map<GraphPropertyEnum, Object> newProp = getVertexProperties(vertex);
500 GraphVertex graphVertex = createAndFill(vertex, parseFlag);
502 result.add(graphVertex);
504 if (logger.isDebugEnabled()) {
505 logger.debug("Number of fetced nodes in graph for criteria : from type = {} and properties = {} is {}", type, props, result.size());
507 if (result.size() == 0) {
508 return Either.right(TitanOperationStatus.NOT_FOUND);
511 return Either.left(result);
512 } catch (Exception e) {
513 if (logger.isDebugEnabled()) {
514 logger.debug("Failed get by criteria for type = {} and properties = {}", type, props, e);
516 return Either.right(TitanGraphClient.handleTitanException(e));
520 if (logger.isDebugEnabled()) {
521 logger.debug("Failed get by criteria for type ={} and properties = {} error : {}", type, props, graph.right().value());
523 return Either.right(graph.right().value());
527 public Either<Iterator<Vertex>, TitanOperationStatus> getCatalogOrArchiveVerticies(boolean isCatalog) {
528 Either<TitanGraph, TitanOperationStatus> graph = titanClient.getGraph();
529 if (graph.isLeft()) {
531 TitanGraph tGraph = graph.left().value();
533 String name = isCatalog ? VertexTypeEnum.CATALOG_ROOT.getName() : VertexTypeEnum.ARCHIVE_ROOT.getName();
534 Iterable<TitanVertex> vCatalogIter = tGraph.query().has(GraphPropertyEnum.LABEL.getProperty(), name).vertices();
535 if (vCatalogIter == null) {
536 logger.debug("Failed to fetch catalog vertex");
537 return Either.right(TitanOperationStatus.GENERAL_ERROR);
539 TitanVertex catalogV = vCatalogIter.iterator().next();
540 if (catalogV == null) {
541 logger.debug("Failed to fetch catalog vertex");
542 return Either.right(TitanOperationStatus.GENERAL_ERROR);
544 String edgeLabel = isCatalog ? EdgeLabelEnum.CATALOG_ELEMENT.name() : EdgeLabelEnum.ARCHIVE_ELEMENT.name();
545 Iterator<Vertex> vertices = catalogV.vertices(Direction.OUT, edgeLabel);
547 return Either.left(vertices);
548 } catch (Exception e) {
549 if (logger.isDebugEnabled()) {
550 logger.debug("Failed get by criteria: ", e);
552 return Either.right(TitanGraphClient.handleTitanException(e));
556 if (logger.isDebugEnabled()) {
557 logger.debug("Failed get by criteria : ", graph.right().value());
559 return Either.right(graph.right().value());
563 private void buildMultipleNegateQueryFromList(Map.Entry<GraphPropertyEnum, Object> entry, TitanGraphQuery query) {
564 List<Object> negateList = (List<Object>) entry.getValue();
565 for (Object listItem : negateList) {
566 query.hasNot(entry.getKey().getProperty(), listItem);
572 * @param parentVertex
577 public Either<GraphVertex, TitanOperationStatus> getChildVertex(GraphVertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
578 Either<List<GraphVertex>, TitanOperationStatus> childrenVertecies = getChildrenVertecies(parentVertex, edgeLabel, parseFlag);
579 if (childrenVertecies.isRight()) {
580 return Either.right(childrenVertecies.right().value());
582 return Either.left(childrenVertecies.left().value().get(0));
587 * @param parentVertex
592 public Either<Vertex, TitanOperationStatus> getChildVertex(Vertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
593 Either<List<Vertex>, TitanOperationStatus> childrenVertecies = getChildrenVertecies(parentVertex, edgeLabel, parseFlag);
594 if (childrenVertecies.isRight()) {
595 return Either.right(childrenVertecies.right().value());
597 return Either.left(childrenVertecies.left().value().get(0));
600 public Either<GraphVertex, TitanOperationStatus> getParentVertex(GraphVertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
601 Either<List<GraphVertex>, TitanOperationStatus> childrenVertecies = getParentVertecies(parentVertex, edgeLabel, parseFlag);
602 if (childrenVertecies.isRight()) {
603 return Either.right(childrenVertecies.right().value());
605 if (isEmpty(childrenVertecies.left().value())){
606 return Either.right(TitanOperationStatus.NOT_FOUND);
608 return Either.left(childrenVertecies.left().value().get(0));
611 public Either<Vertex, TitanOperationStatus> getParentVertex(Vertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
612 Either<List<Vertex>, TitanOperationStatus> childrenVertecies = getParentVertecies(parentVertex, edgeLabel, parseFlag);
613 if (childrenVertecies.isRight() ) {
614 return Either.right(childrenVertecies.right().value());
616 if (isEmpty(childrenVertecies.left().value())){
617 return Either.right(TitanOperationStatus.NOT_FOUND);
619 return Either.left(childrenVertecies.left().value().get(0));
624 * @param parentVertex
629 public Either<List<GraphVertex>, TitanOperationStatus> getChildrenVertecies(GraphVertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
630 return getAdjacentVerticies(parentVertex, edgeLabel, parseFlag, Direction.OUT);
633 public Either<List<GraphVertex>, TitanOperationStatus> getParentVertecies(GraphVertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
634 return getAdjacentVerticies(parentVertex, edgeLabel, parseFlag, Direction.IN);
637 public Either<List<Vertex>, TitanOperationStatus> getParentVertecies(Vertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
638 return getAdjacentVerticies(parentVertex, edgeLabel, parseFlag, Direction.IN);
641 private Either<List<Vertex>, TitanOperationStatus> getAdjacentVerticies(Vertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag, Direction direction) {
642 List<Vertex> list = new ArrayList<>();
644 Either<TitanGraph, TitanOperationStatus> graphRes = titanClient.getGraph();
645 if (graphRes.isRight()) {
646 logger.error("Failed to retrieve graph. status is {}", graphRes);
647 return Either.right(graphRes.right().value());
649 Iterator<Edge> edgesCreatorIterator = parentVertex.edges(direction, edgeLabel.name());
650 if (edgesCreatorIterator != null) {
651 while (edgesCreatorIterator.hasNext()) {
652 Edge edge = edgesCreatorIterator.next();
654 if (direction == Direction.IN) {
655 vertex = (TitanVertex) edge.outVertex();
657 vertex = (TitanVertex) edge.inVertex();
659 // GraphVertex graphVertex = createAndFill(vertex, parseFlag);
664 if (list.isEmpty()) {
665 return Either.right(TitanOperationStatus.NOT_FOUND);
667 } catch (Exception e) {
668 logger.error("Failed to perform graph operation ", e);
669 Either.right(TitanGraphClient.handleTitanException(e));
672 return Either.left(list);
677 * @param parentVertex
682 public Either<List<Vertex>, TitanOperationStatus> getChildrenVertecies(Vertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag) {
683 return getAdjacentVerticies(parentVertex, edgeLabel, parseFlag, Direction.OUT);
686 private Either<List<GraphVertex>, TitanOperationStatus> getAdjacentVerticies(GraphVertex parentVertex, EdgeLabelEnum edgeLabel, JsonParseFlagEnum parseFlag, Direction direction) {
687 List<GraphVertex> list = new ArrayList<>();
689 Either<List<Vertex>, TitanOperationStatus> adjacentVerticies = getAdjacentVerticies(parentVertex.getVertex(), edgeLabel, parseFlag, direction);
690 if (adjacentVerticies.isRight()) {
691 return Either.right(adjacentVerticies.right().value());
693 adjacentVerticies.left().value().stream().forEach(vertex -> {
694 list.add(createAndFill((TitanVertex) vertex, parseFlag));
697 return Either.left(list);
701 * Searches Edge by received label and criteria
706 * @return found edge or TitanOperationStatus
708 public Either<Edge, TitanOperationStatus> getBelongingEdgeByCriteria(GraphVertex vertex, EdgeLabelEnum label, Map<GraphPropertyEnum, Object> properties) {
710 Either<Edge, TitanOperationStatus> result = null;
711 Edge matchingEdge = null;
712 String notFoundMsg = "No edges in graph for criteria";
714 TitanVertexQuery<?> query = vertex.getVertex().query().labels(label.name());
716 if (properties != null && !properties.isEmpty()) {
717 for (Map.Entry<GraphPropertyEnum, Object> entry : properties.entrySet()) {
718 query = query.has(entry.getKey().getProperty(), entry.getValue());
722 Iterable<TitanEdge> edges = query.edges();
724 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, notFoundMsg);
725 result = Either.right(TitanOperationStatus.NOT_FOUND);
727 Iterator<TitanEdge> eIter = edges.iterator();
728 if (eIter.hasNext()) {
729 matchingEdge = eIter.next();
731 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, notFoundMsg);
732 result = Either.right(TitanOperationStatus.NOT_FOUND);
735 if (result == null) {
736 result = Either.left(matchingEdge);
738 } catch (Exception e) {
739 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occured during getting edge by criteria for component with id {}. {}", vertex.getUniqueId(), e);
740 return Either.right(TitanGraphClient.handleTitanException(e));
745 public Either<Edge, TitanOperationStatus> getEdgeByChildrenVertexProperties(GraphVertex vertex, EdgeLabelEnum label, Map<GraphPropertyEnum, Object> properties) {
746 Either<Edge, TitanOperationStatus> result = null;
747 Edge matchingEdge = null;
748 String notFoundMsg = "No edges in graph for criteria";
751 Iterator<Edge> edges = vertex.getVertex().edges(Direction.OUT, label.name());
752 while (edges.hasNext()) {
753 matchingEdge = edges.next();
754 Vertex childV = matchingEdge.inVertex();
755 Map<GraphPropertyEnum, Object> vertexProperties = getVertexProperties(childV);
756 Optional<Entry<GraphPropertyEnum, Object>> findNotMatch = properties.entrySet().stream().filter(e -> vertexProperties.get(e.getKey()) == null || !vertexProperties.get(e.getKey()).equals(e.getValue())).findFirst();
757 if (!findNotMatch.isPresent()) {
758 result = Either.left(matchingEdge);
761 if (result == null) {
763 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, notFoundMsg);
764 result = Either.right(TitanOperationStatus.NOT_FOUND);
766 } catch (Exception e) {
767 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occured during getting edge by criteria for component with id {}. {}", vertex.getUniqueId(), e);
768 return Either.right(TitanGraphClient.handleTitanException(e));
774 * Deletes Edge by received label and criteria
781 public Either<Edge, TitanOperationStatus> deleteBelongingEdgeByCriteria(GraphVertex vertex, EdgeLabelEnum label, Map<GraphPropertyEnum, Object> properties) {
782 Either<Edge, TitanOperationStatus> result = null;
784 result = getBelongingEdgeByCriteria(vertex, label, properties);
785 if (result.isLeft()) {
786 Edge edge = result.left().value();
787 CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "Going to delete an edge with the label {} belonging to the vertex {} ", label.name(), vertex.getUniqueId());
789 result = Either.left(edge);
791 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to find an edge with the label {} belonging to the vertex {} ", label.name(), vertex.getUniqueId());
793 } catch (Exception e) {
794 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occured during deleting an edge by criteria for the component with id {}. {}", vertex == null ? "NULL" : vertex.getUniqueId(), e);
795 return Either.right(TitanGraphClient.handleTitanException(e));
800 @SuppressWarnings("unchecked")
802 * Deletes an edge between vertices fromVertex and toVertex according to received label
810 public Either<Edge, TitanOperationStatus> deleteEdge(GraphVertex fromVertex, GraphVertex toVertex, EdgeLabelEnum label) {
811 return deleteEdge(fromVertex.getVertex(), toVertex.getVertex(), label, fromVertex.getUniqueId(), toVertex.getUniqueId(), false);
814 public Either<Edge, TitanOperationStatus> deleteAllEdges(GraphVertex fromVertex, GraphVertex toVertex, EdgeLabelEnum label) {
815 return deleteEdge(fromVertex.getVertex(), toVertex.getVertex(), label, fromVertex.getUniqueId(), toVertex.getUniqueId(), true);
818 public Either<Edge, TitanOperationStatus> deleteEdge(TitanVertex fromVertex, TitanVertex toVertex, EdgeLabelEnum label, String uniqueIdFrom, String uniqueIdTo, boolean deleteAll) {
819 Either<Edge, TitanOperationStatus> result = null;
821 Iterable<TitanEdge> edges = fromVertex.query().labels(label.name()).edges();
822 Iterator<TitanEdge> eIter = edges.iterator();
823 while (eIter.hasNext()) {
824 Edge edge = eIter.next();
825 String currVertexUniqueId = edge.inVertex().value(GraphPropertyEnum.UNIQUE_ID.getProperty());
826 if (currVertexUniqueId != null && currVertexUniqueId.equals(uniqueIdTo)) {
827 CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "Going to delete an edge with the label {} between vertices {} and {}. ", label.name(), uniqueIdFrom, uniqueIdTo);
829 result = Either.left(edge);
835 if (result == null) {
836 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to delete an edge with the label {} between vertices {} and {}. ", label.name(), uniqueIdFrom, uniqueIdTo);
837 result = Either.right(TitanOperationStatus.NOT_FOUND);
839 } catch (Exception e) {
840 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occured during deleting an edge with the label {} between vertices {} and {}. {}", label.name(), uniqueIdFrom, uniqueIdTo, e);
841 return Either.right(TitanGraphClient.handleTitanException(e));
846 public TitanOperationStatus deleteEdgeByDirection(GraphVertex fromVertex, Direction direction, EdgeLabelEnum label) {
848 Iterator<Edge> edges = fromVertex.getVertex().edges(direction, label.name());
850 while (edges.hasNext()) {
851 Edge edge = edges.next();
854 } catch (Exception e) {
855 logger.debug("Failed to remove from vertex {} edges {} by direction {} ", fromVertex.getUniqueId(), label, direction, e);
856 return TitanGraphClient.handleTitanException(e);
858 return TitanOperationStatus.OK;
862 * Updates vertex properties. Note that graphVertex argument should contain updated data
867 public Either<GraphVertex, TitanOperationStatus> updateVertex(GraphVertex graphVertex) {
868 CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "Going to update metadata of vertex with uniqueId {}. ", graphVertex.getUniqueId());
870 graphVertex.updateMetadataJsonWithCurrentMetadataProperties();
871 setVertexProperties(graphVertex.getVertex(), graphVertex);
873 } catch (Exception e) {
874 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to update metadata of vertex with uniqueId {}. ", graphVertex.getUniqueId(), e);
875 return Either.right(TitanGraphClient.handleTitanException(e));
877 return Either.left(graphVertex);
881 * Fetches vertices by uniqueId according to received parse flag
883 * @param verticesToGet
886 public Either<Map<String, GraphVertex>, TitanOperationStatus> getVerticesByUniqueIdAndParseFlag(Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> verticesToGet) {
888 Either<Map<String, GraphVertex>, TitanOperationStatus> result = null;
889 Map<String, GraphVertex> vertices = new HashMap<>();
890 TitanOperationStatus titatStatus;
891 Either<GraphVertex, TitanOperationStatus> getVertexRes = null;
892 for (Map.Entry<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> entry : verticesToGet.entrySet()) {
893 if (entry.getValue().getKey() == GraphPropertyEnum.UNIQUE_ID) {
894 getVertexRes = getVertexById(entry.getKey(), entry.getValue().getValue());
895 } else if (entry.getValue().getKey() == GraphPropertyEnum.USERID) {
896 getVertexRes = getVertexByPropertyAndLabel(entry.getValue().getKey(), entry.getKey(), VertexTypeEnum.USER, entry.getValue().getValue());
898 if (getVertexRes == null) {
899 titatStatus = TitanOperationStatus.ILLEGAL_ARGUMENT;
900 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Invalid vertex type label {} has been received. ", entry.getValue().getKey(), titatStatus);
901 return Either.right(titatStatus);
903 if (getVertexRes.isRight()) {
904 titatStatus = getVertexRes.right().value();
905 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to get vertex by id {} . Status is {}. ", entry.getKey(), titatStatus);
906 result = Either.right(titatStatus);
909 vertices.put(entry.getKey(), getVertexRes.left().value());
912 if (result == null) {
913 result = Either.left(vertices);
919 * Creates edge between "from" and "to" vertices with specified label and properties extracted from received edge
927 public TitanOperationStatus createEdge(Vertex from, Vertex to, EdgeLabelEnum label, Edge edgeToCopy) {
928 return createEdge(from, to, label, getEdgeProperties(edgeToCopy));
931 public TitanOperationStatus replaceEdgeLabel(Vertex fromVertex, Vertex toVertex, Edge prevEdge, EdgeLabelEnum prevLabel, EdgeLabelEnum newLabel) {
932 CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "Going to replace edge with label {} to {} between vertices {} and {}", prevLabel, newLabel, fromVertex!=null ? fromVertex.property(GraphPropertyEnum.UNIQUE_ID.getProperty()) : "NULL",
933 toVertex!=null ? toVertex.property(GraphPropertyEnum.UNIQUE_ID.getProperty()) : "NULL");
935 TitanOperationStatus result = createEdge(fromVertex, toVertex, newLabel, prevEdge);
936 if (result == TitanOperationStatus.OK) {
943 * Replaces previous label of edge with new label
951 public TitanOperationStatus replaceEdgeLabel(Vertex fromVertex, Vertex toVertex, EdgeLabelEnum prevLabel, EdgeLabelEnum newLabel) {
953 TitanOperationStatus result = null;
954 Iterator<Edge> prevEdgeIter = toVertex.edges(Direction.IN, prevLabel.name());
955 if (prevEdgeIter == null || !prevEdgeIter.hasNext()) {
956 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to replace edge with label {} to {} between vertices {} and {}", prevLabel, newLabel, fromVertex.property(GraphPropertyEnum.UNIQUE_ID.getProperty()),
957 toVertex.property(GraphPropertyEnum.UNIQUE_ID.getProperty()));
958 result = TitanOperationStatus.NOT_FOUND;
960 if (result == null) {
961 result = replaceEdgeLabel(fromVertex, toVertex, prevEdgeIter.next(), prevLabel, newLabel);
967 * Updates metadata properties of vertex on graph. Json metadata property of the vertex will be updated with received properties too.
974 public TitanOperationStatus updateVertexMetadataPropertiesWithJson(Vertex vertex, Map<GraphPropertyEnum, Object> properties) {
976 if (!MapUtils.isEmpty(properties)) {
977 String jsonMetadataStr = (String) vertex.property(GraphPropertyEnum.METADATA.getProperty()).value();
978 Map<String, Object> jsonMetadataMap = JsonParserUtils.toMap(jsonMetadataStr);
979 for (Map.Entry<GraphPropertyEnum, Object> property : properties.entrySet()) {
980 vertex.property(property.getKey().getProperty(), property.getValue());
981 jsonMetadataMap.put(property.getKey().getProperty(), property.getValue());
983 vertex.property(GraphPropertyEnum.METADATA.getProperty(), JsonParserUtils.toJson(jsonMetadataMap));
985 } catch (Exception e) {
986 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occurred during update vertex metadata properties with json{}. {}", vertex.property(GraphPropertyEnum.UNIQUE_ID.getProperty()), e.getMessage());
987 return TitanGraphClient.handleTitanException(e);
989 return TitanOperationStatus.OK;
992 public TitanOperationStatus disassociateAndDeleteLast(GraphVertex vertex, Direction direction, EdgeLabelEnum label) {
994 Iterator<Edge> edges = vertex.getVertex().edges(direction, label.name());
996 while (edges.hasNext()) {
997 Edge edge = edges.next();
999 Direction reverseDirection;
1000 if (direction == Direction.IN) {
1001 secondVertex = edge.outVertex();
1002 reverseDirection = Direction.OUT;
1004 secondVertex = edge.inVertex();
1005 reverseDirection = Direction.IN;
1008 CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "Edge {} with direction {} was removed from {}", label.name(), direction, vertex.getVertex());
1010 Iterator<Edge> restOfEdges = secondVertex.edges(reverseDirection, label.name());
1011 if (!restOfEdges.hasNext()) {
1012 secondVertex.remove();
1013 CommonUtility.addRecordToLog(logger, LogLevelEnum.TRACE, "This was last edge . Vertex {} was removed ", vertex.getUniqueId());
1016 } catch (Exception e) {
1017 CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occured during deleting an edge with the label {} direction {} from vertex {}. {}", label.name(), direction, vertex.getUniqueId(), e);
1018 return TitanGraphClient.handleTitanException(e);
1020 return TitanOperationStatus.OK;
1023 public Object getProperty(TitanVertex vertex, String key) {
1024 PropertyKey propertyKey = titanClient.getGraph().left().value().getPropertyKey(key);
1025 return vertex.valueOrNull(propertyKey);
1028 public Object getProperty(Edge edge, EdgePropertyEnum key) {
1029 Object value = null;
1031 Property<Object> property = edge.property(key.getProperty());
1032 if (property != null) {
1033 value = property.orElse(null);
1034 if (value != null && key == EdgePropertyEnum.INSTANCES) {
1035 return JsonParserUtils.toList((String) value, String.class);
1039 } catch (Exception e) {
1053 public TitanOperationStatus moveEdge(GraphVertex vertexA, GraphVertex vertexB, EdgeLabelEnum label, Direction direction) {
1054 TitanOperationStatus result = deleteEdgeByDirection(vertexA, direction, label);
1055 if (result != TitanOperationStatus.OK) {
1056 logger.error("Failed to diassociate {} from element {}. error {} ", label, vertexA.getUniqueId(), result);
1059 TitanOperationStatus createRelation;
1060 if (direction == Direction.IN) {
1061 createRelation = createEdge(vertexB, vertexA, label, null);
1063 createRelation = createEdge(vertexA, vertexB, label, null);
1065 if (createRelation != TitanOperationStatus.OK) {
1066 return createRelation;
1068 return TitanOperationStatus.OK;
1071 public Either<Edge, TitanOperationStatus> getBelongingEdgeByCriteria(String parentId, EdgeLabelEnum label, Map<GraphPropertyEnum, Object> properties) {
1072 Either<GraphVertex, TitanOperationStatus> getVertexRes = getVertexById(parentId, JsonParseFlagEnum.NoParse);
1073 if (getVertexRes.isRight()) {
1074 return Either.right(getVertexRes.right().value());
1076 return getBelongingEdgeByCriteria(getVertexRes.left().value(), label, properties);