Service Import - Input appearing as a property
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / tosca / ToscaExportHandler.java
index 52ced65..069e4f3 100644 (file)
@@ -22,17 +22,25 @@ package org.openecomp.sdc.be.tosca;
 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
 import static org.apache.commons.collections.MapUtils.isNotEmpty;
 import static org.openecomp.sdc.be.components.utils.PropertiesUtils.resolvePropertyValueFromInput;
-import static org.openecomp.sdc.be.tosca.InterfacesOperationsConverter.addInterfaceTypeElement;
 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.primitives.Ints;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonReader;
 import fj.data.Either;
+import java.io.StringReader;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
@@ -44,9 +52,9 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
-import lombok.NoArgsConstructor;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
+import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.ImmutableTriple;
@@ -56,6 +64,7 @@ import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundExcept
 import org.openecomp.sdc.be.config.Configuration;
 import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
+import org.openecomp.sdc.be.data.model.ToscaImportByModel;
 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
@@ -99,6 +108,8 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade
 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
+import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
+import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
@@ -125,6 +136,7 @@ import org.openecomp.sdc.be.tosca.utils.InputConverter;
 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
 import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.yaml.snakeyaml.DumperOptions;
 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
@@ -139,7 +151,6 @@ import org.yaml.snakeyaml.nodes.Tag;
 import org.yaml.snakeyaml.representer.Represent;
 import org.yaml.snakeyaml.representer.Representer;
 
-@NoArgsConstructor
 @org.springframework.stereotype.Component("tosca-export-handler")
 public class ToscaExportHandler {
 
@@ -156,21 +167,21 @@ public class ToscaExportHandler {
     private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
         .of("Service Function", "Service Role", "Naming Policy", "Service Type");
     private static final YamlUtil yamlUtil = new YamlUtil();
-    private static final String COULD_NOT_PARSE_COMPONENT_ATTRIBUTES_COMPONENT_UNIQUE_ID = "Could not parse component '{}' attributes. Component unique id '{}'.";
-    private ApplicationDataTypeCache dataTypeCache;
-    private ToscaOperationFacade toscaOperationFacade;
-    private CapabilityRequirementConverter capabilityRequirementConverter;
-    private PolicyExportParser policyExportParser;
-    private GroupExportParser groupExportParser;
-    private PropertyConvertor propertyConvertor;
-    private AttributeConverter attributeConverter;
-    private InputConverter inputConverter;
-    private OutputConverter outputConverter;
-    private InterfaceLifecycleOperation interfaceLifecycleOperation;
-    private InterfacesOperationsConverter interfacesOperationsConverter;
+    private final ApplicationDataTypeCache applicationDataTypeCache;
+    private final ToscaOperationFacade toscaOperationFacade;
+    private final CapabilityRequirementConverter capabilityRequirementConverter;
+    private final PolicyExportParser policyExportParser;
+    private final GroupExportParser groupExportParser;
+    private final PropertyConvertor propertyConvertor;
+    private final AttributeConverter attributeConverter;
+    private final InputConverter inputConverter;
+    private final OutputConverter outputConverter;
+    private final InterfaceLifecycleOperation interfaceLifecycleOperation;
+    private final InterfacesOperationsConverter interfacesOperationsConverter;
+    private final ModelOperation modelOperation;
 
     @Autowired
-    public ToscaExportHandler(final ApplicationDataTypeCache dataTypeCache,
+    public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache,
                               final ToscaOperationFacade toscaOperationFacade,
                               final CapabilityRequirementConverter capabilityRequirementConverter,
                               final PolicyExportParser policyExportParser,
@@ -180,8 +191,9 @@ public class ToscaExportHandler {
                               final InputConverter inputConverter,
                               final OutputConverter outputConverter,
                               final InterfaceLifecycleOperation interfaceLifecycleOperation,
-                              final InterfacesOperationsConverter interfacesOperationsConverter) {
-        this.dataTypeCache = dataTypeCache;
+                              final InterfacesOperationsConverter interfacesOperationsConverter,
+                              final ModelOperation modelOperation) {
+        this.applicationDataTypeCache = applicationDataTypeCache;
         this.toscaOperationFacade = toscaOperationFacade;
         this.capabilityRequirementConverter = capabilityRequirementConverter;
         this.policyExportParser = policyExportParser;
@@ -192,6 +204,7 @@ public class ToscaExportHandler {
         this.outputConverter = outputConverter;
         this.interfaceLifecycleOperation = interfaceLifecycleOperation;
         this.interfacesOperationsConverter = interfacesOperationsConverter;
+        this.modelOperation = modelOperation;
     }
 
     public static String getInterfaceFilename(String artifactName) {
@@ -211,7 +224,7 @@ public class ToscaExportHandler {
     }
 
     public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
-        final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImportConfig());
+        final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel()));
         if (CollectionUtils.isEmpty(imports)) {
             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
             return Either.right(ToscaError.GENERAL_ERROR);
@@ -220,7 +233,8 @@ public class ToscaExportHandler {
         if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
             .startsWith("org.openecomp.resource.abstract.nodes.")) {
             final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
-                .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion());
+                .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
+                    component.getModel());
             if (baseType.isLeft() && baseType.left().value() != null) {
                 addDependencies(imports, dependencies, baseType.left().value());
             } else {
@@ -246,7 +260,7 @@ public class ToscaExportHandler {
         return Either.left(toscaRepresentation);
     }
 
-    public ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
+    private ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
         CustomRepresenter representer = new CustomRepresenter();
         DumperOptions options = new DumperOptions();
         options.setAllowReadOnlyProperties(false);
@@ -274,7 +288,7 @@ public class ToscaExportHandler {
     }
 
     public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
-        final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
+        final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
         if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
             return Either.right(ToscaError.GENERAL_ERROR);
@@ -297,6 +311,26 @@ public class ToscaExportHandler {
         }
     }
 
+    private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId) {
+        if (modelId == null) {
+            return getDefaultToscaImportConfig();
+        }
+
+        final List<ToscaImportByModel> allModelImports = modelOperation.findAllModelImports(modelId, true);
+        final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
+        final Set<Path> addedPathList = new HashSet<>();
+        for (final ToscaImportByModel toscaImportByModel : allModelImports) {
+            var importPath = Path.of(toscaImportByModel.getFullPath());
+            if (addedPathList.contains(importPath)) {
+                importPath = ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
+            }
+            final String fileName = FilenameUtils.getBaseName(importPath.toString());
+            importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
+            addedPathList.add(importPath);
+        }
+        return importList;
+    }
+
     private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
         Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
         if (importsRes.isRight()) {
@@ -323,7 +357,7 @@ public class ToscaExportHandler {
         if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
             toscaNode.setInterface_types(proxyInterfaceTypes);
         }
-        Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
+        Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
         if (dataTypesEither.isRight()) {
             log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
             return Either.right(ToscaError.GENERAL_ERROR);
@@ -360,8 +394,6 @@ public class ToscaExportHandler {
         if (!relationshipTemplatesMap.isEmpty()) {
             topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
         }
-        SubstitutionMapping substitutionMapping = new SubstitutionMapping();
-        convertSubstitutionMappingFilter(component, substitutionMapping);
         addGroupsToTopologyTemplate(component, topologyTemplate);
         try {
             addPoliciesToTopologyTemplate(component, topologyTemplate);
@@ -369,48 +401,86 @@ public class ToscaExportHandler {
             log.debug("Fail to add policies to topology template:", e);
             return Either.right(ToscaError.GENERAL_ERROR);
         }
-        String toscaResourceName;
+        try {
+            createSubstitutionMapping(component, componentCache).ifPresent(topologyTemplate::setSubstitution_mappings);
+        } catch (final ToscaExportException e) {
+            log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ToscaExportHandler.class.getName(), e.getMessage());
+            return Either.right(e.getToscaError());
+        }
+        if (!topologyTemplate.isEmpty()) {
+            toscaNode.setTopology_template(topologyTemplate);
+        }
+        return Either.left(toscaNode);
+    }
+
+    private Either<String, ToscaError> createComponentToscaName(final Component component) {
         switch (component.getComponentType()) {
             case RESOURCE:
-                toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition())
-                    .getToscaResourceName();
-                break;
+                final ResourceMetadataDataDefinition resourceMetadata =
+                    (ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition();
+                return Either.left(resourceMetadata.getToscaResourceName());
             case SERVICE:
-                toscaResourceName = SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
-                break;
+                return Either.left(SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName());
             default:
                 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
                 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
         }
+    }
+
+    private Optional<SubstitutionMapping> createSubstitutionMapping(final Component component,
+                                                                    final Map<String, Component> componentCache) throws ToscaExportException {
+        if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
+            return Optional.empty();
+        }
+
+        final Either<String, ToscaError> toscaResourceNameEither = createComponentToscaName(component);
+        if (toscaResourceNameEither.isRight()) {
+            throw new ToscaExportException("Could not create component TOSCA name", toscaResourceNameEither.right().value());
+        }
+        final String toscaResourceName = toscaResourceNameEither.left().value();
+
+        final SubstitutionMapping substitutionMapping = new SubstitutionMapping();
         substitutionMapping.setNode_type(toscaResourceName);
-        Either<SubstitutionMapping, ToscaError> capabilities = convertCapabilities(component, substitutionMapping, componentCache);
-        if (capabilities.isRight()) {
-            return Either.right(capabilities.right().value());
+        convertSubstitutionMappingFilter(component).ifPresent(substitutionMapping::setSubstitution_filter);
+
+        final Either<Map<String, String[]>, ToscaError> capabilitiesEither = convertSubstitutionMappingCapabilities(component, componentCache);
+        if (capabilitiesEither.isRight()) {
+            throw new ToscaExportException("Could not convert substitution mapping capabilities", capabilitiesEither.right().value());
+        }
+        final Map<String, String[]> capabilityMap = capabilitiesEither.left().value();
+        if (!capabilityMap.isEmpty()) {
+            substitutionMapping.setCapabilities(capabilityMap);
         }
-        substitutionMapping = capabilities.left().value();
-        Either<SubstitutionMapping, ToscaError> requirements = capabilityRequirementConverter
-            .convertSubstitutionMappingRequirements(componentCache, component, substitutionMapping);
+
+        final Either<Map<String, String[]>, ToscaError> requirements =
+            capabilityRequirementConverter.convertSubstitutionMappingRequirements(component, componentCache);
         if (requirements.isRight()) {
-            return Either.right(requirements.right().value());
+            throw new ToscaExportException("Could not convert substitution mapping requirements", requirements.right().value());
         }
-        substitutionMapping = requirements.left().value();
+        final Map<String, String[]> requirementMap = requirements.left().value();
+        if (MapUtils.isNotEmpty(requirementMap)) {
+            substitutionMapping.setRequirements(requirementMap);
+        }
+
         final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
-        if (!propertyMappingMap.isEmpty()) {
+        if (MapUtils.isNotEmpty(propertyMappingMap)) {
             substitutionMapping.setProperties(propertyMappingMap);
         }
+
         final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
-        if (!attributesMappingMap.isEmpty()) {
+        if (MapUtils.isNotEmpty(attributesMappingMap)) {
             substitutionMapping.setAttributes(attributesMappingMap);
         }
-        topologyTemplate.setSubstitution_mappings(substitutionMapping);
-        toscaNode.setTopology_template(topologyTemplate);
-        return Either.left(toscaNode);
+
+        return Optional.of(substitutionMapping);
     }
 
-    private void convertSubstitutionMappingFilter(final Component component, final SubstitutionMapping substitutionMapping) {
-        if (component.getSubstitutionFilter() != null && (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() != null) {
-            substitutionMapping.setSubstitution_filter(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
+    private Optional<NodeFilter> convertSubstitutionMappingFilter(final Component component) {
+        if (component.getSubstitutionFilter() == null || (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() == null) {
+            return Optional.empty();
         }
+
+        return Optional.ofNullable(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
     }
 
     private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
@@ -440,6 +510,7 @@ public class ToscaExportHandler {
         toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
         List<CategoryDefinition> categories = component.getCategories();
         CategoryDefinition categoryDefinition = categories.get(0);
+        toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), component.getModel());
         toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
         if (isInstance) {
             toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
@@ -472,7 +543,6 @@ public class ToscaExportHandler {
                 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
                 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
                 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
-                toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), resource.getModel());
                 break;
             case SERVICE:
                 Service service = (Service) component;
@@ -509,7 +579,7 @@ public class ToscaExportHandler {
     }
 
     private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
-        final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
+        final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
         if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
             return Either.right(ToscaError.GENERAL_ERROR);
@@ -520,18 +590,9 @@ public class ToscaExportHandler {
                 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
             List<Triple<String, String, Component>> dependencies = new ArrayList<>();
             Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
-            if (isNotEmpty(toscaArtifacts)) {
-                ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
-                if (artifactDefinition != null) {
-                    Map<String, Map<String, String>> importsListMember = new HashMap<>();
-                    Map<String, String> interfaceFiles = new HashMap<>();
-                    interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()));
-                    StringBuilder keyNameBuilder = new StringBuilder();
-                    keyNameBuilder.append(component.getComponentType().toString().toLowerCase()).append("-").append(component.getName())
-                        .append("-interface");
-                    importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
-                    additionalImports.add(importsListMember);
-                }
+            final Map<String, Map<String, String>> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts);
+            if (!substituteTypeImportEntry.isEmpty()) {
+                additionalImports.add(substituteTypeImportEntry);
             }
             List<ComponentInstance> componentInstances = component.getComponentInstances();
             if (componentInstances != null && !componentInstances.isEmpty()) {
@@ -545,6 +606,25 @@ public class ToscaExportHandler {
         return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
     }
 
+    private Map<String, Map<String, String>> generateComponentSubstituteTypeImport(final Component component,
+                                                                                   final Map<String, ArtifactDefinition> toscaArtifacts) {
+
+        if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
+            return Collections.emptyMap();
+        }
+        if (MapUtils.isEmpty(toscaArtifacts)) {
+            return Collections.emptyMap();
+        }
+        final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
+        if (artifactDefinition == null) {
+            return Collections.emptyMap();
+        }
+        final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface";
+        return Map.of(importEntryName,
+            Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()))
+        );
+    }
+
     private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
         return getConfiguration().getDefaultImports();
     }
@@ -694,29 +774,29 @@ public class ToscaExportHandler {
         log.debug("start convert node type for {}", component.getUniqueId());
         ToscaNodeType toscaNodeType = createNodeType(component);
         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
-            .getAllInterfaceLifecycleTypes();
-        if (lifecycleTypeEither.isRight()) {
+            .getAllInterfaceLifecycleTypes(component.getModel());
+        if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
             log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
             return Either.right(ToscaError.GENERAL_ERROR);
         }
-        List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
-            .collect(Collectors.toList());
-        toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
-        Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
+        if (lifecycleTypeEither.isLeft()) {
+            List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
+                .collect(Collectors.toList());
+            toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
+        }
+        final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
         if (dataTypesEither.isRight()) {
             log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
             return Either.right(ToscaError.GENERAL_ERROR);
         }
         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
         List<InputDefinition> inputDef = component.getInputs();
-        Map<String, ToscaProperty> mergedProperties = new HashMap<>();
         interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
-        addInputsToProperties(dataTypes, inputDef, mergedProperties);
-        final Map<String, ToscaAttribute> toscaAttributeMap;
-        toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
+        final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
         if (!toscaAttributeMap.isEmpty()) {
             toscaNodeType.setAttributes(toscaAttributeMap);
         }
+        final var mergedProperties = convertInputsToProperties(dataTypes, inputDef, component.getUniqueId());
         if (CollectionUtils.isNotEmpty(component.getProperties())) {
             List<PropertyDefinition> properties = component.getProperties();
             Map<String, ToscaProperty> convertedProperties = properties.stream()
@@ -744,8 +824,9 @@ public class ToscaExportHandler {
                     toscaDataType.setProperties(dataType.getProperties().stream()
                         .collect(Collectors.toMap(
                             PropertyDataDefinition::getName,
-                            s -> propertyConvertor
-                                .convertProperty(dataTypes, s, PropertyType.PROPERTY)
+                            s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
+                            (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
+                                toscaProperty)
                         )));
                 }
                 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
@@ -757,6 +838,13 @@ public class ToscaExportHandler {
         return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
     }
 
+    private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
+                                                final ToscaProperty toscaProperty) {
+        final Optional<DataTypeDefinition> match = privateDataTypes.stream()
+            .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
+        return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
+    }
+
     private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
                                                                  final Map<String, DataTypeDefinition> dataTypes) {
         if (CollectionUtils.isEmpty(attributeList)) {
@@ -833,6 +921,20 @@ public class ToscaExportHandler {
             if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
                 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
             }
+            if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
+                List<Object> occur = new ArrayList<>();
+                occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
+                occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
+                nodeTemplate.setOccurrences(occur);
+            }
+            if (componentInstance.getInstanceCount() != null) {
+                ObjectMapper objectMapper = new ObjectMapper();
+                Object obj = convertToToscaObject(componentInstance.getInstanceCount());
+                if (obj != null) {
+                    Map<String, String> map = objectMapper.convertValue(obj, Map.class);
+                    nodeTemplate.setInstance_count(map);
+                }
+            }
             nodeTemplate.setType(componentInstance.getToscaComponentName());
             nodeTemplate.setDirectives(componentInstance.getDirectives());
             nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
@@ -937,6 +1039,32 @@ public class ToscaExportHandler {
         return convertNodeTemplatesRes;
     }
 
+    private Object convertToToscaObject(String value) {
+        try {
+            ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
+            JsonParser jsonParser = new JsonParser();
+            StringReader reader = new StringReader(value);
+            JsonReader jsonReader = new JsonReader(reader);
+            jsonReader.setLenient(true);
+            JsonElement jsonElement = jsonParser.parse(jsonReader);
+            if (jsonElement.isJsonObject()) {
+                JsonObject jsonObj = jsonElement.getAsJsonObject();
+                if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
+                    return mapConverterInst.handleComplexJsonValue(jsonElement);
+                }
+            }
+            return null;
+        } catch (Exception e) {
+            log.debug("convertToToscaValue failed to parse json value :", e);
+            return null;
+        }
+    }
+
+    private Object parseToIntIfPossible(final String value) {
+        final Integer intValue = Ints.tryParse(value);
+        return intValue == null ? value : intValue;
+    }
+
     private void handleInstanceInterfaces(
         Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
         ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
@@ -976,7 +1104,8 @@ public class ToscaExportHandler {
         List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
         if (instanceInputsList != null) {
             instanceInputsList.forEach(input -> {
-                Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue() : input.getDefaultValue();
+                Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
+                    : input.getDefaultValue();
                 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
             });
         }
@@ -1078,7 +1207,7 @@ public class ToscaExportHandler {
             }
 
             Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
-                interfaceLifecycleOperation.getAllInterfaceLifecycleTypes();
+                interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
             if (lifecycleTypeEither.isRight()) {
                 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
                 return Either.right(ToscaError.GENERAL_ERROR);
@@ -1088,7 +1217,7 @@ public class ToscaExportHandler {
                 .map(InterfaceDataDefinition::getType)
                 .collect(Collectors.toList());
             //Add interface types for local interfaces in the original service component for proxy
-            Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
+            Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
                 allGlobalInterfaceTypes);
             if (MapUtils.isNotEmpty(localInterfaceTypes)) {
                 proxyInterfaceTypes.putAll(localInterfaceTypes);
@@ -1183,7 +1312,8 @@ public class ToscaExportHandler {
         String derivedFrom = ((Resource) origComponent).getToscaResourceName();
 
         toscaNodeType.setDerived_from(derivedFrom);
-        Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
+        Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
+            origComponent.getModel());
         if (dataTypesEither.isRight()) {
             log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
         }
@@ -1230,7 +1360,8 @@ public class ToscaExportHandler {
             relations);
         if (isNotEmpty(requirementDefinitionList)) {
             try {
-                final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance, requirementDefinitionList, originComponent, componentCache);
+                final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
+                    requirementDefinitionList, originComponent, componentCache);
                 if (!toscaRequirements.isEmpty()) {
                     nodeTypeTemplate.setRequirements(toscaRequirements);
                 }
@@ -1363,7 +1494,7 @@ public class ToscaExportHandler {
         }
         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
         final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
-            toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName());
+            toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
         if (capabilityNameEither.isRight()) {
             final String errorMsg = String.format(
                 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
@@ -1374,7 +1505,7 @@ public class ToscaExportHandler {
         }
         final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
             .buildSubstitutedName(componentCache, fromOriginComponent,
-                requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName());
+                requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
         if (requirementNameEither.isRight()) {
             final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
                     + "with name %s on a component with uniqueId %s",
@@ -1399,7 +1530,7 @@ public class ToscaExportHandler {
                                                             String fromInstanceId) {
         for (List<RequirementDefinition> reqList : reqMap.values()) {
             Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
-                r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
+                    r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
                 .findFirst();
             if (reqOpt.isPresent()) {
                 return reqOpt;
@@ -1435,20 +1566,21 @@ public class ToscaExportHandler {
         return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
     }
 
-    private Either<SubstitutionMapping, ToscaError> convertCapabilities(Component component, SubstitutionMapping substitutionMappings,
-                                                                        Map<String, Component> componentCache) {
-        Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
-        Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes = capabilityRequirementConverter
-            .convertSubstitutionMappingCapabilities(componentCache, component);
+    private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
+                                                                                             final Map<String, Component> componentCache) {
+        Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
+            capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
         if (toscaCapabilitiesRes.isRight()) {
-            result = Either.right(toscaCapabilitiesRes.right().value());
             log.debug("Failed convert capabilities for the component {}. ", component.getName());
-        } else if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
-            substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value());
+            return Either.right(toscaCapabilitiesRes.right().value());
+        }
+        if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
             log.debug("Finish convert capabilities for the component {}. ", component.getName());
+            return Either.left(toscaCapabilitiesRes.left().value());
         }
         log.debug("Finished to convert capabilities for the component {}. ", component.getName());
-        return result;
+
+        return Either.left(Collections.emptyMap());
     }
 
     private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
@@ -1470,6 +1602,7 @@ public class ToscaExportHandler {
             ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
             artifact.setFile(entry.getValue().getFile());
             artifact.setType(entry.getValue().getType());
+            artifact.setProperties(entry.getValue().getProperties());
             arts.put(entry.getKey(), artifact);
         }
         return arts;
@@ -1620,33 +1753,30 @@ public class ToscaExportHandler {
             .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
     }
 
-    Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
+    private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
         if (Objects.isNull(proxyComponent)) {
             return Optional.empty();
         }
-        Map<String, ToscaProperty> proxyProperties = new HashMap<>();
-        addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties);
+        final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
         if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
             proxyProperties.putAll(proxyComponent.getProperties().stream()
                 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
                     .toMap(PropertyDataDefinition::getName,
-                        property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))));
+                        property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
         }
         return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
     }
 
-    void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
-                               Map<String, ToscaProperty> mergedProperties) {
+    private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
+                                                             String componentUniqueId) {
         if (CollectionUtils.isEmpty(componentInputs)) {
-            return;
-        }
-        for (InputDefinition input : componentInputs) {
-            ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
-            mergedProperties.put(input.getName(), property);
+            return new HashMap<>();
         }
+        return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
+            .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
     }
 
-    Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
+    private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
         if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
             return Optional.empty();
         }