Support unknown data types in service import 44/130144/6
authorMichaelMorris <michael.morris@est.tech>
Mon, 25 Jul 2022 22:01:50 +0000 (23:01 +0100)
committerAndr� Schmid <andre.schmid@est.tech>
Thu, 11 Aug 2022 10:32:47 +0000 (10:32 +0000)
Signed-off-by: MichaelMorris <michael.morris@est.tech>
Issue-ID: SDC-4119
Change-Id: I426ebb96e7b354dfd5dfb06a10845c3162055968

18 files changed:
catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarInfo.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/OnboardedCsarInfo.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfo.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/OnboardedCsarInfoTest.java [moved from catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java with 94% similarity]
catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfoTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandlerTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypesImportManagerTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBussinessLogicBaseTestSetup.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogicTest.java
catalog-be/src/test/resources/csars/service-Ser09080002-csar.csar [new file with mode: 0644]
catalog-be/src/test/resources/csars/serviceWithUnknownDataTypes.csar [new file with mode: 0644]
catalog-be/src/test/resources/valid_vf.csar

index 1d37efe..aa5706c 100644 (file)
@@ -106,7 +106,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic {
         }
     }
 
-    public CsarInfo getCsarInfo(Resource resource, Resource oldResource, User user, Map<String, byte[]> payload, String csarUUID) {
+    public OnboardedCsarInfo getCsarInfo(Resource resource, Resource oldResource, User user, Map<String, byte[]> payload, String csarUUID) {
         Map<String, byte[]> csar = payload;
         if (csar == null) {
             final var vendorSoftwareProduct = getCsar(resource, user);
@@ -125,7 +125,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic {
                 csarUUID, oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().getImportedToscaChecksum(), checksum);
             oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().setImportedToscaChecksum(checksum);
         }
-        return new CsarInfo(user, csarUUID, resource.getCsarVersionId(), csar, resource.getName(), toscaYamlCsarStatus.getKey(),
+        return new OnboardedCsarInfo(user, csarUUID, resource.getCsarVersionId(), csar, resource.getName(), toscaYamlCsarStatus.getKey(),
             toscaYamlCsarStatus.getValue(), true);
     }
 
@@ -144,7 +144,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic {
         }
     }
 
-    public CsarInfo getCsarInfo(Service service, Service oldResource, User user, Map<String, byte[]> payload, String csarUUID) {
+    public ServiceCsarInfo getCsarInfo(Service service, Service oldResource, User user, Map<String, byte[]> payload, String csarUUID) {
         Map<String, byte[]> csar = getCsar(service, user, payload, csarUUID);
         ImmutablePair<String, String> toscaYamlCsarStatus = validateAndParseCsar(service, user, csar, csarUUID).left()
             .on(this::throwComponentException);
@@ -157,7 +157,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic {
                 csarUUID, oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().getImportedToscaChecksum(), checksum);
             oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().setImportedToscaChecksum(checksum);
         }
-        return new CsarInfo(user, csarUUID, csar, service.getName(), toscaYamlCsarStatus.getKey(), toscaYamlCsarStatus.getValue(), true);
+        return new ServiceCsarInfo(user, csarUUID, csar, service.getName(), toscaYamlCsarStatus.getKey(), toscaYamlCsarStatus.getValue(), true);
     }
 
     public ParsedToscaYamlInfo getParsedToscaYamlInfo(String topologyTemplateYaml, String yamlName, Map<String, NodeTypeInfo> nodeTypesInfo,
index dc6f7c4..49b7bb2 100644 (file)
@@ -21,8 +21,6 @@
  */
 package org.openecomp.sdc.be.components.csar;
 
-import static org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
-import static org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
 import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -37,11 +35,11 @@ import java.util.Optional;
 import java.util.PriorityQueue;
 import java.util.Queue;
 import java.util.Set;
-import java.util.regex.Pattern;
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
+import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
+import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
 import org.openecomp.sdc.be.config.NonManoArtifactType;
 import org.openecomp.sdc.be.config.NonManoConfiguration;
@@ -51,13 +49,15 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.model.NodeTypeInfo;
 import org.openecomp.sdc.be.model.Resource;
 import org.openecomp.sdc.be.model.User;
-import org.openecomp.sdc.be.tosca.CsarUtils;
 import org.openecomp.sdc.be.utils.TypeUtils;
 import org.openecomp.sdc.common.api.Constants;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.yaml.snakeyaml.Yaml;
 
-public class CsarInfo {
+/**
+ * Provides access to the contents of a CSAR
+ */
+public abstract class CsarInfo {
 
     private static final Logger log = Logger.getLogger(CsarInfo.class);
     private final NonManoConfiguration nonManoConfiguration;
@@ -74,22 +74,21 @@ public class CsarInfo {
     private String csarVersionId;
     @Getter
     @Setter
-    private Map<String, byte[]> csar;
+    protected Map<String, byte[]> csar;
     @Getter
     private String mainTemplateName;
     @Getter
     private String mainTemplateContent;
     @Getter
-    private Map<String, Object> mappedToscaMainTemplate;
+    protected Map<String, Object> mappedToscaMainTemplate;
     @Getter
     private Map<String, String> createdNodesToscaResourceNames;
     private Queue<String> cvfcToCreateQueue;
     private boolean isUpdate;
     @Getter
     private Map<String, Resource> createdNodes;
-    private Map<String, Object> datatypeDefinitions;
+    protected Map<String, Object> datatypeDefinitions;
     private Map<String, Object> policytypeDefinitions;
-    private List<Map.Entry<String, byte[]>> globalSubstitutes;
 
 
     public CsarInfo(User modifier, String csarUUID, Map<String, byte[]> csar, String vfResourceName, String mainTemplateName,
@@ -106,18 +105,11 @@ public class CsarInfo {
         this.isUpdate = isUpdate;
         this.createdNodes = new HashMap<>();
         this.nonManoConfiguration = NonManoConfigurationManager.getInstance().getNonManoConfiguration();
-        this.globalSubstitutes = getGlobalSubstitutes(csar);
     }
     
-    private List<Map.Entry<String, byte[]>> getGlobalSubstitutes(final Map<String, byte[]> csar){
-        final List<Map.Entry<String, byte[]>> globalSubstitutesInCsar = new ArrayList<>();
-        for (Map.Entry<String, byte[]> entry : csar.entrySet()) {
-            if (isAServiceTemplate(entry.getKey()) && isGlobalSubstitute(entry.getKey())) {
-                globalSubstitutesInCsar.add(entry);
-            }
-        }
-        return globalSubstitutesInCsar;
-    }    
+    public String getVfResourceName() {
+        return vfResourceName;
+    }
 
     public CsarInfo(final User modifier, final String csarUUID, final String csarVersionId, final Map<String, byte[]> csarContent,
                     final String vfResourceName, final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) {
@@ -174,34 +166,15 @@ public class CsarInfo {
     public void setUpdate(boolean isUpdate) {
         this.isUpdate = isUpdate;
     }
-
-    public Map<String, NodeTypeInfo> extractTypesInfo() {
-        Map<String, NodeTypeInfo> nodeTypesInfo = new HashMap<>();
-        final Set<String> nodeTypesUsedInNodeTemplates = new HashSet<>();
-        for (Map.Entry<String, byte[]> entry : getCsar().entrySet()) {
-            extractNodeTypeInfo(nodeTypesInfo,  nodeTypesUsedInNodeTemplates, entry);
-        }
-        if (CollectionUtils.isNotEmpty(globalSubstitutes)) {
-            setDerivedFrom(nodeTypesInfo);
-            addGlobalSubstitutionsToNodeTypes(nodeTypesUsedInNodeTemplates, nodeTypesInfo);
-        }
-        
-        markNestedVfc(getMappedToscaMainTemplate(), nodeTypesInfo);
-        return nodeTypesInfo;
-    }
     
-    public Map<String, Object> getDataTypes() {
-        if (datatypeDefinitions == null) {
-            datatypeDefinitions = new HashMap<>();
-            for (Map.Entry<String, byte[]> entry : globalSubstitutes) {
-                final String yamlFileContents = new String(entry.getValue());
-                final Map<String, Object> mappedToscaTemplate = new Yaml().load(yamlFileContents);
-                datatypeDefinitions.putAll(getTypesFromTemplate(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.DATA_TYPES));
-            }
-            datatypeDefinitions.putAll(getTypesFromTemplate(mappedToscaMainTemplate, TypeUtils.ToscaTagNamesEnum.DATA_TYPES));
-        }
-        return datatypeDefinitions;
-    }
+    public abstract Map<String, NodeTypeInfo> extractTypesInfo();
+    
+    /**
+     * Get the data types defined in the CSAR
+     * 
+     * @return map with the data type name as key and representaion of the data type defintion as value
+     */
+    public abstract Map<String, Object> getDataTypes();
 
     public Map<String, Object> getPolicyTypes() {
         if (policytypeDefinitions == null) {
@@ -211,8 +184,8 @@ public class CsarInfo {
         return policytypeDefinitions;
     }
     
-    @SuppressWarnings("unchecked")    
-    private Map<String, Object> getTypesFromTemplate(final Map<String, Object> mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum type) {
+    @SuppressWarnings("unchecked")
+    protected Map<String, Object> getTypesFromTemplate(final Map<String, Object> mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum type) {
         final Either<Object, ResultStatusEnum> dataTypesEither = findToscaElement(mappedToscaTemplate, type,
                         ToscaElementTypeEnum.MAP);
         if (dataTypesEither != null && dataTypesEither.isLeft()) {
@@ -221,27 +194,7 @@ public class CsarInfo {
         return Collections.emptyMap();
     }
 
-    @SuppressWarnings("unchecked")
-    private void extractNodeTypeInfo(Map<String, NodeTypeInfo> nodeTypesInfo,
-                                     final Set<String> nodeTypesUsedInNodeTemplates, Map.Entry<String, byte[]> entry) {
-        if (isAServiceTemplate(entry.getKey()) && !isGlobalSubstitute(entry.getKey())) {
-            Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(new String(entry.getValue()));
-            findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS, ToscaElementTypeEnum.MAP).right()
-                .on(sub -> handleSubstitutionMappings(nodeTypesInfo, entry, mappedToscaTemplate, (Map<String, Object>) sub));
-            final Either<Object, ResultStatusEnum> nodeTypesEither = findToscaElement(mappedToscaTemplate,
-                TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES, ToscaElementTypeEnum.MAP);
-            if (nodeTypesEither.isLeft()) {
-                final Map<String, Map<String, Object>> nodeTemplates = (Map<String, Map<String, Object>>) nodeTypesEither.left().value();
-                nodeTypesUsedInNodeTemplates.addAll(findNodeTypesUsedInNodeTemplates(nodeTemplates));
-            }
-        }
-    }
-
-    private boolean isAServiceTemplate(final String filePath) {
-        return Pattern.compile(CsarUtils.SERVICE_TEMPLATE_PATH_PATTERN).matcher(filePath).matches();
-    }
-
-    private Set<String> findNodeTypesUsedInNodeTemplates(final Map<String, Map<String, Object>> nodeTemplates) {
+    protected Set<String> findNodeTypesUsedInNodeTemplates(final Map<String, Map<String, Object>> nodeTemplates) {
         final Set<String> nodeTypes = new HashSet<>();
         for (final Map<String, Object> nodeTemplate : nodeTemplates.values()) {
             nodeTypes.add((String) nodeTemplate.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName()));
@@ -249,84 +202,8 @@ public class CsarInfo {
         return nodeTypes;
     }
 
-    private ResultStatusEnum handleSubstitutionMappings(Map<String, NodeTypeInfo> nodeTypesInfo, Map.Entry<String, byte[]> entry,
-                                                        Map<String, Object> mappedToscaTemplate, Map<String, Object> substitutionMappings) {
-        final Set<String> nodeTypesDefinedInTemplate = findNodeTypesDefinedInTemplate(mappedToscaTemplate);
-        if (substitutionMappings.containsKey(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()) && !nodeTypesDefinedInTemplate
-            .contains(substitutionMappings.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()))) {
-            NodeTypeInfo nodeTypeInfo = new NodeTypeInfo();
-            nodeTypeInfo.setSubstitutionMapping(true);
-            nodeTypeInfo.setType((String) substitutionMappings.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()));
-            nodeTypeInfo.setTemplateFileName(entry.getKey());
-            nodeTypeInfo.setMappedToscaTemplate(mappedToscaTemplate);
-            nodeTypesInfo.put(nodeTypeInfo.getType(), nodeTypeInfo);
-        }
-        return ResultStatusEnum.OK;
-    }
-
-    @SuppressWarnings("unchecked")
-    private Set<String> findNodeTypesDefinedInTemplate(final Map<String, Object> mappedToscaTemplate) {
-        final Either<Object, ResultStatusEnum> nodeTypesEither = findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES,
-            ToscaElementTypeEnum.MAP);
-        if (nodeTypesEither.isLeft()) {
-            final Map<String, Object> nodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
-            return nodeTypes.keySet();
-        }
-        return Collections.emptySet();
-    }
-
-    private boolean isGlobalSubstitute(String fileName) {
-        return fileName.equalsIgnoreCase(Constants.GLOBAL_SUBSTITUTION_TYPES_SERVICE_TEMPLATE) || fileName
-            .equalsIgnoreCase(Constants.ABSTRACT_SUBSTITUTE_GLOBAL_TYPES_SERVICE_TEMPLATE);
-    }
-
-    @SuppressWarnings("unchecked")
-    private void setDerivedFrom(Map<String, NodeTypeInfo> nodeTypesInfo) {
-        for (Map.Entry<String, byte[]> entry : globalSubstitutes) {
-            String yamlFileContents = new String(entry.getValue());
-            Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(yamlFileContents);
-            Either<Object, ResultStatusEnum> nodeTypesEither = findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES,
-                ToscaElementTypeEnum.MAP);
-            if (nodeTypesEither.isLeft()) {
-                Map<String, Object> nodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
-                for (Map.Entry<String, Object> nodeType : nodeTypes.entrySet()) {
-                    processNodeType(nodeTypesInfo, nodeType);
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private void processNodeType(Map<String, NodeTypeInfo> nodeTypesInfo, Map.Entry<String, Object> nodeType) {
-        Map<String, Object> nodeTypeMap = (Map<String, Object>) nodeType.getValue();
-        if (nodeTypeMap.containsKey(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()) && nodeTypesInfo.containsKey(nodeType.getKey())) {
-            NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(nodeType.getKey());
-            List<String> derivedFrom = new ArrayList<>();
-            derivedFrom.add((String) nodeTypeMap.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()));
-            nodeTypeInfo.setDerivedFrom(derivedFrom);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private void addGlobalSubstitutionsToNodeTypes(final Set<String> nodeTypesUsedInNodeTemplates, final Map<String, NodeTypeInfo> nodeTypesInfo) {
-        for (Map.Entry<String, byte[]> entry : globalSubstitutes) {
-            final String yamlFileContents = new String(entry.getValue());
-            final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(yamlFileContents);
-            final Either<Object, ResultStatusEnum> nodeTypesEither = findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES,
-                ToscaElementTypeEnum.MAP);
-            if (nodeTypesEither.isLeft()) {
-                final Map<String, Object> nodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
-                for (final Map.Entry<String, Object> nodeType : nodeTypes.entrySet()) {
-                    if (!nodeTypesInfo.containsKey(nodeType.getKey()) && nodeTypesUsedInNodeTemplates.contains(nodeType.getKey())) {
-                        nodeTypesInfo.put(nodeType.getKey(), buildNodeTypeInfo(nodeType, entry.getKey(), mappedToscaTemplate));
-                    }
-                }
-            }
-        }
-    }
-
     @SuppressWarnings("unchecked")
-    private NodeTypeInfo buildNodeTypeInfo(final Map.Entry<String, Object> nodeType, final String templateFileName,
+    protected NodeTypeInfo buildNodeTypeInfo(final Map.Entry<String, Object> nodeType, final String templateFileName,
                                            final Map<String, Object> mappedToscaTemplate) {
         final NodeTypeInfo nodeTypeInfo = new NodeTypeInfo();
         nodeTypeInfo.setSubstitutionMapping(false);
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/OnboardedCsarInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/OnboardedCsarInfo.java
new file mode 100644 (file)
index 0000000..85f6469
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * -
+ *  ============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.components.csar;
+
+import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import org.apache.commons.collections.CollectionUtils;
+import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
+import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
+import org.openecomp.sdc.be.config.NonManoConfiguration;
+import org.openecomp.sdc.be.model.NodeTypeInfo;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.tosca.CsarUtils;
+import org.openecomp.sdc.be.utils.TypeUtils;
+import org.openecomp.sdc.common.api.Constants;
+import org.yaml.snakeyaml.Yaml;
+import fj.data.Either;
+
+/**
+ * Provides access to the contents of a CSAR which has been created through the SDC onboarding
+ * process
+ */
+public class OnboardedCsarInfo extends CsarInfo {
+
+    private List<Map.Entry<String, byte[]>> globalSubstitutes;
+
+    OnboardedCsarInfo(NonManoConfiguration nonManoConfiguration) {
+        super(nonManoConfiguration);
+    }
+
+    public OnboardedCsarInfo(final User modifier, final String csarUUID, final Map<String, byte[]> csar, final String vfResourceName,
+            final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) {
+        super(modifier, csarUUID, csar, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate);
+        this.globalSubstitutes = getGlobalSubstitutes(csar);
+    }
+
+    public OnboardedCsarInfo(final User modifier, final String csarUUID, final String csarVersionId, final Map<String, byte[]> csarContent,
+            final String vfResourceName, final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) {
+        super(modifier, csarUUID, csarVersionId, csarContent, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate);
+        this.globalSubstitutes = getGlobalSubstitutes(csar);
+    }
+
+    private List<Map.Entry<String, byte[]>> getGlobalSubstitutes(final Map<String, byte[]> csar) {
+        final List<Map.Entry<String, byte[]>> globalSubstitutesInCsar = new ArrayList<>();
+        for (Map.Entry<String, byte[]> entry : csar.entrySet()) {
+            if (isAServiceTemplate(entry.getKey()) && isGlobalSubstitute(entry.getKey())) {
+                globalSubstitutesInCsar.add(entry);
+            }
+        }
+        return globalSubstitutesInCsar;
+    }
+
+    public Map<String, NodeTypeInfo> extractTypesInfo() {
+        final Map<String, NodeTypeInfo> nodeTypesInfo = new HashMap<>();
+        final Set<String> nodeTypesUsedInNodeTemplates = new HashSet<>();
+        for (Map.Entry<String, byte[]> entry : getCsar().entrySet()) {
+            extractNodeTypeInfo(nodeTypesInfo, nodeTypesUsedInNodeTemplates, entry);
+        }
+        if (CollectionUtils.isNotEmpty(globalSubstitutes)) {
+            setDerivedFrom(nodeTypesInfo);
+            addGlobalSubstitutionsToNodeTypes(nodeTypesUsedInNodeTemplates, nodeTypesInfo);
+        }
+
+        markNestedVfc(getMappedToscaMainTemplate(), nodeTypesInfo);
+        return nodeTypesInfo;
+    }
+
+    @SuppressWarnings("unchecked")
+    private void extractNodeTypeInfo(final Map<String, NodeTypeInfo> nodeTypesInfo, final Set<String> nodeTypesUsedInNodeTemplates,
+            final Map.Entry<String, byte[]> entry) {
+        if (isAServiceTemplate(entry.getKey()) && !isGlobalSubstitute(entry.getKey())) {
+            final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(new String(entry.getValue()));
+            findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS, ToscaElementTypeEnum.MAP).right()
+                    .on(sub -> handleSubstitutionMappings(nodeTypesInfo, entry, mappedToscaTemplate, (Map<String, Object>) sub));
+            final Either<Object, ResultStatusEnum> nodeTypesEither =
+                    findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES, ToscaElementTypeEnum.MAP);
+            if (nodeTypesEither.isLeft()) {
+                final Map<String, Map<String, Object>> nodeTemplates = (Map<String, Map<String, Object>>) nodeTypesEither.left().value();
+                nodeTypesUsedInNodeTemplates.addAll(findNodeTypesUsedInNodeTemplates(nodeTemplates));
+            }
+        }
+    }
+
+    private boolean isAServiceTemplate(final String filePath) {
+        return Pattern.compile(CsarUtils.SERVICE_TEMPLATE_PATH_PATTERN).matcher(filePath).matches();
+    }
+
+    private boolean isGlobalSubstitute(final String fileName) {
+        return fileName.equalsIgnoreCase(Constants.GLOBAL_SUBSTITUTION_TYPES_SERVICE_TEMPLATE)
+                || fileName.equalsIgnoreCase(Constants.ABSTRACT_SUBSTITUTE_GLOBAL_TYPES_SERVICE_TEMPLATE);
+    }
+
+
+    private ResultStatusEnum handleSubstitutionMappings(final Map<String, NodeTypeInfo> nodeTypesInfo, final Map.Entry<String, byte[]> entry,
+            final Map<String, Object> mappedToscaTemplate, final Map<String, Object> substitutionMappings) {
+        final Set<String> nodeTypesDefinedInTemplate = findNodeTypesDefinedInTemplate(mappedToscaTemplate);
+        if (substitutionMappings.containsKey(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName())
+                && !nodeTypesDefinedInTemplate.contains(substitutionMappings.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()))) {
+            NodeTypeInfo nodeTypeInfo = new NodeTypeInfo();
+            nodeTypeInfo.setSubstitutionMapping(true);
+            nodeTypeInfo.setType((String) substitutionMappings.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()));
+            nodeTypeInfo.setTemplateFileName(entry.getKey());
+            nodeTypeInfo.setMappedToscaTemplate(mappedToscaTemplate);
+            nodeTypesInfo.put(nodeTypeInfo.getType(), nodeTypeInfo);
+        }
+        return ResultStatusEnum.OK;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Set<String> findNodeTypesDefinedInTemplate(final Map<String, Object> mappedToscaTemplate) {
+        final Either<Object, ResultStatusEnum> nodeTypesEither =
+                findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP);
+        if (nodeTypesEither.isLeft()) {
+            final Map<String, Object> nodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
+            return nodeTypes.keySet();
+        }
+        return Collections.emptySet();
+    }
+
+    @SuppressWarnings("unchecked")
+    private void setDerivedFrom(final Map<String, NodeTypeInfo> nodeTypesInfo) {
+        for (Map.Entry<String, byte[]> entry : globalSubstitutes) {
+            final String yamlFileContents = new String(entry.getValue());
+            final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(yamlFileContents);
+            Either<Object, ResultStatusEnum> nodeTypesEither =
+                    findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP);
+            if (nodeTypesEither.isLeft()) {
+                Map<String, Object> nodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
+                for (Map.Entry<String, Object> nodeType : nodeTypes.entrySet()) {
+                    processNodeType(nodeTypesInfo, nodeType);
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void processNodeType(final Map<String, NodeTypeInfo> nodeTypesInfo, final Map.Entry<String, Object> nodeType) {
+        final Map<String, Object> nodeTypeMap = (Map<String, Object>) nodeType.getValue();
+        if (nodeTypeMap.containsKey(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()) && nodeTypesInfo.containsKey(nodeType.getKey())) {
+            final NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(nodeType.getKey());
+            final List<String> derivedFrom = new ArrayList<>();
+            derivedFrom.add((String) nodeTypeMap.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()));
+            nodeTypeInfo.setDerivedFrom(derivedFrom);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void addGlobalSubstitutionsToNodeTypes(final Set<String> nodeTypesUsedInNodeTemplates, final Map<String, NodeTypeInfo> nodeTypesInfo) {
+        for (Map.Entry<String, byte[]> entry : globalSubstitutes) {
+            final String yamlFileContents = new String(entry.getValue());
+            final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(yamlFileContents);
+            final Either<Object, ResultStatusEnum> nodeTypesEither =
+                    findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP);
+            if (nodeTypesEither.isLeft()) {
+                final Map<String, Object> nodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
+                for (final Map.Entry<String, Object> nodeType : nodeTypes.entrySet()) {
+                    if (!nodeTypesInfo.containsKey(nodeType.getKey()) && nodeTypesUsedInNodeTemplates.contains(nodeType.getKey())) {
+                        nodeTypesInfo.put(nodeType.getKey(), buildNodeTypeInfo(nodeType, entry.getKey(), mappedToscaTemplate));
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public Map<String, Object> getDataTypes() {
+        if (datatypeDefinitions == null) {
+            datatypeDefinitions = new HashMap<>();
+            for (Map.Entry<String, byte[]> entry : globalSubstitutes) {
+                final String yamlFileContents = new String(entry.getValue());
+                final Map<String, Object> mappedToscaTemplate = new Yaml().load(yamlFileContents);
+                datatypeDefinitions.putAll(getTypesFromTemplate(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.DATA_TYPES));
+            }
+            datatypeDefinitions.putAll(getTypesFromTemplate(mappedToscaMainTemplate, TypeUtils.ToscaTagNamesEnum.DATA_TYPES));
+        }
+        return datatypeDefinitions;
+    }
+
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfo.java
new file mode 100644 (file)
index 0000000..ca3c92b
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * -
+ *  ============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.components.csar;
+
+import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
+import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
+import org.openecomp.sdc.be.model.NodeTypeInfo;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.utils.TypeUtils;
+import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.yaml.snakeyaml.Yaml;
+import fj.data.Either;
+
+/**
+ * Provides access to the contents of a Service CSAR
+ */
+public class ServiceCsarInfo extends CsarInfo {
+
+    private Map<String, Map<String, Object>> mainTemplateImports;
+    private static final Logger log = Logger.getLogger(ServiceCsarInfo.class);
+
+    public ServiceCsarInfo(final User modifier, final String csarUUID, final Map<String, byte[]> csar, final String vfResourceName,
+            final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) {
+        super(modifier, csarUUID, csar, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate);
+
+        final Path mainTemplateDir = Paths.get(getMainTemplateName().substring(0, getMainTemplateName().lastIndexOf('/') + 1));
+        final Collection<Path> filesHandled = new HashSet<>();
+        filesHandled.add(Paths.get(mainTemplateName));
+        this.mainTemplateImports = getTemplateImports(csar, new Yaml().load(mainTemplateContent), mainTemplateDir, filesHandled);
+    }
+    
+    private Map<String, Map<String, Object>> getTemplateImports(final Map<String, byte[]> csar, Map<String, Object> mappedToscaMainTemplate,
+            final Path fileParentDir, final Collection<Path> filesHandled) {
+        final Map<String, Map<String, Object>> templateImports = new HashMap<>();
+
+        final List<Path> importFilePaths = getTempateImportFilePaths(mappedToscaMainTemplate, fileParentDir);
+
+        importFilePaths.stream().filter(path -> !filesHandled.contains(path)).forEach(
+                importFilePath -> {
+                    byte[] importFile = csar.get(importFilePath.toString());
+                    if (importFile != null) {
+                        filesHandled.add(importFilePath);
+                        Map<String, Object> mappedImportFile = new Yaml().load(new String(csar.get(importFilePath.toString())));
+                        templateImports.put(importFilePath.toString(), mappedImportFile);
+                        
+                        templateImports.putAll(getTemplateImports(csar, mappedImportFile, importFilePath.getParent(), filesHandled));
+                        
+                    } else {
+                        log.info("Import {} cannot be found in CSAR", importFilePath.toString());
+                    }
+                });
+
+        return templateImports;
+    }
+    
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    private List<Path> getTempateImportFilePaths(final Map<String, Object> mappedToscaTemplate, final Path fileParentDir) {
+        final Either<Object, ResultStatusEnum> importsEither =
+                findToscaElement(mappedToscaTemplate, ToscaTagNamesEnum.IMPORTS, ToscaElementTypeEnum.ALL);
+
+        if (importsEither.isLeft()) {
+            final List importsList = (List) importsEither.left().value();
+            if (CollectionUtils.isNotEmpty(importsList)) {
+                if (importsList.get(0) instanceof String) {
+                    List<Path> importPaths = new ArrayList<>();
+                    importsList.stream().forEach(importPath -> importPaths.add(Paths.get((String)importPath)));
+                    return importPaths;
+                } else if (importsList.get(0) instanceof Map) {
+                    return getTemplateImportFilePathsMultiLineGrammar(importsList, fileParentDir);
+                }
+            }
+
+        }
+        return Collections.emptyList();
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<Path> getTemplateImportFilePathsMultiLineGrammar(final List<Map<String, Object>> importsList, final Path fileParentDir) {
+        final List<Path> importFiles = new ArrayList<>();
+
+        for (Map<String, Object> importFileMultiLineGrammar : (List<Map<String, Object>>) importsList) {
+            if (MapUtils.isNotEmpty(importFileMultiLineGrammar)) {
+                if (importFileMultiLineGrammar.values().iterator().next() instanceof String) {
+                    Path relativePath = Paths.get((String) importFileMultiLineGrammar.get("file"));
+                    Path absolutePath = fileParentDir.resolve(relativePath).normalize();
+                    importFiles.add(absolutePath);
+                } else if (importFileMultiLineGrammar.values().iterator().next() instanceof Map) {
+                    importFileMultiLineGrammar.values().forEach(value -> {
+                        Path relativePath = Paths.get((String) ((Map<String, Object>) value).get("file"));
+                        Path absolutePath = fileParentDir == null ? relativePath : fileParentDir.resolve(relativePath).normalize();
+                        importFiles.add(absolutePath);
+                    });
+                }
+            }
+        }
+        return importFiles;
+    }
+
+    @Override
+    public Map<String, NodeTypeInfo> extractTypesInfo() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<String, Object> getDataTypes() {
+        final Map<String, Object> definitions = new HashMap<>();
+        mainTemplateImports.entrySet().stream()
+                .forEach(entry -> definitions.putAll(getTypesFromTemplate(entry.getValue(), TypeUtils.ToscaTagNamesEnum.DATA_TYPES)));
+        definitions.putAll(getTypesFromTemplate(getMappedToscaMainTemplate(), TypeUtils.ToscaTagNamesEnum.DATA_TYPES));
+        return definitions;
+    }
+
+}
index cad0f28..60fdc0b 100644 (file)
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
+
 package org.openecomp.sdc.be.components.impl;
 
 import fj.data.Either;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -72,17 +75,66 @@ public class DataTypeImportManager {
     }
 
     private Either<List<DataTypeDefinition>, ActionStatus> createDataTypesFromYml(final String dataTypesYml, final String modelName) {
-        final Either<List<DataTypeDefinition>, ActionStatus> dataTypes = commonImportManager.createElementTypesFromYml(dataTypesYml,
+        final Either<List<DataTypeDefinition>, ActionStatus> dataTypesEither = commonImportManager.createElementTypesFromYml(dataTypesYml,
             this::createDataType);
-        if (dataTypes.isLeft() && StringUtils.isNotEmpty(modelName)) {
+        if (dataTypesEither.isRight()) {
+            return dataTypesEither;
+        }
+        final List<DataTypeDefinition> dataTypes = dataTypesEither.left().value();
+        if (StringUtils.isNotEmpty(modelName)) {
             final Optional<Model> modelOptional = modelOperation.findModelByName(modelName);
             if (modelOptional.isPresent()) {
-                dataTypes.left().value().forEach(dataType -> dataType.setModel(modelName));
-                return dataTypes;
+                dataTypes.forEach(dataType -> dataType.setModel(modelName));
+            } else {
+                return Either.right(ActionStatus.INVALID_MODEL);
+            }
+        }
+        if (log.isTraceEnabled()) {
+            log.trace("Unsorted datatypes order:");
+            dataTypes.stream().forEach(dt -> log.trace(dt.getName()));
+        }
+
+        long startTime = System.currentTimeMillis();
+        List<DataTypeDefinition> sortedDataTypeDefinitions = sortDataTypesByDependencyOrder(dataTypes);
+
+        if (log.isTraceEnabled()) {
+            long sortTime = System.currentTimeMillis() - startTime;
+            log.trace("Sorting " + sortedDataTypeDefinitions.size() + " data types from model: " + modelName + " took: " + sortTime);
+            log.trace("Sorted datatypes order:");
+            sortedDataTypeDefinitions.stream().forEach(dt -> log.trace(dt.getName()));
+        }
+        return Either.left(sortedDataTypeDefinitions);
+    }
+    
+    private List<DataTypeDefinition> sortDataTypesByDependencyOrder(final List<DataTypeDefinition> dataTypes) {
+        final List<DataTypeDefinition> sortedDataTypeDefinitions = new ArrayList<>();
+        final Map<String, DataTypeDefinition> dataTypeDefinitionsMap = new HashMap<>();
+        
+        dataTypes.forEach(dataType -> {
+            
+            int highestDependencyIndex = -1;
+            for (final String dependencyName : getDependencyTypes(dataType)) {
+                final DataTypeDefinition dependency = dataTypeDefinitionsMap.get(dependencyName);
+                final int indexOfDependency = sortedDataTypeDefinitions.lastIndexOf(dependency);
+                highestDependencyIndex = indexOfDependency > highestDependencyIndex ? indexOfDependency : highestDependencyIndex;
             }
-            return Either.right(ActionStatus.INVALID_MODEL);
+            sortedDataTypeDefinitions.add(highestDependencyIndex + 1, dataType);
+            dataTypeDefinitionsMap.put(dataType.getName(), dataType);
+       
+            } );
+        
+        return sortedDataTypeDefinitions;
+    }
+    
+    private Collection<String> getDependencyTypes(final DataTypeDefinition dataType) {
+        final Set<String> dependencies = new HashSet<>();
+        if (dataType.getDerivedFromName() != null) {
+            dependencies.add(dataType.getDerivedFromName());
+        }
+        if (dataType.getProperties() != null) {
+            dataType.getProperties().stream().forEach(property -> dependencies.add(property.getType()));
         }
-        return dataTypes;
+        return dependencies;
     }
 
     private Either<List<ImmutablePair<DataTypeDefinition, Boolean>>, ResponseFormat> createDataTypesByDao(
index 1f107e4..b923cbc 100644 (file)
@@ -58,6 +58,7 @@ import org.openecomp.sdc.be.catalog.enums.ChangeTypeEnum;
 import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic;
 import org.openecomp.sdc.be.components.csar.CsarBusinessLogic;
 import org.openecomp.sdc.be.components.csar.CsarInfo;
+import org.openecomp.sdc.be.components.csar.OnboardedCsarInfo;
 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum;
 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
 import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo;
@@ -1041,7 +1042,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic {
         loggerSupportability
             .log(LoggerSupportabilityActions.CREATE_RESOURCE_FROM_YAML, StatusCode.STARTED, "Starting to create Resource From Csar by user {}",
                 user.getUserId());
-        CsarInfo csarInfo = csarBusinessLogic.getCsarInfo(resource, null, user, csarUIPayload, csarUUID);
+        OnboardedCsarInfo csarInfo = csarBusinessLogic.getCsarInfo(resource, null, user, csarUIPayload, csarUUID);
+
         Map<String, NodeTypeInfo> nodeTypesInfo = csarInfo.extractTypesInfo();
         final String model = resource.getModel();
         if (StringUtils.isNotEmpty(model)) {
@@ -1057,7 +1059,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic {
                 policyTypeBusinessLogic.createPolicyTypeFromYaml(new Yaml().dump(policyTypesToCreate), model, true);
             }
         }
-
         Either<Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>>, ResponseFormat> findNodeTypesArtifactsToHandleRes = findNodeTypesArtifactsToHandle(
             nodeTypesInfo, csarInfo, resource);
         if (findNodeTypesArtifactsToHandleRes.isRight()) {
index 7e15a52..e4129a2 100644 (file)
@@ -48,6 +48,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic;
 import org.openecomp.sdc.be.components.csar.CsarBusinessLogic;
 import org.openecomp.sdc.be.components.csar.CsarInfo;
+import org.openecomp.sdc.be.components.csar.ServiceCsarInfo;
 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum;
 import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo;
 import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
@@ -62,6 +63,7 @@ import org.openecomp.sdc.be.config.BeEcompErrorManager;
 import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
 import org.openecomp.sdc.be.datamodel.utils.ArtifactUtils;
 import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter;
 import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
@@ -118,6 +120,8 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
 import org.openecomp.sdc.be.model.operations.StorageException;
 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
+import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
 import org.openecomp.sdc.be.tosca.CsarUtils;
 import org.openecomp.sdc.be.ui.model.OperationUi;
@@ -130,6 +134,7 @@ import org.openecomp.sdc.common.kpi.api.ASDCKpiApi;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.ValidationUtils;
 import org.openecomp.sdc.exception.ResponseFormat;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.yaml.snakeyaml.Yaml;
 
 @Getter
@@ -167,6 +172,9 @@ public class ServiceImportBusinessLogic {
     private final ArtifactsBusinessLogic artifactsBusinessLogic;
     private final IGraphLockOperation graphLockOperation;
     private final ToscaFunctionService toscaFunctionService;
+    private final PropertyOperation propertyOperation;
+    private final DataTypeBusinessLogic dataTypeBusinessLogic;
+    private ApplicationDataTypeCache applicationDataTypeCache;
 
     public ServiceImportBusinessLogic(final GroupBusinessLogic groupBusinessLogic,
                                       final ArtifactsBusinessLogic artifactsBusinessLogic,
@@ -180,7 +188,8 @@ public class ServiceImportBusinessLogic {
                                       final ServiceImportParseLogic serviceImportParseLogic,
                                       final ComponentNodeFilterBusinessLogic componentNodeFilterBusinessLogic,
                                       final PolicyBusinessLogic policyBusinessLogic, final JanusGraphDao janusGraphDao,
-                                      final IGraphLockOperation graphLockOperation, final ToscaFunctionService toscaFunctionService) {
+                                      final IGraphLockOperation graphLockOperation, final ToscaFunctionService toscaFunctionService,
+                                      final PropertyOperation propertyOperation, final DataTypeBusinessLogic dataTypeBusinessLogic) {
         this.componentInstanceBusinessLogic = componentInstanceBusinessLogic;
         this.uiComponentDataConverter = uiComponentDataConverter;
         this.componentsUtils = componentsUtils;
@@ -199,6 +208,13 @@ public class ServiceImportBusinessLogic {
         this.artifactsBusinessLogic = artifactsBusinessLogic;
         this.graphLockOperation = graphLockOperation;
         this.toscaFunctionService = toscaFunctionService;
+        this.propertyOperation = propertyOperation;
+        this.dataTypeBusinessLogic = dataTypeBusinessLogic;
+    }
+    
+    @Autowired
+    public void setApplicationDataTypeCache(ApplicationDataTypeCache applicationDataTypeCache) {
+        this.applicationDataTypeCache = applicationDataTypeCache;
     }
 
     public Service createService(Service service, AuditingActionEnum auditingAction, User user, Map<String, byte[]> csarUIPayload,
@@ -232,7 +248,13 @@ public class ServiceImportBusinessLogic {
     protected Service createServiceFromCsar(Service service, User user, Map<String, byte[]> csarUIPayload, String csarUUID) {
         log.trace("************* created successfully from YAML, resource TOSCA ");
         try {
-            CsarInfo csarInfo = csarBusinessLogic.getCsarInfo(service, null, user, csarUIPayload, csarUUID);
+            ServiceCsarInfo csarInfo = csarBusinessLogic.getCsarInfo(service, null, user, csarUIPayload, csarUUID);
+            
+            final Map<String, Object> dataTypesToCreate = getDatatypesToCreate(service.getModel(), csarInfo);
+            if (MapUtils.isNotEmpty(dataTypesToCreate)) {
+                dataTypeBusinessLogic.createDataTypeFromYaml(new Yaml().dump(dataTypesToCreate), service.getModel(), true);
+            }
+            
             Map<String, NodeTypeInfo> nodeTypesInfo = csarInfo.extractTypesInfo();
             Either<Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>>, ResponseFormat> findNodeTypesArtifactsToHandleRes = serviceImportParseLogic
                 .findNodeTypesArtifactsToHandle(nodeTypesInfo, csarInfo, service);
@@ -250,6 +272,19 @@ public class ServiceImportBusinessLogic {
             throw new ComponentException(ActionStatus.GENERAL_ERROR);
         }
     }
+    
+    private Map<String, Object> getDatatypesToCreate(final String model, final CsarInfo csarInfo) {
+        final Map<String, Object> dataTypesToCreate = new HashMap<>();
+
+        for (final Entry<String, Object> dataTypeEntry : csarInfo.getDataTypes().entrySet()){
+            final Either<DataTypeDefinition, JanusGraphOperationStatus> result = applicationDataTypeCache.get(model, UniqueIdBuilder.buildDataTypeUid(model, dataTypeEntry.getKey()));
+            if (result.isRight() && result.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
+                dataTypesToCreate.put(dataTypeEntry.getKey(), dataTypeEntry.getValue());
+                log.info("Deploying unknown type " + dataTypeEntry.getKey() + " to model " + model + " from package " + csarInfo.getCsarUUID());
+            }
+        }
+        return dataTypesToCreate;
+    }
 
     protected Service createServiceFromYaml(Service service, String topologyTemplateYaml, String yamlName, Map<String, NodeTypeInfo> nodeTypesInfo,
                                             CsarInfo csarInfo,
@@ -2545,7 +2580,7 @@ public class ServiceImportBusinessLogic {
             mapToConvert.put(TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION.getElementName(), toscaVersion.left().value());
             Map<String, Object> nodeTypes = serviceImportParseLogic.getNodeTypesFromTemplate(mappedToscaTemplate);
             createNodeTypes(yamlName, service, needLock, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo,
-                mapToConvert, nodeTypes);
+                    mapToConvert, nodeTypes);
             return csarInfo.getCreatedNodes();
         } catch (Exception e) {
             log.debug("Exception occured when createResourcesFromYamlNodeTypesList,error is:{}", e.getMessage(), e);
@@ -58,9 +58,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
-public class CsarInfoTest {
+public class OnboardedCsarInfoTest {
 
-    private CsarInfo csarInfo;
+    private OnboardedCsarInfo csarInfo;
 
     @Mock
     private User user;
@@ -81,12 +81,12 @@ public class CsarInfoTest {
         new ConfigurationManager(new FSConfigurationSource(ExternalConfiguration.getChangeListener(), "src/test/resources/config/catalog-be"));
     }
     
-    private CsarInfo createCsarInfo(final String csarFileName, final String mainTemplateName) throws URISyntaxException, ZipException {
-      final File csarFile = new File(CsarInfoTest.class.getClassLoader().getResource(csarFileName).toURI());
+    private OnboardedCsarInfo createCsarInfo(final String csarFileName, final String mainTemplateName) throws URISyntaxException, ZipException {
+      final File csarFile = new File(OnboardedCsarInfoTest.class.getClassLoader().getResource(csarFileName).toURI());
       final Map<String, byte[]> payload = ZipUtils.readZip(csarFile, false);
       String mainTemplateContent = new String(payload.get(mainTemplateName));
 
-      return new CsarInfo(user, CSAR_UUID, payload, RESOURCE_NAME,
+      return new OnboardedCsarInfo(user, CSAR_UUID, payload, RESOURCE_NAME,
               mainTemplateName, mainTemplateContent, true);
   }
 
@@ -149,7 +149,7 @@ public class CsarInfoTest {
     @Test
     public void getSoftwareInformationPathTest() {
         final NonManoConfiguration nonManoConfigurationMock = Mockito.mock(NonManoConfiguration.class);
-        final CsarInfo csarInfo = new CsarInfo(nonManoConfigurationMock);
+        final CsarInfo csarInfo = new OnboardedCsarInfo(nonManoConfigurationMock);
         final NonManoFolderType testNonManoFolderType = new NonManoFolderType();
         testNonManoFolderType.setLocation("sw-location-test");
         testNonManoFolderType.setType("informational-test");
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfoTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfoTest.java
new file mode 100644 (file)
index 0000000..80ecc21
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * -
+ *  ============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.components.csar;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import java.io.File;
+import java.net.URISyntaxException;
+import java.util.Map;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.openecomp.sdc.be.config.ConfigurationManager;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.common.impl.ExternalConfiguration;
+import org.openecomp.sdc.common.impl.FSConfigurationSource;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
+
+@ExtendWith(MockitoExtension.class)
+class ServiceCsarInfoTest {
+
+    private ServiceCsarInfo csarInfo;
+
+    @Mock
+    private User user;
+
+    private static final String CSAR_UUID = "csarUUID";
+    private static final String PAYLOAD_NAME = "csars/serviceWithUnknownDataTypes.csar";
+    private static final String SERVICE_NAME = "serviceWithDataType";
+    private static final String MAIN_TEMPLATE_NAME = "Definitions/service-Servicewithdatatype-template.yml";
+
+    @BeforeEach
+    void setup() throws ZipException, URISyntaxException {
+        csarInfo = createCsarInfo(PAYLOAD_NAME, MAIN_TEMPLATE_NAME);
+
+        new ConfigurationManager(new FSConfigurationSource(ExternalConfiguration.getChangeListener(), "src/test/resources/config/catalog-be"));
+    }
+
+    private ServiceCsarInfo createCsarInfo(final String csarFileName, final String mainTemplateName) throws URISyntaxException, ZipException {
+        final File csarFile = new File(ServiceCsarInfoTest.class.getClassLoader().getResource(csarFileName).toURI());
+        final Map<String, byte[]> payload = ZipUtils.readZip(csarFile, false);
+        String mainTemplateContent = new String(payload.get(mainTemplateName));
+
+return new ServiceCsarInfo(user, CSAR_UUID, payload, SERVICE_NAME, mainTemplateName, mainTemplateContent, true);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    void testGetDataTypes() {
+        final Map<String, Object> dataTypes = csarInfo.getDataTypes();
+        assertEquals(184, dataTypes.size());
+        final Map<String, Object> dataTypeDefinition = (Map<String, Object>) dataTypes.get("tosca.datatypes.test_g");
+        assertNotNull(dataTypeDefinition);
+        assertEquals("tosca.datatypes.Root", dataTypeDefinition.get("derived_from"));
+        assertEquals("tosca.datatypes.test_h",
+                ((Map<String, Object>) ((Map<String, Object>) dataTypeDefinition.get("properties")).get("prop2")).get("type"));
+    }
+
+}
index d9525b1..967beb2 100644 (file)
@@ -148,7 +148,7 @@ public class YamlTemplateParsingHandlerTest {
         when(groupTypeBusinessLogic.getLatestGroupTypeByType(eq(HEAT_GROUP_TYPE), any())).thenReturn(heatGroupType);
 
         String main_template_content = new String(csar.get(MAIN_TEMPLATE_NAME));
-        CsarInfo csarInfo = new CsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME,
+        CsarInfo csarInfo = new OnboardedCsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME,
             MAIN_TEMPLATE_NAME, main_template_content, true);
 
         Resource resource = new Resource();
@@ -163,7 +163,7 @@ public class YamlTemplateParsingHandlerTest {
     void parseServicePropertiesInfoFromYamlTest() {
         when(groupTypeBusinessLogic.getLatestGroupTypeByType(eq(HEAT_GROUP_TYPE), any())).thenReturn(heatGroupType);
         String main_template_content = new String(csar.get(MAIN_TEMPLATE_NAME));
-        CsarInfo csarInfo = new CsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME,
+        CsarInfo csarInfo = new OnboardedCsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME,
             MAIN_TEMPLATE_NAME, main_template_content, true);
 
         Service service = new Service();
@@ -183,7 +183,7 @@ public class YamlTemplateParsingHandlerTest {
     void parseRelationshipTemplateInfoFromYamlTest() {
         when(groupTypeBusinessLogic.getLatestGroupTypeByType(eq(HEAT_GROUP_TYPE), any())).thenReturn(heatGroupType);
         String main_template_content = new String(csar.get(MAIN_TEMPLATE_NAME));
-        CsarInfo csarInfo = new CsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME,
+        CsarInfo csarInfo = new OnboardedCsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME,
             MAIN_TEMPLATE_NAME, main_template_content, true);
 
         Service service = new Service();
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypesImportManagerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypesImportManagerTest.java
new file mode 100644 (file)
index 0000000..e4e63fc
--- /dev/null
@@ -0,0 +1,121 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.components.impl;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+import fj.data.Either;
+import java.util.Collections;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
+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;
+
+public class DataTypesImportManagerTest {
+
+    private static final ComponentsUtils componentsUtils = mock(ComponentsUtils.class);
+    private static final JanusGraphGenericDao janusGraphGenericDao = mock(JanusGraphGenericDao.class);
+    private static final PropertyOperation propertyOperation = mock(PropertyOperation.class);
+    private static final ModelOperation modelOperation = mock(ModelOperation.class);
+    @Spy
+    private CommonImportManager commonImportManager = new CommonImportManager(componentsUtils, propertyOperation, modelOperation);
+
+    @InjectMocks
+    private DataTypeImportManager dataTypeImportManager = new DataTypeImportManager();
+
+    private AutoCloseable closeable;
+
+    @BeforeEach
+    public void openMocks() {
+        closeable = MockitoAnnotations.openMocks(this);
+    }
+
+    @AfterEach
+    public void releaseMocks() throws Exception {
+        closeable.close();
+    }
+
+    @Test
+    public void testCreateDataTypes() {
+
+        DataTypeDefinition rootDataTypeDef = new DataTypeDefinition();
+        rootDataTypeDef.setName("tosca.datatypes.Root");
+        rootDataTypeDef.setProperties(Collections.emptyList());
+        DataTypeDefinition testADataTypeDef = new DataTypeDefinition();
+        testADataTypeDef.setName("tosca.datatypes.test_a");
+        testADataTypeDef.setProperties(Collections.emptyList());
+        DataTypeDefinition testCDataTypeDef = new DataTypeDefinition();
+        testCDataTypeDef.setName("tosca.datatypes.test_c");
+        testCDataTypeDef.setProperties(Collections.emptyList());
+        when(propertyOperation.getDataTypeByName("tosca.datatypes.Root", null)).thenReturn(Either.left(rootDataTypeDef));
+        when(propertyOperation.getDataTypeByName("tosca.datatypes.test_c", null)).thenReturn(Either.left(testCDataTypeDef));
+
+        when(propertyOperation.getJanusGraphGenericDao()).thenReturn(janusGraphGenericDao);
+        when(propertyOperation.getDataTypeByUidWithoutDerived("tosca.datatypes.Root.datatype", true)).thenReturn(Either.left(rootDataTypeDef));
+        when(propertyOperation.getDataTypeByUidWithoutDerived("tosca.datatypes.test_a.datatype", true))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        when(propertyOperation.getDataTypeByUidWithoutDerived("tosca.datatypes.test_b.datatype", true))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        when(propertyOperation.getDataTypeByUidWithoutDerived("tosca.datatypes.test_c.datatype", true))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        when(propertyOperation.addDataType(any())).thenReturn(Either.left(testADataTypeDef));
+
+        String dataTypeYml = 
+                "tosca.datatypes.test_a:\n" + 
+                "  derived_from: tosca.datatypes.Root\n" + 
+                "  properties:\n" + 
+                "    prop2:\n" +
+                "      type: tosca.datatypes.test_b\n" +
+                "tosca.datatypes.test_b:\n" +
+                "  derived_from: tosca.datatypes.test_c\n" +
+                "  properties:\n" +
+                "    prop2:\n" +
+                "      type: string\n" +
+                "tosca.datatypes.test_c:\n" +
+                "  derived_from: tosca.datatypes.Root\n" +
+                "  properties:\n" +
+                "    prop1:\n" +
+                "      type: string";
+        dataTypeImportManager.createDataTypes(dataTypeYml, "", false);
+
+        ArgumentCaptor<DataTypeDefinition> dataTypeDefinitionCaptor = ArgumentCaptor.forClass(DataTypeDefinition.class);
+        Mockito.verify(propertyOperation, times(3)).addDataType(dataTypeDefinitionCaptor.capture());
+
+        assertEquals("tosca.datatypes.test_c", dataTypeDefinitionCaptor.getAllValues().get(0).getName());
+        assertEquals("tosca.datatypes.test_b", dataTypeDefinitionCaptor.getAllValues().get(1).getName());
+        assertEquals("tosca.datatypes.test_a", dataTypeDefinitionCaptor.getAllValues().get(2).getName());
+    }
+
+
+}
index ff47d75..cee47ec 100644 (file)
@@ -64,6 +64,7 @@ import org.openecomp.sdc.be.components.ArtifactsResolver;
 import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic;
 import org.openecomp.sdc.be.components.csar.CsarBusinessLogic;
 import org.openecomp.sdc.be.components.csar.CsarInfo;
+import org.openecomp.sdc.be.components.csar.OnboardedCsarInfo;
 import org.openecomp.sdc.be.components.csar.YamlTemplateParsingHandler;
 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum;
 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
@@ -387,7 +388,7 @@ class ResourceBusinessLogicTest {
                 nodeTypesArtifactsToHandle,
                 nodeTypesNewCreatedArtifacts,
                 nodeTypesInfo,
-                new CsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name",
+                new OnboardedCsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name",
                     ImportUtilsTest.loadFileNameToJsonString("normative-types-new-webServer.yml"), true), "");
         });
     }
@@ -1876,7 +1877,7 @@ class ResourceBusinessLogicTest {
         Resource resourceToUpdate = createResourceObject(false);
         String nodeName = Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + "." + "abc";
         String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-webServer.yml");
-        CsarInfo csarInfo = new CsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", jsonContent,
+        CsarInfo csarInfo = new OnboardedCsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", jsonContent,
             true);
         String nestedResourceName = bl.buildNestedToscaResourceName(resourceToUpdate.getResourceType()
                 .name(), csarInfo.getVfResourceName(), nodeName)
@@ -1914,7 +1915,7 @@ class ResourceBusinessLogicTest {
         setCanWorkOnResource(resourceResponse);
         String nodeName = Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + "." + "abc";
         String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-webServer.yml");
-        CsarInfo csarInfo = new CsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", jsonContent,
+        CsarInfo csarInfo = new OnboardedCsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", jsonContent,
             true);
         String nestedResourceName = bl.buildNestedToscaResourceName(resourceToUpdate.getResourceType()
                 .name(), csarInfo.getVfResourceName(), nodeName)
index 1f45f77..d40bac1 100644 (file)
@@ -19,21 +19,28 @@ package org.openecomp.sdc.be.components.impl;
 import static org.assertj.core.api.Java6Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyList;
 import static org.mockito.Mockito.anyMap;
-import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.contains;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.matches;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.isNull;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.openecomp.sdc.be.components.impl.ServiceImportBusinessLogic.CREATE_RESOURCE;
 
 import fj.data.Either;
+import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.net.URISyntaxException;
 import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -43,6 +50,7 @@ import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.collections.map.HashedMap;
@@ -50,9 +58,11 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
 import org.mockito.InjectMocks;
 import org.mockito.MockitoAnnotations;
 import org.openecomp.sdc.be.components.csar.CsarInfo;
+import org.openecomp.sdc.be.components.csar.ServiceCsarInfo;
 import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo;
 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
 import org.openecomp.sdc.be.components.impl.utils.CreateServiceFromYamlParameter;
@@ -96,6 +106,7 @@ import org.openecomp.sdc.be.model.UploadPropInfo;
 import org.openecomp.sdc.be.model.UploadReqInfo;
 import org.openecomp.sdc.be.model.UploadResourceInfo;
 import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
 import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
@@ -104,7 +115,10 @@ import org.openecomp.sdc.be.tosca.CsarUtils;
 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
 import org.openecomp.sdc.common.api.Constants;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.exception.ResponseFormat;
+import org.yaml.snakeyaml.Yaml;
 
 class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTestSetup {
 
@@ -115,6 +129,9 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest
     private final ServletUtils servletUtils = mock(ServletUtils.class);
     private final AbstractValidationsServlet servlet = new ArtifactExternalServlet(userBusinessLogic,
         componentInstanceBusinessLogic, componentsUtils, servletUtils, resourceImportManager, artifactsBusinessLogic);
+    private final ApplicationDataTypeCache applicationDataTypeCache = mock(ApplicationDataTypeCache.class);
+    private final DataTypeBusinessLogic dataTypeBusinessLogic = mock(DataTypeBusinessLogic.class);
+
     @InjectMocks
     private ServiceImportBusinessLogic sIBL;
 
@@ -148,7 +165,7 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest
         when(serviceBusinessLogic.validateServiceBeforeCreate(eq(newService), any(User.class), any(AuditingActionEnum.class)))
             .thenReturn(Either.left(newService));
         when(toscaOperationFacade.validateCsarUuidUniqueness(anyString())).thenReturn(StorageOperationStatus.OK);
-        CsarInfo csarInfo = getCsarInfo();
+        ServiceCsarInfo csarInfo = getCsarInfo();
         when(csarBusinessLogic.getCsarInfo(any(Service.class), any(), any(User.class), any(Map.class), anyString())).thenReturn(csarInfo);
         when(serviceImportParseLogic.findNodeTypesArtifactsToHandle(any(Map.class), any(CsarInfo.class), any(Service.class)))
             .thenReturn(Either.left(new HashMap<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>>()));
@@ -183,7 +200,10 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest
         when(mockJanusGraphDao.commit()).thenReturn(JanusGraphOperationStatus.OK);
         when(graphLockOperation.unlockComponentByName(anyString(), anyString(), any(NodeTypeEnum.class))).thenReturn(StorageOperationStatus.OK);
         when(serviceImportParseLogic.createOutputsOnService(any(Service.class), any(), anyString())).thenReturn(newService);
-
+        
+        when(applicationDataTypeCache.get(any(), contains("tosca.datatypes.test_"))).thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
+        when(applicationDataTypeCache.get(any(), matches("^((?!tosca.datatypes.test_).)*$"))).thenReturn(Either.left(new DataTypeDefinition()));
+        
         Service result = sIBL.createService(oldService, AuditingActionEnum.CREATE_RESOURCE, user, payload, payloadName);
         assertNotNull(result);
         assertNotNull(result.getComponentInstances());
@@ -195,6 +215,13 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest
         assertEquals(1, result.getComponentInstances().get(0).getRequirements().size());
         assertNotNull(result.getCategories());
         assertEquals(1, result.getCategories().size());
+        
+        ArgumentCaptor<String> yaml = ArgumentCaptor.forClass(String.class);
+        verify(dataTypeBusinessLogic).createDataTypeFromYaml(yaml.capture(), isNull(), anyBoolean());
+        Map<String, Object> yamlMap = new Yaml().load(yaml.getValue());
+        assertEquals(2, yamlMap.size());
+        assertNotNull(yamlMap.get("tosca.datatypes.test_a"));
+        assertNotNull(yamlMap.get("tosca.datatypes.test_b"));
     }
 
     @Test
@@ -222,7 +249,7 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest
         Service oldService = createServiceObject(true);
         String csarUUID = "valid_vf";
         Map<String, byte[]> payload = crateCsarFromPayload();
-        CsarInfo csarInfo = getCsarInfo();
+        ServiceCsarInfo csarInfo = getCsarInfo();
         Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> map =
             new HashedMap();
 
@@ -240,7 +267,7 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest
         Resource resource = createOldResource();
         String topologyTemplateYaml = getMainTemplateContent("service_import_template.yml");
         String yamlName = "group.yml";
-        CsarInfo csarInfo = getCsarInfo();
+        ServiceCsarInfo csarInfo = getCsarInfo();
         Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate = new HashMap<>();
         String nodeName = "org.openecomp.resource.derivedFrom.zxjTestImportServiceAb.test";
 
@@ -2342,14 +2369,28 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest
         return mainTemplateContent;
     }
 
-    protected CsarInfo getCsarInfo() {
+    protected ServiceCsarInfo getCsarInfo() {
         String csarUuid = "0010";
         User user = new User("jh0003");
-        Map<String, byte[]> csar = crateCsarFromPayload();
-        String vfReousrceName = "resouceName";
-        String mainTemplateName = "mainTemplateName";
-        String mainTemplateContent = getMainTemplateContent("service_import_template.yml");
-        return new CsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false);
+        
+        try {
+            File csarFile = new File(
+                    ServiceImportBusinessLogicTest.class.getClassLoader().getResource("csars/service-Ser09080002-csar.csar").toURI());
+            Map<String, byte[]> csar = ZipUtils.readZip(csarFile, false);
+        
+            String vfReousrceName = "resouceName";
+            String mainTemplateName = "Definitions/service_import_template.yml";
+            
+            Optional<String> keyOp = csar.keySet().stream().filter(k -> k.endsWith("service-Ser09080002-template.yml")).findAny();
+            byte[] mainTemplateService = keyOp.map(csar::get).orElse(null);
+            assertNotNull(mainTemplateService);
+            final String mainTemplateContent = new String(mainTemplateService);
+            
+            return new ServiceCsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false);
+        } catch (URISyntaxException | ZipException e) {
+            fail(e);
+        }
+        return null;
     }
 
     protected CsarUtils.NonMetaArtifactInfo getNonMetaArtifactInfo() {
index c8fd87c..06594dc 100644 (file)
@@ -44,6 +44,7 @@ import org.openecomp.sdc.ElementOperationMock;
 import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic;
 import org.openecomp.sdc.be.components.csar.CsarBusinessLogic;
 import org.openecomp.sdc.be.components.csar.CsarInfo;
+import org.openecomp.sdc.be.components.csar.OnboardedCsarInfo;
 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
 import org.openecomp.sdc.be.components.impl.utils.CreateServiceFromYamlParameter;
 import org.openecomp.sdc.be.components.validation.UserValidations;
@@ -673,7 +674,7 @@ public class ServiceImportBussinessLogicBaseTestSetup extends BaseBusinessLogicM
         String mainTemplateName = "mainTemplateName";
         String mainTemplateContent = getMainTemplateContent();
         final Service service = createServiceObject(false);
-        CsarInfo csarInfo = new CsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false);
+        CsarInfo csarInfo = new OnboardedCsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false);
         return csarInfo;
     }
 
index c564f59..b3154ef 100644 (file)
@@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyMap;
@@ -33,7 +34,9 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import fj.data.Either;
+import java.io.File;
 import java.io.IOException;
+import java.net.URISyntaxException;
 import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.util.ArrayList;
@@ -44,6 +47,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.NoSuchElementException;
+import java.util.Optional;
 import org.apache.commons.collections.map.HashedMap;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.glassfish.grizzly.http.util.HttpStatus;
@@ -54,6 +58,7 @@ import org.mockito.MockitoAnnotations;
 import org.openecomp.sdc.ElementOperationMock;
 import org.openecomp.sdc.be.auditing.impl.AuditingManager;
 import org.openecomp.sdc.be.components.csar.CsarInfo;
+import org.openecomp.sdc.be.components.csar.ServiceCsarInfo;
 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum;
 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
 import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic;
@@ -103,16 +108,14 @@ import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
 import org.openecomp.sdc.be.user.Role;
 import org.openecomp.sdc.common.api.Constants;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.exception.ResponseFormat;
 
 class ServiceImportParseLogicTest extends ServiceImportBussinessLogicBaseTestSetup {
 
     private static final String RESOURCE_NAME = "My-Resource_Name with   space";
     private static final String RESOURCE_TOSCA_NAME = "My-Resource_Tosca_Name";
-    private static final String GENERIC_ROOT_NAME = "tosca.nodes.Root";
-    private static final String GENERIC_VF_NAME = "org.openecomp.resource.abstract.nodes.VF";
-    private static final String GENERIC_CR_NAME = "org.openecomp.resource.abstract.nodes.CR";
-    private static final String GENERIC_PNF_NAME = "org.openecomp.resource.abstract.nodes.PNF";
     private static final String RESOURCE_CATEGORY1 = "Network Layer 2-3";
     private static final String RESOURCE_SUBCATEGORY = "Router";
 
@@ -2074,16 +2077,25 @@ class ServiceImportParseLogicTest extends ServiceImportBussinessLogicBaseTestSet
     protected CsarInfo getCsarInfo() {
         String csarUuid = "0010";
         User user = new User();
-        Map<String, byte[]> csar = new HashMap<>();
-        String vfReousrceName = "resouceName";
-        String mainTemplateName = "mainTemplateName";
-        String mainTemplateContent = null;
+        File csarFile;
         try {
-            mainTemplateContent = loadFileNameToJsonString("service_import_template.yml");
-        } catch (IOException e) {
-            e.printStackTrace();
+            csarFile = new File(
+                    ServiceImportBusinessLogicTest.class.getClassLoader().getResource("csars/service-Ser09080002-csar.csar").toURI());
+            Map<String, byte[]> csar = ZipUtils.readZip(csarFile, false);
+        
+            String vfReousrceName = "resouceName";
+            String mainTemplateName = "Definitions/service_import_template.yml";
+            
+            Optional<String> keyOp = csar.keySet().stream().filter(k -> k.endsWith("service-Ser09080002-template.yml")).findAny();
+            byte[] mainTemplateService = keyOp.map(csar::get).orElse(null);
+            assertNotNull(mainTemplateService);
+            final String mainTemplateContent = new String(mainTemplateService);
+            
+            return new ServiceCsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false);
+        } catch (URISyntaxException | ZipException e) {
+            fail(e);
         }
-        return new CsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false);
+        return null;
     }
 
     private String loadFileNameToJsonString(String fileName) throws IOException {
diff --git a/catalog-be/src/test/resources/csars/service-Ser09080002-csar.csar b/catalog-be/src/test/resources/csars/service-Ser09080002-csar.csar
new file mode 100644 (file)
index 0000000..a658504
Binary files /dev/null and b/catalog-be/src/test/resources/csars/service-Ser09080002-csar.csar differ
diff --git a/catalog-be/src/test/resources/csars/serviceWithUnknownDataTypes.csar b/catalog-be/src/test/resources/csars/serviceWithUnknownDataTypes.csar
new file mode 100644 (file)
index 0000000..ffd2099
Binary files /dev/null and b/catalog-be/src/test/resources/csars/serviceWithUnknownDataTypes.csar differ
index 01bf159..cb9be9b 100644 (file)
Binary files a/catalog-be/src/test/resources/valid_vf.csar and b/catalog-be/src/test/resources/valid_vf.csar differ