aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-model
diff options
context:
space:
mode:
authorfranciscovila <javier.paradela.vila@est.tech>2022-01-17 10:41:23 +0000
committerMichael Morris <michael.morris@est.tech>2022-01-21 14:13:52 +0000
commita5362c70a2dc989a5cbc7ac2e4129b12b8bde53f (patch)
tree23397a1cfc58a9da01fc1afaf25d93add76f86c4 /catalog-model
parent049d078d8abbe637b213a2f14c2192379208c168 (diff)
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 <javier.paradela.vila@est.tech> Change-Id: Ia380dd4d790a94aa030ccf434de0440cc620f55c
Diffstat (limited to 'catalog-model')
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperation.java178
-rw-r--r--catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperationTest.java144
2 files changed, 295 insertions, 27 deletions
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<ArtifactTypeData, JanusGraphOperationStatus> createNodeResult = null;
+ Either<ArtifactTypeDefinition, StorageOperationStatus> createNodeResult = null;
try {
artifactType.setUniqueId(UniqueIdBuilder.buildArtifactTypeUid(artifactType.getModel(), artifactType.getType()));
final ArtifactTypeData artifactTypeData = new ArtifactTypeData(artifactType);
final Either<ArtifactTypeData, JanusGraphOperationStatus> 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<Map<String, PropertyData>, StorageOperationStatus> updateArtifactProperties(final String artifactId, final List<PropertyDefinition> 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<GraphRelation, StorageOperationStatus> 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<Map<String, PropertyData>, StorageOperationStatus> addPropertiesToArtifact(String artifactId,
+ List<PropertyDefinition> 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<ArtifactTypeDefinition, StorageOperationStatus> getProjectionLatestArtifactTypeByType(String type, String model) {
+ Map<String, Object> 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<GraphRelation, StorageOperationStatus> 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<ArtifactTypeDefinition, StorageOperationStatus> getArtifactTypeByCriteria(String type, Map<String, Object> properties, String model) {
+ Either<ArtifactTypeDefinition, StorageOperationStatus> result;
+ if (type == null || type.isEmpty()) {
+ LOGGER.error("type is empty");
+ result = Either.right(StorageOperationStatus.INVALID_ID);
+ return result;
+ }
+ Either<List<ArtifactTypeData>, 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<ArtifactTypeDefinition, StorageOperationStatus> 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<ArtifactTypeDefinition, StorageOperationStatus> createArtifactTypeDefinition(String uniqueId, ArtifactTypeData artifactTypeNode) {
+ ArtifactTypeDefinition artifactType = new ArtifactTypeDefinition(artifactTypeNode.getArtifactTypeDataDefinition());
+ Optional<String> 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<String> getAssociatedModelName(String uniqueId) {
+ final Either<ImmutablePair<ModelData, GraphEdge>, 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<ArtifactTypeData, StorageOperationStatus> 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<ArtifactTypeData, StorageOperationStatus> handleDerivedFromNotExist(final StorageOperationStatus storageOperationStatus) {
if (storageOperationStatus == StorageOperationStatus.NOT_FOUND) {
return Either.left(null);
@@ -316,6 +426,20 @@ public class ArtifactTypeOperation implements IArtifactTypeOperation {
}
}
+ private Either<List<PropertyDefinition>, 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<Map<String, PropertyDefinition>, StorageOperationStatus> handleArtifactTypeHasNoProperties(JanusGraphOperationStatus err) {
+ if (err == JanusGraphOperationStatus.NOT_FOUND) {
+ return Either.left(new HashMap<>());
+ }
+ return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(err));
+ }
+
private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNoProperties(
final JanusGraphOperationStatus janusGraphOperationStatus) {
if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperationTest.java
new file mode 100644
index 0000000000..4ec0963fec
--- /dev/null
+++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperationTest.java
@@ -0,0 +1,144 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ *
+ *
+ */
+
+package org.openecomp.sdc.be.model.operations.impl;
+
+import fj.data.Either;
+import org.janusgraph.core.JanusGraph;
+import org.janusgraph.core.JanusGraphVertex;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
+import org.openecomp.sdc.be.datatypes.elements.ArtifactTypeDataDefinition;
+import org.openecomp.sdc.be.model.ArtifactTypeDefinition;
+import org.openecomp.sdc.be.model.ModelTestBase;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+
+import java.util.Iterator;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+@SpringJUnitConfig(locations = "classpath:application-context-test.xml")
+public class ArtifactTypeOperationTest extends ModelTestBase {
+
+ private static final String NULL_STRING = null;
+
+ @Autowired
+ private ArtifactTypeOperation artifactTypeOperation;
+
+ @Autowired
+ private HealingJanusGraphGenericDao janusGraphGenericDao;
+
+ @BeforeAll
+ public static void setupBeforeClass() {
+ ModelTestBase.init();
+ }
+
+ @BeforeEach
+ public void cleanUp() {
+ JanusGraphGenericDao janusGraphGenericDao = artifactTypeOperation.janusGraphGenericDao;
+ Either<JanusGraph, JanusGraphOperationStatus> graphResult = janusGraphGenericDao.getGraph();
+ JanusGraph graph = graphResult.left().value();
+
+ Iterable<JanusGraphVertex> vertices = graph.query().vertices();
+ if (vertices != null) {
+ Iterator<JanusGraphVertex> iterator = vertices.iterator();
+ while (iterator.hasNext()) {
+ JanusGraphVertex vertex = iterator.next();
+ vertex.remove();
+ }
+ }
+ janusGraphGenericDao.commit();
+ }
+
+ @Test
+ public void createArtifactType() {
+
+ ArtifactTypeDefinition createdType = createArtifactTypeDef("type1", "description1", "derivedFromTest1");
+ artifactTypeOperation.createArtifactType(createdType, false);
+
+ assertNotNull(createdType);
+ assertEquals("type1name", createdType.getName());
+ assertEquals("description1", createdType.getDescription());
+ assertEquals("derivedFromTest1", createdType.getDerivedFrom());
+ }
+
+ @Test
+ public void createAndModifyArtifactType() {
+
+ ArtifactTypeDefinition createdType = createArtifactTypeDef("type2", "description1", "derivedFromTest2");
+ artifactTypeOperation.createArtifactType(createdType, false);
+
+ createdType = createArtifactTypeDef("type2", "description2", NULL_STRING);
+ createdType.setName("newName2");
+
+ createdType = artifactTypeOperation.createArtifactType(createdType, false);
+ assertNotNull(createdType);
+ assertEquals("newName2", createdType.getName());
+ assertEquals("description2", createdType.getDescription());
+ assertEquals(null, createdType.getDerivedFrom());
+ }
+
+ @Test
+ public void createAndModifyArtifactType_WithProps() {
+
+ ArtifactTypeDefinition createdType = createArtifactTypeDef("type3", "description1", "derivedFromTest3");
+ artifactTypeOperation.createArtifactType(createdType, false);
+
+ PropertyDefinition prop1 = createSimpleProperty("val1", "prop1", "string");
+ PropertyDefinition prop2 = createSimpleProperty("val2", "prop2", "string");
+ createdType = createArtifactTypeDef("type3", "description2", NULL_STRING, prop1, prop2);
+ createdType.setName("newName");
+
+ createdType = artifactTypeOperation.createArtifactType(createdType, false);
+ assertNotNull(createdType);
+ assertEquals("newName", createdType.getName());
+ assertEquals("description2", createdType.getDescription());
+ assertEquals(null, createdType.getDerivedFrom());
+ assertEquals(2, createdType.getProperties().size());
+ }
+
+ private ArtifactTypeDefinition createArtifactTypeDef(String type, String description, String derivedFrom) {
+ return createArtifactTypeDef(type, description, derivedFrom, null);
+ }
+
+ private ArtifactTypeDefinition createArtifactTypeDef(String type, String description, String derivedFrom, PropertyDefinition... props) {
+ ArtifactTypeDataDefinition artifactTypeDataDefinition = new ArtifactTypeDataDefinition();
+ artifactTypeDataDefinition.setDescription(description);
+ artifactTypeDataDefinition.setType(type);
+ artifactTypeDataDefinition.setName(type + "name");
+ artifactTypeDataDefinition.setDerivedFrom(derivedFrom);
+ ArtifactTypeDefinition artifactTypeDefinition = new ArtifactTypeDefinition(artifactTypeDataDefinition);
+
+ if (props != null) {
+ artifactTypeDefinition.setProperties(asList(props));
+ }
+ return artifactTypeDefinition;
+ }
+
+} \ No newline at end of file