Fix additional types import file generation 15/123715/1
authorandre.schmid <andre.schmid@est.tech>
Tue, 31 Aug 2021 09:04:26 +0000 (10:04 +0100)
committerandre.schmid <andre.schmid@est.tech>
Tue, 31 Aug 2021 09:20:06 +0000 (10:20 +0100)
The additional_type_definitions.yaml is missing types entries and
header.
Also, the solution is not considering the types entries, i.e.
'data_types:', 'policy_types:', etc., when replacing types and
generating the new file, which renders the solution broken.
This change aims to fix the related problems.

Change-Id: I412683b49966c09dd067ecbf8a1d778155b23fa6
Issue-ID: SDC-3703
Signed-off-by: andre.schmid <andre.schmid@est.tech>
22 files changed:
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CapabilityTypeImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupTypeImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceLifecycleTypeImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PolicyTypeImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeImportManager.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CommonImportManagerTest.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDao.java
catalog-dao/src/test/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDaoTest.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/normatives/ElementTypeEnum.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java
catalog-model/src/test/resources/modelOperation/expected-additional_types-1.yaml [new file with mode: 0644]
catalog-model/src/test/resources/modelOperation/expected-additional_types-2.yaml [new file with mode: 0644]
catalog-model/src/test/resources/modelOperation/expected-import-1.yaml [new file with mode: 0644]
catalog-model/src/test/resources/modelOperation/expected-import-2.yaml [new file with mode: 0644]
catalog-model/src/test/resources/modelOperation/input-data_types.yaml [new file with mode: 0644]
catalog-model/src/test/resources/modelOperation/original-additional_types-1.yaml [new file with mode: 0644]
catalog-model/src/test/resources/modelOperation/original-import-1.yaml [new file with mode: 0644]
catalog-model/src/test/resources/modelOperation/original-import-2.yaml [new file with mode: 0644]
common-be/src/main/java/org/openecomp/sdc/be/data/model/ToscaImportByModel.java

index c0188d7..48b9c58 100644 (file)
@@ -25,10 +25,10 @@ import java.util.Map;
 import java.util.Optional;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.openecomp.sdc.be.components.impl.CommonImportManager.ElementTypeEnum;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
 import org.openecomp.sdc.be.model.Model;
+import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.CapabilityTypeOperation;
 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
@@ -63,7 +63,7 @@ public class CapabilityTypeImportManager {
             capabilityTypesYml, capabilityTypesFromYml -> createCapabilityTypesFromYml(capabilityTypesYml, modelName),
             this::upsertCapabilityTypesByDao, ElementTypeEnum.CAPABILITY_TYPE);
         if (includeToModelDefaultImports && StringUtils.isNotEmpty(modelName)) {
-            commonImportManager.addTypesToDefaultImports(capabilityTypesYml, modelName);
+            commonImportManager.addTypesToDefaultImports(ElementTypeEnum.CAPABILITY_TYPE, capabilityTypesYml, modelName);
         }
         return elementTypes;
     }
@@ -86,7 +86,7 @@ public class CapabilityTypeImportManager {
     private Either<List<ImmutablePair<CapabilityTypeDefinition, Boolean>>, ResponseFormat> upsertCapabilityTypesByDao(
         List<CapabilityTypeDefinition> capabilityTypesToCreate) {
         return commonImportManager.createElementTypesByDao(capabilityTypesToCreate, capabilityType -> Either.left(ActionStatus.OK),
-            capabilityType -> new ImmutablePair<>(CommonImportManager.ElementTypeEnum.CAPABILITY_TYPE,
+            capabilityType -> new ImmutablePair<>(ElementTypeEnum.CAPABILITY_TYPE,
                 UniqueIdBuilder.buildCapabilityTypeUid(capabilityType.getModel(), capabilityType.getType())),
             capabilityTypeOperation::getCapabilityType, capabilityTypeOperation::addCapabilityType, this::updateCapabilityType);
     }
index c0da9eb..f1582ee 100644 (file)
@@ -48,6 +48,7 @@ import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.GroupTypeDefinition;
 import org.openecomp.sdc.be.model.PolicyTypeDefinition;
 import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
 import org.openecomp.sdc.be.model.normatives.ToscaTypeMetadata;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.api.TypeOperations;
@@ -534,12 +535,8 @@ public class CommonImportManager {
 
     }
 
-    public void addTypesToDefaultImports(final String typesYaml, final String modelName) {
-        modelOperation.addTypesToDefaultImports(typesYaml, modelName);
-    }
-
-    public enum ElementTypeEnum {
-        POLICY_TYPE, GROUP_TYPE, DATA_TYPE, CAPABILITY_TYPE, INTERFACE_LIFECYCLE_TYPE, RELATIONSHIP_TYPE
+    public void addTypesToDefaultImports(final ElementTypeEnum elementTypeEnum, final String typesYaml, final String modelName) {
+        modelOperation.addTypesToDefaultImports(elementTypeEnum, typesYaml, modelName);
     }
 
     public interface ICreateElementType<T1, T2, T3> {
index b24d81b..cad0f28 100644 (file)
@@ -30,13 +30,13 @@ import java.util.stream.Collectors;
 import javax.annotation.Resource;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.openecomp.sdc.be.components.impl.CommonImportManager.ElementTypeEnum;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.Model;
 import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
@@ -66,7 +66,7 @@ public class DataTypeImportManager {
             dataTypeYml, dataTypesFromYml -> createDataTypesFromYml(dataTypeYml, modelName), this::createDataTypesByDao, ElementTypeEnum.DATA_TYPE);
 
         if (includeToModelDefaultImports && StringUtils.isNotEmpty(modelName)) {
-            commonImportManager.addTypesToDefaultImports(dataTypeYml, modelName);
+            commonImportManager.addTypesToDefaultImports(ElementTypeEnum.DATA_TYPE, dataTypeYml, modelName);
         }
         return elementTypes;
     }
index e043bc2..8ff7d99 100644 (file)
@@ -27,7 +27,6 @@ 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.components.impl.CommonImportManager.ElementTypeEnum;
 import org.openecomp.sdc.be.components.impl.model.ToscaTypeImportData;
 import org.openecomp.sdc.be.config.BeEcompErrorManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
@@ -39,6 +38,7 @@ import org.openecomp.sdc.be.model.GroupTypeDefinition;
 import org.openecomp.sdc.be.model.Model;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
+import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.GroupTypeOperation;
 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
@@ -74,7 +74,7 @@ public class GroupTypeImportManager {
         final Either<List<ImmutablePair<GroupTypeDefinition, Boolean>>, ResponseFormat> elementTypes = commonImportManager.createElementTypes(
             toscaTypeImportData, this::createGroupTypesFromYml, this::upsertGroupTypesByDao, modelName);
         if (includeToModelDefaultImports && StringUtils.isNotEmpty(modelName)) {
-            commonImportManager.addTypesToDefaultImports(toscaTypeImportData.getToscaTypesYml(), modelName);
+            commonImportManager.addTypesToDefaultImports(ElementTypeEnum.GROUP_TYPE, toscaTypeImportData.getToscaTypesYml(), modelName);
         }
         return elementTypes;
     }
index 5cc8985..b757faf 100644 (file)
@@ -39,6 +39,7 @@ import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.Model;
 import org.openecomp.sdc.be.model.Operation;
+import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
 import org.openecomp.sdc.be.model.operations.api.IInterfaceLifecycleOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
@@ -72,7 +73,7 @@ public class InterfaceLifecycleTypeImportManager {
         }
         final Either<List<InterfaceDefinition>, ResponseFormat> elementTypes = createInterfacesByDao(interfaces.left().value());
         if (includeToModelDefaultImports && StringUtils.isNotEmpty(modelName)) {
-            commonImportManager.addTypesToDefaultImports(interfaceLifecycleTypesYml, modelName);
+            commonImportManager.addTypesToDefaultImports(ElementTypeEnum.INTERFACE_LIFECYCLE_TYPE, interfaceLifecycleTypesYml, modelName);
         }
         return elementTypes;
     }
index 54d5780..be34cce 100644 (file)
@@ -26,7 +26,6 @@ import java.util.Optional;
 import java.util.function.Consumer;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.openecomp.sdc.be.components.impl.CommonImportManager.ElementTypeEnum;
 import org.openecomp.sdc.be.components.impl.model.ToscaTypeImportData;
 import org.openecomp.sdc.be.components.impl.utils.PolicyTypeImportUtils;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
@@ -36,6 +35,7 @@ import org.openecomp.sdc.be.model.GroupTypeDefinition;
 import org.openecomp.sdc.be.model.Model;
 import org.openecomp.sdc.be.model.PolicyTypeDefinition;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
+import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
 import org.openecomp.sdc.be.model.operations.api.IPolicyTypeOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.GroupOperation;
@@ -75,7 +75,7 @@ public class PolicyTypeImportManager {
         final Either<List<ImmutablePair<PolicyTypeDefinition, Boolean>>, ResponseFormat> elementTypes = commonImportManager.createElementTypes(
             toscaTypeImportData, this::createPolicyTypesFromYml, this::upsertPolicyTypesByDao, modelName);
         if (includeToModelDefaultImports && StringUtils.isNotEmpty(modelName)) {
-            commonImportManager.addTypesToDefaultImports(toscaTypeImportData.getToscaTypesYml(), modelName);
+            commonImportManager.addTypesToDefaultImports(ElementTypeEnum.POLICY_TYPE, toscaTypeImportData.getToscaTypesYml(), modelName);
         }
         return elementTypes;
     }
index 564eb3a..1bd1914 100644 (file)
@@ -21,11 +21,11 @@ import java.util.Map;
 import java.util.Optional;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.openecomp.sdc.be.components.impl.CommonImportManager.ElementTypeEnum;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.model.Model;
 import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
+import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
 import org.openecomp.sdc.be.model.operations.impl.RelationshipTypeOperation;
@@ -67,7 +67,7 @@ public class RelationshipTypeImportManager {
                 relationshipTypesToCreate -> createRelationshipTypesByDao(relationshipTypesToCreate, inTransaction),
                 ElementTypeEnum.RELATIONSHIP_TYPE);
         if (includeToModelDefaultImports && StringUtils.isNotEmpty(modelName)) {
-            commonImportManager.addTypesToDefaultImports(relationshipTypeYml, modelName);
+            commonImportManager.addTypesToDefaultImports(ElementTypeEnum.RELATIONSHIP_TYPE, relationshipTypeYml, modelName);
         }
         return elementTypes;
     }
index b360a94..ce3e124 100644 (file)
@@ -38,11 +38,11 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.junit.MockitoJUnitRunner;
-import org.openecomp.sdc.be.components.impl.CommonImportManager.ElementTypeEnum;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
+import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
index 5d1501c..c250aec 100644 (file)
@@ -84,7 +84,14 @@ public class ToscaModelImportCassandraDao extends CassandraDao {
         LOGGER.info("{} successfully initialized", ToscaModelImportCassandraDao.class.getName());
     }
 
-    public void importAll(final String modelId, final List<ToscaImportByModel> toscaImportByModelList) {
+    /**
+     * Completely replaces the previous model imports by the imports on the given list that are from the same model.
+     * New imports will be added, existing will be replaced and the remaining will be deleted.
+     *
+     * @param modelId                the model id
+     * @param toscaImportByModelList the new list of imports
+     */
+    public void replaceImports(final String modelId, final List<ToscaImportByModel> toscaImportByModelList) {
         final List<ToscaImportByModel> importOfModelList = toscaImportByModelList.stream()
             .filter(toscaImportByModel -> modelId.equals(toscaImportByModel.getModelId()))
             .collect(Collectors.toList());
@@ -99,7 +106,13 @@ public class ToscaModelImportCassandraDao extends CassandraDao {
         );
     }
 
-    public void importOnly(final String modelId, final List<ToscaImportByModel> toscaImportByModelList) {
+    /**
+     * Saves all imports provided on the list that are from the given modelId.
+     *
+     * @param modelId                the model id
+     * @param toscaImportByModelList the list of imports to save
+     */
+    public void saveAll(final String modelId, final List<ToscaImportByModel> toscaImportByModelList) {
         toscaImportByModelList.stream()
             .filter(toscaImportByModel -> modelId.equals(toscaImportByModel.getModelId()))
             .forEach(toscaImportByModelMapper::save);
index cddf3a2..a43e153 100644 (file)
@@ -95,7 +95,7 @@ class ToscaModelImportCassandraDaoTest {
         when(findAllByModelResult.all()).thenReturn(List.of(toscaImportByModel1, toscaImportByModelDatabase1));
         when(toscaImportByModelAccessorMock.findAllByModel(modelId)).thenReturn(findAllByModelResult);
 
-        toscaModelImportCassandraDao.importAll(modelId, importModelList);
+        toscaModelImportCassandraDao.replaceImports(modelId, importModelList);
 
         verify(toscaImportByModelMapperMock).save(toscaImportByModel1);
         verify(toscaImportByModelMapperMock).save(toscaImportByModel2);
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/normatives/ElementTypeEnum.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/normatives/ElementTypeEnum.java
new file mode 100644 (file)
index 0000000..57ca559
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * -
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 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.normatives;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum ElementTypeEnum {
+    POLICY_TYPE("policy_types"),
+    GROUP_TYPE("group_types"),
+    DATA_TYPE("data_types"),
+    CAPABILITY_TYPE("capability_types"),
+    INTERFACE_LIFECYCLE_TYPE("interface_types"),
+    RELATIONSHIP_TYPE("relationship_types");
+
+    private final String toscaEntryName;
+}
index 87ab3fc..967ffdc 100644 (file)
@@ -20,15 +20,15 @@ package org.openecomp.sdc.be.model.operations.impl;
 
 import fj.data.Either;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumMap;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -51,6 +51,7 @@ import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.model.Model;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
+import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.resources.data.ModelData;
@@ -64,7 +65,7 @@ import org.yaml.snakeyaml.Yaml;
 public class ModelOperation {
 
     private static final Logger log = Logger.getLogger(ModelOperation.class);
-    private static final String ADDITIONAL_TYPE_DEFINITIONS = "additional_type_definitions.yml";
+    static final Path ADDITIONAL_TYPE_DEFINITIONS_PATH = Path.of("additional_type_definitions.yaml");
 
     private final JanusGraphGenericDao janusGraphGenericDao;
     private final JanusGraphDao janusGraphDao;
@@ -173,7 +174,7 @@ public class ModelOperation {
                 toscaImportByModel.setContent(content);
                 return toscaImportByModel;
             }).collect(Collectors.toList());
-        toscaModelImportCassandraDao.importAll(modelId, toscaImportByModelList);
+        toscaModelImportCassandraDao.replaceImports(modelId, toscaImportByModelList);
     }
 
     /**
@@ -257,75 +258,61 @@ public class ModelOperation {
         }
     }
 
-    public void addTypesToDefaultImports(final String typesYaml, final String modelName) {
-        final List<ToscaImportByModel> allSchemaImportsByModel = toscaModelImportCassandraDao.findAllByModel(modelName);
-        final Optional<ToscaImportByModel> additionalTypeDefinitionsOptional = allSchemaImportsByModel.stream()
-            .filter(t -> ADDITIONAL_TYPE_DEFINITIONS.equals(t.getFullPath())).findAny();
-        final ToscaImportByModel toscaImportByModelAdditionalTypeDefinitions;
-        final List<ToscaImportByModel> schemaImportsByModel;
-        if (additionalTypeDefinitionsOptional.isPresent()) {
-            toscaImportByModelAdditionalTypeDefinitions = additionalTypeDefinitionsOptional.get();
-            schemaImportsByModel = allSchemaImportsByModel.stream()
-                .filter(toscaImportByModel -> !ADDITIONAL_TYPE_DEFINITIONS.equals(toscaImportByModel.getFullPath()))
+    public void addTypesToDefaultImports(final ElementTypeEnum elementTypeEnum, final String typesYaml, final String modelName) {
+        final List<ToscaImportByModel> modelImportList = toscaModelImportCassandraDao.findAllByModel(modelName);
+        final Optional<ToscaImportByModel> additionalTypeDefinitionsImportOptional = modelImportList.stream()
+            .filter(t -> ADDITIONAL_TYPE_DEFINITIONS_PATH.equals(Path.of(t.getFullPath()))).findAny();
+        final ToscaImportByModel additionalTypeDefinitionsImport;
+        final List<ToscaImportByModel> rebuiltModelImportList;
+        if (additionalTypeDefinitionsImportOptional.isPresent()) {
+            additionalTypeDefinitionsImport = additionalTypeDefinitionsImportOptional.get();
+            rebuiltModelImportList = modelImportList.stream()
+                .filter(toscaImportByModel -> !ADDITIONAL_TYPE_DEFINITIONS_PATH.equals(Path.of(toscaImportByModel.getFullPath())))
                 .collect(Collectors.toList());
         } else {
-            toscaImportByModelAdditionalTypeDefinitions = new ToscaImportByModel();
-            toscaImportByModelAdditionalTypeDefinitions.setModelId(modelName);
-            toscaImportByModelAdditionalTypeDefinitions.setFullPath(ADDITIONAL_TYPE_DEFINITIONS);
-            toscaImportByModelAdditionalTypeDefinitions.setContent(typesYaml);
-            schemaImportsByModel = new ArrayList<>(allSchemaImportsByModel);
+            additionalTypeDefinitionsImport = new ToscaImportByModel();
+            additionalTypeDefinitionsImport.setModelId(modelName);
+            additionalTypeDefinitionsImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
+            additionalTypeDefinitionsImport.setContent(createAdditionalTypeDefinitionsHeader());
+            rebuiltModelImportList = new ArrayList<>(modelImportList);
         }
 
-        final List<ToscaImportByModel> toscaImportByModels = removeExistingDefaultImports(typesYaml, schemaImportsByModel);
+        final Map<String, Object> typesYamlMap = new Yaml().load(typesYaml);
+        removeExistingTypesFromDefaultImports(elementTypeEnum, typesYamlMap, rebuiltModelImportList);
 
-        final Map<String, Object> originalContent = (Map<String, Object>) new Yaml().load(toscaImportByModelAdditionalTypeDefinitions.getContent());
-        toscaImportByModelAdditionalTypeDefinitions.setContent(buildAdditionalTypeDefinitionsContent(typesYaml, originalContent).toString());
-        toscaImportByModels.add(toscaImportByModelAdditionalTypeDefinitions);
+        final Map<String, Object> originalContent = new Yaml().load(additionalTypeDefinitionsImport.getContent());
+        additionalTypeDefinitionsImport.setContent(buildAdditionalTypeDefinitionsContent(elementTypeEnum, typesYamlMap, originalContent));
+        rebuiltModelImportList.add(additionalTypeDefinitionsImport);
 
-        toscaModelImportCassandraDao.importOnly(modelName, toscaImportByModels);
+        toscaModelImportCassandraDao.saveAll(modelName, rebuiltModelImportList);
     }
 
-    private List<ToscaImportByModel> removeExistingDefaultImports(final String typesYaml, final List<ToscaImportByModel> schemaImportsByModel) {
-        final List<ToscaImportByModel> toscaImportByModels = new ArrayList<>();
-        schemaImportsByModel.forEach(toscaImportByModel -> {
-            final ToscaImportByModel toscaImportByModelNew = new ToscaImportByModel();
-            toscaImportByModelNew.setModelId(toscaImportByModel.getModelId());
-            toscaImportByModelNew.setFullPath(toscaImportByModel.getFullPath());
-
-            final Map<String, Object> existingImportYamlMap = (Map<String, Object>) new Yaml().load(toscaImportByModel.getContent());
-
-            ((Map<String, Object>) new Yaml().load(typesYaml)).keySet().forEach(existingImportYamlMap::remove);
-
-            final StringBuilder stringBuilder = new StringBuilder();
-            existingImportYamlMap.forEach((key, value) -> {
-                final Map<Object, Object> hashMap = new HashMap<>();
-                hashMap.put(key, value);
-                stringBuilder.append("\n").append(new YamlUtil().objectToYaml(hashMap));
-            });
-
-            toscaImportByModelNew.setContent(stringBuilder.toString());
-            toscaImportByModels.add(toscaImportByModelNew);
+    private void removeExistingTypesFromDefaultImports(final ElementTypeEnum elementTypeEnum, final Map<String, Object> typesYaml,
+                                                       final List<ToscaImportByModel> defaultImportList) {
+        defaultImportList.forEach(toscaImportByModel -> {
+            final Map<String, Object> existingImportYamlMap = new Yaml().load(toscaImportByModel.getContent());
+            final Map<String, Object> currentTypeYamlMap = (Map<String, Object>) existingImportYamlMap.get(elementTypeEnum.getToscaEntryName());
+            if (MapUtils.isNotEmpty(currentTypeYamlMap)) {
+                typesYaml.keySet().forEach(currentTypeYamlMap::remove);
+            }
+            toscaImportByModel.setContent(new YamlUtil().objectToYaml(existingImportYamlMap));
         });
-        return toscaImportByModels;
     }
 
-    private StringBuilder buildAdditionalTypeDefinitionsContent(final String typesYaml, final Map<String, Object> originalContent) {
-        final var stringBuilder = new StringBuilder();
-
-        final Map<String, Object> typesYamlMap = (Map<String, Object>) new Yaml().load(typesYaml);
-        final Set<String> typeYmlKeySet = typesYamlMap.keySet();
+    private String buildAdditionalTypeDefinitionsContent(final ElementTypeEnum elementTypeEnum, final Map<String, Object> typesYamlMap,
+                                                         final Map<String, Object> originalContent) {
+        final Map<String, Object> originalTypeContent = (Map<String, Object>) originalContent.get(elementTypeEnum.getToscaEntryName());
+        if (MapUtils.isEmpty(originalTypeContent)) {
+            originalContent.put(elementTypeEnum.getToscaEntryName(), new LinkedHashMap<>(typesYamlMap));
+        } else {
+            originalTypeContent.putAll(typesYamlMap);
+        }
+        return new YamlUtil().objectToYaml(originalContent);
+    }
 
-        originalContent.forEach((key, value) -> {
-            final Map<Object, Object> hashMap = new HashMap<>();
-            if (typeYmlKeySet.contains(key)) {
-                hashMap.put(key, typesYamlMap.get(key));
-            } else {
-                hashMap.put(key, value);
-            }
-            final String newContent = new YamlUtil().objectToYaml(hashMap);
-            stringBuilder.append("\n").append(newContent);
-        });
-        return stringBuilder;
+    private String createAdditionalTypeDefinitionsHeader() {
+        return "tosca_definitions_version: tosca_simple_yaml_1_3" + "\n"
+            + "description: Auto-generated file that contains package custom types or types added after system installation." + "\n";
     }
 
 }
index e7c5ddb..a27177a 100644 (file)
@@ -21,6 +21,7 @@ package org.openecomp.sdc.be.model.operations.impl;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -32,9 +33,13 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.openecomp.sdc.be.model.operations.impl.ModelOperation.ADDITIONAL_TYPE_DEFINITIONS_PATH;
 
 import fj.data.Either;
+import java.io.IOException;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -68,6 +73,7 @@ import org.openecomp.sdc.be.model.Model;
 import org.openecomp.sdc.be.model.ModelTestBase;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
+import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
 import org.openecomp.sdc.be.resources.data.ModelData;
 import org.springframework.test.context.ContextConfiguration;
@@ -162,16 +168,16 @@ class ModelOperationTest extends ModelTestBase {
         toscaImport2.setFullPath(pathEntry2);
         final List<ToscaImportByModel> toscaImportByModelList = List.of(toscaImport1, toscaImport2);
 
-        verify(toscaModelImportCassandraDao).importAll(modelId, toscaImportByModelList);
+        verify(toscaModelImportCassandraDao).replaceImports(modelId, toscaImportByModelList);
     }
 
     @Test
     void createModelImportsTest_emptyZipContent() {
         var modelId = "modelId";
         modelOperation.createModelImports(modelId, Collections.emptyMap());
-        verify(toscaModelImportCassandraDao, never()).importAll(eq(modelId), anyList());
+        verify(toscaModelImportCassandraDao, never()).replaceImports(eq(modelId), anyList());
         modelOperation.createModelImports(modelId, null);
-        verify(toscaModelImportCassandraDao, never()).importAll(eq(null), anyList());
+        verify(toscaModelImportCassandraDao, never()).replaceImports(eq(null), anyList());
     }
 
     @Test
@@ -335,6 +341,123 @@ class ModelOperationTest extends ModelTestBase {
             .forEach(toscaImportByModel -> assertTrue(actualModelImportList.contains(toscaImportByModel)));
     }
 
+    @Test
+    void addTypesToDefaultImportsTest_nonExistingAdditionalTypesImport() throws IOException {
+        var modelName = "model";
+        final Path testResourcePath = Path.of("src/test/resources/modelOperation");
+
+        final var dataTypesPath = testResourcePath.resolve(Path.of("input-data_types.yaml"));
+        final var dataTypes = Files.readString(dataTypesPath);
+
+        final Path import1RelativePath = Path.of("original-import-1.yaml");
+        final Path import1Path = testResourcePath.resolve(import1RelativePath);
+        final Path import2RelativePath = Path.of("original-import-2.yaml");
+        final Path import2Path = testResourcePath.resolve(import2RelativePath);
+
+        var toscaImportByModel1 = new ToscaImportByModel();
+        toscaImportByModel1.setModelId(modelName);
+        toscaImportByModel1.setFullPath(import1RelativePath.toString());
+        toscaImportByModel1.setContent(Files.readString(import1Path));
+
+        var toscaImportByModel2 = new ToscaImportByModel();
+        toscaImportByModel2.setModelId(modelName);
+        toscaImportByModel2.setFullPath(import2RelativePath.toString());
+        toscaImportByModel2.setContent(Files.readString(import2Path));
+
+        final List<ToscaImportByModel> modelImports = new ArrayList<>();
+        modelImports.add(toscaImportByModel1);
+        modelImports.add(toscaImportByModel2);
+        when(toscaModelImportCassandraDao.findAllByModel(modelName)).thenReturn(modelImports);
+
+        modelOperation.addTypesToDefaultImports(ElementTypeEnum.DATA_TYPE, dataTypes, modelName);
+        ArgumentCaptor<List<ToscaImportByModel>> importListArgumentCaptor = ArgumentCaptor.forClass(List.class);
+        verify(toscaModelImportCassandraDao).saveAll(eq(modelName), importListArgumentCaptor.capture());
+
+        final List<ToscaImportByModel> actualImportList = importListArgumentCaptor.getValue();
+        assertEquals(3, actualImportList.size());
+        assertTrue(actualImportList.contains(toscaImportByModel1));
+        assertTrue(actualImportList.contains(toscaImportByModel2));
+
+        var expectedAdditionalTypesImport = new ToscaImportByModel();
+        expectedAdditionalTypesImport.setModelId(modelName);
+        expectedAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
+        expectedAdditionalTypesImport.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-additional_types-1.yaml"))));
+        final ToscaImportByModel actualAdditionalTypesImport =
+            actualImportList.stream().filter(expectedAdditionalTypesImport::equals).findFirst().orElse(null);
+        assertNotNull(actualAdditionalTypesImport);
+        assertEquals(expectedAdditionalTypesImport.getContent(), actualAdditionalTypesImport.getContent());
+
+        var expectedImport1 = new ToscaImportByModel();
+        expectedImport1.setModelId(modelName);
+        expectedImport1.setFullPath(import1RelativePath.toString());
+        expectedImport1.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-import-1.yaml"))));
+        final ToscaImportByModel actualImport1 = actualImportList.stream().filter(expectedImport1::equals).findFirst().orElse(null);
+        assertNotNull(actualImport1);
+        assertEquals(expectedImport1.getContent(), actualImport1.getContent());
+
+        var expectedImport2 = new ToscaImportByModel();
+        expectedImport2.setModelId(modelName);
+        expectedImport2.setFullPath(import2RelativePath.toString());
+        expectedImport2.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-import-2.yaml"))));
+        final ToscaImportByModel actualImport2 = actualImportList.stream().filter(expectedImport2::equals).findFirst().orElse(null);
+        assertNotNull(actualImport2);
+        assertEquals(expectedImport2.getContent(), actualImport2.getContent());
+    }
+
+    @Test
+    void addTypesToDefaultImportsTest_existingAdditionalTypesImport() throws IOException {
+        var modelName = "model";
+        final Path testResourcePath = Path.of("src/test/resources/modelOperation");
+
+        final var dataTypesPath = testResourcePath.resolve(Path.of("input-data_types.yaml"));
+        final var dataTypes = Files.readString(dataTypesPath);
+
+        final Path import1RelativePath = Path.of("original-import-1.yaml");
+        final Path import1Path = testResourcePath.resolve(import1RelativePath);
+
+        var toscaImportByModel1 = new ToscaImportByModel();
+        toscaImportByModel1.setModelId(modelName);
+        toscaImportByModel1.setFullPath(import1RelativePath.toString());
+        toscaImportByModel1.setContent(Files.readString(import1Path));
+
+        var originalAdditionalTypesImport = new ToscaImportByModel();
+        originalAdditionalTypesImport.setModelId(modelName);
+        originalAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
+        final Path originalAdditionalTypesImportPath = testResourcePath.resolve(Path.of("original-additional_types-1.yaml"));
+        originalAdditionalTypesImport.setContent(Files.readString(originalAdditionalTypesImportPath));
+
+        final List<ToscaImportByModel> modelImports = new ArrayList<>();
+        modelImports.add(toscaImportByModel1);
+        modelImports.add(originalAdditionalTypesImport);
+        when(toscaModelImportCassandraDao.findAllByModel(modelName)).thenReturn(modelImports);
+
+        modelOperation.addTypesToDefaultImports(ElementTypeEnum.DATA_TYPE, dataTypes, modelName);
+        ArgumentCaptor<List<ToscaImportByModel>> importListArgumentCaptor = ArgumentCaptor.forClass(List.class);
+        verify(toscaModelImportCassandraDao).saveAll(eq(modelName), importListArgumentCaptor.capture());
+
+        final List<ToscaImportByModel> actualImportList = importListArgumentCaptor.getValue();
+        assertEquals(2, actualImportList.size());
+        assertTrue(actualImportList.contains(toscaImportByModel1));
+
+        var expectedAdditionalTypesImport = new ToscaImportByModel();
+        expectedAdditionalTypesImport.setModelId(modelName);
+        expectedAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
+        expectedAdditionalTypesImport.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-additional_types-2.yaml"))));
+        final ToscaImportByModel actualAdditionalTypesImport =
+            actualImportList.stream().filter(expectedAdditionalTypesImport::equals).findFirst().orElse(null);
+        assertNotNull(actualAdditionalTypesImport);
+        assertEquals(expectedAdditionalTypesImport.getContent(), actualAdditionalTypesImport.getContent());
+
+        var expectedImport1 = new ToscaImportByModel();
+        expectedImport1.setModelId(modelName);
+        expectedImport1.setFullPath(import1RelativePath.toString());
+        expectedImport1.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-import-1.yaml"))));
+        final ToscaImportByModel actualImport1 = actualImportList.stream().filter(expectedImport1::equals).findFirst().orElse(null);
+        assertNotNull(actualImport1);
+        assertEquals(expectedImport1.getContent(), actualImport1.getContent());
+
+    }
+
     private ToscaImportByModel createModelImport(final String parentModelName, final String importPath) {
         var toscaImportByModel = new ToscaImportByModel();
         toscaImportByModel.setModelId(parentModelName);
diff --git a/catalog-model/src/test/resources/modelOperation/expected-additional_types-1.yaml b/catalog-model/src/test/resources/modelOperation/expected-additional_types-1.yaml
new file mode 100644 (file)
index 0000000..c9e6741
--- /dev/null
@@ -0,0 +1,13 @@
+tosca_definitions_version: tosca_simple_yaml_1_3
+description: Auto-generated file that contains package custom types or types added
+  after system installation.
+data_types:
+  tosca.datatypes.nfv.ServiceAvailability:
+    derived_from: tosca.datatypes.Root
+    description: additional type
+  tosca.datatypes.nfv.L2AddressData:
+    derived_from: tosca.datatypes.Root
+    description: additional type
+  tosca.datatypes.nfv.Unknown:
+    derived_from: tosca.datatypes.Root
+    description: additional type
diff --git a/catalog-model/src/test/resources/modelOperation/expected-additional_types-2.yaml b/catalog-model/src/test/resources/modelOperation/expected-additional_types-2.yaml
new file mode 100644 (file)
index 0000000..2d2c542
--- /dev/null
@@ -0,0 +1,19 @@
+tosca_definitions_version: tosca_simple_yaml_1_3
+description: Auto-generated file that contains package custom types or types added
+  after system installation.
+data_types:
+  tosca.datatypes.nfv.PreviouslyExistingType1:
+    derived_from: tosca.datatypes.Root
+    description: additional type
+  tosca.datatypes.nfv.PreviouslyExistingType2:
+    derived_from: tosca.datatypes.Root
+    description: additional type
+  tosca.datatypes.nfv.ServiceAvailability:
+    derived_from: tosca.datatypes.Root
+    description: additional type
+  tosca.datatypes.nfv.L2AddressData:
+    derived_from: tosca.datatypes.Root
+    description: additional type
+  tosca.datatypes.nfv.Unknown:
+    derived_from: tosca.datatypes.Root
+    description: additional type
diff --git a/catalog-model/src/test/resources/modelOperation/expected-import-1.yaml b/catalog-model/src/test/resources/modelOperation/expected-import-1.yaml
new file mode 100644 (file)
index 0000000..cecb1b4
--- /dev/null
@@ -0,0 +1,5 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+description: ETSI NFV SOL 001 nsd types definitions version 2.5.1
+data_types:
+  tosca.datatypes.nfv.AddressData:
+    derived_from: tosca.datatypes.Root
diff --git a/catalog-model/src/test/resources/modelOperation/expected-import-2.yaml b/catalog-model/src/test/resources/modelOperation/expected-import-2.yaml
new file mode 100644 (file)
index 0000000..cdee947
--- /dev/null
@@ -0,0 +1,7 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+description: ETSI NFV SOL 001 vnfd types definitions version 2.5.1
+data_types:
+  tosca.datatypes.nfv.L3AddressData:
+    derived_from: tosca.datatypes.Root
+  tosca.datatypes.nfv.AddressData:
+    derived_from: tosca.datatypes.Root
diff --git a/catalog-model/src/test/resources/modelOperation/input-data_types.yaml b/catalog-model/src/test/resources/modelOperation/input-data_types.yaml
new file mode 100644 (file)
index 0000000..77b7d97
--- /dev/null
@@ -0,0 +1,9 @@
+tosca.datatypes.nfv.ServiceAvailability:
+  derived_from: tosca.datatypes.Root
+  description: additional type
+tosca.datatypes.nfv.L2AddressData:
+  derived_from: tosca.datatypes.Root
+  description: additional type
+tosca.datatypes.nfv.Unknown:
+  derived_from: tosca.datatypes.Root
+  description: additional type
\ No newline at end of file
diff --git a/catalog-model/src/test/resources/modelOperation/original-additional_types-1.yaml b/catalog-model/src/test/resources/modelOperation/original-additional_types-1.yaml
new file mode 100644 (file)
index 0000000..c2cc7f1
--- /dev/null
@@ -0,0 +1,10 @@
+tosca_definitions_version: tosca_simple_yaml_1_3
+description: Auto-generated file that contains package custom types or types added
+  after system installation.
+data_types:
+  tosca.datatypes.nfv.PreviouslyExistingType1:
+    derived_from: tosca.datatypes.Root
+    description: additional type
+  tosca.datatypes.nfv.PreviouslyExistingType2:
+    derived_from: tosca.datatypes.Root
+    description: additional type
diff --git a/catalog-model/src/test/resources/modelOperation/original-import-1.yaml b/catalog-model/src/test/resources/modelOperation/original-import-1.yaml
new file mode 100644 (file)
index 0000000..d54e61e
--- /dev/null
@@ -0,0 +1,9 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+description: ETSI NFV SOL 001 nsd types definitions version 2.5.1
+
+data_types:
+  tosca.datatypes.nfv.ServiceAvailability:
+    derived_from: tosca.datatypes.Root
+    description: original type that will be replaced
+  tosca.datatypes.nfv.AddressData:
+    derived_from: tosca.datatypes.Root
diff --git a/catalog-model/src/test/resources/modelOperation/original-import-2.yaml b/catalog-model/src/test/resources/modelOperation/original-import-2.yaml
new file mode 100644 (file)
index 0000000..8ba6b8b
--- /dev/null
@@ -0,0 +1,11 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+description: ETSI NFV SOL 001 vnfd types definitions version 2.5.1
+
+data_types:
+  tosca.datatypes.nfv.L2AddressData:
+    derived_from: tosca.datatypes.Root
+    description: original type that will be replaced
+  tosca.datatypes.nfv.L3AddressData:
+    derived_from: tosca.datatypes.Root
+  tosca.datatypes.nfv.AddressData:
+    derived_from: tosca.datatypes.Root
\ No newline at end of file
index 5e8818b..fabb04f 100644 (file)
@@ -23,9 +23,11 @@ import com.datastax.driver.mapping.annotations.Column;
 import com.datastax.driver.mapping.annotations.PartitionKey;
 import com.datastax.driver.mapping.annotations.Table;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 @Data
 @Table(keyspace = "sdcartifact", name = "tosca_import_by_model")
+@EqualsAndHashCode
 public class ToscaImportByModel {
 
     @PartitionKey
@@ -35,6 +37,7 @@ public class ToscaImportByModel {
     @Column(name = "full_path")
     private String fullPath;
     @Column(name = "content")
+    @EqualsAndHashCode.Exclude
     private String content;
 
 }