1 package org.openecomp.sdc.be.model.operations.impl;
3 import java.util.ArrayList;
4 import java.util.HashMap;
9 import org.apache.commons.collections.MapUtils;
10 import org.apache.commons.lang3.tuple.ImmutablePair;
11 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
12 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
13 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
14 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
15 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
16 import org.openecomp.sdc.be.model.PropertyDefinition;
17 import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
18 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
19 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
20 import org.openecomp.sdc.be.resources.data.PropertyData;
21 import org.openecomp.sdc.be.resources.data.RelationshipTypeData;
22 import org.openecomp.sdc.common.log.wrappers.Logger;
23 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.stereotype.Component;
26 @Component("relationship-type-operation")
27 public class RelationshipTypeOperation extends AbstractOperation {
30 private PropertyOperation propertyOperation;
33 private DerivedFromOperation derivedFromOperation;
35 private static final Logger logger = Logger.getLogger(RelationshipTypeOperation.class.getName());
36 private static final String RELATIONSHIP_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Relationship type {} cannot be "
38 + "graph status is {}";
39 private static final String FAILED_TO_FETCH_PROPERTIES_OF_RELATIONSHIP_TYPE = "Failed to fetch properties of "
40 + "relationship type {}";
42 public Either<RelationshipTypeDefinition, JanusGraphOperationStatus> getRelationshipTypeByName(String name) {
43 String uid = UniqueIdBuilder.buildRelationshipTypeUid(name);
44 Either<RelationshipTypeDefinition, JanusGraphOperationStatus> result = getRelationshipTypeByUid(uid);
45 if (result.isRight()) {
46 JanusGraphOperationStatus status = result.right().value();
47 if (status != JanusGraphOperationStatus.NOT_FOUND) {
48 logger.error("Failed to get information on relationship type {} status is {}", name, status);
50 return Either.right(status);
52 return Either.left(result.left().value());
55 public Either<RelationshipTypeDefinition, JanusGraphOperationStatus> getRelationshipTypeByUid(String uniqueId) {
57 Either<RelationshipTypeDefinition, JanusGraphOperationStatus> result;
59 Either<RelationshipTypeData, JanusGraphOperationStatus> relationshipTypesRes =
60 janusGraphGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(
61 NodeTypeEnum.RelationshipType), uniqueId, RelationshipTypeData.class);
63 if (relationshipTypesRes.isRight()) {
64 JanusGraphOperationStatus status = relationshipTypesRes.right().value();
65 logger.debug("Relationship type {} cannot be found in graph. status is {}", uniqueId, status);
66 return Either.right(status);
69 RelationshipTypeData relationshipTypeData = relationshipTypesRes.left().value();
70 RelationshipTypeDefinition relationshipTypeDefinition =
71 new RelationshipTypeDefinition(relationshipTypeData.getRelationshipTypeDataDefinition());
73 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesStatus =
74 OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.RelationshipType);
75 if (propertiesStatus.isRight() && propertiesStatus.right().value() != JanusGraphOperationStatus.OK) {
76 logger.error("Failed to fetch properties of relationship type {}", uniqueId);
77 return Either.right(propertiesStatus.right().value());
80 if (propertiesStatus.isLeft()) {
81 relationshipTypeDefinition.setProperties(propertiesStatus.left().value());
84 Either<ImmutablePair<RelationshipTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
85 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.RelationshipType), uniqueId,
86 GraphEdgeLabels.DERIVED_FROM,
87 NodeTypeEnum.RelationshipType, RelationshipTypeData.class);
88 logger.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode);
89 if (parentNode.isRight()) {
90 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
91 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
92 logger.error("Failed to find the parent relationship of relationship type {}. status is {}", uniqueId,
93 janusGraphOperationStatus);
94 result = Either.right(janusGraphOperationStatus);
98 // derived from node was found
99 ImmutablePair<RelationshipTypeData, GraphEdge> immutablePair = parentNode.left().value();
100 RelationshipTypeData parentCT = immutablePair.getKey();
101 relationshipTypeDefinition.setDerivedFrom(parentCT.getRelationshipTypeDataDefinition().getType());
103 result = Either.left(relationshipTypeDefinition);
108 private Either<RelationshipTypeDefinition, StorageOperationStatus> validateUpdateProperties(
109 RelationshipTypeDefinition relationshipTypeDefinition) {
110 JanusGraphOperationStatus error = null;
111 if (MapUtils.isNotEmpty(relationshipTypeDefinition.getProperties())
112 && relationshipTypeDefinition.getDerivedFrom() != null) {
113 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesRes =
114 getAllRelationshipTypePropertiesFromAllDerivedFrom(relationshipTypeDefinition.getDerivedFrom());
115 if (allPropertiesRes.isRight() && !JanusGraphOperationStatus.NOT_FOUND.equals(allPropertiesRes.right().value())) {
116 error = allPropertiesRes.right().value();
117 logger.debug("Couldn't fetch derived from property nodes for relationship type {}, error: {}",
118 relationshipTypeDefinition.getType(), error);
120 error = getJanusGraphOperationStatus(relationshipTypeDefinition, error, allPropertiesRes);
123 return Either.left(relationshipTypeDefinition);
125 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(error));
128 private JanusGraphOperationStatus getJanusGraphOperationStatus(RelationshipTypeDefinition relationshipTypeDefinition,
129 JanusGraphOperationStatus error,
130 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesRes) {
131 if (error == null && !allPropertiesRes.left().value().isEmpty()) {
132 Map<String, PropertyDefinition> derivedFromProperties = allPropertiesRes.left().value();
133 relationshipTypeDefinition.getProperties().entrySet().stream()
134 .filter(e -> derivedFromProperties.containsKey(e.getKey()) && e.getValue().getType() == null)
135 .forEach(e -> e.getValue().setType(derivedFromProperties.get(e.getKey()).getType()));
137 List<PropertyDefinition>
138 properties = new ArrayList<>(relationshipTypeDefinition.getProperties().values());
139 Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesRes =
140 propertyOperation.validatePropertiesUniqueness(allPropertiesRes.left().value(), properties);
141 if (validatePropertiesRes.isRight()) {
142 error = validatePropertiesRes.right().value();
148 private Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllRelationshipTypePropertiesFromAllDerivedFrom(
149 String firstParentType) {
150 return propertyOperation.getAllTypePropertiesFromAllDerivedFrom(firstParentType, NodeTypeEnum.RelationshipType,
151 RelationshipTypeData.class);
154 public Either<RelationshipTypeDefinition, StorageOperationStatus> addRelationshipType(
155 RelationshipTypeDefinition relationshipTypeDefinition,
156 boolean inTransaction) {
158 Either<RelationshipTypeDefinition, StorageOperationStatus> result = null;
161 Either<RelationshipTypeDefinition, StorageOperationStatus> validationRes =
162 validateUpdateProperties(relationshipTypeDefinition);
163 if (validationRes.isRight()) {
165 "#addRelationshipType - One or all properties of relationship type {} not valid. status is {}"
166 , relationshipTypeDefinition, validationRes.right().value());
167 return validationRes;
170 Either<RelationshipTypeData, StorageOperationStatus> eitherStatus =
171 addRelationshipTypeToGraph(relationshipTypeDefinition);
173 result = eitherStatus.left()
174 .map(RelationshipTypeData::getUniqueId)
176 .bind(uniqueId -> getRelationshipType(uniqueId, inTransaction));
178 if (result.isLeft()) {
179 logger.debug("#addRelationshipType - The returned RelationshipTypeDefinition is {}",
180 result.left().value());
185 if (!inTransaction) {
186 if (result == null || result.isRight()) {
187 logger.error("#addRelationshipType - Going to execute rollback on graph.");
188 janusGraphGenericDao.rollback();
190 logger.debug("#addRelationshipType - Going to execute commit on graph.");
191 janusGraphGenericDao.commit();
197 public Either<RelationshipTypeDefinition, StorageOperationStatus> getRelationshipType(String uniqueId,
198 boolean inTransaction) {
200 Either<RelationshipTypeDefinition, StorageOperationStatus> result;
203 Either<RelationshipTypeDefinition, JanusGraphOperationStatus> ctResult = this.getRelationshipTypeByUid(uniqueId);
205 if (ctResult.isRight()) {
206 JanusGraphOperationStatus status = ctResult.right().value();
207 if (status != JanusGraphOperationStatus.NOT_FOUND) {
208 logger.error("Failed to retrieve information on relationship type {}. status is {}", uniqueId,
211 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
215 result = Either.left(ctResult.left().value());
219 if (!inTransaction) {
220 logger.debug("Going to execute commit on graph.");
221 janusGraphGenericDao.commit();
226 private Either<RelationshipTypeData, StorageOperationStatus> addRelationshipTypeToGraph(
227 RelationshipTypeDefinition relationshipTypeDefinition) {
229 logger.debug("Got relationship type {}", relationshipTypeDefinition);
231 String ctUniqueId = UniqueIdBuilder.buildRelationshipTypeUid(relationshipTypeDefinition.getType());
232 RelationshipTypeData relationshipTypeData = buildRelationshipTypeData(relationshipTypeDefinition, ctUniqueId);
234 logger.debug("Before adding relationship type to graph. relationshipTypeData = {}", relationshipTypeData);
235 Either<RelationshipTypeData, JanusGraphOperationStatus> createCTResult =
236 janusGraphGenericDao.createNode(relationshipTypeData, RelationshipTypeData.class);
237 logger.debug("After adding relationship type to graph. status is = {}", createCTResult);
239 if (createCTResult.isRight()) {
240 JanusGraphOperationStatus operationStatus = createCTResult.right().value();
241 logger.error("Failed to relationship type {} to graph. status is {}", relationshipTypeDefinition.getType(),
243 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(operationStatus));
246 RelationshipTypeData resultCTD = createCTResult.left().value();
247 Map<String, PropertyDefinition> propertiesMap = relationshipTypeDefinition.getProperties();
248 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToRelationshipType = propertyOperation
249 .addPropertiesToElementType(resultCTD.getUniqueId(), NodeTypeEnum.RelationshipType, propertiesMap);
250 if (addPropertiesToRelationshipType.isRight()) {
251 logger.error("Failed add properties {} to relationship {}", propertiesMap,
252 relationshipTypeDefinition.getType());
253 return Either.right(DaoStatusConverter
254 .convertJanusGraphStatusToStorageStatus(addPropertiesToRelationshipType.right().value()));
257 return addDerivedFromRelation(relationshipTypeDefinition, ctUniqueId)
259 .map(updatedDerivedFrom -> createCTResult.left().value());
264 private RelationshipTypeData buildRelationshipTypeData(RelationshipTypeDefinition relationshipTypeDefinition,
267 RelationshipTypeData relationshipTypeData = new RelationshipTypeData(relationshipTypeDefinition);
269 relationshipTypeData.getRelationshipTypeDataDefinition().setUniqueId(ctUniqueId);
270 Long creationDate = relationshipTypeData.getRelationshipTypeDataDefinition().getCreationTime();
271 if (creationDate == null) {
272 creationDate = System.currentTimeMillis();
274 relationshipTypeData.getRelationshipTypeDataDefinition().setCreationTime(creationDate);
275 relationshipTypeData.getRelationshipTypeDataDefinition().setModificationTime(creationDate);
276 return relationshipTypeData;
279 private Either<GraphRelation, StorageOperationStatus> addDerivedFromRelation(
280 RelationshipTypeDefinition relationshipTypeDefinition,
281 String relationshipTypeUniqueId) {
282 String derivedFrom = relationshipTypeDefinition.getDerivedFrom();
283 if (derivedFrom == null) {
284 return Either.left(null);
287 "#addDerivedFromRelation - adding derived from relation between relationship type {} to its parent "
288 + "{}", relationshipTypeDefinition.getType(), derivedFrom);
289 return getRelationshipTypeByType(derivedFrom)
291 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus)
293 .bind(derivedFromRelationship -> derivedFromOperation.addDerivedFromRelation(relationshipTypeUniqueId,
294 derivedFromRelationship.getUniqueId(), NodeTypeEnum.RelationshipType));
297 private Either<RelationshipTypeDefinition, JanusGraphOperationStatus> getRelationshipTypeByType(
298 String relationshipType) {
299 // Optimization: In case of Relationship Type its unique ID is the same as type
300 return getRelationshipTypeByUid(relationshipType);
303 public Either<RelationshipTypeDefinition, StorageOperationStatus> updateRelationshipType(
304 RelationshipTypeDefinition newRelationshipTypeDefinition,
305 RelationshipTypeDefinition oldRelationshipTypeDefinition, boolean inTransaction) {
306 logger.debug("updating relationship type {}", newRelationshipTypeDefinition.getType());
307 Either<RelationshipTypeDefinition, StorageOperationStatus> updateRelationshipEither = null;
310 updateRelationshipEither =
311 updateRelationshipTypeOnGraph(newRelationshipTypeDefinition, oldRelationshipTypeDefinition);
313 if (!inTransaction) {
314 if (updateRelationshipEither == null || updateRelationshipEither.isRight()) {
315 janusGraphGenericDao.rollback();
317 janusGraphGenericDao.commit();
321 return updateRelationshipEither;
324 private Either<RelationshipTypeDefinition, StorageOperationStatus> updateRelationshipTypeOnGraph(
325 RelationshipTypeDefinition newRelationshipTypeDefinition,
326 RelationshipTypeDefinition oldRelationshipTypeDefinition) {
327 updateRelationshipTypeData(newRelationshipTypeDefinition, oldRelationshipTypeDefinition);
328 return janusGraphGenericDao
329 .updateNode(new RelationshipTypeData(newRelationshipTypeDefinition), RelationshipTypeData.class)
331 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus)
333 .bind(updatedNode -> updateRelationshipTypeProperties(newRelationshipTypeDefinition.getUniqueId(),
334 newRelationshipTypeDefinition.getProperties()))
336 .bind(updatedProperties -> updateRelationshipTypeDerivedFrom(newRelationshipTypeDefinition,
337 oldRelationshipTypeDefinition.getDerivedFrom()))
339 .map(updatedDerivedFrom -> newRelationshipTypeDefinition);
342 private Either<Map<String, PropertyData>, StorageOperationStatus> updateRelationshipTypeProperties(
343 String relationshipTypeId, Map<String, PropertyDefinition> properties) {
345 "#updateRelationshipTypeProperties - updating relationship type properties for relationship type with "
346 + "id {}", relationshipTypeId);
347 return propertyOperation.deletePropertiesAssociatedToNode(NodeTypeEnum.RelationshipType, relationshipTypeId)
349 .bind(deleteProps -> addPropertiesToRelationshipType(relationshipTypeId, properties));
352 private Either<GraphRelation, StorageOperationStatus> updateRelationshipTypeDerivedFrom(
353 RelationshipTypeDefinition newRelationshipTypeDefinition, String currDerivedFromRelationshipType) {
354 String relationshipTypeId = newRelationshipTypeDefinition.getUniqueId();
356 "#updateRelationshipTypeDerivedFrom - updating relationship derived from relation for relationship "
357 + "type with id {}. old derived type {}. new derived type {}", relationshipTypeId,
358 currDerivedFromRelationshipType, newRelationshipTypeDefinition.getDerivedFrom());
359 StorageOperationStatus deleteDerivedRelationStatus =
360 deleteDerivedFromRelationshipType(relationshipTypeId, currDerivedFromRelationshipType);
361 if (deleteDerivedRelationStatus != StorageOperationStatus.OK) {
362 return Either.right(deleteDerivedRelationStatus);
364 return addDerivedFromRelation(newRelationshipTypeDefinition, relationshipTypeId);
367 private void updateRelationshipTypeData(RelationshipTypeDefinition newRelationshipTypeDefinition,
368 RelationshipTypeDefinition oldRelationshipTypeDefinition) {
369 newRelationshipTypeDefinition.setUniqueId(oldRelationshipTypeDefinition.getUniqueId());
370 newRelationshipTypeDefinition.setCreationTime(oldRelationshipTypeDefinition.getCreationTime());
371 newRelationshipTypeDefinition.setModificationTime(System.currentTimeMillis());
374 private Either<Map<String, PropertyData>, StorageOperationStatus> addPropertiesToRelationshipType(
375 String relationshipTypeId, Map<String, PropertyDefinition> properties) {
377 "#addPropertiesToRelationshipType - adding relationship type properties for relationship type with "
378 + "id {}", relationshipTypeId);
379 return propertyOperation
380 .addPropertiesToElementType(relationshipTypeId, NodeTypeEnum.RelationshipType, properties)
382 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
385 private StorageOperationStatus deleteDerivedFromRelationshipType(String relationshipTypeId,
386 String derivedFromType) {
387 if (derivedFromType == null) {
388 return StorageOperationStatus.OK;
390 logger.debug("#deleteDerivedFromRelationshipType - deleting derivedFrom relation for relationship type with id "
391 + "{} and its derived type {}", relationshipTypeId, derivedFromType);
392 return getRelationshipTypeByType(derivedFromType)
393 .either(derivedFromNode -> derivedFromOperation
394 .removeDerivedFromRelation(relationshipTypeId, derivedFromNode.getUniqueId(),
395 NodeTypeEnum.RelationshipType),
396 DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
399 public Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> getAllRelationshipTypes() {
401 Map<String, RelationshipTypeDefinition> relationshipTypeDefinitionMap = new HashMap<>();
402 Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> result = Either.left(relationshipTypeDefinitionMap);
404 Either<List<RelationshipTypeData>, JanusGraphOperationStatus> getAllRelationshipTypes =
406 .getByCriteria(NodeTypeEnum.RelationshipType, null, RelationshipTypeData.class);
407 if (getAllRelationshipTypes.isRight()) {
408 JanusGraphOperationStatus status = getAllRelationshipTypes.right().value();
409 if (status != JanusGraphOperationStatus.NOT_FOUND) {
410 return Either.right(status);
416 List<RelationshipTypeData> list = getAllRelationshipTypes.left().value();
419 logger.trace("Number of relationship types to load is {}", list.size());
421 Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> status =
422 getMapJanusGraphOperationStatusEither(relationshipTypeDefinitionMap, list);
423 if (status != null) {
431 private Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> getMapJanusGraphOperationStatusEither(
432 Map<String, RelationshipTypeDefinition> relationshipTypeDefinitionMap,
433 List<RelationshipTypeData> list) {
434 for (RelationshipTypeData relationshipTypeData : list) {
436 logger.trace("Going to fetch relationship type {}. uid is {}",
437 relationshipTypeData.getRelationshipTypeDataDefinition().getType(),
438 relationshipTypeData.getUniqueId());
439 Either<RelationshipTypeDefinition, JanusGraphOperationStatus> relationshipTypesByUid =
440 getAndAddPropertiesANdDerivedFrom(relationshipTypeData.getUniqueId(), relationshipTypeDefinitionMap);
441 if (relationshipTypesByUid.isRight()) {
442 JanusGraphOperationStatus status = relationshipTypesByUid.right().value();
443 if (status == JanusGraphOperationStatus.NOT_FOUND) {
444 status = JanusGraphOperationStatus.INVALID_ID;
446 return Either.right(status);
452 private Either<RelationshipTypeDefinition, JanusGraphOperationStatus> getAndAddPropertiesANdDerivedFrom(
453 String uniqueId, Map<String, RelationshipTypeDefinition> relationshipTypeDefinitionMap) {
454 if (relationshipTypeDefinitionMap.containsKey(uniqueId)) {
455 return Either.left(relationshipTypeDefinitionMap.get(uniqueId));
458 Either<RelationshipTypeData, JanusGraphOperationStatus> relationshipTypesRes =
459 janusGraphGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.RelationshipType), uniqueId,
460 RelationshipTypeData.class);
462 if (relationshipTypesRes.isRight()) {
463 JanusGraphOperationStatus status = relationshipTypesRes.right().value();
464 logger.debug(RELATIONSHIP_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
465 return Either.right(status);
468 RelationshipTypeData ctData = relationshipTypesRes.left().value();
469 RelationshipTypeDefinition relationshipTypeDefinition =
470 new RelationshipTypeDefinition(ctData.getRelationshipTypeDataDefinition());
472 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesStatus =
473 OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.RelationshipType);
474 if (propertiesStatus.isRight() && propertiesStatus.right().value() != JanusGraphOperationStatus.OK) {
475 logger.error(FAILED_TO_FETCH_PROPERTIES_OF_RELATIONSHIP_TYPE, uniqueId);
476 return Either.right(propertiesStatus.right().value());
479 if (propertiesStatus.isLeft()) {
480 relationshipTypeDefinition.setProperties(propertiesStatus.left().value());
483 fillDerivedFrom(uniqueId, relationshipTypeDefinition);
485 relationshipTypeDefinitionMap.put(relationshipTypeDefinition.getType(), relationshipTypeDefinition);
487 return Either.left(relationshipTypeDefinition);
490 private void fillDerivedFrom(String uniqueId,
491 RelationshipTypeDefinition relationshipType) {
492 logger.debug("#fillDerivedFrom - fetching relationship type {} derived node", relationshipType.getType());
493 derivedFromOperation.getDerivedFromChild(uniqueId, NodeTypeEnum.RelationshipType, RelationshipTypeData.class)
495 .bind(this::handleDerivedFromNotExist)
497 .map(derivedFrom -> setDerivedFrom(relationshipType, derivedFrom));
501 private Either<RelationshipTypeData, StorageOperationStatus> handleDerivedFromNotExist(StorageOperationStatus err) {
502 if (err == StorageOperationStatus.NOT_FOUND) {
503 return Either.left(null);
505 return Either.right(err);
508 private RelationshipTypeData setDerivedFrom(RelationshipTypeDefinition relationshipTypeDefinition, RelationshipTypeData derivedFrom) {
509 if (derivedFrom != null) {
510 relationshipTypeDefinition.setDerivedFrom(derivedFrom.getRelationshipTypeDataDefinition().getType());