From a5362c70a2dc989a5cbc7ac2e4129b12b8bde53f Mon Sep 17 00:00:00 2001 From: franciscovila Date: Mon, 17 Jan 2022 10:41:23 +0000 Subject: Add support for update to artifact types endpoint Creates a new artifact type or overwrites it, if this already exists. Issue-ID: SDC-3846 Signed-off-by: franciscovila Change-Id: Ia380dd4d790a94aa030ccf434de0440cc620f55c --- .../operations/impl/ArtifactTypeOperation.java | 178 +++++++++++++++++---- 1 file changed, 151 insertions(+), 27 deletions(-) (limited to 'catalog-model/src/main/java') diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperation.java index d8a78cdd7d..d16a7353cb 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperation.java @@ -20,23 +20,16 @@ package org.openecomp.sdc.be.model.operations.impl; import fj.data.Either; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge; import org.openecomp.sdc.be.dao.graph.datatype.GraphNode; import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation; -import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao; import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels; import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary; +import org.openecomp.sdc.be.datatypes.elements.ArtifactTypeDataDefinition; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.model.ArtifactTypeDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; @@ -54,25 +47,26 @@ import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.*; +import java.util.stream.Collectors; + + /** * This class is responsible for handling all operations for the TOSCA artifact types */ @Component("artifact-type-operation") -public class ArtifactTypeOperation implements IArtifactTypeOperation { +public class ArtifactTypeOperation extends AbstractOperation implements IArtifactTypeOperation { private static final Logger LOGGER = Logger.getLogger(ArtifactTypeOperation.class.getName()); - private final JanusGraphGenericDao janusGraphGenericDao; private final PropertyOperation propertyOperation; private final DerivedFromOperation derivedFromOperation; private final ModelOperation modelOperation; @Autowired - public ArtifactTypeOperation(final JanusGraphGenericDao janusGraphGenericDao, - final PropertyOperation propertyOperation, + public ArtifactTypeOperation(final PropertyOperation propertyOperation, final DerivedFromOperation derivedFromOperation, final ModelOperation modelOperation) { - this.janusGraphGenericDao = janusGraphGenericDao; this.propertyOperation = propertyOperation; this.derivedFromOperation = derivedFromOperation; this.modelOperation = modelOperation; @@ -91,30 +85,39 @@ public class ArtifactTypeOperation implements IArtifactTypeOperation { @Override public ArtifactTypeDefinition createArtifactType(final ArtifactTypeDefinition artifactType, final boolean inTransaction) { - Either createNodeResult = null; + Either createNodeResult = null; try { artifactType.setUniqueId(UniqueIdBuilder.buildArtifactTypeUid(artifactType.getModel(), artifactType.getType())); final ArtifactTypeData artifactTypeData = new ArtifactTypeData(artifactType); final Either existArtifact = janusGraphGenericDao .getNode(artifactTypeData.getUniqueIdKey(), artifactTypeData.getUniqueId(), ArtifactTypeData.class); if (!existArtifact.isLeft()) { - createNodeResult = janusGraphGenericDao.createNode(artifactTypeData, ArtifactTypeData.class); - if (createNodeResult.isRight()) { - final JanusGraphOperationStatus operationStatus = createNodeResult.right().value(); - LOGGER.error(EcompLoggerErrorCode.DATA_ERROR, - "Failed to add artifact type {} to graph. Operation status {}", artifactType.getType(), operationStatus); - throw new OperationException(ActionStatus.GENERAL_ERROR, - String.format("Failed to create artifact type %s with status %s", artifactType.getType(), - DaoStatusConverter.convertJanusGraphStatusToStorageStatus(operationStatus))); - } + LOGGER.debug("Artifact type did not exist, creating new one {}", artifactType); + createNodeResult = janusGraphGenericDao.createNode(artifactTypeData, ArtifactTypeData.class).right() + .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus).left() + .map(createdDerivedFrom -> artifactType); addPropertiesToArtifactType(artifactType); addModelRelation(artifactType); addDerivedFromRelation(artifactType); - return convertArtifactDataDefinition(createNodeResult.left().value()); - } else { - LOGGER.debug("Artifact type already exist {}", artifactType); - return convertArtifactDataDefinition(existArtifact.left().value()); } + else { + LOGGER.debug("Artifact type {} already exists", artifactType); + createNodeResult = janusGraphGenericDao.updateNode(artifactTypeData, ArtifactTypeData.class).right() + .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus).left() + .bind(updatedNode -> updateArtifactProperties(artifactType.getUniqueId(), artifactType.getProperties())).left() + .bind(updatedProperties -> updateArtifactDerivedFrom(artifactType, artifactType.getDerivedFrom())).left() + .map(updatedDerivedFrom -> artifactType); + } + if (createNodeResult.isRight()) { + final StorageOperationStatus operationStatus = createNodeResult.right().value(); + LOGGER.error(EcompLoggerErrorCode.DATA_ERROR, + "Failed to add artifact type {} to graph. Operation status {}", artifactType.getType(), operationStatus); + throw new OperationException(ActionStatus.GENERAL_ERROR, + String.format("Failed to create artifact type %s with status %s", artifactType.getType(), + operationStatus)); + } + return createNodeResult.left().value(); + } finally { if (!inTransaction) { if (createNodeResult == null || createNodeResult.isRight()) { @@ -156,6 +159,43 @@ public class ArtifactTypeOperation implements IArtifactTypeOperation { return artifactTypeDefinitionTypes; } + private Either, StorageOperationStatus> updateArtifactProperties(final String artifactId, final List properties) { + LOGGER.debug("#updateArtifactProperties - updating artifact type properties for artifact type with id {}", artifactId); + return propertyOperation.deletePropertiesAssociatedToNode(NodeTypeEnum.ArtifactType, artifactId).left() + .bind(deleteProps -> addPropertiesToArtifact(artifactId, properties)); + } + + private Either updateArtifactDerivedFrom(ArtifactTypeDefinition updatedArtifactType, + String currDerivedFromArtifactType) { + String artifactTypeId = updatedArtifactType.getUniqueId(); + LOGGER.debug( + "#updateArtifactDerivedFrom - updating artifact derived from relation for artifact type with id {}. old derived type {}. new derived type {}", + artifactTypeId, currDerivedFromArtifactType, updatedArtifactType.getDerivedFrom()); + StorageOperationStatus deleteDerivedRelationStatus = deleteDerivedFromArtifactType(artifactTypeId, currDerivedFromArtifactType, updatedArtifactType.getModel()); + if (deleteDerivedRelationStatus != StorageOperationStatus.OK) { + return Either.right(deleteDerivedRelationStatus); + } + return addDerivedFromRelation(updatedArtifactType, artifactTypeId); + } + + private StorageOperationStatus deleteDerivedFromArtifactType(String artifactTypeId, String derivedFromType, String model) { + if (derivedFromType == null) { + return StorageOperationStatus.OK; + } + LOGGER.debug("#deleteDerivedFromArtifactType - deleting derivedFrom relation for artifact type with id {} and its derived type {}", artifactTypeId, + derivedFromType); + return getProjectionLatestArtifactTypeByType(derivedFromType, model).either( + derivedFromNode -> derivedFromOperation.removeDerivedFromRelation(artifactTypeId, derivedFromNode.getUniqueId(), NodeTypeEnum.ArtifactType), + err -> err); + } + + private Either, StorageOperationStatus> addPropertiesToArtifact(String artifactId, + List properties) { + LOGGER.debug("#addPropertiesToArtifact - adding artifact type properties for artifact type with id {}", artifactId); + return propertyOperation.addPropertiesToElementType(artifactId, NodeTypeEnum.ArtifactType, properties).right() + .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus); + } + /** * Coverts the given artifact type data into a TOSCA artifact types definition * @param artifactTypeData artifact type data representation @@ -197,6 +237,13 @@ public class ArtifactTypeOperation implements IArtifactTypeOperation { return Optional.of(result.left().value().get(0)); } + private Either getProjectionLatestArtifactTypeByType(String type, String model) { + Map mapCriteria = new HashMap<>(); + mapCriteria.put(GraphPropertiesDictionary.TYPE.getProperty(), type); + mapCriteria.put(GraphPropertiesDictionary.IS_HIGHEST_VERSION.getProperty(), true); + return getArtifactTypeByCriteria(type, mapCriteria, model); + } + /** * Creates the derivedFrom relation for the given TOSCA artifact types * @param artifactType the TOSCA artifact types definition @@ -217,6 +264,63 @@ public class ArtifactTypeOperation implements IArtifactTypeOperation { } } + private Either addDerivedFromRelation(ArtifactTypeDefinition artifactType, String atUniqueId) { + String derivedFrom = artifactType.getDerivedFrom(); + if (derivedFrom == null) { + return Either.left(null); + } + LOGGER.debug("#addDerivedFromRelationBefore - adding derived from relation between artifact type {} to its parent {}", artifactType.getType(), + derivedFrom); + return this.getProjectionLatestArtifactTypeByType(derivedFrom, artifactType.getModel()).left().bind( + derivedFromArtifact -> derivedFromOperation.addDerivedFromRelation(atUniqueId, derivedFromArtifact.getUniqueId(), NodeTypeEnum.ArtifactType)); + } + + private Either getArtifactTypeByCriteria(String type, Map properties, String model) { + Either result; + if (type == null || type.isEmpty()) { + LOGGER.error("type is empty"); + result = Either.right(StorageOperationStatus.INVALID_ID); + return result; + } + Either, JanusGraphOperationStatus> eitherArtifactData = janusGraphGenericDao + .getByCriteriaForModel(NodeTypeEnum.ArtifactType, properties, model, ArtifactTypeData.class); + if (eitherArtifactData.isRight()) { + result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherArtifactData.right().value())); + } else { + ArtifactTypeDataDefinition dataDefinition = eitherArtifactData.left().value().stream().map(ArtifactTypeData::getArtifactTypeDataDefinition) + .findFirst().get(); + result = getArtifactTypeByUid(dataDefinition.getUniqueId()); + } + return result; + } + + private Either getArtifactTypeByUid(String uniqueId) { + LOGGER.debug("#getArtifactTypeByUid - fetching artifact type with id {}", uniqueId); + return janusGraphGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ArtifactType), uniqueId, ArtifactTypeData.class).right() + .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus).left() + .bind(artifactType -> createArtifactTypeDefinition(uniqueId, artifactType)); + } + + private Either createArtifactTypeDefinition(String uniqueId, ArtifactTypeData artifactTypeNode) { + ArtifactTypeDefinition artifactType = new ArtifactTypeDefinition(artifactTypeNode.getArtifactTypeDataDefinition()); + Optional modelName = getAssociatedModelName(uniqueId); + if (modelName.isPresent()) { + artifactType.setModel(modelName.get()); + } + return fillDerivedFrom(uniqueId, artifactType).left().map(derivedFrom -> fillProperties(uniqueId, artifactType, derivedFrom)).left() + .map(props -> artifactType); + } + + private Optional getAssociatedModelName(String uniqueId) { + final Either, JanusGraphOperationStatus> modelName = janusGraphGenericDao.getParentNode( + UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ArtifactType), uniqueId, GraphEdgeLabels.MODEL_ELEMENT, + NodeTypeEnum.Model, ModelData.class); + if (modelName.isRight()) { + return Optional.empty(); + } + return Optional.ofNullable(modelName.left().value().getLeft().getName()); + } + /** * Adds a property definition to the given TOSCA artifact types definition * @param artifactType the TOSCA artifact types @@ -285,6 +389,12 @@ public class ArtifactTypeOperation implements IArtifactTypeOperation { return result.left().value(); } + private Either fillDerivedFrom(String uniqueId, ArtifactTypeDefinition artifactType) { + LOGGER.debug("#fillDerivedFrom - fetching artifact type {} derived node", artifactType.getType()); + return derivedFromOperation.getDerivedFromChild(uniqueId, NodeTypeEnum.ArtifactType, ArtifactTypeData.class).right() + .bind(this::handleDerivedFromNotExist).left().map(derivedFrom -> setDerivedFrom(artifactType, derivedFrom)); + } + private Either handleDerivedFromNotExist(final StorageOperationStatus storageOperationStatus) { if (storageOperationStatus == StorageOperationStatus.NOT_FOUND) { return Either.left(null); @@ -316,6 +426,20 @@ public class ArtifactTypeOperation implements IArtifactTypeOperation { } } + private Either, StorageOperationStatus> fillProperties(String uniqueId, ArtifactTypeDefinition artifactType, + ArtifactTypeData derivedFromNode) { + LOGGER.debug("#fillProperties - fetching all properties for artifact type {}", artifactType.getType()); + return propertyOperation.findPropertiesOfNode(NodeTypeEnum.ArtifactType, uniqueId).right().bind(this::handleArtifactTypeHasNoProperties).left() + .bind(propsMap -> fillDerivedFromProperties(artifactType, derivedFromNode, new ArrayList<>(propsMap.values()))); + } + + private Either, StorageOperationStatus> handleArtifactTypeHasNoProperties(JanusGraphOperationStatus err) { + if (err == JanusGraphOperationStatus.NOT_FOUND) { + return Either.left(new HashMap<>()); + } + return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(err)); + } + private Either, StorageOperationStatus> handleNoProperties( final JanusGraphOperationStatus janusGraphOperationStatus) { if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) { -- cgit 1.2.3-korg