1 package org.openecomp.sdc.be.model.operations.impl;
4 import org.apache.commons.lang3.tuple.ImmutablePair;
5 import org.apache.commons.lang3.tuple.Pair;
6 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
7 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
8 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
9 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
10 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
11 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
12 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
13 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
14 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
15 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
16 import org.openecomp.sdc.be.resources.data.UniqueIdData;
17 import org.openecomp.sdc.common.log.wrappers.Logger;
18 import org.springframework.stereotype.Component;
21 import java.util.function.Function;
24 public class DefaultDerivedFromOperation implements DerivedFromOperation {
26 private static final Logger log = Logger.getLogger(DefaultDerivedFromOperation.class.getName());
27 private JanusGraphGenericDao janusGraphGenericDao;
29 public DefaultDerivedFromOperation(JanusGraphGenericDao janusGraphGenericDao) {
30 this.janusGraphGenericDao = janusGraphGenericDao;
34 public Either<GraphRelation, StorageOperationStatus> addDerivedFromRelation(String parentUniqueId, String derivedFromUniqueId, NodeTypeEnum nodeType) {
35 UniqueIdData from = new UniqueIdData(nodeType, parentUniqueId);
36 UniqueIdData to = new UniqueIdData(nodeType, derivedFromUniqueId);
37 return janusGraphGenericDao.createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null)
39 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
43 public <T extends GraphNode> Either<T, StorageOperationStatus> getDerivedFromChild(String uniqueId, NodeTypeEnum nodeType, Class<T> clazz) {
44 log.debug("#getDerivedFromChild - fetching derived from entity for node type {} with id {}", nodeType, uniqueId);
45 return janusGraphGenericDao
46 .getChild(UniqueIdBuilder.getKeyByNodeType(nodeType), uniqueId, GraphEdgeLabels.DERIVED_FROM, nodeType, clazz)
48 DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
52 public StorageOperationStatus removeDerivedFromRelation(String uniqueId, String derivedFromUniqueId, NodeTypeEnum nodeType) {
53 UniqueIdData from = new UniqueIdData(nodeType, uniqueId);
54 UniqueIdData to = new UniqueIdData(nodeType, derivedFromUniqueId);
55 return isDerivedFromExists(from, to)
56 .either(isRelationExist -> isRelationExist ? deleteDerivedFrom(from, to) : StorageOperationStatus.OK,
57 DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
62 private StorageOperationStatus deleteDerivedFrom(UniqueIdData from, UniqueIdData to) {
63 return janusGraphGenericDao.deleteRelation(from, to, GraphEdgeLabels.DERIVED_FROM)
64 .either(deletedRelation -> StorageOperationStatus.OK,
65 DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
68 private Either<Boolean, JanusGraphOperationStatus> isDerivedFromExists(UniqueIdData from, UniqueIdData to) {
69 return janusGraphGenericDao.isRelationExist(from, to, GraphEdgeLabels.DERIVED_FROM);
73 public <T extends GraphNode> Either<Boolean, StorageOperationStatus> isTypeDerivedFrom(String childCandidateType, String parentCandidateType, String currentChildType,
74 NodeTypeEnum nodeType, Class<T> clazz, Function<T, String> typeProvider) {
75 Map<String, Object> propertiesToMatch = new HashMap<>();
76 propertiesToMatch.put(GraphPropertiesDictionary.TYPE.getProperty(), childCandidateType);
78 Either<List<T>, JanusGraphOperationStatus> getResponse = janusGraphGenericDao
79 .getByCriteria(nodeType, propertiesToMatch, clazz);
80 if (getResponse.isRight()) {
81 JanusGraphOperationStatus janusGraphOperationStatus = getResponse.right().value();
82 log.debug("Couldn't fetch type {}, error: {}", childCandidateType,
83 janusGraphOperationStatus);
84 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(
85 janusGraphOperationStatus));
87 T node = getResponse.left().value().get(0);
88 String childUniqueId = node.getUniqueId();
89 String childType = typeProvider.apply(node);
91 Set<String> travelledTypes = new HashSet<>();
92 if (currentChildType != null) {
93 travelledTypes.add(currentChildType);
97 travelledTypes.add(childType);
98 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
99 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), childUniqueId, GraphEdgeLabels.DERIVED_FROM,
101 if (childrenNodes.isRight()) {
102 if (childrenNodes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
103 JanusGraphOperationStatus janusGraphOperationStatus = getResponse.right().value();
104 log.debug("Couldn't fetch derived from node for type {}, error: {}", childCandidateType,
105 janusGraphOperationStatus);
106 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(
107 janusGraphOperationStatus));
109 log.debug("Derived from node is not found for type {} - this is OK for root capability.", childCandidateType);
110 return Either.left(false);
113 String derivedFromUniqueId = childrenNodes.left().value().get(0).getLeft().getUniqueId();
114 String derivedFromType = typeProvider.apply(childrenNodes.left().value().get(0).getLeft());
115 if (derivedFromType.equals(parentCandidateType)) {
116 log.debug("Verified that type {} derives from type {}", childCandidateType, parentCandidateType);
117 return Either.left(true);
119 childUniqueId = derivedFromUniqueId;
120 childType = derivedFromType;
121 } while (!travelledTypes.contains(childType));
122 // this stop condition should never be used, if we use it, we have an
123 // illegal cycle in graph - "derived from" hierarchy cannot be cycled.
124 // It's here just to avoid infinite loop in case we have such cycle.
125 log.error("Detected a cycle of \"derived from\" edges starting at type node {}", childType);
126 return Either.right(StorageOperationStatus.GENERAL_ERROR);
132 public <T extends GraphNode> StorageOperationStatus isUpdateParentAllowed(String oldTypeParent, String newTypeParent, String childType,
133 NodeTypeEnum nodeType, Class<T> clazz,
134 Function<T, String> typeProvider) {
135 StorageOperationStatus status;
136 if (oldTypeParent != null) {
138 Either<Boolean, StorageOperationStatus> result = isTypeDerivedFrom(newTypeParent, oldTypeParent, childType, nodeType, clazz, typeProvider);
139 if (result.isRight()) {
140 log.debug("#isUpdateParentAllowed - failed to detect that new parent {} is derived from the current parent {}", newTypeParent, oldTypeParent);
141 status = result.right().value();
144 if (result.left().value()) {
145 log.debug("#isUpdateParentAllowed - update is allowed since new parent {} is derived from the current parent {}", newTypeParent, oldTypeParent);
146 status = StorageOperationStatus.OK;
149 log.debug("#isUpdateParentAllowed - update is not allowed since new parent {} is not derived from the current parent {}", newTypeParent, oldTypeParent);
150 status = StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY;
156 log.debug("#isUpdateParentAllowed - the update is allowed since the parent still has been not set." );
157 status = StorageOperationStatus.OK;