diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/NsDescriptorGeneratorImpl.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/NsDescriptorGeneratorImpl.java
index eb601d8..5398c36 100644
--- a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/NsDescriptorGeneratorImpl.java
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/NsDescriptorGeneratorImpl.java
@@ -1,4 +1,3 @@
- 
 /*
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2020 Nordix Foundation
@@ -21,7 +20,6 @@
 
 import com.google.common.collect.ImmutableMap;
 import fj.data.Either;
-import groovy.util.MapEntry;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -36,8 +34,8 @@
 import org.apache.commons.collections4.MapUtils;
 import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
-import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
+import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.exception.NsdException;
 import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.Nsd;
 import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.VnfDescriptor;
@@ -72,7 +70,7 @@
     private static final List<String> PROPERTIES_TO_EXCLUDE_FROM_ETSI_SOL_NSD_NS_NODE_TYPE = Arrays
         .asList("cds_model_name", "cds_model_version", "skip_post_instantiation_configuration", "controller_actor");
     private static final List<String> ETSI_SOL_NSD_NS_NODE_TYPE_PROPERTIES = Arrays
-            .asList("descriptor_id", "designer", "version", "name", "invariant_id", "flavour_id", "ns_profile", "service_availability_level");
+        .asList("descriptor_id", "designer", "version", "name", "invariant_id", "flavour_id", "ns_profile", "service_availability_level");
     private static final List<String> PROPERTIES_TO_EXCLUDE_FROM_ETSI_SOL_NSD_NS_NODE_TEMPLATE = Arrays
         .asList("nf_function", "nf_role", "nf_naming_code", "nf_type", "nf_naming", "availability_zone_max_count", "min_instances", "max_instances",
             "multi_stage_design", "sdnc_model_name", "sdnc_model_version", "sdnc_artifact_name", "skip_post_instantiation_configuration",
@@ -202,7 +200,7 @@
         }
         componentToscaTemplate.getTopology_template().setSubstitution_mappings(substitutionMapping);
     }
-    
+
     private Map<String, String[]> adjustRequirementNamesToMatchVnfd(final Map<String, String[]> requirements) {
         for (final Map.Entry<String, String[]> entry : requirements.entrySet()) {
             try {
@@ -239,7 +237,7 @@
             removeCapabilitiesFromNodeTemplate(nodeTemplate);
         }
     }
-    
+
     private void setPropertiesForNodeTemplate(final Entry<String, ToscaNodeTemplate> nodeTemplate) {
         final Map<String, Object> propertyMap = nodeTemplate.getValue().getProperties();
         if (MapUtils.isEmpty(propertyMap)) {
@@ -261,12 +259,13 @@
     }
 
     private void setRequirementsForNodeTemplate(final Entry<String, ToscaNodeTemplate> nodeTemplateMap) {
-        final List<Map<String,ToscaTemplateRequirement>> requirementAssignments = nodeTemplateMap.getValue().getRequirements();
-        if (requirementAssignments != null) {  
-            final List<Map<String,ToscaTemplateRequirement>> requirementAssignmentsMatchingVnfdRequirements = new ArrayList<>();
-            for (final Map<String, ToscaTemplateRequirement> requirementAssignment: requirementAssignments) {
-                final Map<String, ToscaTemplateRequirement> requirementAssignmentMatchingVnfd = 
-                        requirementAssignment.entrySet().stream().collect(Collectors.toMap(entry -> entry.getKey().substring(entry.getKey().lastIndexOf('.') + 1), Map.Entry::getValue));
+        final List<Map<String, ToscaTemplateRequirement>> requirementAssignments = nodeTemplateMap.getValue().getRequirements();
+        if (requirementAssignments != null) {
+            final List<Map<String, ToscaTemplateRequirement>> requirementAssignmentsMatchingVnfdRequirements = new ArrayList<>();
+            for (final Map<String, ToscaTemplateRequirement> requirementAssignment : requirementAssignments) {
+                final Map<String, ToscaTemplateRequirement> requirementAssignmentMatchingVnfd =
+                    requirementAssignment.entrySet().stream()
+                        .collect(Collectors.toMap(entry -> entry.getKey().substring(entry.getKey().lastIndexOf('.') + 1), Map.Entry::getValue));
                 requirementAssignmentsMatchingVnfdRequirements.add(requirementAssignmentMatchingVnfd);
             }
             nodeTemplateMap.getValue().setRequirements(requirementAssignmentsMatchingVnfdRequirements);
@@ -281,10 +280,10 @@
     private void removeOnapAndEtsiNsdPropertiesFromInputs(final ToscaTemplate template) {
         final ToscaTopolgyTemplate topologyTemplate = template.getTopology_template();
         final Map<String, ToscaProperty> inputMap = topologyTemplate.getInputs();
-        
-        
+
         if (MapUtils.isNotEmpty(inputMap)) {
-            inputMap.entrySet().removeIf(entry -> PROPERTIES_TO_EXCLUDE_FROM_ETSI_SOL_NSD_NS_NODE_TYPE.contains(entry.getKey()) || ETSI_SOL_NSD_NS_NODE_TYPE_PROPERTIES.contains(entry.getKey()));
+            inputMap.entrySet().removeIf(entry -> PROPERTIES_TO_EXCLUDE_FROM_ETSI_SOL_NSD_NS_NODE_TYPE.contains(entry.getKey())
+                || ETSI_SOL_NSD_NS_NODE_TYPE_PROPERTIES.contains(entry.getKey()));
         }
         if (MapUtils.isEmpty(inputMap)) {
             topologyTemplate.setInputs(null);
@@ -319,7 +318,7 @@
     }
 
     private Map<String, Map<String, String>> generateDefaultImportEntry() {
-        return ImmutableMap.of("etsi_nfv_sol001_nsd_types", ImmutableMap.of("file", "etsi_nfv_sol001_nsd_types.yaml"));
+        return Map.of("etsi_nfv_sol001_nsd_types", Map.of("file", "etsi_nfv_sol001_nsd_types.yaml"));
     }
 
     private ToscaNodeType createEtsiSolNsNodeType(final ToscaNodeType nsNodeType, final ToscaTemplate componentToscaTemplate) {
@@ -336,29 +335,34 @@
         }
         propertiesInNsNodeType.entrySet().removeIf(entry -> PROPERTIES_TO_EXCLUDE_FROM_ETSI_SOL_NSD_NS_NODE_TYPE.contains(entry.getKey()));
         toscaNodeType.setProperties(propertiesInNsNodeType);
-        
-        final List<Map<String, ToscaRequirement>> requirementsInNsNodeType = getRequirementsForNsNodeType(nsNodeType.getRequirements(), componentToscaTemplate);
+
+        final List<Map<String, ToscaRequirement>> requirementsInNsNodeType = getRequirementsForNsNodeType(nsNodeType.getRequirements(),
+            componentToscaTemplate);
         if (!requirementsInNsNodeType.isEmpty()) {
-            toscaNodeType.setRequirements(requirementsInNsNodeType);  
+            toscaNodeType.setRequirements(requirementsInNsNodeType);
         }
 
         return toscaNodeType;
     }
-    
-    private List<Map<String,ToscaRequirement>> getRequirementsForNsNodeType(final List<Map<String,ToscaRequirement>> requirements, final ToscaTemplate componentToscaTemplate) {
-        final Map<String, String[]> requirementsInSubstitutionMapping = componentToscaTemplate.getTopology_template().getSubstitution_mappings().getRequirements();
+
+    private List<Map<String, ToscaRequirement>> getRequirementsForNsNodeType(final List<Map<String, ToscaRequirement>> requirements,
+                                                                             final ToscaTemplate componentToscaTemplate) {
+        final Map<String, String[]> requirementsInSubstitutionMapping = componentToscaTemplate.getTopology_template().getSubstitution_mappings()
+            .getRequirements();
         if (requirements == null || MapUtils.isEmpty(requirementsInSubstitutionMapping)) {
             return Collections.emptyList();
         }
-        final List<Map<String,ToscaRequirement>> requirementsToAdd = new ArrayList<>();
-        for (final Map<String,ToscaRequirement> requirementMap : requirements) {
-            final Map<String,ToscaRequirement> neededRequirements = requirementMap.entrySet().stream().filter(entry -> requirementsInSubstitutionMapping.containsKey(entry.getKey())).collect(Collectors.toMap(Entry::getKey, Entry::getValue));
+        final List<Map<String, ToscaRequirement>> requirementsToAdd = new ArrayList<>();
+        for (final Map<String, ToscaRequirement> requirementMap : requirements) {
+            final Map<String, ToscaRequirement> neededRequirements = requirementMap.entrySet().stream()
+                .filter(entry -> requirementsInSubstitutionMapping.containsKey(entry.getKey()))
+                .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
             if (!neededRequirements.isEmpty()) {
                 requirementsToAdd.add(neededRequirements);
             }
         }
         return requirementsToAdd;
-       
+
     }
 
     private boolean propertyIsDefinedInNodeType(final String propertyName) {
@@ -394,7 +398,7 @@
     }
 
     private ToscaTemplate parseToToscaTemplate(final Component component) throws NsdException {
-        final Either<ToscaTemplate, ToscaError> toscaTemplateRes = toscaExportHandler.convertToToscaTemplate(component);
+        final Either<ToscaTemplate, ToscaError> toscaTemplateRes = toscaExportHandler.convertToToscaTemplate(component, false);
         if (toscaTemplateRes.isRight()) {
             String errorMsg = String
                 .format("Could not parse component '%s' to tosca template. Error '%s'", component.getName(), toscaTemplateRes.right().value().name());
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/NsDescriptorGeneratorImplTest.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/NsDescriptorGeneratorImplTest.java
index 4c2c0a9..7ad43db 100644
--- a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/NsDescriptorGeneratorImplTest.java
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/NsDescriptorGeneratorImplTest.java
@@ -181,7 +181,7 @@
         interfaceToscaNodeType.setRequirements(interfaceNodeTypeRequirements);
         final String nsNodeTypeName = "nsNodeTypeName";
         componentInterfaceToscaTemplate.setNode_types(ImmutableMap.of(nsNodeTypeName, interfaceToscaNodeType));
-        when(toscaExportHandler.convertToToscaTemplate(component)).thenReturn(Either.left(componentToscaTemplate));
+        when(toscaExportHandler.convertToToscaTemplate(component, false)).thenReturn(Either.left(componentToscaTemplate));
         when(toscaExportHandler.convertInterfaceNodeType(any(), any(), any(), any(), anyBoolean()))
             .thenReturn(Either.left(componentInterfaceToscaTemplate));
         final List<VnfDescriptor> vnfDescriptorList = new ArrayList<>();
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/plugins/CsarZipGenerator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/plugins/CsarZipGenerator.java
new file mode 100644
index 0000000..f03c930
--- /dev/null
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/plugins/CsarZipGenerator.java
@@ -0,0 +1,48 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2023 Nordix Foundation. 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.plugins;
+
+import fj.data.Either;
+import java.io.IOException;
+import java.util.zip.ZipOutputStream;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.exception.ResponseFormat;
+
+/**
+ * Implementations of this interface shall generate a csar file.
+ */
+public interface CsarZipGenerator {
+
+    /**
+     * Generate the csar file.
+     *
+     * @param component the component the csar is based on
+     * @return Map of name to contents for entries to be included in the csar
+     */
+    Either<ZipOutputStream, ResponseFormat> generateCsarZip(
+        final Component component,
+        boolean getFromCS,
+        ZipOutputStream zip,
+        boolean isInCertificationRequest,
+        boolean isAsdPackage
+    ) throws IOException;
+
+    String getModel();
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CommonCsarGenerator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CommonCsarGenerator.java
new file mode 100644
index 0000000..633dd6e
--- /dev/null
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CommonCsarGenerator.java
@@ -0,0 +1,1235 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2023 Nordix Foundation. 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.tosca;
+
+import static org.openecomp.sdc.be.dao.api.ActionStatus.ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION;
+import static org.openecomp.sdc.be.dao.api.ActionStatus.ERROR_DURING_CSAR_CREATION;
+import static org.openecomp.sdc.be.tosca.ComponentCache.MergeStrategy.overwriteIfSameVersions;
+import static org.openecomp.sdc.be.tosca.FJToVavrHelper.Try0.fromEither;
+import static org.openecomp.sdc.be.tosca.FJToVavrHelper.Try0.javaListToVavrList;
+import static org.openecomp.sdc.common.api.Constants.ADDITIONAL_TYPE_DEFINITIONS;
+
+import com.google.common.primitives.Bytes;
+import fj.F;
+import fj.data.Either;
+import io.vavr.Tuple2;
+import io.vavr.control.Try;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutableTriple;
+import org.apache.commons.lang3.tuple.Triple;
+import org.apache.commons.text.WordUtils;
+import org.onap.sdc.tosca.services.YamlUtil;
+import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
+import org.openecomp.sdc.be.config.CategoryBaseTypeConfig;
+import org.openecomp.sdc.be.config.ConfigurationManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
+import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
+import org.openecomp.sdc.be.dao.cassandra.SdcSchemaFilesCassandraDao;
+import org.openecomp.sdc.be.data.model.ToscaImportByModel;
+import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.ArtifactDefinition;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstance;
+import org.openecomp.sdc.be.model.InterfaceDefinition;
+import org.openecomp.sdc.be.model.LifecycleStateEnum;
+import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.category.CategoryDefinition;
+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.DaoStatusConverter;
+import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
+import org.openecomp.sdc.be.plugins.CsarEntryGenerator;
+import org.openecomp.sdc.be.resources.data.DAOArtifactData;
+import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil;
+import org.openecomp.sdc.be.utils.TypeUtils;
+import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
+import org.openecomp.sdc.common.api.ArtifactTypeEnum;
+import org.openecomp.sdc.common.impl.ExternalConfiguration;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
+import org.openecomp.sdc.common.util.GeneralUtility;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * Generates a Network Service CSAR based on a SERVICE component and wraps it in a SDC CSAR entry.
+ */
+@org.springframework.stereotype.Component("commonCsarGenerator")
+public class CommonCsarGenerator {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(CommonCsarGenerator.class);
+    public static final String ARTIFACTS_PATH = "Artifacts/";
+    private static final String RESOURCES_PATH = "Resources/";
+    private static final String PATH_DELIMITER = "/";
+    private static final String SERVICE_MANIFEST = "NS.mf";
+    private static final String ARTIFACT_NAME_UNIQUE_ID = "ArtifactName {}, unique ID {}";
+    private static final String TOSCA_META_PATH_FILE_NAME = "TOSCA-Metadata/TOSCA.meta";
+    private static final String TOSCA_META_VERSION = "1.0";
+    private static final String CSAR_VERSION = "1.1";
+    private static final String SDC_VERSION = ExternalConfiguration.getAppVersion();
+    public static final String NODES_YML = "nodes.yml";
+    private static final String CONFORMANCE_LEVEL = ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel();
+    private final ToscaOperationFacade toscaOperationFacade;
+    private final ComponentsUtils componentsUtils;
+    private final ToscaExportHandler toscaExportUtils;
+    private final List<CsarEntryGenerator> generators;
+    private final ArtifactCassandraDao artifactCassandraDao;
+    private final String versionFirstThreeOctets;
+    private final SdcSchemaFilesCassandraDao sdcSchemaFilesCassandraDao;
+    private final ModelOperation modelOperation;
+
+    @Autowired
+    public CommonCsarGenerator(
+        final ToscaOperationFacade toscaOperationFacade,
+        final ComponentsUtils componentsUtils,
+        final ToscaExportHandler toscaExportUtils,
+        final List<CsarEntryGenerator> generators,
+        final ArtifactCassandraDao artifactCassandraDao,
+        final SdcSchemaFilesCassandraDao sdcSchemaFilesCassandraDao,
+        final ModelOperation modelOperation) {
+        this.toscaOperationFacade = toscaOperationFacade;
+        this.componentsUtils = componentsUtils;
+        this.toscaExportUtils = toscaExportUtils;
+        this.generators = generators;
+        this.artifactCassandraDao = artifactCassandraDao;
+        this.versionFirstThreeOctets = readVersionFirstThreeOctets();
+        this.sdcSchemaFilesCassandraDao = sdcSchemaFilesCassandraDao;
+        this.modelOperation = modelOperation;
+    }
+
+    private String readVersionFirstThreeOctets() {
+        if (StringUtils.isEmpty(SDC_VERSION)) {
+            return "";
+        }
+        // change regex to avoid DoS sonar issue
+        Matcher matcher = Pattern.compile("(?!\\.)(\\d{1,9}(\\.\\d{1,9}){1,9})(?![\\d\\.])").matcher(SDC_VERSION);
+        matcher.find();
+        return matcher.group(0);
+    }
+
+    /**
+     * Generates a Network Service CSAR based on a SERVICE component that has category configured in
+     * CategoriesToGenerateNsd enum and wraps it in a SDC CSAR entry.
+     *
+     * @param component the component to create the NS CSAR from
+     * @return an entry to be added in the Component CSAR by SDC
+     */
+
+    public Either<ZipOutputStream, ResponseFormat> generateCsarZip(Component component,
+                                                                   boolean getFromCS,
+                                                                   ZipOutputStream zip,
+                                                                   boolean isInCertificationRequest,
+                                                                   boolean isAsdPackage,
+                                                                   String definitionsPath,
+                                                                   boolean addDependencies,
+                                                                   boolean isSkipImports) throws IOException {
+        ArtifactDefinition artifactDef = component.getToscaArtifacts().get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
+        Either<ToscaRepresentation, ResponseFormat> toscaRepresentation = fetchToscaRepresentation(component, getFromCS, artifactDef, isSkipImports);
+
+        // This should not be done but in order to keep the refactoring small enough we stop here.
+        // TODO: Refactor the rest of this function
+        byte[] mainYaml;
+        List<Triple<String, String, Component>> dependencies;
+        if (toscaRepresentation.isLeft()) {
+            mainYaml = toscaRepresentation.left().value().getMainYaml();
+            dependencies = toscaRepresentation.left().value().getDependencies().getOrElse(new ArrayList<>());
+        } else {
+            return Either.right(toscaRepresentation.right().value());
+        }
+        final String fileName = artifactDef.getArtifactName();
+        final byte[] toscaBlock0Byte =
+            createToscaBlock0(TOSCA_META_VERSION, CSAR_VERSION, component.getCreatorFullName(), fileName, isAsdPackage, definitionsPath).getBytes();
+        zip.putNextEntry(new ZipEntry(TOSCA_META_PATH_FILE_NAME));
+        zip.write(toscaBlock0Byte);
+        zip.putNextEntry(new ZipEntry(definitionsPath + fileName));
+        zip.write(mainYaml);
+        LifecycleStateEnum lifecycleState = component.getLifecycleState();
+        addServiceMf(component, zip, lifecycleState, isInCertificationRequest, fileName, mainYaml, definitionsPath);
+        if (addDependencies) {
+            //US798487 - Abstraction of complex types
+            if (hasToWriteComponentSubstitutionType(component)) {
+                LOGGER.debug("Component {} is complex - generating abstract type for it..", component.getName());
+                dependencies.addAll(writeComponentInterface(component, zip, fileName, definitionsPath));
+            }
+            //UID <cassandraId,filename,component>
+            Either<ZipOutputStream, ResponseFormat> zipOutputStreamOrResponseFormat =
+                getZipOutputStreamResponseFormatEither(zip, dependencies, definitionsPath);
+            if (zipOutputStreamOrResponseFormat != null && zipOutputStreamOrResponseFormat.isRight()) {
+                return zipOutputStreamOrResponseFormat;
+            }
+        }
+        if (component.getModel() == null) {
+            //retrieve SDC.zip from Cassandra
+            Either<byte[], ResponseFormat> latestSchemaFiles = getLatestSchemaFilesFromCassandra();
+            if (latestSchemaFiles.isRight()) {
+                LOGGER.error("Error retrieving SDC Schema files from cassandra");
+                return Either.right(latestSchemaFiles.right().value());
+            }
+            final byte[] schemaFileZip = latestSchemaFiles.left().value();
+            final List<String> nodesFromPackage = findNonRootNodesFromPackage(dependencies);
+            //add files from retrieved SDC.zip to Definitions folder in CSAR
+            addSchemaFilesFromCassandra(zip, schemaFileZip, nodesFromPackage, definitionsPath);
+        } else {
+            //retrieve schema files by model from Cassandra
+            addSchemaFilesByModel(zip, component.getModel(), definitionsPath, addDependencies);
+        }
+        Either<CsarDefinition, ResponseFormat> collectedComponentCsarDefinition = collectComponentCsarDefinition(component);
+        if (collectedComponentCsarDefinition.isRight()) {
+            return Either.right(collectedComponentCsarDefinition.right().value());
+        }
+        if (generators != null) {
+            for (CsarEntryGenerator generator : generators) {
+                LOGGER.debug("Invoking CsarEntryGenerator: {}", generator.getClass().getName());
+                for (Map.Entry<String, byte[]> pluginGeneratedFile : generator.generateCsarEntries(component).entrySet()) {
+                    zip.putNextEntry(new ZipEntry(pluginGeneratedFile.getKey()));
+                    zip.write(pluginGeneratedFile.getValue());
+                }
+            }
+        }
+        return writeAllFilesToCsar(component, collectedComponentCsarDefinition.left().value(), zip, isInCertificationRequest);
+    }
+
+    private Either<ToscaRepresentation, ResponseFormat> fetchToscaRepresentation(Component component, boolean getFromCS,
+                                                                                 ArtifactDefinition artifactDef, boolean isSkipImports) {
+        LifecycleStateEnum lifecycleState = component.getLifecycleState();
+        boolean shouldBeFetchedFromCassandra =
+            getFromCS || !(lifecycleState == LifecycleStateEnum.NOT_CERTIFIED_CHECKIN || lifecycleState == LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
+        Either<ToscaRepresentation, ResponseFormat> toscaRepresentation =
+            shouldBeFetchedFromCassandra ? fetchToscaRepresentation(artifactDef) : generateToscaRepresentation(component, isSkipImports);
+        return toscaRepresentation.left()
+            .bind(iff(myd -> !myd.getDependencies().isDefined(), myd -> fetchToscaTemplateDependencies(myd.getMainYaml(), component)));
+    }
+
+    private Either<ToscaRepresentation, ResponseFormat> fetchToscaTemplateDependencies(byte[] mainYml, Component component) {
+        return toscaExportUtils.getDependencies(component).right().map(toscaError -> {
+            LOGGER.debug("Failed to retrieve dependencies for component {}, error {}", component.getUniqueId(), toscaError);
+            return componentsUtils.getResponseFormat(componentsUtils.convertFromToscaError(toscaError));
+        }).left().map(tt -> ToscaRepresentation.make(mainYml, tt));
+    }
+
+    private Either<ToscaRepresentation, ResponseFormat> fetchToscaRepresentation(ArtifactDefinition artifactDef) {
+        return getFromCassandra(artifactDef.getEsId()).right().map(as -> {
+            LOGGER.debug(ARTIFACT_NAME_UNIQUE_ID, artifactDef.getArtifactName(), artifactDef.getUniqueId());
+            return componentsUtils.getResponseFormat(as);
+        }).left().map(ToscaRepresentation::make);
+    }
+
+    private Either<byte[], ActionStatus> getFromCassandra(String cassandraId) {
+        return artifactCassandraDao.getArtifact(cassandraId).right().map(operationstatus -> {
+            LOGGER.info("Failed to fetch artifact from Cassandra by id {} error {}.", cassandraId, operationstatus);
+            StorageOperationStatus storageStatus = DaoStatusConverter.convertCassandraStatusToStorageStatus(operationstatus);
+            return componentsUtils.convertFromStorageResponse(storageStatus);
+        }).left().map(DAOArtifactData::getDataAsArray);
+    }
+
+    private static <L, R> F<L, Either<L, R>> iff(Predicate<L> p, Function<L, Either<L, R>> ifTrue) {
+        return l -> p.test(l) ? ifTrue.apply(l) : Either.left(l);
+    }
+
+    private static <A, B> F<A, B> iff(Predicate<A> p, Supplier<B> s, Function<A, B> orElse) {
+        return a -> p.test(a) ? s.get() : orElse.apply(a);
+    }
+
+    private void addServiceMf(Component component, ZipOutputStream zip, LifecycleStateEnum lifecycleState, boolean isInCertificationRequest,
+                              String fileName, byte[] mainYaml, String definitionsPath) throws IOException {
+        // add mf
+        if ((component.getComponentType() == ComponentTypeEnum.SERVICE) && (lifecycleState != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT)) {
+            String serviceName = component.getName();
+            String createdBy = component.getCreatorUserId();
+            String serviceVersion;
+            if (isInCertificationRequest) {
+                int tmp = Integer.valueOf(component.getVersion().split("\\.")[0]) + 1;
+                serviceVersion = String.valueOf(tmp) + ".0";
+            } else {
+                serviceVersion = component.getVersion();
+            }
+            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
+            format.setTimeZone(TimeZone.getTimeZone("UTC"));
+            Date date = new Date();
+            String releaseTime = format.format(date);
+            if (component.getCategories() == null || component.getCategories().get(0) == null) {
+                return;
+            }
+            String serviceType = component.getCategories().get(0).getName();
+            String description = component.getDescription();
+            String serviceTemplate = definitionsPath + fileName;
+            String hash = GeneralUtility.calculateMD5Base64EncodedByByteArray(mainYaml);
+            String nsMfBlock0 = createNsMfBlock0(serviceName, createdBy, serviceVersion, releaseTime, serviceType, description, serviceTemplate,
+                hash);
+            byte[] nsMfBlock0Byte = nsMfBlock0.getBytes();
+            zip.putNextEntry(new ZipEntry(SERVICE_MANIFEST));
+            zip.write(nsMfBlock0Byte);
+        }
+    }
+
+    private String createNsMfBlock0(String serviceName, String createdBy, String serviceVersion, String releaseTime, String serviceType,
+                                    String description, String serviceTemplate, String hash) {
+        final String block0template = "metadata??\n" + "ns_product_name: %s\n" + "ns_provider_id: %s\n" + "ns_package_version: %s\n" +
+            "ns_release_data_time: %s\n" + "ns_type: %s\n" + "ns_package_description: %s\n\n" + "Source: %s\n" + "Algorithm: MD5\n" + "Hash: %s\n\n";
+        return String.format(block0template, serviceName, createdBy, serviceVersion, releaseTime, serviceType, description, serviceTemplate, hash);
+    }
+
+    private boolean hasToWriteComponentSubstitutionType(final Component component) {
+        final Map<String, CategoryBaseTypeConfig> serviceNodeTypesConfig =
+            ConfigurationManager.getConfigurationManager().getConfiguration().getServiceBaseNodeTypes();
+        List<CategoryDefinition> categories = component.getCategories();
+        if (CollectionUtils.isNotEmpty(categories) && MapUtils.isNotEmpty(serviceNodeTypesConfig)
+            && serviceNodeTypesConfig.get(categories.get(0).getName()) != null) {
+            boolean doNotExtendBaseType = serviceNodeTypesConfig.get(categories.get(0).getName()).isDoNotExtendBaseType();
+            if (doNotExtendBaseType) {
+                return false;
+            }
+        }
+        if (component instanceof Service) {
+            return !ModelConverter.isAtomicComponent(component) && ((Service) component).isSubstituteCandidate();
+        }
+        return !ModelConverter.isAtomicComponent(component);
+    }
+
+    private Either<ZipOutputStream, ResponseFormat> writeComponentInterface(Either<ToscaRepresentation, ToscaError> interfaceRepresentation,
+                                                                            ZipOutputStream zip, String fileName, String definitionsPath) {
+        // TODO: This should not be done but we need this to keep the refactoring small enough to be easily reviewable
+        return writeComponentInterface(interfaceRepresentation, fileName, ZipWriter.live(zip), definitionsPath)
+            .map(void0 -> Either.<ZipOutputStream, ResponseFormat>left(zip)).recover(th -> {
+                LOGGER.error("#writeComponentInterface - zip writing failed with error: ", th);
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+            }).get();
+    }
+
+    private Try<Void> writeComponentInterface(
+        Either<ToscaRepresentation, ToscaError> interfaceRepresentation, String fileName, ZipWriter zw, String definitionsPath) {
+        Either<byte[], ToscaError> yml = interfaceRepresentation.left()
+            .map(ToscaRepresentation::getMainYaml);
+        return fromEither(yml, ToscaErrorException::new).flatMap(zw.write(definitionsPath + ToscaExportHandler.getInterfaceFilename(fileName)));
+    }
+
+    private List<Triple<String, String, Component>> writeComponentInterface(final Component component, final ZipOutputStream zip,
+                                                                            final String fileName, final String definitionsPath) {
+        final Either<ToscaRepresentation, ToscaError> interfaceRepresentation = toscaExportUtils.exportComponentInterface(component, false);
+        writeComponentInterface(interfaceRepresentation, zip, fileName, definitionsPath);
+        return interfaceRepresentation.left().value().getDependencies().getOrElse(new ArrayList<>());
+    }
+
+    private Either<ZipOutputStream, ResponseFormat> getZipOutputStreamResponseFormatEither(ZipOutputStream zip,
+                                                                                           List<Triple<String, String, Component>> dependencies,
+                                                                                           String definitionsPath)
+        throws IOException {
+        ComponentCache
+            innerComponentsCache = ComponentCache.overwritable(overwriteIfSameVersions()).onMerge((oldValue, newValue) ->
+            LOGGER.warn("Overwriting component invariantID {} of version {} with a newer version {}", oldValue.getId(),
+                oldValue.getComponentVersion(),
+                newValue.getComponentVersion()));
+        if (dependencies != null && !dependencies.isEmpty()) {
+            for (Triple<String, String, Component> d : dependencies) {
+                String cassandraId = d.getMiddle();
+                Component childComponent = d.getRight();
+                Either<byte[], ResponseFormat> entryData = getEntryData(cassandraId, childComponent).right()
+                    .map(componentsUtils::getResponseFormat);
+                if (entryData.isRight()) {
+                    return Either.right(entryData.right().value());
+                }
+                //fill innerComponentsCache
+                String fileName = d.getLeft();
+                innerComponentsCache.put(cassandraId, fileName, childComponent);
+                addInnerComponentsToCache(innerComponentsCache, childComponent);
+            }
+            //add inner components to CSAR
+            return addInnerComponentsToCSAR(zip, innerComponentsCache, definitionsPath);
+        }
+        return null;
+    }
+
+    private Either<ZipOutputStream, ResponseFormat> addInnerComponentsToCSAR(ZipOutputStream zip, ComponentCache innerComponentsCache,
+                                                                             String definitionsPath)
+        throws IOException {
+        for (ImmutableTriple<String, String, Component> ict : innerComponentsCache.iterable()) {
+            Component innerComponent = ict.getRight();
+            String icFileName = ict.getMiddle();
+            // add component to zip
+            Either<Tuple2<byte[], ZipEntry>, ResponseFormat> zipEntry = toZipEntry(ict, definitionsPath);
+            // TODO: this should not be done, we should instead compose this either further,
+
+            // but in order to keep this refactoring small, we'll stop here.
+            if (zipEntry.isRight()) {
+                return Either.right(zipEntry.right().value());
+            }
+            Tuple2<byte[], ZipEntry> value = zipEntry.left().value();
+            zip.putNextEntry(value._2);
+            zip.write(value._1);
+            // add component interface to zip
+            if (hasToWriteComponentSubstitutionType(innerComponent)) {
+                writeComponentInterface(innerComponent, zip, icFileName, definitionsPath);
+            }
+        }
+        return null;
+    }
+
+    private Either<Tuple2<byte[], ZipEntry>, ResponseFormat> toZipEntry(ImmutableTriple<String, String, Component> cachedEntry,
+                                                                        String definitionsPath) {
+        String cassandraId = cachedEntry.getLeft();
+        String fileName = cachedEntry.getMiddle();
+        Component innerComponent = cachedEntry.getRight();
+        return getEntryData(cassandraId, innerComponent).right().map(status -> {
+            LOGGER.debug("Failed adding to zip component {}, error {}", cassandraId, status);
+            return componentsUtils.getResponseFormat(status);
+        }).left().map(content -> new Tuple2<>(content, new ZipEntry(definitionsPath + fileName)));
+    }
+
+    private void addInnerComponentsToCache(ComponentCache componentCache, Component childComponent) {
+        javaListToVavrList(childComponent.getComponentInstances()).filter(ci -> componentCache.notCached(ci.getComponentUid())).forEach(ci -> {
+            // all resource must be only once!
+            Either<Resource, StorageOperationStatus> resource = toscaOperationFacade.getToscaElement(ci.getComponentUid());
+            Component componentRI = checkAndAddComponent(componentCache, ci, resource);
+            //if not atomic - insert inner components as well
+
+            // TODO: This could potentially create a StackOverflowException if the call stack
+
+            // happens to be too large. Tail-recursive optimization should be used here.
+            if (!ModelConverter.isAtomicComponent(componentRI)) {
+                addInnerComponentsToCache(componentCache, componentRI);
+            }
+        });
+    }
+
+    private Component checkAndAddComponent(ComponentCache componentCache, ComponentInstance ci, Either<Resource, StorageOperationStatus> resource) {
+        if (resource.isRight()) {
+            LOGGER.debug("Failed to fetch resource with id {} for instance {}", ci.getComponentUid(), ci.getName());
+        }
+        Component componentRI = resource.left().value();
+        Map<String, ArtifactDefinition> childToscaArtifacts = componentRI.getToscaArtifacts();
+        ArtifactDefinition childArtifactDefinition = childToscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
+        if (childArtifactDefinition != null) {
+            //add to cache
+            componentCache.put(childArtifactDefinition.getEsId(), childArtifactDefinition.getArtifactName(), componentRI);
+        }
+        return componentRI;
+    }
+
+    private Either<byte[], ActionStatus> getEntryData(String cassandraId, Component childComponent) {
+        if (cassandraId == null || cassandraId.isEmpty()) {
+            return toscaExportUtils.exportComponent(childComponent).right().map(toscaErrorToActionStatus(childComponent)).left()
+                .map(ToscaRepresentation::getMainYaml);
+        } else {
+            return getFromCassandra(cassandraId);
+        }
+    }
+
+    private F<ToscaError, ActionStatus> toscaErrorToActionStatus(Component childComponent) {
+        return toscaError -> {
+            LOGGER.debug("Failed to export tosca template for child component {} error {}", childComponent.getUniqueId(), toscaError);
+            return componentsUtils.convertFromToscaError(toscaError);
+        };
+    }
+
+    private Either<byte[], ResponseFormat> getLatestSchemaFilesFromCassandra() {
+        String fto = versionFirstThreeOctets;
+        return sdcSchemaFilesCassandraDao.getSpecificSchemaFiles(fto, CONFORMANCE_LEVEL).right().map(schemaFilesFetchDBError(fto)).left()
+            .bind(iff(List::isEmpty, () -> schemaFileFetchError(fto), s -> Either.left(s.iterator().next().getPayloadAsArray())));
+    }
+
+    private F<CassandraOperationStatus, ResponseFormat> schemaFilesFetchDBError(String firstThreeOctets) {
+        return cos -> {
+            LOGGER.debug("Failed to get the schema files SDC-Version: {} Conformance-Level {}. Please fix DB table accordingly.", firstThreeOctets,
+                CONFORMANCE_LEVEL);
+            StorageOperationStatus sos = DaoStatusConverter.convertCassandraStatusToStorageStatus(cos);
+            return componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(sos));
+        };
+    }
+
+    private Either<byte[], ResponseFormat> schemaFileFetchError(String firstThreeOctets) {
+        LOGGER.debug("Failed to get the schema files SDC-Version: {} Conformance-Level {}", firstThreeOctets, CONFORMANCE_LEVEL);
+        return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_SCHEMA_FILES_NOT_FOUND, firstThreeOctets, CONFORMANCE_LEVEL));
+    }
+
+    /**
+     * Create a list of all derived nodes found on the package
+     *
+     * @param dependencies all node dependencies
+     * @return a list of nodes
+     */
+    private List<String> findNonRootNodesFromPackage(final List<Triple<String, String, Component>> dependencies) {
+        final List<String> nodes = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(dependencies)) {
+            final String NATIVE_ROOT = "tosca.nodes.Root";
+            dependencies.forEach(dependency -> {
+                if (dependency.getRight() instanceof Resource) {
+                    final Resource resource = (Resource) dependency.getRight();
+                    if (CollectionUtils.isNotEmpty(resource.getDerivedList())) {
+                        resource.getDerivedList().stream().filter(node -> !nodes.contains(node) && !NATIVE_ROOT.equalsIgnoreCase(node))
+                            .forEach(node -> nodes.add(node));
+                    }
+                }
+            });
+        }
+        return nodes;
+    }
+
+    /**
+     * Writes to a CSAR zip from casandra schema data
+     *
+     * @param zipOutputStream  stores the input stream content
+     * @param schemaFileZip    zip data from Cassandra
+     * @param nodesFromPackage list of all nodes found on the onboarded package
+     */
+    private void addSchemaFilesFromCassandra(final ZipOutputStream zipOutputStream, final byte[] schemaFileZip, final List<String> nodesFromPackage,
+                                             final String definitionsPath) {
+        final int initSize = 2048;
+        LOGGER.debug("Starting copy from Schema file zip to CSAR zip");
+        try (final ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(
+            schemaFileZip)); final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
+            byteArrayOutputStream, initSize)) {
+            ZipEntry entry;
+            while ((entry = zipInputStream.getNextEntry()) != null) {
+                ZipUtils.checkForZipSlipInRead(entry);
+                final String entryName = entry.getName();
+                int readSize = initSize;
+                final byte[] entryData = new byte[initSize];
+                if (shouldZipEntryBeHandled(entryName)) {
+                    if (NODES_YML.equalsIgnoreCase(entryName)) {
+                        handleNode(zipInputStream, byteArrayOutputStream, nodesFromPackage);
+                    } else {
+                        while ((readSize = zipInputStream.read(entryData, 0, readSize)) != -1) {
+                            bufferedOutputStream.write(entryData, 0, readSize);
+                        }
+                        bufferedOutputStream.flush();
+                    }
+                    byteArrayOutputStream.flush();
+                    zipOutputStream.putNextEntry(new ZipEntry(definitionsPath + entryName));
+                    zipOutputStream.write(byteArrayOutputStream.toByteArray());
+                    zipOutputStream.flush();
+                    byteArrayOutputStream.reset();
+                }
+            }
+        } catch (final Exception e) {
+            LOGGER.error("Error while writing the SDC schema file to the CSAR", e);
+            throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+        LOGGER.debug("Finished copy from Schema file zip to CSAR zip");
+    }
+
+    /**
+     * Handles the nodes.yml zip entry, updating the nodes.yml to avoid duplicated nodes on it.
+     *
+     * @param zipInputStream        the zip entry to be read
+     * @param byteArrayOutputStream an output stream in which the data is written into a byte array.
+     * @param nodesFromPackage      list of all nodes found on the onboarded package
+     */
+    private void handleNode(final ZipInputStream zipInputStream, final ByteArrayOutputStream byteArrayOutputStream,
+                            final List<String> nodesFromPackage) throws IOException {
+        final Map<String, Object> nodesFromArtifactFile = readYamlZipEntry(zipInputStream);
+        final Map<String, Object> nodesYaml = updateNodeYml(nodesFromPackage, nodesFromArtifactFile);
+        updateZipEntry(byteArrayOutputStream, nodesYaml);
+    }
+
+    /**
+     * Updates the zip entry from the given parameters
+     *
+     * @param byteArrayOutputStream an output stream in which the data is written into a byte array.
+     * @param nodesYaml             a Map of nodes to be written
+     */
+    private void updateZipEntry(final ByteArrayOutputStream byteArrayOutputStream, final Map<String, Object> nodesYaml) throws IOException {
+        if (MapUtils.isNotEmpty(nodesYaml)) {
+            byteArrayOutputStream.write(new YamlUtil().objectToYaml(nodesYaml).getBytes());
+        }
+    }
+
+    /**
+     * Filters and removes all duplicated nodes found
+     *
+     * @param nodesFromPackage      a List of all derived nodes found on the given package
+     * @param nodesFromArtifactFile represents the nodes.yml file stored in Cassandra
+     * @return a nodes Map updated
+     */
+    private Map<String, Object> updateNodeYml(final List<String> nodesFromPackage, final Map<String, Object> nodesFromArtifactFile) {
+        if (MapUtils.isNotEmpty(nodesFromArtifactFile)) {
+            final String nodeTypeBlock = TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName();
+            final Map<String, Object> nodeTypes = (Map<String, Object>) nodesFromArtifactFile.get(nodeTypeBlock);
+            nodesFromPackage.stream().filter(nodeTypes::containsKey).forEach(nodeTypes::remove);
+            nodesFromArtifactFile.replace(nodeTypeBlock, nodeTypes);
+        }
+        return nodesFromArtifactFile;
+    }
+
+    /**
+     * Writes a new zip entry
+     *
+     * @param zipInputStream the zip entry to be read
+     * @return a map of the given zip entry
+     */
+    private Map<String, Object> readYamlZipEntry(final ZipInputStream zipInputStream) throws IOException {
+        final int initSize = 2048;
+        final StringBuilder zipEntry = new StringBuilder();
+        final byte[] buffer = new byte[initSize];
+        int read = 0;
+        while ((read = zipInputStream.read(buffer, 0, initSize)) >= 0) {
+            zipEntry.append(new String(buffer, 0, read));
+        }
+        return (Map<String, Object>) new Yaml().load(zipEntry.toString());
+    }
+
+    /**
+     * Checks if the zip entry should or should not be added to the CSAR based on the given global type list
+     *
+     * @param entryName the zip entry name
+     * @return true if the zip entry should be handled
+     */
+    private boolean shouldZipEntryBeHandled(final String entryName) {
+        return ConfigurationManager.getConfigurationManager().getConfiguration().getGlobalCsarImports().stream()
+            .anyMatch(entry -> entry.contains(entryName));
+    }
+
+    private void addSchemaFilesByModel(final ZipOutputStream zipOutputStream, final String modelName,
+                                       final String definitionsPath, final boolean isSingleImportsFile) {
+        try {
+            final List<ToscaImportByModel> modelDefaultImportList = modelOperation.findAllModelImports(modelName, true);
+            final Set<Path> writtenEntryPathList = new HashSet<>();
+            final var defsPath = Path.of(definitionsPath);
+            Map<Path, byte[]> contentToMerge = new HashMap();
+            for (final ToscaImportByModel toscaImportByModel : modelDefaultImportList) {
+                var importPath = Path.of(toscaImportByModel.getFullPath());
+                if (!isSingleImportsFile) {
+                    if (ADDITIONAL_TYPE_DEFINITIONS.equals(Paths.get(String.valueOf(importPath)).normalize().toString())) {
+                        final Path entryPath = defsPath.resolve(importPath);
+                        contentToMerge.put(entryPath, toscaImportByModel.getContent().getBytes(StandardCharsets.UTF_8));
+                    } else {
+                        if (writtenEntryPathList.contains(defsPath.resolve(importPath))) {
+                            importPath =
+                                ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
+                        }
+                        final Path entryPath = defsPath.resolve(importPath);
+                        writtenEntryPathList.add(entryPath);
+                        contentToMerge.put(entryPath, toscaImportByModel.getContent().getBytes(StandardCharsets.UTF_8));
+                    }
+                } else {
+                    if (writtenEntryPathList.contains(defsPath.resolve(importPath))) {
+                        importPath =
+                            ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
+                    }
+                    final Path entryPath = defsPath.resolve(importPath);
+                    final var zipEntry = new ZipEntry(entryPath.toString());
+                    zipOutputStream.putNextEntry(zipEntry);
+                    writtenEntryPathList.add(entryPath);
+                    final byte[] content = toscaImportByModel.getContent().getBytes(StandardCharsets.UTF_8);
+                    zipOutputStream.write(content, 0, content.length);
+                    zipOutputStream.closeEntry();
+                }
+            }
+            if (!isSingleImportsFile) {
+                byte[] mergingContent = new byte[0];
+                for (Map.Entry entry : contentToMerge.entrySet()) {
+                    if (ADDITIONAL_TYPE_DEFINITIONS.equals(Paths.get(String.valueOf(entry.getKey())).normalize().toString())) {
+                        mergingContent = (byte[]) entry.getValue();
+                    } else {
+                        final var zipEntry = new ZipEntry(entry.getKey().toString());
+                        zipOutputStream.putNextEntry(zipEntry);
+                        writtenEntryPathList.add((Path) entry.getKey());
+                        zipOutputStream.write(Bytes.concat(mergingContent, (byte[]) entry.getValue()), 0,
+                            ((byte[]) entry.getValue()).length);
+                        zipOutputStream.closeEntry();
+                    }
+                }
+            }
+        } catch (final IOException e) {
+            LOGGER.error(String.valueOf(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR), CsarUtils.class.getName(),
+                "Error while writing the schema files by model to the CSAR", e);
+            throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.CSAR_TOSCA_IMPORTS_ERROR));
+        }
+    }
+
+    private Either<CsarDefinition, ResponseFormat> collectComponentCsarDefinition(Component component) {
+        ComponentArtifacts componentArtifacts = new ComponentArtifacts();
+        Component updatedComponent = component;
+
+        //get service to receive the AII artifacts uploaded to the service
+        if (updatedComponent.getComponentType() == ComponentTypeEnum.SERVICE) {
+            Either<Service, StorageOperationStatus> getServiceResponse = toscaOperationFacade.getToscaElement(updatedComponent.getUniqueId());
+
+            if (getServiceResponse.isRight()) {
+                ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getServiceResponse.right().value());
+                return Either.right(componentsUtils.getResponseFormat(actionStatus));
+            }
+
+            updatedComponent = getServiceResponse.left().value();
+        }
+
+        //find the artifacts of the main component, it would have its composed instances artifacts in a separate folder
+        ComponentTypeArtifacts componentInstanceArtifacts = new ComponentTypeArtifacts();
+        ArtifactsInfo artifactsInfo = collectComponentArtifacts(updatedComponent);
+        componentInstanceArtifacts.setComponentArtifacts(artifactsInfo);
+        componentArtifacts.setMainTypeAndCIArtifacts(componentInstanceArtifacts);
+
+        Map<String, ComponentTypeArtifacts> resourceTypeArtifacts = componentArtifacts
+            .getComponentTypeArtifacts();    //artifacts mapped by the component type(tosca name+version)
+        //get the component instances
+        List<ComponentInstance> componentInstances = updatedComponent.getComponentInstances();
+        if (componentInstances != null) {
+            for (ComponentInstance componentInstance : componentInstances) {
+                //call recursive to find artifacts for all the path
+                Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts = collectComponentInstanceArtifacts(
+                    updatedComponent, componentInstance, resourceTypeArtifacts, componentInstanceArtifacts);
+                if (collectComponentInstanceArtifacts.isRight()) {
+                    return Either.right(collectComponentInstanceArtifacts.right().value());
+                }
+            }
+        }
+
+        if (LOGGER.isDebugEnabled()) {
+            printResult(componentArtifacts, updatedComponent.getName());
+        }
+
+        return Either.left(new CsarDefinition(componentArtifacts));
+    }
+
+    private void printResult(ComponentArtifacts componentArtifacts, String name) {
+        StringBuilder result = new StringBuilder();
+        result.append("Artifacts of main component " + name + "\n");
+        ComponentTypeArtifacts componentInstanceArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
+        printArtifacts(componentInstanceArtifacts);
+        result.append("Type Artifacts\n");
+        for (Map.Entry<String, ComponentTypeArtifacts> typeArtifacts : componentArtifacts.getComponentTypeArtifacts().entrySet()) {
+            result.append("Folder " + typeArtifacts.getKey() + "\n");
+            result.append(printArtifacts(typeArtifacts.getValue()));
+        }
+
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug(result.toString());
+        }
+    }
+
+    private String printArtifacts(ComponentTypeArtifacts componentInstanceArtifacts) {
+        StringBuilder result = new StringBuilder();
+        ArtifactsInfo artifactsInfo = componentInstanceArtifacts.getComponentArtifacts();
+        Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componentArtifacts = artifactsInfo.getArtifactsInfo();
+        printArtifacts(componentArtifacts);
+        result = result.append("Resources\n");
+        for (Map.Entry<String, ArtifactsInfo> resourceInstance : componentInstanceArtifacts.getComponentInstancesArtifacts().entrySet()) {
+            result.append("Folder" + resourceInstance.getKey() + "\n");
+            result.append(printArtifacts(resourceInstance.getValue().getArtifactsInfo()));
+        }
+
+        return result.toString();
+    }
+
+    private String printArtifacts(Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componetArtifacts) {
+        StringBuilder result = new StringBuilder();
+        for (Map.Entry<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactGroup : componetArtifacts.entrySet()) {
+            result.append("    " + artifactGroup.getKey().getType());
+            for (Map.Entry<String, List<ArtifactDefinition>> groupArtifacts : artifactGroup.getValue().entrySet()) {
+                result.append("        " + groupArtifacts.getKey());
+                for (ArtifactDefinition artifact : groupArtifacts.getValue()) {
+                    result.append("            " + artifact.getArtifactDisplayName());
+                }
+            }
+        }
+
+        return result.toString();
+    }
+
+    private Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts(Component parentComponent, ComponentInstance componentInstance,
+                                                                              Map<String, ComponentTypeArtifacts> resourcesTypeArtifacts,
+                                                                              ComponentTypeArtifacts instanceArtifactsLocation) {
+        //1. get the component instance component
+        String componentUid;
+        if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
+            componentUid = componentInstance.getSourceModelUid();
+        } else {
+            componentUid = componentInstance.getComponentUid();
+        }
+        Either<Component, StorageOperationStatus> component = toscaOperationFacade.getToscaElement(componentUid);
+        if (component.isRight()) {
+            LOGGER.error("Failed to fetch resource with id {} for instance {}", componentUid, parentComponent.getUUID());
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.ASSET_NOT_FOUND_DURING_CSAR_CREATION,
+                parentComponent.getComponentType().getValue(), parentComponent.getUUID(),
+                componentInstance.getOriginType().getComponentType().getValue(), componentUid));
+        }
+        Component fetchedComponent = component.left().value();
+
+        //2. fill the artifacts for the current component parent type
+        String toscaComponentName =
+            componentInstance.getToscaComponentName() + "_v" + componentInstance.getComponentVersion();
+
+        // if there are no artifacts for this component type we need to fetch and build them
+        ComponentTypeArtifacts componentParentArtifacts = Optional
+            .ofNullable(resourcesTypeArtifacts.get(toscaComponentName))
+            .orElseGet(() -> collectComponentTypeArtifacts(fetchedComponent));
+
+        if (componentParentArtifacts.getComponentArtifacts().isNotEmpty()) {
+            resourcesTypeArtifacts.put(toscaComponentName, componentParentArtifacts);
+        }
+
+        //3. find the artifacts specific to the instance
+        Map<String, List<ArtifactDefinition>> componentInstanceSpecificInformationalArtifacts =
+            getComponentInstanceSpecificArtifacts(componentInstance.getArtifacts(),
+                componentParentArtifacts.getComponentArtifacts().getArtifactsInfo(), ArtifactGroupTypeEnum.INFORMATIONAL);
+        Map<String, List<ArtifactDefinition>> componentInstanceSpecificDeploymentArtifacts =
+            getComponentInstanceSpecificArtifacts(componentInstance.getDeploymentArtifacts(),
+                componentParentArtifacts.getComponentArtifacts().getArtifactsInfo(), ArtifactGroupTypeEnum.DEPLOYMENT);
+
+        //4. add the instances artifacts to the component type
+        ArtifactsInfo artifactsInfo = new ArtifactsInfo();
+        if (!componentInstanceSpecificInformationalArtifacts.isEmpty()) {
+            artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.INFORMATIONAL, componentInstanceSpecificInformationalArtifacts);
+        }
+        if (!componentInstanceSpecificDeploymentArtifacts.isEmpty()) {
+            artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.DEPLOYMENT, componentInstanceSpecificDeploymentArtifacts);
+        }
+        if (!artifactsInfo.isEmpty()) {
+            instanceArtifactsLocation.addComponentInstancesArtifacts(componentInstance.getNormalizedName(), artifactsInfo);
+        }
+
+        //5. do the same for all the component instances
+        List<ComponentInstance> componentInstances = fetchedComponent.getComponentInstances();
+        if (componentInstances != null) {
+            for (ComponentInstance childComponentInstance : componentInstances) {
+                Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts = collectComponentInstanceArtifacts(
+                    fetchedComponent, childComponentInstance, resourcesTypeArtifacts, componentParentArtifacts);
+                if (collectComponentInstanceArtifacts.isRight()) {
+                    return collectComponentInstanceArtifacts;
+                }
+            }
+        }
+
+        return Either.left(true);
+    }
+
+    private Map<String, List<ArtifactDefinition>> getComponentInstanceSpecificArtifacts(Map<String, ArtifactDefinition> componentArtifacts,
+                                                                                        Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componentTypeArtifacts,
+                                                                                        ArtifactGroupTypeEnum artifactGroupTypeEnum) {
+        Map<String, List<ArtifactDefinition>> parentArtifacts = componentTypeArtifacts
+            .get(artifactGroupTypeEnum);    //the artfiacts of the component itself and not the instance
+
+        Map<String, List<ArtifactDefinition>> artifactsByTypeOfComponentInstance = new HashMap<>();
+        if (componentArtifacts != null) {
+            for (ArtifactDefinition artifact : componentArtifacts.values()) {
+                List<ArtifactDefinition> parentArtifactsByType = null;
+                if (parentArtifacts != null) {
+                    parentArtifactsByType = parentArtifacts.get(artifact.getArtifactType());
+                }
+                //the artifact is of instance
+                if (parentArtifactsByType == null || !parentArtifactsByType.contains(artifact)) {
+                    List<ArtifactDefinition> typeArtifacts = artifactsByTypeOfComponentInstance.get(artifact.getArtifactType());
+                    if (typeArtifacts == null) {
+                        typeArtifacts = new ArrayList<>();
+                        artifactsByTypeOfComponentInstance.put(artifact.getArtifactType(), typeArtifacts);
+                    }
+                    typeArtifacts.add(artifact);
+                }
+            }
+        }
+
+        return artifactsByTypeOfComponentInstance;
+    }
+
+    private ComponentTypeArtifacts collectComponentTypeArtifacts(Component fetchedComponent) {
+        ArtifactsInfo componentArtifacts = collectComponentArtifacts(fetchedComponent);
+        ComponentTypeArtifacts componentArtifactsInfo = new ComponentTypeArtifacts();
+        if (componentArtifacts.isNotEmpty()) {
+            componentArtifactsInfo.setComponentArtifacts(componentArtifacts);
+        }
+        return componentArtifactsInfo;
+    }
+
+    private ArtifactsInfo collectComponentArtifacts(Component component) {
+        Map<String, ArtifactDefinition> informationalArtifacts = component.getArtifacts();
+        Map<String, List<ArtifactDefinition>> informationalArtifactsByType = collectGroupArtifacts(informationalArtifacts);
+        Map<String, ArtifactDefinition> deploymentArtifacts = component.getDeploymentArtifacts();
+        Map<String, List<ArtifactDefinition>> deploymentArtifactsByType = collectGroupArtifacts(deploymentArtifacts);
+        ArtifactsInfo artifactsInfo = new ArtifactsInfo();
+        if (!informationalArtifactsByType.isEmpty()) {
+            artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.INFORMATIONAL, informationalArtifactsByType);
+        }
+        if (!deploymentArtifactsByType.isEmpty()) {
+            artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.DEPLOYMENT, deploymentArtifactsByType);
+        }
+
+        return artifactsInfo;
+    }
+
+    private Map<String, List<ArtifactDefinition>> collectGroupArtifacts(
+        final Map<String, ArtifactDefinition> componentArtifacts) {
+        final Map<String, List<ArtifactDefinition>> artifactsByType = new HashMap<>();
+        for (final ArtifactDefinition artifact : componentArtifacts.values()) {
+            if (artifact.getArtifactUUID() != null) {
+                artifactsByType.putIfAbsent(artifact.getArtifactType(), new ArrayList<>());
+                final List<ArtifactDefinition> typeArtifacts = artifactsByType.get(artifact.getArtifactType());
+                typeArtifacts.add(artifact);
+            }
+        }
+        return artifactsByType;
+    }
+
+    private Either<ZipOutputStream, ResponseFormat> writeAllFilesToCsar(Component mainComponent, CsarDefinition csarDefinition,
+                                                                        ZipOutputStream zipstream, boolean isInCertificationRequest)
+        throws IOException {
+        ComponentArtifacts componentArtifacts = csarDefinition.getComponentArtifacts();
+        Either<ZipOutputStream, ResponseFormat> writeComponentArtifactsToSpecifiedPath = writeComponentArtifactsToSpecifiedPath(mainComponent,
+            componentArtifacts, zipstream, ARTIFACTS_PATH, isInCertificationRequest);
+        if (writeComponentArtifactsToSpecifiedPath.isRight()) {
+            return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
+        }
+        ComponentTypeArtifacts mainTypeAndCIArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
+        writeComponentArtifactsToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent, mainTypeAndCIArtifacts.getComponentArtifacts(),
+            zipstream, ARTIFACTS_PATH, isInCertificationRequest);
+        if (writeComponentArtifactsToSpecifiedPath.isRight()) {
+            return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
+        }
+        Map<String, ArtifactsInfo> componentInstancesArtifacts = mainTypeAndCIArtifacts.getComponentInstancesArtifacts();
+        String currentPath = ARTIFACTS_PATH + RESOURCES_PATH;
+        for (String keyAssetName : componentInstancesArtifacts.keySet()) {
+            ArtifactsInfo artifactsInfo = componentInstancesArtifacts.get(keyAssetName);
+            String pathWithAssetName = currentPath + keyAssetName + PATH_DELIMITER;
+            writeComponentArtifactsToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent, artifactsInfo, zipstream, pathWithAssetName,
+                isInCertificationRequest);
+            if (writeComponentArtifactsToSpecifiedPath.isRight()) {
+                return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
+            }
+        }
+        writeComponentArtifactsToSpecifiedPath = writeOperationsArtifactsToCsar(mainComponent, zipstream);
+        if (writeComponentArtifactsToSpecifiedPath.isRight()) {
+            return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
+        }
+        return Either.left(zipstream);
+    }
+
+    private Either<ZipOutputStream, ResponseFormat> writeOperationsArtifactsToCsar(Component component, ZipOutputStream zipstream) {
+        if (checkComponentBeforeOperation(component)) {
+            return Either.left(zipstream);
+        }
+        for (Map.Entry<String, InterfaceDefinition> interfaceEntry : ((Resource) component).getInterfaces().entrySet()) {
+            for (OperationDataDefinition operation : interfaceEntry.getValue().getOperations().values()) {
+                try {
+                    if (checkComponentBeforeWrite(component, interfaceEntry, operation)) {
+                        continue;
+                    }
+                    final String artifactUUID = operation.getImplementation().getArtifactUUID();
+                    if (artifactUUID == null) {
+                        continue;
+                    }
+                    final Either<byte[], ActionStatus> artifactFromCassandra = getFromCassandra(artifactUUID);
+                    final String artifactName = operation.getImplementation().getArtifactName();
+                    if (artifactFromCassandra.isRight()) {
+                        LOGGER.error(ARTIFACT_NAME_UNIQUE_ID, artifactName, artifactUUID);
+                        LOGGER.error("Failed to get {} payload from DB reason: {}", artifactName, artifactFromCassandra.right().value());
+                        return Either.right(componentsUtils.getResponseFormat(
+                            ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION, "Resource", component.getUniqueId(), artifactName, artifactUUID));
+                    }
+                    zipstream.putNextEntry(new ZipEntry(OperationArtifactUtil.createOperationArtifactPath(component, null, operation, true)));
+                    zipstream.write(artifactFromCassandra.left().value());
+                } catch (IOException e) {
+                    LOGGER.error("Component Name {},  Interface Name {}, Operation Name {}", component.getNormalizedName(), interfaceEntry.getKey(),
+                        operation.getName());
+                    LOGGER.error("Error while writing the operation's artifacts to the CSAR", e);
+                    return Either.right(componentsUtils.getResponseFormat(ERROR_DURING_CSAR_CREATION, "Resource", component.getUniqueId()));
+                }
+            }
+        }
+        return Either.left(zipstream);
+    }
+
+    private boolean checkComponentBeforeWrite(Component component, Map.Entry<String, InterfaceDefinition> interfaceEntry,
+                                              OperationDataDefinition operation) {
+        final ArtifactDataDefinition implementation = operation.getImplementation();
+        if (implementation == null) {
+            LOGGER.debug("Component Name {}, Interface Id {}, Operation Name {} - no Operation Implementation found", component.getNormalizedName(),
+                interfaceEntry.getValue().getUniqueId(), operation.getName());
+            return true;
+        }
+        final String artifactName = implementation.getArtifactName();
+        if (artifactName == null) {
+            LOGGER.debug("Component Name {}, Interface Id {}, Operation Name {} - no artifact found", component.getNormalizedName(),
+                interfaceEntry.getValue().getUniqueId(), operation.getName());
+            return true;
+        }
+        if (OperationArtifactUtil.artifactNameIsALiteralValue(artifactName)) {
+            LOGGER.debug("Component Name {}, Interface Id {}, Operation Name {} - artifact name is a literal value rather than an SDC artifact",
+                component.getNormalizedName(), interfaceEntry.getValue().getUniqueId(), operation.getName());
+            return true;
+        }
+        return false;
+    }
+
+    private boolean checkComponentBeforeOperation(Component component) {
+        if (component instanceof Service) {
+            return true;
+        }
+        if (Objects.isNull(((Resource) component).getInterfaces())) {
+            LOGGER.debug("Component Name {}- no interfaces found", component.getNormalizedName());
+            return true;
+        }
+        return false;
+    }
+
+    private Either<ZipOutputStream, ResponseFormat> writeArtifactsInfoToSpecifiedPath(final Component mainComponent,
+                                                                                      final ArtifactsInfo currArtifactsInfo,
+                                                                                      final ZipOutputStream zip, final String path,
+                                                                                      final boolean isInCertificationRequest) throws IOException {
+        final Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactsInfo = currArtifactsInfo.getArtifactsInfo();
+        for (final ArtifactGroupTypeEnum artifactGroupTypeEnum : artifactsInfo.keySet()) {
+            final String groupTypeFolder = path + WordUtils.capitalizeFully(artifactGroupTypeEnum.getType()) + PATH_DELIMITER;
+            final Map<String, List<ArtifactDefinition>> artifactTypesMap = artifactsInfo.get(artifactGroupTypeEnum);
+            for (final String artifactType : artifactTypesMap.keySet()) {
+                final List<ArtifactDefinition> artifactDefinitionList = artifactTypesMap.get(artifactType);
+                String artifactTypeFolder = groupTypeFolder + artifactType + PATH_DELIMITER;
+                if (ArtifactTypeEnum.WORKFLOW.getType().equals(artifactType) && path.contains(ARTIFACTS_PATH + RESOURCES_PATH)) {
+                    // Ignore this packaging as BPMN artifacts needs to be packaged in different manner
+                    continue;
+                }
+                if (ArtifactTypeEnum.WORKFLOW.getType().equals(artifactType)) {
+                    artifactTypeFolder += OperationArtifactUtil.BPMN_ARTIFACT_PATH + File.separator;
+                } else if (ArtifactTypeEnum.ONBOARDED_PACKAGE.getType().equals(artifactType)) {
+                    // renaming legacy folder ONBOARDED_PACKAGE to the new folder ETSI_PACKAGE
+                    artifactTypeFolder = artifactTypeFolder
+                        .replace(ArtifactTypeEnum.ONBOARDED_PACKAGE.getType(), ArtifactTypeEnum.ETSI_PACKAGE.getType());
+                }
+                // TODO: We should not do this but in order to keep this refactoring small enough,
+
+                // we'll leave this as is for now
+                List<ArtifactDefinition> collect = filterArtifactDefinitionToZip(mainComponent, artifactDefinitionList, isInCertificationRequest)
+                    .collect(Collectors.toList());
+                for (ArtifactDefinition ad : collect) {
+                    zip.putNextEntry(new ZipEntry(artifactTypeFolder + ad.getArtifactName()));
+                    zip.write(ad.getPayloadData());
+                }
+            }
+        }
+        return Either.left(zip);
+    }
+
+    private Stream<ArtifactDefinition> filterArtifactDefinitionToZip(Component mainComponent, List<ArtifactDefinition> artifactDefinitionList,
+                                                                     boolean isInCertificationRequest) {
+        return artifactDefinitionList.stream().filter(shouldBeInZip(isInCertificationRequest, mainComponent)).map(this::fetchPayLoadData)
+            .filter(Either::isLeft).map(e -> e.left().value());
+    }
+
+    private Predicate<ArtifactDefinition> shouldBeInZip(boolean isInCertificationRequest, Component component) {
+        return artifactDefinition -> !(!isInCertificationRequest && component.isService() && artifactDefinition.isHeatEnvType() || artifactDefinition
+            .hasNoMandatoryEsId());
+    }
+
+    private Either<ArtifactDefinition, ActionStatus> fetchPayLoadData(ArtifactDefinition ad) {
+        byte[] payloadData = ad.getPayloadData();
+        if (payloadData == null) {
+            return getFromCassandra(ad.getEsId()).left().map(pd -> {
+                ad.setPayload(pd);
+                return ad;
+            }).right().map(as -> {
+                LOGGER.debug(ARTIFACT_NAME_UNIQUE_ID, ad.getArtifactName(), ad.getUniqueId());
+                LOGGER.debug("Failed to get {} payload from DB reason: {}", ad.getArtifactName(), as);
+                return as;
+            });
+        } else {
+            return Either.left(ad);
+        }
+    }
+
+    private Either<ZipOutputStream, ResponseFormat> writeComponentArtifactsToSpecifiedPath(Component mainComponent,
+                                                                                           ComponentArtifacts componentArtifacts,
+                                                                                           ZipOutputStream zipstream, String currentPath,
+                                                                                           boolean isInCertificationRequest) throws IOException {
+        Map<String, ComponentTypeArtifacts> componentTypeArtifacts = componentArtifacts.getComponentTypeArtifacts();
+        //Keys are defined:
+
+        //<Inner Asset TOSCA name (e.g. VFC name)> folder name: <Inner Asset TOSCA name (e.g. VFC name)>_v<version>.
+
+        //E.g. "org.openecomp.resource.vf.vipr_atm_v1.0"
+        Set<String> componentTypeArtifactsKeys = componentTypeArtifacts.keySet();
+        for (String keyAssetName : componentTypeArtifactsKeys) {
+            ComponentTypeArtifacts componentInstanceArtifacts = componentTypeArtifacts.get(keyAssetName);
+            ArtifactsInfo componentArtifacts2 = componentInstanceArtifacts.getComponentArtifacts();
+            String pathWithAssetName = currentPath + keyAssetName + PATH_DELIMITER;
+            Either<ZipOutputStream, ResponseFormat> writeArtifactsInfoToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent,
+                componentArtifacts2, zipstream, pathWithAssetName, isInCertificationRequest);
+            if (writeArtifactsInfoToSpecifiedPath.isRight()) {
+                return writeArtifactsInfoToSpecifiedPath;
+            }
+        }
+        return Either.left(zipstream);
+    }
+
+    private Either<ToscaRepresentation, ResponseFormat> generateToscaRepresentation(Component component, boolean isSkipImports) {
+        return toscaExportUtils.exportComponent(component, isSkipImports).right().map(toscaError -> {
+            LOGGER.debug("exportComponent failed {}", toscaError);
+            return componentsUtils.getResponseFormat(componentsUtils.convertFromToscaError(toscaError));
+        });
+    }
+
+    private String createToscaBlock0(String metaFileVersion, String csarVersion, String createdBy, String entryDef, boolean isAsdPackage,
+                                     String definitionsPath) {
+        final String block0template = "TOSCA-Meta-File-Version: %s\nCSAR-Version: %s\nCreated-By: %s\nEntry-Definitions: "
+            + definitionsPath + "%s\n%s\nName: csar.meta\nContent-Type: text/plain\n";
+        return String.format(block0template, metaFileVersion, csarVersion, createdBy, entryDef, isAsdPackage ? "entry_definition_type: asd" : "");
+    }
+
+    private class CsarDefinition {
+
+        private ComponentArtifacts componentArtifacts;
+
+        // add list of tosca artifacts and meta describes CSAR zip root
+        public CsarDefinition(ComponentArtifacts componentArtifacts) {
+            this.componentArtifacts = componentArtifacts;
+        }
+
+        public ComponentArtifacts getComponentArtifacts() {
+            return componentArtifacts;
+        }
+    }
+
+    private class ComponentArtifacts {
+
+        //artifacts of the component and CI's artifacts contained in it's composition (represents Informational, Deployment & Resource folders of main component)
+        private ComponentTypeArtifacts mainTypeAndCIArtifacts;
+        //artifacts of all component types mapped by their tosca name
+        private Map<String, ComponentTypeArtifacts> componentTypeArtifacts;
+
+        public ComponentArtifacts() {
+            mainTypeAndCIArtifacts = new ComponentTypeArtifacts();
+            componentTypeArtifacts = new HashMap<>();
+        }
+
+        public ComponentTypeArtifacts getMainTypeAndCIArtifacts() {
+            return mainTypeAndCIArtifacts;
+        }
+
+        public void setMainTypeAndCIArtifacts(ComponentTypeArtifacts componentInstanceArtifacts) {
+            this.mainTypeAndCIArtifacts = componentInstanceArtifacts;
+        }
+
+        public Map<String, ComponentTypeArtifacts> getComponentTypeArtifacts() {
+            return componentTypeArtifacts;
+        }
+    }
+
+    /**
+     * The artifacts of the component and of all its composed instances
+     */
+    private class ComponentTypeArtifacts {
+
+        private ArtifactsInfo componentArtifacts;    //component artifacts (describes the Informational Deployment folders)
+
+        private Map<String, ArtifactsInfo> componentInstancesArtifacts;        //artifacts of the composed instances mapped by the resourceInstance normalized name (describes the Resources folder)
+
+        public ComponentTypeArtifacts() {
+            componentArtifacts = new ArtifactsInfo();
+            componentInstancesArtifacts = new HashMap<>();
+        }
+
+        public ArtifactsInfo getComponentArtifacts() {
+            return componentArtifacts;
+        }
+
+        public void setComponentArtifacts(ArtifactsInfo artifactsInfo) {
+            this.componentArtifacts = artifactsInfo;
+        }
+
+        public Map<String, ArtifactsInfo> getComponentInstancesArtifacts() {
+            return componentInstancesArtifacts;
+        }
+
+        public void addComponentInstancesArtifacts(String normalizedName, ArtifactsInfo artifactsInfo) {
+            componentInstancesArtifacts.put(normalizedName, artifactsInfo);
+        }
+    }
+
+    /**
+     * The artifacts Definition saved by their structure
+     */
+    private class ArtifactsInfo {
+        //Key is the type of artifacts(Informational/Deployment)
+
+        //Value is a map between an artifact type and a list of all artifacts of this type
+        private Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactsInfoField;
+
+        public ArtifactsInfo() {
+            this.artifactsInfoField = new EnumMap<>(ArtifactGroupTypeEnum.class);
+        }
+
+        public Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> getArtifactsInfo() {
+            return artifactsInfoField;
+        }
+
+        public void addArtifactsToGroup(ArtifactGroupTypeEnum artifactGroup, Map<String, List<ArtifactDefinition>> artifactsDefinition) {
+            if (artifactsInfoField.get(artifactGroup) == null) {
+                artifactsInfoField.put(artifactGroup, artifactsDefinition);
+            } else {
+                Map<String, List<ArtifactDefinition>> artifactTypeEnumListMap = artifactsInfoField.get(artifactGroup);
+                artifactTypeEnumListMap.putAll(artifactsDefinition);
+                artifactsInfoField.put(artifactGroup, artifactTypeEnumListMap);
+            }
+        }
+
+        public boolean isEmpty() {
+            return artifactsInfoField.isEmpty();
+        }
+
+        public boolean isNotEmpty() {
+            return !isEmpty();
+        }
+    }
+
+    public static class ToscaErrorException extends Exception {
+
+        ToscaErrorException(ToscaError error) {
+            super("Error while exporting component's interface (toscaError:" + error + ")");
+        }
+    }
+
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ComponentCache.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ComponentCache.java
index 57ebcf6..5171923 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ComponentCache.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ComponentCache.java
@@ -27,6 +27,7 @@
 import java.util.function.BiConsumer;
 import java.util.function.BinaryOperator;
 import lombok.EqualsAndHashCode;
+import lombok.Getter;
 import org.apache.commons.lang3.tuple.ImmutableTriple;
 import org.openecomp.sdc.be.model.Component;
 
@@ -132,6 +133,7 @@
      * Entry stored by the cache
      */
     @EqualsAndHashCode
+    @Getter
     public static final class CacheEntry {
 
         final String id;
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
index 6a35307..35854d3 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
@@ -19,124 +19,65 @@
  */
 package org.openecomp.sdc.be.tosca;
 
-import static org.openecomp.sdc.be.dao.api.ActionStatus.ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION;
-import static org.openecomp.sdc.be.dao.api.ActionStatus.ERROR_DURING_CSAR_CREATION;
-import static org.openecomp.sdc.be.tosca.ComponentCache.MergeStrategy.overwriteIfSameVersions;
-import static org.openecomp.sdc.be.tosca.FJToVavrHelper.Try0.fromEither;
-
 import fj.F;
 import fj.data.Either;
-import io.vavr.Tuple2;
-import io.vavr.control.Option;
-import io.vavr.control.Try;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.File;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Path;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
-import java.util.TimeZone;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.io.output.ByteArrayOutputStream;
-import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.ImmutableTriple;
-import org.apache.commons.lang3.tuple.Triple;
-import org.apache.commons.text.WordUtils;
-import org.onap.sdc.tosca.services.YamlUtil;
 import org.openecomp.sdc.be.components.impl.ImportUtils;
-import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
-import org.openecomp.sdc.be.config.*;
+import org.openecomp.sdc.be.config.ArtifactConfigManager;
+import org.openecomp.sdc.be.config.ArtifactConfiguration;
+import org.openecomp.sdc.be.config.ComponentType;
+import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
-import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
-import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
-import org.openecomp.sdc.be.dao.cassandra.SdcSchemaFilesCassandraDao;
-import org.openecomp.sdc.be.data.model.ToscaImportByModel;
-import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.model.ArtifactDefinition;
 import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.ComponentInstance;
-import org.openecomp.sdc.be.model.InterfaceDefinition;
-import org.openecomp.sdc.be.model.LifecycleStateEnum;
-import org.openecomp.sdc.be.model.Resource;
 import org.openecomp.sdc.be.model.Service;
-import org.openecomp.sdc.be.model.category.CategoryDefinition;
 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.DaoStatusConverter;
-import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
-import org.openecomp.sdc.be.plugins.CsarEntryGenerator;
-import org.openecomp.sdc.be.resources.data.DAOArtifactData;
-import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil;
-import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
-import org.openecomp.sdc.common.impl.ExternalConfiguration;
 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
-import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
 import org.openecomp.sdc.common.log.enums.StatusCode;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.GeneralUtility;
 import org.openecomp.sdc.common.util.ValidationUtils;
-import org.openecomp.sdc.common.zip.ZipUtils;
 import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.yaml.snakeyaml.Yaml;
 
 @org.springframework.stereotype.Component("csar-utils")
 public class CsarUtils {
 
-    public static final String NODES_YML = "nodes.yml";
     public static final String ARTIFACTS_PATH = "Artifacts/";
     public static final String ARTIFACTS = "Artifacts";
     public static final String ARTIFACT_CREATED_FROM_CSAR = "Artifact created from csar";
     private static final Logger log = Logger.getLogger(CsarUtils.class);
     private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(CsarUtils.class.getName());
     private static final String PATH_DELIMITER = "/";
-    private static final String CONFORMANCE_LEVEL = ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel();
-    private static final String SDC_VERSION = ExternalConfiguration.getAppVersion();
-    private static final String RESOURCES_PATH = "Resources/";
-    private static final String DEFINITIONS_PATH = "Definitions/";
     private static final String CSAR_META_VERSION = "1.0";
     private static final String CSAR_META_PATH_FILE_NAME = "csar.meta";
-    private static final String TOSCA_META_PATH_FILE_NAME = "TOSCA-Metadata/TOSCA.meta";
-    private static final String TOSCA_META_VERSION = "1.0";
-    private static final String CSAR_VERSION = "1.1";
-    // add manifest
-    private static final String SERVICE_MANIFEST = "NS.mf";
     private static final String DEFINITION = "Definitions";
     private static final String DEL_PATTERN = "([/\\\\]+)";
     private static final String WORD_PATTERN = "\\w\\_\\@\\-\\.\\s]+)";
@@ -152,7 +93,6 @@
         // Service Template File Name
         VALID_ENGLISH_ARTIFACT_NAME;
     private static final String VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS = "([\\d" + WORD_PATTERN;
-    private static final String ARTIFACT_NAME_UNIQUE_ID = "ArtifactName {}, unique ID {}";
     private static final String VFC_NODE_TYPE_ARTIFACTS_PATH_PATTERN =
         ARTIFACTS + DEL_PATTERN + ImportUtils.Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS + DEL_PATTERN
             + VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS + DEL_PATTERN + VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS + DEL_PATTERN
@@ -160,44 +100,16 @@
     private static final String BLOCK_0_TEMPLATE = "SDC-TOSCA-Meta-File-Version: %s\nSDC-TOSCA-Definitions-Version: %s\n";
 
     private final ToscaOperationFacade toscaOperationFacade;
-    private final SdcSchemaFilesCassandraDao sdcSchemaFilesCassandraDao;
-    private final ArtifactCassandraDao artifactCassandraDao;
     private final ComponentsUtils componentsUtils;
-    private final ToscaExportHandler toscaExportUtils;
-    private final List<CsarEntryGenerator> generators;
-    private final ModelOperation modelOperation;
-    private final String versionFirstThreeOctets;
+    private final MapFromModelCsarGeneratorService mapFromModelCsarGeneratorService;
 
     @Autowired
-    public CsarUtils(final ToscaOperationFacade toscaOperationFacade, final SdcSchemaFilesCassandraDao sdcSchemaFilesCassandraDao,
-                     final ArtifactCassandraDao artifactCassandraDao, final ComponentsUtils componentsUtils,
-                     final ToscaExportHandler toscaExportUtils, final List<CsarEntryGenerator> generators, final ModelOperation modelOperation) {
+    public CsarUtils(final ToscaOperationFacade toscaOperationFacade,
+                     final ComponentsUtils componentsUtils,
+                     final MapFromModelCsarGeneratorService mapFromModelCsarGeneratorService) {
         this.toscaOperationFacade = toscaOperationFacade;
-        this.sdcSchemaFilesCassandraDao = sdcSchemaFilesCassandraDao;
-        this.artifactCassandraDao = artifactCassandraDao;
         this.componentsUtils = componentsUtils;
-        this.toscaExportUtils = toscaExportUtils;
-        this.generators = generators;
-        this.modelOperation = modelOperation;
-        this.versionFirstThreeOctets = readVersionFirstThreeOctets();
-    }
-
-    private String readVersionFirstThreeOctets() {
-        if (StringUtils.isEmpty(SDC_VERSION)) {
-            return "";
-        }
-        // change regex to avoid DoS sonar issue
-        Matcher matcher = Pattern.compile("(?!\\.)(\\d{1,9}(\\.\\d{1,9}){1,9})(?![\\d\\.])").matcher(SDC_VERSION);
-        matcher.find();
-        return matcher.group(0);
-    }
-
-    private static <L, R> F<L, Either<L, R>> iff(Predicate<L> p, Function<L, Either<L, R>> ifTrue) {
-        return l -> p.test(l) ? ifTrue.apply(l) : Either.left(l);
-    }
-
-    private static <A, B> F<A, B> iff(Predicate<A> p, Supplier<B> s, Function<A, B> orElse) {
-        return a -> p.test(a) ? s.get() : orElse.apply(a);
+        this.mapFromModelCsarGeneratorService = mapFromModelCsarGeneratorService;
     }
 
     /**
@@ -367,15 +279,11 @@
     public Either<byte[], ResponseFormat> createCsar(final Component component, final boolean getFromCS, final boolean isInCertificationRequest) {
         loggerSupportability
             .log(LoggerSupportabilityActions.GENERATE_CSAR, StatusCode.STARTED, "Starting to create Csar for component {} ", component.getName());
-        final String createdBy = component.getCreatorFullName();
-        final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
-        final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
-        final String fileName = artifactDefinition.getArtifactName();
         final String toscaConformanceLevel = ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel();
         final byte[] csarBlock0Byte = createCsarBlock0(CSAR_META_VERSION, toscaConformanceLevel).getBytes();
-        final byte[] toscaBlock0Byte = createToscaBlock0(TOSCA_META_VERSION, CSAR_VERSION, createdBy, fileName, isAsdPackage(component)).getBytes();
 
-        return generateCsarZip(csarBlock0Byte, toscaBlock0Byte, component, getFromCS, isInCertificationRequest).left().map(responseFormat -> {
+        return generateCsarZip(csarBlock0Byte,
+            isAsdPackage(component), component, getFromCS, isInCertificationRequest).left().map(responseFormat -> {
             loggerSupportability
                 .log(LoggerSupportabilityActions.GENERATE_CSAR, StatusCode.COMPLETE, "Ended create Csar for component {} ", component.getName());
             return responseFormat;
@@ -402,21 +310,22 @@
         return false;
     }
 
-    private Either<byte[], ResponseFormat> generateCsarZip(byte[] csarBlock0Byte, byte[] toscaBlock0Byte, Component component, boolean getFromCS,
+    private Either<byte[], ResponseFormat> generateCsarZip(byte[] csarBlock0Byte,
+                                                           boolean isAsdPackage,
+                                                           Component component,
+                                                           boolean getFromCS,
                                                            boolean isInCertificationRequest) {
-        try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out)) {
+        try (final ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out)) {
             zip.putNextEntry(new ZipEntry(CSAR_META_PATH_FILE_NAME));
             zip.write(csarBlock0Byte);
-            zip.putNextEntry(new ZipEntry(TOSCA_META_PATH_FILE_NAME));
-            zip.write(toscaBlock0Byte);
-            Either<ZipOutputStream, ResponseFormat> populateZip = populateZip(component, getFromCS, zip, isInCertificationRequest);
+            Either<ZipOutputStream, ResponseFormat> populateZip = mapFromModelCsarGeneratorService.generateCsarZip(
+                component, getFromCS, zip, isInCertificationRequest, isAsdPackage);
             if (populateZip.isRight()) {
                 log.debug("Failed to populate CSAR zip file {}. Please fix DB table accordingly ", populateZip.right().value());
                 return Either.right(populateZip.right().value());
             }
             zip.finish();
-            byte[] byteArray = out.toByteArray();
-            return Either.left(byteArray);
+            return Either.left(out.toByteArray());
         } catch (IOException e) {
             log.debug("Failed with IOexception to create CSAR zip for component {}. Please fix DB table accordingly ", component.getUniqueId(), e);
             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
@@ -424,679 +333,10 @@
         }
     }
 
-    private Either<ZipOutputStream, ResponseFormat> populateZip(Component component, boolean getFromCS, ZipOutputStream zip,
-                                                                boolean isInCertificationRequest) throws IOException {
-        ArtifactDefinition artifactDef = component.getToscaArtifacts().get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
-        Either<ToscaRepresentation, ResponseFormat> toscaRepresentation = fetchToscaRepresentation(component, getFromCS, artifactDef);
-
-        // This should not be done but in order to keep the refactoring small enough we stop here.
-
-        // TODO: Refactor the rest of this function
-        byte[] mainYaml;
-        List<Triple<String, String, Component>> dependencies;
-        if (toscaRepresentation.isLeft()) {
-            mainYaml = toscaRepresentation.left().value().getMainYaml();
-            dependencies = toscaRepresentation.left().value().getDependencies().getOrElse(new ArrayList<>());
-        } else {
-            return Either.right(toscaRepresentation.right().value());
-        }
-        String fileName = artifactDef.getArtifactName();
-        zip.putNextEntry(new ZipEntry(DEFINITIONS_PATH + fileName));
-        zip.write(mainYaml);
-        LifecycleStateEnum lifecycleState = component.getLifecycleState();
-        addServiceMf(component, zip, lifecycleState, isInCertificationRequest, fileName, mainYaml);
-        //US798487 - Abstraction of complex types
-        if (hasToWriteComponentSubstitutionType(component)) {
-            log.debug("Component {} is complex - generating abstract type for it..", component.getName());
-            dependencies.addAll(writeComponentInterface(component, zip, fileName));
-        }
-        //UID <cassandraId,filename,component>
-        Either<ZipOutputStream, ResponseFormat> zipOutputStreamOrResponseFormat = getZipOutputStreamResponseFormatEither(zip, dependencies);
-        if (zipOutputStreamOrResponseFormat != null && zipOutputStreamOrResponseFormat.isRight()) {
-            return zipOutputStreamOrResponseFormat;
-        }
-        if (component.getModel() == null) {
-            //retrieve SDC.zip from Cassandra
-            Either<byte[], ResponseFormat> latestSchemaFiles = getLatestSchemaFilesFromCassandra();
-            if (latestSchemaFiles.isRight()) {
-                log.error("Error retrieving SDC Schema files from cassandra");
-                return Either.right(latestSchemaFiles.right().value());
-            }
-            final byte[] schemaFileZip = latestSchemaFiles.left().value();
-            final List<String> nodesFromPackage = findNonRootNodesFromPackage(dependencies);
-            //add files from retrieved SDC.zip to Definitions folder in CSAR
-            addSchemaFilesFromCassandra(zip, schemaFileZip, nodesFromPackage);
-        } else {
-            //retrieve schema files by model from Cassandra
-            addSchemaFilesByModel(zip, component.getModel());
-        }
-        Either<CsarDefinition, ResponseFormat> collectedComponentCsarDefinition = collectComponentCsarDefinition(component);
-        if (collectedComponentCsarDefinition.isRight()) {
-            return Either.right(collectedComponentCsarDefinition.right().value());
-        }
-        if (generators != null) {
-            for (CsarEntryGenerator generator : generators) {
-                log.debug("Invoking CsarEntryGenerator: {}", generator.getClass().getName());
-                for (Entry<String, byte[]> pluginGeneratedFile : generator.generateCsarEntries(component).entrySet()) {
-                    zip.putNextEntry(new ZipEntry(pluginGeneratedFile.getKey()));
-                    zip.write(pluginGeneratedFile.getValue());
-                }
-            }
-        }
-        return writeAllFilesToCsar(component, collectedComponentCsarDefinition.left().value(), zip, isInCertificationRequest);
-    }
-
-    private void addServiceMf(Component component, ZipOutputStream zip, LifecycleStateEnum lifecycleState, boolean isInCertificationRequest,
-                              String fileName, byte[] mainYaml) throws IOException {
-        // add mf
-        if ((component.getComponentType() == ComponentTypeEnum.SERVICE) && (lifecycleState != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT)) {
-            String serviceName = component.getName();
-            String createdBy = component.getCreatorUserId();
-            String serviceVersion;
-            if (isInCertificationRequest) {
-                int tmp = Integer.valueOf(component.getVersion().split("\\.")[0]) + 1;
-                serviceVersion = String.valueOf(tmp) + ".0";
-            } else {
-                serviceVersion = component.getVersion();
-            }
-            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
-            format.setTimeZone(TimeZone.getTimeZone("UTC"));
-            Date date = new Date();
-            String releaseTime = format.format(date);
-            if (component.getCategories() == null || component.getCategories().get(0) == null) {
-                return;
-            }
-            String serviceType = component.getCategories().get(0).getName();
-            String description = component.getDescription();
-            String serviceTemplate = DEFINITIONS_PATH + fileName;
-            String hash = GeneralUtility.calculateMD5Base64EncodedByByteArray(mainYaml);
-            String nsMfBlock0 = createNsMfBlock0(serviceName, createdBy, serviceVersion, releaseTime, serviceType, description, serviceTemplate,
-                hash);
-            byte[] nsMfBlock0Byte = nsMfBlock0.getBytes();
-            zip.putNextEntry(new ZipEntry(SERVICE_MANIFEST));
-            zip.write(nsMfBlock0Byte);
-        }
-    }
-
-    private Either<ToscaRepresentation, ResponseFormat> fetchToscaRepresentation(Component component, boolean getFromCS,
-                                                                                 ArtifactDefinition artifactDef) {
-        LifecycleStateEnum lifecycleState = component.getLifecycleState();
-        boolean shouldBeFetchedFromCassandra =
-            getFromCS || !(lifecycleState == LifecycleStateEnum.NOT_CERTIFIED_CHECKIN || lifecycleState == LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
-        Either<ToscaRepresentation, ResponseFormat> toscaRepresentation =
-            shouldBeFetchedFromCassandra ? fetchToscaRepresentation(artifactDef) : generateToscaRepresentation(component);
-        return toscaRepresentation.left()
-            .bind(iff(myd -> !myd.getDependencies().isDefined(), myd -> fetchToscaTemplateDependencies(myd.getMainYaml(), component)));
-    }
-
-    private Either<ToscaRepresentation, ResponseFormat> fetchToscaTemplateDependencies(byte[] mainYml, Component component) {
-        return toscaExportUtils.getDependencies(component).right().map(toscaError -> {
-            log.debug("Failed to retrieve dependencies for component {}, error {}", component.getUniqueId(), toscaError);
-            return componentsUtils.getResponseFormat(componentsUtils.convertFromToscaError(toscaError));
-        }).left().map(tt -> ToscaRepresentation.make(mainYml, tt));
-    }
-
-    private Either<ToscaRepresentation, ResponseFormat> generateToscaRepresentation(Component component) {
-        return toscaExportUtils.exportComponent(component).right().map(toscaError -> {
-            log.debug("exportComponent failed {}", toscaError);
-            return componentsUtils.getResponseFormat(componentsUtils.convertFromToscaError(toscaError));
-        });
-    }
-
-    private Either<ToscaRepresentation, ResponseFormat> fetchToscaRepresentation(ArtifactDefinition artifactDef) {
-        return getFromCassandra(artifactDef.getEsId()).right().map(as -> {
-            log.debug(ARTIFACT_NAME_UNIQUE_ID, artifactDef.getArtifactName(), artifactDef.getUniqueId());
-            return componentsUtils.getResponseFormat(as);
-        }).left().map(ToscaRepresentation::make);
-    }
-
-    /**
-     * Create a list of all derived nodes found on the package
-     *
-     * @param dependencies all node dependencies
-     * @return a list of nodes
-     */
-    private List<String> findNonRootNodesFromPackage(final List<Triple<String, String, Component>> dependencies) {
-        final List<String> nodes = new ArrayList<>();
-        if (CollectionUtils.isNotEmpty(dependencies)) {
-            final String NATIVE_ROOT = "tosca.nodes.Root";
-            dependencies.forEach(dependency -> {
-                if (dependency.getRight() instanceof Resource) {
-                    final Resource resource = (Resource) dependency.getRight();
-                    if (CollectionUtils.isNotEmpty(resource.getDerivedList())) {
-                        resource.getDerivedList().stream().filter(node -> !nodes.contains(node) && !NATIVE_ROOT.equalsIgnoreCase(node))
-                            .forEach(node -> nodes.add(node));
-                    }
-                }
-            });
-        }
-        return nodes;
-    }
-
-    /**
-     * Writes a new zip entry
-     *
-     * @param zipInputStream the zip entry to be read
-     * @return a map of the given zip entry
-     */
-    private Map<String, Object> readYamlZipEntry(final ZipInputStream zipInputStream) throws IOException {
-        final int initSize = 2048;
-        final StringBuilder zipEntry = new StringBuilder();
-        final byte[] buffer = new byte[initSize];
-        int read = 0;
-        while ((read = zipInputStream.read(buffer, 0, initSize)) >= 0) {
-            zipEntry.append(new String(buffer, 0, read));
-        }
-        return (Map<String, Object>) new Yaml().load(zipEntry.toString());
-    }
-
-    /**
-     * Filters and removes all duplicated nodes found
-     *
-     * @param nodesFromPackage      a List of all derived nodes found on the given package
-     * @param nodesFromArtifactFile represents the nodes.yml file stored in Cassandra
-     * @return a nodes Map updated
-     */
-    private Map<String, Object> updateNodeYml(final List<String> nodesFromPackage, final Map<String, Object> nodesFromArtifactFile) {
-        if (MapUtils.isNotEmpty(nodesFromArtifactFile)) {
-            final String nodeTypeBlock = ToscaTagNamesEnum.NODE_TYPES.getElementName();
-            final Map<String, Object> nodeTypes = (Map<String, Object>) nodesFromArtifactFile.get(nodeTypeBlock);
-            nodesFromPackage.stream().filter(nodeTypes::containsKey).forEach(nodeTypes::remove);
-            nodesFromArtifactFile.replace(nodeTypeBlock, nodeTypes);
-        }
-        return nodesFromArtifactFile;
-    }
-
-    /**
-     * Updates the zip entry from the given parameters
-     *
-     * @param byteArrayOutputStream an output stream in which the data is written into a byte array.
-     * @param nodesYaml             a Map of nodes to be written
-     */
-    private void updateZipEntry(final ByteArrayOutputStream byteArrayOutputStream, final Map<String, Object> nodesYaml) throws IOException {
-        if (MapUtils.isNotEmpty(nodesYaml)) {
-            byteArrayOutputStream.write(new YamlUtil().objectToYaml(nodesYaml).getBytes());
-        }
-    }
-
-    private Either<ZipOutputStream, ResponseFormat> getZipOutputStreamResponseFormatEither(ZipOutputStream zip,
-                                                                                           List<Triple<String, String, Component>> dependencies)
-        throws IOException {
-        ComponentCache innerComponentsCache = ComponentCache.overwritable(overwriteIfSameVersions()).onMerge((oldValue, newValue) -> {
-            log.warn("Overwriting component invariantID {} of version {} with a newer version {}", oldValue.id, oldValue.getComponentVersion(),
-                newValue.getComponentVersion());
-        });
-        if (dependencies != null && !dependencies.isEmpty()) {
-            for (Triple<String, String, Component> d : dependencies) {
-                String cassandraId = d.getMiddle();
-                Component childComponent = d.getRight();
-                Either<byte[], ResponseFormat> entryData = getEntryData(cassandraId, childComponent).right()
-                    .map(componentsUtils::getResponseFormat);
-                if (entryData.isRight()) {
-                    return Either.right(entryData.right().value());
-                }
-                //fill innerComponentsCache
-                String fileName = d.getLeft();
-                innerComponentsCache.put(cassandraId, fileName, childComponent);
-                addInnerComponentsToCache(innerComponentsCache, childComponent);
-            }
-            //add inner components to CSAR
-            return addInnerComponentsToCSAR(zip, innerComponentsCache);
-        }
-        return null;
-    }
-
-    private Either<ZipOutputStream, ResponseFormat> addInnerComponentsToCSAR(ZipOutputStream zip, ComponentCache innerComponentsCache)
-        throws IOException {
-        for (ImmutableTriple<String, String, Component> ict : innerComponentsCache.iterable()) {
-            Component innerComponent = ict.getRight();
-            String icFileName = ict.getMiddle();
-            // add component to zip
-            Either<Tuple2<byte[], ZipEntry>, ResponseFormat> zipEntry = toZipEntry(ict);
-            // TODO: this should not be done, we should instead compose this either further,
-
-            // but in order to keep this refactoring small, we'll stop here.
-            if (zipEntry.isRight()) {
-                return Either.right(zipEntry.right().value());
-            }
-            Tuple2<byte[], ZipEntry> value = zipEntry.left().value();
-            zip.putNextEntry(value._2);
-            zip.write(value._1);
-            // add component interface to zip
-            if (hasToWriteComponentSubstitutionType(innerComponent)) {
-                writeComponentInterface(innerComponent, zip, icFileName);
-            }
-        }
-        return null;
-    }
-
-    private boolean hasToWriteComponentSubstitutionType(final Component component) {
-        final Map<String, CategoryBaseTypeConfig> serviceNodeTypesConfig =
-                ConfigurationManager.getConfigurationManager().getConfiguration().getServiceBaseNodeTypes();
-        List<CategoryDefinition> categories = component.getCategories();
-        if (CollectionUtils.isNotEmpty(categories) && MapUtils.isNotEmpty(serviceNodeTypesConfig) && serviceNodeTypesConfig.get(categories.get(0).getName()) != null) {
-            boolean doNotExtendBaseType = serviceNodeTypesConfig.get(categories.get(0).getName()).isDoNotExtendBaseType();
-            if (doNotExtendBaseType) {
-                return false;
-            }
-        }
-        if (component instanceof Service) {
-            return !ModelConverter.isAtomicComponent(component) && ((Service) component).isSubstituteCandidate();
-        }
-        return !ModelConverter.isAtomicComponent(component);
-    }
-
-    private Either<Tuple2<byte[], ZipEntry>, ResponseFormat> toZipEntry(ImmutableTriple<String, String, Component> cachedEntry) {
-        String cassandraId = cachedEntry.getLeft();
-        String fileName = cachedEntry.getMiddle();
-        Component innerComponent = cachedEntry.getRight();
-        return getEntryData(cassandraId, innerComponent).right().map(status -> {
-            log.debug("Failed adding to zip component {}, error {}", cassandraId, status);
-            return componentsUtils.getResponseFormat(status);
-        }).left().map(content -> new Tuple2<>(content, new ZipEntry(DEFINITIONS_PATH + fileName)));
-    }
-
-    /**
-     * Writes to a CSAR zip from casandra schema data
-     *
-     * @param zipOutputStream  stores the input stream content
-     * @param schemaFileZip    zip data from Cassandra
-     * @param nodesFromPackage list of all nodes found on the onboarded package
-     */
-    private void addSchemaFilesFromCassandra(final ZipOutputStream zipOutputStream, final byte[] schemaFileZip, final List<String> nodesFromPackage) {
-        final int initSize = 2048;
-        log.debug("Starting copy from Schema file zip to CSAR zip");
-        try (final ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(
-            schemaFileZip)); final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
-            byteArrayOutputStream, initSize)) {
-            ZipEntry entry;
-            while ((entry = zipInputStream.getNextEntry()) != null) {
-                ZipUtils.checkForZipSlipInRead(entry);
-                final String entryName = entry.getName();
-                int readSize = initSize;
-                final byte[] entryData = new byte[initSize];
-                if (shouldZipEntryBeHandled(entryName)) {
-                    if (NODES_YML.equalsIgnoreCase(entryName)) {
-                        handleNode(zipInputStream, byteArrayOutputStream, nodesFromPackage);
-                    } else {
-                        while ((readSize = zipInputStream.read(entryData, 0, readSize)) != -1) {
-                            bufferedOutputStream.write(entryData, 0, readSize);
-                        }
-                        bufferedOutputStream.flush();
-                    }
-                    byteArrayOutputStream.flush();
-                    zipOutputStream.putNextEntry(new ZipEntry(DEFINITIONS_PATH + entryName));
-                    zipOutputStream.write(byteArrayOutputStream.toByteArray());
-                    zipOutputStream.flush();
-                    byteArrayOutputStream.reset();
-                }
-            }
-        } catch (final Exception e) {
-            log.error("Error while writing the SDC schema file to the CSAR", e);
-            throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
-        }
-        log.debug("Finished copy from Schema file zip to CSAR zip");
-    }
-
-    /**
-     * Checks if the zip entry should or should not be added to the CSAR based on the given global type list
-     *
-     * @param entryName the zip entry name
-     * @return true if the zip entry should be handled
-     */
-    private boolean shouldZipEntryBeHandled(final String entryName) {
-        return ConfigurationManager.getConfigurationManager().getConfiguration().getGlobalCsarImports().stream()
-            .anyMatch(entry -> entry.contains(entryName));
-    }
-
-    /**
-     * Handles the nodes.yml zip entry, updating the nodes.yml to avoid duplicated nodes on it.
-     *
-     * @param zipInputStream        the zip entry to be read
-     * @param byteArrayOutputStream an output stream in which the data is written into a byte array.
-     * @param nodesFromPackage      list of all nodes found on the onboarded package
-     */
-    private void handleNode(final ZipInputStream zipInputStream, final ByteArrayOutputStream byteArrayOutputStream,
-                            final List<String> nodesFromPackage) throws IOException {
-        final Map<String, Object> nodesFromArtifactFile = readYamlZipEntry(zipInputStream);
-        final Map<String, Object> nodesYaml = updateNodeYml(nodesFromPackage, nodesFromArtifactFile);
-        updateZipEntry(byteArrayOutputStream, nodesYaml);
-    }
-
-    private void addInnerComponentsToCache(ComponentCache componentCache, Component childComponent) {
-        javaListToVavrList(childComponent.getComponentInstances()).filter(ci -> componentCache.notCached(ci.getComponentUid())).forEach(ci -> {
-            // all resource must be only once!
-            Either<Resource, StorageOperationStatus> resource = toscaOperationFacade.getToscaElement(ci.getComponentUid());
-            Component componentRI = checkAndAddComponent(componentCache, ci, resource);
-            //if not atomic - insert inner components as well
-
-            // TODO: This could potentially create a StackOverflowException if the call stack
-
-            // happens to be too large. Tail-recursive optimization should be used here.
-            if (!ModelConverter.isAtomicComponent(componentRI)) {
-                addInnerComponentsToCache(componentCache, componentRI);
-            }
-        });
-    }
-
-    // TODO: Move this function in FJToVavrHelper.java once Change 108540 is merged
-    private io.vavr.collection.List<ComponentInstance> javaListToVavrList(List<ComponentInstance> componentInstances) {
-        return Option.of(componentInstances).map(io.vavr.collection.List::ofAll).getOrElse(io.vavr.collection.List::empty);
-    }
-
-    private Component checkAndAddComponent(ComponentCache componentCache, ComponentInstance ci, Either<Resource, StorageOperationStatus> resource) {
-        if (resource.isRight()) {
-            log.debug("Failed to fetch resource with id {} for instance {}", ci.getComponentUid(), ci.getName());
-        }
-        Component componentRI = resource.left().value();
-        Map<String, ArtifactDefinition> childToscaArtifacts = componentRI.getToscaArtifacts();
-        ArtifactDefinition childArtifactDefinition = childToscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
-        if (childArtifactDefinition != null) {
-            //add to cache
-            componentCache.put(childArtifactDefinition.getEsId(), childArtifactDefinition.getArtifactName(), componentRI);
-        }
-        return componentRI;
-    }
-
-    private List<Triple<String, String, Component>> writeComponentInterface(final Component component, final ZipOutputStream zip,
-                                                                            final String fileName) {
-        final Either<ToscaRepresentation, ToscaError> interfaceRepresentation = toscaExportUtils.exportComponentInterface(component, false);
-        writeComponentInterface(interfaceRepresentation, zip, fileName);
-        return interfaceRepresentation.left().value().getDependencies().getOrElse(new ArrayList<>());
-    }
-
-
-    private Either<ZipOutputStream, ResponseFormat> writeComponentInterface(Either<ToscaRepresentation, ToscaError> interfaceRepresentation,
-                                                                            ZipOutputStream zip, String fileName) {
-        // TODO: This should not be done but we need this to keep the refactoring small enough to be easily reviewable
-        return writeComponentInterface(interfaceRepresentation, fileName, ZipWriter.live(zip))
-            .map(void0 -> Either.<ZipOutputStream, ResponseFormat>left(zip)).recover(th -> {
-                log.error("#writeComponentInterface - zip writing failed with error: ", th);
-                return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
-            }).get();
-    }
-
-    private Try<Void> writeComponentInterface(
-        Either<ToscaRepresentation, ToscaError> interfaceRepresentation, String fileName, ZipWriter zw) {
-        Either<byte[], ToscaError> yml = interfaceRepresentation.left()
-            .map(ToscaRepresentation::getMainYaml);
-        return fromEither(yml, ToscaErrorException::new).flatMap(zw.write(DEFINITIONS_PATH + ToscaExportHandler.getInterfaceFilename(fileName)));
-    }
-
-    private Either<byte[], ActionStatus> getEntryData(String cassandraId, Component childComponent) {
-        if (cassandraId == null || cassandraId.isEmpty()) {
-            return toscaExportUtils.exportComponent(childComponent).right().map(toscaErrorToActionStatus(childComponent)).left()
-                .map(ToscaRepresentation::getMainYaml);
-        } else {
-            return getFromCassandra(cassandraId);
-        }
-    }
-
-    private F<ToscaError, ActionStatus> toscaErrorToActionStatus(Component childComponent) {
-        return toscaError -> {
-            log.debug("Failed to export tosca template for child component {} error {}", childComponent.getUniqueId(), toscaError);
-            return componentsUtils.convertFromToscaError(toscaError);
-        };
-    }
-
-    private Either<byte[], ResponseFormat> getLatestSchemaFilesFromCassandra() {
-        String fto = versionFirstThreeOctets;
-        return sdcSchemaFilesCassandraDao.getSpecificSchemaFiles(fto, CONFORMANCE_LEVEL).right().map(schemaFilesFetchDBError(fto)).left()
-            .bind(iff(List::isEmpty, () -> schemaFileFetchError(fto), s -> Either.left(s.iterator().next().getPayloadAsArray())));
-    }
-
-    private void addSchemaFilesByModel(final ZipOutputStream zipOutputStream, final String modelName) {
-        try {
-            final List<ToscaImportByModel> modelDefaultImportList = modelOperation.findAllModelImports(modelName, true);
-            final Set<Path> writtenEntryPathList = new HashSet<>();
-            final var definitionsPath = Path.of(DEFINITIONS_PATH);
-            for (final ToscaImportByModel toscaImportByModel : modelDefaultImportList) {
-                var importPath = Path.of(toscaImportByModel.getFullPath());
-                if (writtenEntryPathList.contains(definitionsPath.resolve(importPath))) {
-                    importPath =
-                        ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
-                }
-                final Path entryPath = definitionsPath.resolve(importPath);
-                final var zipEntry = new ZipEntry(entryPath.toString());
-                zipOutputStream.putNextEntry(zipEntry);
-                writtenEntryPathList.add(entryPath);
-                final byte[] content = toscaImportByModel.getContent().getBytes(StandardCharsets.UTF_8);
-                zipOutputStream.write(content, 0, content.length);
-                zipOutputStream.closeEntry();
-            }
-        } catch (final IOException e) {
-            log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, CsarUtils.class.getName(),
-                "Error while writing the schema files by model to the CSAR", e);
-            throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.CSAR_TOSCA_IMPORTS_ERROR));
-        }
-    }
-
-    private F<CassandraOperationStatus, ResponseFormat> schemaFilesFetchDBError(String firstThreeOctets) {
-        return cos -> {
-            log.debug("Failed to get the schema files SDC-Version: {} Conformance-Level {}. Please fix DB table accordingly.", firstThreeOctets,
-                CONFORMANCE_LEVEL);
-            StorageOperationStatus sos = DaoStatusConverter.convertCassandraStatusToStorageStatus(cos);
-            return componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(sos));
-        };
-    }
-
-    private Either<byte[], ResponseFormat> schemaFileFetchError(String firstThreeOctets) {
-        log.debug("Failed to get the schema files SDC-Version: {} Conformance-Level {}", firstThreeOctets, CONFORMANCE_LEVEL);
-        return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_SCHEMA_FILES_NOT_FOUND, firstThreeOctets, CONFORMANCE_LEVEL));
-    }
-
-    private Either<byte[], ActionStatus> getFromCassandra(String cassandraId) {
-        return artifactCassandraDao.getArtifact(cassandraId).right().map(operationstatus -> {
-            log.info("Failed to fetch artifact from Cassandra by id {} error {}.", cassandraId, operationstatus);
-            StorageOperationStatus storageStatus = DaoStatusConverter.convertCassandraStatusToStorageStatus(operationstatus);
-            return componentsUtils.convertFromStorageResponse(storageStatus);
-        }).left().map(DAOArtifactData::getDataAsArray);
-    }
-
     private String createCsarBlock0(String metaFileVersion, String toscaConformanceLevel) {
         return String.format(BLOCK_0_TEMPLATE, metaFileVersion, toscaConformanceLevel);
     }
 
-    private String createToscaBlock0(String metaFileVersion, String csarVersion, String createdBy, String entryDef, boolean isAsdPackage) {
-        final String block0template = "TOSCA-Meta-File-Version: %s\nCSAR-Version: %s\nCreated-By: %s\nEntry-Definitions: Definitions/%s\n%s\nName: csar.meta\nContent-Type: text/plain\n";
-        return String.format(block0template, metaFileVersion, csarVersion, createdBy, entryDef, isAsdPackage ? "entry_definition_type: asd" : "");
-    }
-
-    private String createNsMfBlock0(String serviceName, String createdBy, String serviceVersion, String releaseTime, String serviceType,
-                                    String description, String serviceTemplate, String hash) {
-        final String block0template = "metadata??\n" + "ns_product_name: %s\n" + "ns_provider_id: %s\n" + "ns_package_version: %s\n" +
-            "ns_release_data_time: %s\n" + "ns_type: %s\n" + "ns_package_description: %s\n\n" + "Source: %s\n" + "Algorithm: MD5\n" + "Hash: %s\n\n";
-        return String.format(block0template, serviceName, createdBy, serviceVersion, releaseTime, serviceType, description, serviceTemplate, hash);
-    }
-
-    private Either<ZipOutputStream, ResponseFormat> writeAllFilesToCsar(Component mainComponent, CsarDefinition csarDefinition,
-                                                                        ZipOutputStream zipstream, boolean isInCertificationRequest)
-        throws IOException {
-        ComponentArtifacts componentArtifacts = csarDefinition.getComponentArtifacts();
-        Either<ZipOutputStream, ResponseFormat> writeComponentArtifactsToSpecifiedPath = writeComponentArtifactsToSpecifiedPath(mainComponent,
-            componentArtifacts, zipstream, ARTIFACTS_PATH, isInCertificationRequest);
-        if (writeComponentArtifactsToSpecifiedPath.isRight()) {
-            return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
-        }
-        ComponentTypeArtifacts mainTypeAndCIArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
-        writeComponentArtifactsToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent, mainTypeAndCIArtifacts.getComponentArtifacts(),
-            zipstream, ARTIFACTS_PATH, isInCertificationRequest);
-        if (writeComponentArtifactsToSpecifiedPath.isRight()) {
-            return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
-        }
-        Map<String, ArtifactsInfo> componentInstancesArtifacts = mainTypeAndCIArtifacts.getComponentInstancesArtifacts();
-        String currentPath = ARTIFACTS_PATH + RESOURCES_PATH;
-        for (String keyAssetName : componentInstancesArtifacts.keySet()) {
-            ArtifactsInfo artifactsInfo = componentInstancesArtifacts.get(keyAssetName);
-            String pathWithAssetName = currentPath + keyAssetName + PATH_DELIMITER;
-            writeComponentArtifactsToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent, artifactsInfo, zipstream, pathWithAssetName,
-                isInCertificationRequest);
-            if (writeComponentArtifactsToSpecifiedPath.isRight()) {
-                return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
-            }
-        }
-        writeComponentArtifactsToSpecifiedPath = writeOperationsArtifactsToCsar(mainComponent, zipstream);
-        if (writeComponentArtifactsToSpecifiedPath.isRight()) {
-            return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
-        }
-        return Either.left(zipstream);
-    }
-
-    private Either<ZipOutputStream, ResponseFormat> writeOperationsArtifactsToCsar(Component component, ZipOutputStream zipstream) {
-        if (checkComponentBeforeOperation(component)) {
-            return Either.left(zipstream);
-        }
-        for (Map.Entry<String, InterfaceDefinition> interfaceEntry : ((Resource) component).getInterfaces().entrySet()) {
-            for (OperationDataDefinition operation : interfaceEntry.getValue().getOperations().values()) {
-                try {
-                    if (checkComponentBeforeWrite(component, interfaceEntry, operation)) {
-                        continue;
-                    }
-                    final String artifactUUID = operation.getImplementation().getArtifactUUID();
-                    if (artifactUUID == null) {
-                        continue;
-                    }
-                    final Either<byte[], ActionStatus> artifactFromCassandra = getFromCassandra(artifactUUID);
-                    final String artifactName = operation.getImplementation().getArtifactName();
-                    if (artifactFromCassandra.isRight()) {
-                        log.error(ARTIFACT_NAME_UNIQUE_ID, artifactName, artifactUUID);
-                        log.error("Failed to get {} payload from DB reason: {}", artifactName, artifactFromCassandra.right().value());
-                        return Either.right(componentsUtils.getResponseFormat(
-                            ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION, "Resource", component.getUniqueId(), artifactName, artifactUUID));
-                    }
-                    zipstream.putNextEntry(new ZipEntry(OperationArtifactUtil.createOperationArtifactPath(component, null, operation, true)));
-                    zipstream.write(artifactFromCassandra.left().value());
-                } catch (IOException e) {
-                    log.error("Component Name {},  Interface Name {}, Operation Name {}", component.getNormalizedName(), interfaceEntry.getKey(),
-                        operation.getName());
-                    log.error("Error while writing the operation's artifacts to the CSAR", e);
-                    return Either.right(componentsUtils.getResponseFormat(ERROR_DURING_CSAR_CREATION, "Resource", component.getUniqueId()));
-                }
-            }
-        }
-        return Either.left(zipstream);
-    }
-
-    private boolean checkComponentBeforeWrite(Component component, Entry<String, InterfaceDefinition> interfaceEntry,
-                                              OperationDataDefinition operation) {
-        final ArtifactDataDefinition implementation = operation.getImplementation();
-        if (Objects.isNull(implementation)) {
-            log.debug("Component Name {}, Interface Id {}, Operation Name {} - no Operation Implementation found", component.getNormalizedName(),
-                interfaceEntry.getValue().getUniqueId(), operation.getName());
-            return true;
-        }
-        final String artifactName = implementation.getArtifactName();
-        if (Objects.isNull(artifactName)) {
-            log.debug("Component Name {}, Interface Id {}, Operation Name {} - no artifact found", component.getNormalizedName(),
-                interfaceEntry.getValue().getUniqueId(), operation.getName());
-            return true;
-        }
-        if (OperationArtifactUtil.artifactNameIsALiteralValue(artifactName)) {
-            log.debug("Component Name {}, Interface Id {}, Operation Name {} - artifact name is a literal value rather than an SDC artifact",
-                component.getNormalizedName(), interfaceEntry.getValue().getUniqueId(), operation.getName());
-            return true;
-        }
-        return false;
-    }
-
-    private boolean checkComponentBeforeOperation(Component component) {
-        if (component instanceof Service) {
-            return true;
-        }
-        if (Objects.isNull(((Resource) component).getInterfaces())) {
-            log.debug("Component Name {}- no interfaces found", component.getNormalizedName());
-            return true;
-        }
-        return false;
-    }
-
-    private Either<ZipOutputStream, ResponseFormat> writeComponentArtifactsToSpecifiedPath(Component mainComponent,
-                                                                                           ComponentArtifacts componentArtifacts,
-                                                                                           ZipOutputStream zipstream, String currentPath,
-                                                                                           boolean isInCertificationRequest) throws IOException {
-        Map<String, ComponentTypeArtifacts> componentTypeArtifacts = componentArtifacts.getComponentTypeArtifacts();
-        //Keys are defined:
-
-        //<Inner Asset TOSCA name (e.g. VFC name)> folder name: <Inner Asset TOSCA name (e.g. VFC name)>_v<version>.
-
-        //E.g. "org.openecomp.resource.vf.vipr_atm_v1.0"
-        Set<String> componentTypeArtifactsKeys = componentTypeArtifacts.keySet();
-        for (String keyAssetName : componentTypeArtifactsKeys) {
-            ComponentTypeArtifacts componentInstanceArtifacts = componentTypeArtifacts.get(keyAssetName);
-            ArtifactsInfo componentArtifacts2 = componentInstanceArtifacts.getComponentArtifacts();
-            String pathWithAssetName = currentPath + keyAssetName + PATH_DELIMITER;
-            Either<ZipOutputStream, ResponseFormat> writeArtifactsInfoToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent,
-                componentArtifacts2, zipstream, pathWithAssetName, isInCertificationRequest);
-            if (writeArtifactsInfoToSpecifiedPath.isRight()) {
-                return writeArtifactsInfoToSpecifiedPath;
-            }
-        }
-        return Either.left(zipstream);
-    }
-
-    private Either<ZipOutputStream, ResponseFormat> writeArtifactsInfoToSpecifiedPath(final Component mainComponent,
-                                                                                      final ArtifactsInfo currArtifactsInfo,
-                                                                                      final ZipOutputStream zip, final String path,
-                                                                                      final boolean isInCertificationRequest) throws IOException {
-        final Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactsInfo = currArtifactsInfo.getArtifactsInfo();
-        for (final ArtifactGroupTypeEnum artifactGroupTypeEnum : artifactsInfo.keySet()) {
-            final String groupTypeFolder = path + WordUtils.capitalizeFully(artifactGroupTypeEnum.getType()) + PATH_DELIMITER;
-            final Map<String, List<ArtifactDefinition>> artifactTypesMap = artifactsInfo.get(artifactGroupTypeEnum);
-            for (final String artifactType : artifactTypesMap.keySet()) {
-                final List<ArtifactDefinition> artifactDefinitionList = artifactTypesMap.get(artifactType);
-                String artifactTypeFolder = groupTypeFolder + artifactType + PATH_DELIMITER;
-                if (ArtifactTypeEnum.WORKFLOW.getType().equals(artifactType) && path.contains(ARTIFACTS_PATH + RESOURCES_PATH)) {
-                    // Ignore this packaging as BPMN artifacts needs to be packaged in different manner
-                    continue;
-                }
-                if (ArtifactTypeEnum.WORKFLOW.getType().equals(artifactType)) {
-                    artifactTypeFolder += OperationArtifactUtil.BPMN_ARTIFACT_PATH + File.separator;
-                } else if (ArtifactTypeEnum.ONBOARDED_PACKAGE.getType().equals(artifactType)) {
-                    // renaming legacy folder ONBOARDED_PACKAGE to the new folder ETSI_PACKAGE
-                    artifactTypeFolder = artifactTypeFolder
-                        .replace(ArtifactTypeEnum.ONBOARDED_PACKAGE.getType(), ArtifactTypeEnum.ETSI_PACKAGE.getType());
-                }
-                // TODO: We should not do this but in order to keep this refactoring small enough,
-
-                // we'll leave this as is for now
-                List<ArtifactDefinition> collect = filterArtifactDefinitionToZip(mainComponent, artifactDefinitionList, isInCertificationRequest)
-                    .collect(Collectors.toList());
-                for (ArtifactDefinition ad : collect) {
-                    zip.putNextEntry(new ZipEntry(artifactTypeFolder + ad.getArtifactName()));
-                    zip.write(ad.getPayloadData());
-                }
-            }
-        }
-        return Either.left(zip);
-    }
-
-    private Stream<ArtifactDefinition> filterArtifactDefinitionToZip(Component mainComponent, List<ArtifactDefinition> artifactDefinitionList,
-                                                                     boolean isInCertificationRequest) {
-        return artifactDefinitionList.stream().filter(shouldBeInZip(isInCertificationRequest, mainComponent)).map(this::fetchPayLoadData)
-            .filter(Either::isLeft).map(e -> e.left().value());
-    }
-
-    private Predicate<ArtifactDefinition> shouldBeInZip(boolean isInCertificationRequest, Component component) {
-        return artifactDefinition -> !(!isInCertificationRequest && component.isService() && artifactDefinition.isHeatEnvType() || artifactDefinition
-            .hasNoMandatoryEsId());
-    }
-
-    private Either<ArtifactDefinition, ActionStatus> fetchPayLoadData(ArtifactDefinition ad) {
-        byte[] payloadData = ad.getPayloadData();
-        if (payloadData == null) {
-            return getFromCassandra(ad.getEsId()).left().map(pd -> {
-                ad.setPayload(pd);
-                return ad;
-            }).right().map(as -> {
-                log.debug(ARTIFACT_NAME_UNIQUE_ID, ad.getArtifactName(), ad.getUniqueId());
-                log.debug("Failed to get {} payload from DB reason: {}", ad.getArtifactName(), as);
-                return as;
-            });
-        } else {
-            return Either.left(ad);
-        }
-    }
-
     /************************************ Artifacts Structure END******************************************************************/
 
     private Either<CsarDefinition, ResponseFormat> collectComponentCsarDefinition(Component component) {
@@ -1149,7 +389,7 @@
         ComponentTypeArtifacts componentInstanceArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
         printArtifacts(componentInstanceArtifacts);
         result.append("Type Artifacts\n");
-        for (Map.Entry<String, ComponentTypeArtifacts> typeArtifacts : componentArtifacts.getComponentTypeArtifacts().entrySet()) {
+        for (Entry<String, ComponentTypeArtifacts> typeArtifacts : componentArtifacts.getComponentTypeArtifacts().entrySet()) {
             result.append("Folder " + typeArtifacts.getKey() + "\n");
             result.append(printArtifacts(typeArtifacts.getValue()));
         }
@@ -1167,7 +407,7 @@
         Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componentArtifacts = artifactsInfo.getArtifactsInfo();
         printArtifacts(componentArtifacts);
         result = result.append("Resources\n");
-        for (Map.Entry<String, ArtifactsInfo> resourceInstance : componentInstanceArtifacts.getComponentInstancesArtifacts().entrySet()) {
+        for (Entry<String, ArtifactsInfo> resourceInstance : componentInstanceArtifacts.getComponentInstancesArtifacts().entrySet()) {
             result.append("Folder" + resourceInstance.getKey() + "\n");
             result.append(printArtifacts(resourceInstance.getValue().getArtifactsInfo()));
         }
@@ -1177,9 +417,9 @@
 
     private String printArtifacts(Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componetArtifacts) {
         StringBuilder result = new StringBuilder();
-        for (Map.Entry<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactGroup : componetArtifacts.entrySet()) {
+        for (Entry<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactGroup : componetArtifacts.entrySet()) {
             result.append("    " + artifactGroup.getKey().getType());
-            for (Map.Entry<String, List<ArtifactDefinition>> groupArtifacts : artifactGroup.getValue().entrySet()) {
+            for (Entry<String, List<ArtifactDefinition>> groupArtifacts : artifactGroup.getValue().entrySet()) {
                 result.append("        " + groupArtifacts.getKey());
                 for (ArtifactDefinition artifact : groupArtifacts.getValue()) {
                     result.append("            " + artifact.getArtifactDisplayName());
@@ -1323,12 +563,6 @@
         return artifactsByType;
     }
 
-    public static class ToscaErrorException extends Exception {
-
-        ToscaErrorException(ToscaError error) {
-            super("Error while exporting component's interface (toscaError:" + error + ")");
-        }
-    }
 
     @Getter
     public static final class NonMetaArtifactInfo {
@@ -1348,7 +582,6 @@
         public NonMetaArtifactInfo(final String artifactName, final String path, final String artifactType,
                                    final ArtifactGroupTypeEnum artifactGroupType, final byte[] payloadData, final String artifactUniqueId,
                                    final boolean isFromCsar) {
-            super();
             this.path = path;
             this.isFromCsar = isFromCsar;
             this.artifactName = ValidationUtils.normalizeFileName(artifactName);
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/DefaultCsarGenerator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/DefaultCsarGenerator.java
new file mode 100644
index 0000000..cad5ace
--- /dev/null
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/DefaultCsarGenerator.java
@@ -0,0 +1,56 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2023 Nordix Foundation. 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.tosca;
+
+import fj.data.Either;
+import java.io.IOException;
+import java.util.zip.ZipOutputStream;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.plugins.CsarZipGenerator;
+import org.openecomp.sdc.exception.ResponseFormat;
+
+/**
+ * Generates a Network Service CSAR based on a SERVICE component and wraps it in a SDC CSAR entry.
+ */
+@org.springframework.stereotype.Component("defaultCsarGenerator")
+public class DefaultCsarGenerator implements CsarZipGenerator {
+
+    private static final String DEFINITIONS_PATH = "Definitions/";
+    private final CommonCsarGenerator commonCsarGenerator;
+
+    public DefaultCsarGenerator(final CommonCsarGenerator commonCsarGenerator) {
+        this.commonCsarGenerator = commonCsarGenerator;
+    }
+
+    @Override
+    public Either<ZipOutputStream, ResponseFormat> generateCsarZip(Component component,
+                                                                   boolean getFromCS,
+                                                                   ZipOutputStream zip,
+                                                                   boolean isInCertificationRequest,
+                                                                   boolean isAsdPackage) throws IOException {
+        return commonCsarGenerator.generateCsarZip(component, getFromCS, zip, isInCertificationRequest, isAsdPackage, DEFINITIONS_PATH, true, false);
+    }
+
+    @Override
+    public String getModel() {
+        return null;
+    }
+
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java
index 94bc279..0b07506 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java
@@ -19,8 +19,11 @@
  */
 package org.openecomp.sdc.be.tosca;
 
+import io.vavr.control.Option;
 import io.vavr.control.Try;
+import java.util.List;
 import java.util.function.Function;
+import org.openecomp.sdc.be.model.ComponentInstance;
 
 /**
  * Helper class providing facilities for migrating from FJ to VAVR
@@ -42,5 +45,9 @@
         static <L, R> Try<L> fromEither(fj.data.Either<L, R> e, Function<R, Throwable> onError) {
             return e.either(Try::success, r -> Try.failure(onError.apply(r)));
         }
+
+        static io.vavr.collection.List<ComponentInstance> javaListToVavrList(List<ComponentInstance> componentInstances) {
+            return Option.of(componentInstances).map(io.vavr.collection.List::ofAll).getOrElse(io.vavr.collection.List::empty);
+        }
     }
 }
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/MapFromModelCsarGeneratorService.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/MapFromModelCsarGeneratorService.java
new file mode 100644
index 0000000..8e255c7
--- /dev/null
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/MapFromModelCsarGeneratorService.java
@@ -0,0 +1,59 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2023 Nordix Foundation. 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.tosca;
+
+import fj.data.Either;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.zip.ZipOutputStream;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.plugins.CsarZipGenerator;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class MapFromModelCsarGeneratorService {
+
+    private final Map<String, CsarZipGenerator> servicesByModel;
+
+    @Autowired
+    public MapFromModelCsarGeneratorService(List<CsarZipGenerator> modelServices) {
+        servicesByModel = modelServices.stream()
+            .collect(Collectors.toMap(CsarZipGenerator::getModel, Function.identity()));
+    }
+
+    public Either<ZipOutputStream, ResponseFormat> generateCsarZip(final Component component,
+                                                                   boolean getFromCS,
+                                                                   ZipOutputStream zip,
+                                                                   boolean isInCertificationRequest,
+                                                                   boolean isAsdPackage) throws IOException {
+        CsarZipGenerator generatorImpl = servicesByModel.get(component.getModel());
+
+        if (null == generatorImpl) {
+            generatorImpl = servicesByModel.get(null);
+        }
+
+        return generatorImpl.generateCsarZip(component, getFromCS, zip, isInCertificationRequest, isAsdPackage);
+    }
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
index 4d99b4d..0b57cfe 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
@@ -22,6 +22,7 @@
 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.common.api.Constants.ADDITIONAL_TYPE_DEFINITIONS;
 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;
@@ -228,7 +229,11 @@
     }
 
     public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
-        return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
+        return convertToToscaTemplate(component, false).left().map(this::createToscaRepresentation);
+    }
+
+    public Either<ToscaRepresentation, ToscaError> exportComponent(Component component, Boolean isSkipImports) {
+        return convertToToscaTemplate(component, isSkipImports).left().map(this::createToscaRepresentation);
     }
 
     public Either<ToscaRepresentation, ToscaError> exportDataType(DataTypeDefinition dataTypeDefinition) {
@@ -236,7 +241,7 @@
     }
 
     public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
-        final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel()));
+        final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel(), false));
         if (CollectionUtils.isEmpty(imports)) {
             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
             return Either.right(ToscaError.GENERAL_ERROR);
@@ -248,7 +253,7 @@
                     .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
                             component.getModel());
             if (baseType.isLeft() && baseType.left().value() != null) {
-                addDependencies(imports, dependencies, baseType.left().value());
+                addDependencies(imports, dependencies, baseType.left().value(), false);
             } else {
                 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
             }
@@ -272,6 +277,44 @@
         return Either.left(toscaRepresentation);
     }
 
+    public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent,
+                                                                            final boolean isSkipImports) {
+        final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel(), isSkipImports));
+        if (CollectionUtils.isEmpty(imports)) {
+            log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
+            return Either.right(ToscaError.GENERAL_ERROR);
+        }
+        List<Triple<String, String, Component>> dependencies = new ArrayList<>();
+        if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
+            .startsWith("org.openecomp.resource.abstract.nodes.")) {
+            final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
+                .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
+                    component.getModel());
+            if (baseType.isLeft() && baseType.left().value() != null) {
+                addDependencies(imports, dependencies, baseType.left().value(), isSkipImports);
+            } else {
+                log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
+            }
+        }
+
+        String toscaVersion = null;
+        if (component instanceof Resource) {
+            toscaVersion = ((Resource) component).getToscaVersion();
+        }
+        ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
+        toscaTemplate.setImports(imports);
+        final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
+        final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
+            isAssociatedComponent);
+        if (toscaTemplateRes.isRight()) {
+            return Either.right(toscaTemplateRes.right().value());
+        }
+        toscaTemplate = toscaTemplateRes.left().value();
+        toscaTemplate.setDependencies(dependencies);
+        ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
+        return Either.left(toscaRepresentation);
+    }
+
     private ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
         CustomRepresenter representer = new CustomRepresenter();
         DumperOptions options = new DumperOptions();
@@ -292,15 +335,24 @@
 
     public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
         ToscaTemplate toscaTemplate = new ToscaTemplate(null);
-        Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
+        Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate, false);
         if (fillImports.isRight()) {
             return Either.right(fillImports.right().value());
         }
         return Either.left(fillImports.left().value().left);
     }
 
-    public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
-        final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
+    public Either<ToscaTemplate, ToscaError> getDependencies(Component component, boolean isSkipImports) {
+        ToscaTemplate toscaTemplate = new ToscaTemplate(null);
+        Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate, isSkipImports);
+        if (fillImports.isRight()) {
+            return Either.right(fillImports.right().value());
+        }
+        return Either.left(fillImports.left().value().left);
+    }
+
+    public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component, final boolean isSkipImports) {
+        final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel(), isSkipImports);
         if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
             return Either.right(ToscaError.GENERAL_ERROR);
@@ -319,7 +371,7 @@
             return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
         } else {
             log.trace("convert component as topology template");
-            return convertToscaTemplate(component, toscaTemplate);
+            return convertToscaTemplate(component, toscaTemplate, isSkipImports);
         }
     }
 
@@ -357,7 +409,7 @@
         return Either.left(toscaTemplate);
     }
 
-    private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId) {
+    private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId, final boolean isSkipImports) {
         if (StringUtils.isEmpty(modelId)) {
             return getDefaultToscaImportConfig();
         }
@@ -367,18 +419,21 @@
         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());
+            if (!(isSkipImports && importPath.toString().equals(ADDITIONAL_TYPE_DEFINITIONS))) {
+                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);
             }
-            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);
+    private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode, boolean isSkipImports) {
+        Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode, isSkipImports);
         if (importsRes.isRight()) {
             return Either.right(importsRes.right().value());
         }
@@ -641,8 +696,8 @@
         return jsonPresentationField.getPresentation();
     }
 
-    private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
-        final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
+    private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate, boolean isSkipImports) {
+        final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel(), isSkipImports);
         if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
             return Either.right(ToscaError.GENERAL_ERROR);
@@ -659,7 +714,7 @@
             }
             List<ComponentInstance> componentInstances = component.getComponentInstances();
             if (componentInstances != null && !componentInstances.isEmpty()) {
-                componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
+                componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci, isSkipImports));
             }
             toscaTemplate.setDependencies(dependencies);
             toscaTemplate.setImports(additionalImports);
@@ -695,7 +750,8 @@
     }
 
     private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
-                                  final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
+                                  final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance,
+                                  final boolean isSkipImports) {
         log.debug("createDependency componentCache {}", componentCache);
         Component componentRI = componentCache.get(componentInstance.getComponentUid());
         if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
@@ -708,7 +764,7 @@
             }
             final Component fetchedComponent = resource.left().value();
             componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
-            addDependencies(imports, dependencies, componentRI);
+            addDependencies(imports, dependencies, componentRI, isSkipImports);
         }
     }
 
@@ -737,9 +793,9 @@
      * Retrieves all derived_from nodes and stores it in a predictable order.
      */
     private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
-                                 final Component fetchedComponent) {
+                                 final Component fetchedComponent, final boolean isSkipImports) {
         final Set<Component> componentsList = new LinkedHashSet<>();
-        if (fetchedComponent instanceof Resource) {
+        if (fetchedComponent instanceof Resource && !isSkipImports) {
             log.debug("fetchedComponent is a resource {}", fetchedComponent);
             final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
             if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
@@ -789,7 +845,7 @@
      */
     private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
                             final Set<Component> componentsList) {
-        componentsList.forEach(component -> setImports(imports, dependencies, component));
+        componentsList.forEach(component ->  setImports(imports, dependencies, component));
     }
 
     private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
@@ -1679,8 +1735,7 @@
             nodeFilter.setProperties(propertiesCopy);
         }
         nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
-        nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
-        return nodeFilter;
+        return cloneObjectFromYml(nodeFilter, NodeFilter.class);
     }
 
     private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
@@ -1693,14 +1748,14 @@
             nodeFilter.setProperties(propertiesCopy);
         }
         nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
-        return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
+        return cloneObjectFromYml(nodeFilter, NodeFilter.class);
     }
 
     private Object cloneToscaId(Object toscaId) {
         return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
     }
 
-    private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
+    private <T> T cloneObjectFromYml(Object objToClone, Class<T> classOfObj) {
         String objectAsYml = yamlUtil.objectToYaml(objToClone);
         return yamlUtil.yamlToObject(objectAsYml, classOfObj);
     }
@@ -1884,7 +1939,6 @@
     private static class CustomRepresenter extends Representer {
 
         CustomRepresenter() {
-            super();
             this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
             this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
             // null representer is exceptional and it is stored as an instance
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java b/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java
index 5c018fc..17f7a04 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java
@@ -34,6 +34,8 @@
 import org.openecomp.sdc.be.filters.FilterConfiguration;
 import org.openecomp.sdc.be.filters.PortalConfiguration;
 import org.openecomp.sdc.be.filters.ThreadLocalUtils;
+import org.openecomp.sdc.be.tosca.CommonCsarGenerator;
+import org.openecomp.sdc.be.tosca.DefaultCsarGenerator;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
@@ -132,6 +134,11 @@
         return new PortalClient(httpClientConnectionManager(), portalConfiguration());
     }
 
+    @Bean(name = "defaultCsarGenerator")
+    public DefaultCsarGenerator defaultCsarGenerator(CommonCsarGenerator commonCsarGenerator) {
+        return new DefaultCsarGenerator(commonCsarGenerator);
+    }
+
     @Bean
     public org.openecomp.sdc.be.config.Configuration configuration() {
         return ConfigurationManager.getConfigurationManager().getConfiguration();
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java
index 373e9b1..b749ef6 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java
@@ -100,7 +100,10 @@
 class CsarUtilsTest extends BaseConfDependent {
 
 	@InjectMocks
-	CsarUtils testSubject;
+	private CsarUtils testSubject;
+
+    @InjectMocks
+	private CommonCsarGenerator commonCsarGenerator;
 
 	@Mock
 	private ArtifactCassandraDao artifactCassandraDao;
@@ -124,7 +127,7 @@
 
 	private final byte[] contentData;
 
-	public CsarUtilsTest() throws IOException {
+    public CsarUtilsTest() throws IOException {
 		contentData = getFileResource("yamlValidation/resource-serviceTemplate.yml");
 	}
 
@@ -158,7 +161,7 @@
 	}
 
 	@Test
-	void testCreateCsar() {
+	void testCreateCsar() throws IOException {
 		Component component = new Resource();
 		Map<String, ArtifactDefinition> artifactDefinitionHashMap = new HashMap<>();
 		ArtifactDefinition artifact = new ArtifactDefinition();
@@ -170,17 +173,22 @@
 		component.setArtifacts(artifactDefinitionHashMap);
 		component.setDeploymentArtifacts(artifactDefinitionHashMap);
 
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ZipOutputStream zip = new ZipOutputStream(out);
+
 		Mockito.when(artifactCassandraDao.getArtifact(Mockito.any(String.class)))
 				.thenReturn(Either.right(CassandraOperationStatus.GENERAL_ERROR));
 
 		Mockito.when(componentsUtils.convertFromStorageResponse(Mockito.any(StorageOperationStatus.class)))
 				.thenReturn(ActionStatus.GENERAL_ERROR);
 
-		testSubject.createCsar(component, true, true);
+        assertNotNull(commonCsarGenerator.generateCsarZip(component, false, zip,
+            false,  true,
+            "Definitions/", true, false).right());
 	}
 
 	@Test
-	void testCreateCsarWithGenerateCsarZipResponseIsLeft() {
+	void testCreateCsarWithGenerateCsarZipResponseIsLeft() throws IOException {
 		Component component = new Resource();
 		Map<String, ArtifactDefinition> toscaArtifacts = new HashMap<>();
 		ArtifactDefinition artifact = new ArtifactDefinition();
@@ -207,6 +215,9 @@
 		filedata.setPayloadAsArray(data);
 		filesData.add(filedata);
 
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ZipOutputStream zip = new ZipOutputStream(out);
+
 		Mockito.when(artifactCassandraDao.getArtifact(Mockito.any(String.class))).thenReturn(Either.left(artifactData));
 
 		Mockito.when(componentsUtils.convertFromStorageResponse(Mockito.any(StorageOperationStatus.class)))
@@ -219,7 +230,9 @@
 				sdcSchemaFilesCassandraDao.getSpecificSchemaFiles(Mockito.any(String.class), Mockito.any(String.class)))
 				.thenReturn(Either.left(filesData));
 
-		testSubject.createCsar(component, false, true);
+        assertNotNull(commonCsarGenerator.generateCsarZip(component, false, zip,
+            false, true,
+            "Definitions/", true, false).right());
 	}
 
 	@Test
@@ -253,11 +266,11 @@
 		Mockito.when(toscaExportUtils.getDependencies(Mockito.any(Component.class)))
 				.thenReturn(Either.right(ToscaError.GENERAL_ERROR));
 
-		try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
-			Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, false);
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
+        try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
+            Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, true, "Definitions/", true, false);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
 	}
 
 	@Test
@@ -285,11 +298,11 @@
 		Mockito.when(toscaExportUtils.exportComponent(Mockito.any(Component.class)))
 				.thenReturn(Either.right(ToscaError.GENERAL_ERROR));
 
-		try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
-			Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, false);
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
+        try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
+            Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, true, "Definitions/", true, false);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
 	}
 
 	@Test
@@ -357,7 +370,7 @@
 				.thenReturn(Either.left(Mockito.any(ArtifactDefinition.class)));
 
 		try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
-			Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, true);
+			Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, true, "/Definitions", true, false);
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
@@ -405,11 +418,11 @@
 		Mockito.when(toscaExportUtils.getDependencies(Mockito.any(Component.class)))
 				.thenReturn(Either.left(toscaTemplate));
 
-		try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
-			Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, true);
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
+        try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
+            Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, true, "Definitions/", true, false);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
 	}
 
 	@Test
@@ -455,11 +468,11 @@
 		Mockito.when(toscaExportUtils.getDependencies(Mockito.any(Component.class)))
 				.thenReturn(Either.left(toscaTemplate));
 
-		try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
-			Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, true);
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
+        try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
+            Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, true, "Definitions/", true, false);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
 	}
 
 	@Test
@@ -509,7 +522,7 @@
 				.thenReturn(Either.right(CassandraOperationStatus.GENERAL_ERROR));
 
 		try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
-			Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, true);
+			Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, "toscaMetaFileName", true, "Definitions/", true, false);
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
@@ -542,7 +555,7 @@
 		Mockito.when(toscaOperationFacade.getToscaElement(Mockito.any(String.class)))
 				.thenReturn(Either.left(componentRI));
 
-		Deencapsulation.invoke(testSubject, "addInnerComponentsToCache", componentCache, childComponent);
+		Deencapsulation.invoke(commonCsarGenerator, "addInnerComponentsToCache", componentCache, childComponent);
 
 		io.vavr.collection.List<CacheEntry> expected = io.vavr.collection.List.of(entry("esId","artifactName",componentRI));
 		assertEquals(expected, componentCache.all().toList());
@@ -591,7 +604,8 @@
 
 
 		try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out)) {
-		    List<Triple<String, String, Component>> output = Deencapsulation.invoke(testSubject, "writeComponentInterface", new Resource(), zip, fileName);
+		    List<Triple<String, String, Component>> output = Deencapsulation.invoke(commonCsarGenerator, "writeComponentInterface", new Resource(),
+                zip, fileName, "Definitions/");
 			assertNotNull(output);
 		}
 	}
@@ -604,7 +618,7 @@
 		Mockito.when(artifactCassandraDao.getArtifact(Mockito.any(String.class)))
 				.thenReturn(Either.right(CassandraOperationStatus.GENERAL_ERROR));
 
-		Either<byte[], ActionStatus> output = Deencapsulation.invoke(testSubject, "getEntryData", cassandraId, childComponent);
+		Either<byte[], ActionStatus> output = Deencapsulation.invoke(commonCsarGenerator, "getEntryData", cassandraId, childComponent);
 
 		assertNotNull(output);
 		assertTrue(output.isRight());
@@ -618,7 +632,7 @@
 				sdcSchemaFilesCassandraDao.getSpecificSchemaFiles(Mockito.any(String.class), Mockito.any(String.class)))
 				.thenReturn(Either.left(filesData));
 
-		Either<byte[], ResponseFormat> output = Deencapsulation.invoke(testSubject, "getLatestSchemaFilesFromCassandra");
+		Either<byte[], ResponseFormat> output = Deencapsulation.invoke(commonCsarGenerator, "getLatestSchemaFilesFromCassandra");
 
 		assertNotNull(output);
 		assertTrue(output.isRight());
@@ -704,88 +718,6 @@
 	}
 
 	@Test
-	void testNonMetaArtifactInfoCtor() {
-		createNonMetaArtifactInfoTestSubject();
-	}
-
-	@Test
-	void testNonMetaArtifactInfoGetPath() {
-		NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
-		testSubject.getPath();
-	}
-
-	@Test
-	void testNonMetaArtifactInfoGetArtifactName() {
-		NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
-		testSubject.getArtifactName();
-	}
-
-	@Test
-	void testNonMetaArtifactInfoGetArtifactType() {
-		final NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-		assertThat("The artifact type should be as expected",
-			testSubject.getArtifactType(), is(ArtifactTypeEnum.AAI_SERVICE_MODEL.getType()));
-	}
-
-	@Test
-	void testNonMetaArtifactInfoGetDisplayName() {
-		NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
-		testSubject.getDisplayName();
-	}
-
-	@Test
-	void testNonMetaArtifactInfoGetArtifactGroupType() {
-		NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
-		testSubject.getArtifactGroupType();
-	}
-
-	@Test
-	void testNonMetaArtifactInfoGetArtifactLabel() {
-		NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
-		testSubject.getArtifactLabel();
-	}
-
-	@Test
-	void testNonMetaArtifactInfoGetIsFromCsar() {
-		NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
-		testSubject.isFromCsar();
-	}
-
-	@Test
-	void testNonMetaArtifactInfoGetPayloadData() {
-		NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
-		testSubject.getPayloadData();
-	}
-
-	@Test
-	void testNonMetaArtifactInfoGetArtifaactChecksum() {
-		NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
-		testSubject.getArtifactChecksum();
-	}
-
-	@Test
-	void testNonMetaArtifactInfoGetArtifactUniqueId() {
-		NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
-		testSubject.getArtifactUniqueId();
-	}
-
-	@Test
-	void testNonMetaArtifactInfosetArtifactUniqueId() {
-		NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
-		testSubject.setArtifactUniqueId("artifactUniqueId");
-	}
-
-	@Test
 	void testValidateNonMetaArtifactWithExceptionCaught() {
 		CsarUtils.validateNonMetaArtifact("", new byte[0], new HashMap<>());
 	}
@@ -950,7 +882,7 @@
 		final Path path = Paths.get(rootPath + "/src/test/resources/sdc.zip");
 		final byte[] data = Files.readAllBytes(path);
 		try (final ByteArrayOutputStream out = new ByteArrayOutputStream(); final ZipOutputStream zip = new ZipOutputStream(out)) {
-			Deencapsulation.invoke(testSubject, "addSchemaFilesFromCassandra", zip, data, nodesFromPackage);
+			Deencapsulation.invoke(commonCsarGenerator, "addSchemaFilesFromCassandra", zip, data, nodesFromPackage, "Definitions/");
 			final IOException actualException = assertThrows(IOException.class, () -> zip.putNextEntry(new ZipEntry("Definitions/nodes.yml")));
 			assertEquals("duplicate entry: Definitions/nodes.yml", actualException.getMessage());
 		}
@@ -965,7 +897,7 @@
 		final Triple<String, String, Component> triple = Triple.of("fileName", "cassandraId", component);
 		dependencies.add(triple);
 		final List<String> expectedResult = Arrays.asList("tosca.nodes.Container.Application");
-		final List<String> result = Deencapsulation.invoke(testSubject,
+		final List<String> result = Deencapsulation.invoke(commonCsarGenerator,
 			"findNonRootNodesFromPackage", dependencies);
 		assertTrue(CollectionUtils.isNotEmpty(result));
 		assertEquals(expectedResult, result);
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
index 4f26713..0b37962 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
@@ -386,7 +386,7 @@
         when(toscaOperationFacade.getToscaFullElement("name")).thenReturn(Either.left(resource));
 
         Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> result;
-        result = Deencapsulation.invoke(testSubject, "fillImports", resource, toscaTemplate);
+        result = Deencapsulation.invoke(testSubject, "fillImports", resource, toscaTemplate, false);
 
         verify(toscaOperationFacade, times(1)).getToscaFullElement("name");
         assertTrue(result.isLeft());
@@ -421,7 +421,7 @@
         doReturn(map).when(outputConverter).convert(any(), any());
 
         // default test
-        result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode);
+        result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode, false);
         assertNotNull(result);
     }
 
@@ -471,7 +471,7 @@
         doReturn(map).when(outputConverter).convert(any(), any());
 
         // test component contains group
-        final var result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode);
+        final var result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode, false);
         assertNotNull(result);
     }
 
@@ -510,7 +510,7 @@
         doReturn(map).when(outputConverter).convert(any(), any());
 
         // test component contains group
-        result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode);
+        result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode, false);
         assertNotNull(result);
     }
 
@@ -561,7 +561,7 @@
         when(toscaOperationFacade.getByToscaResourceNameAndVersion("org.typeA", "1.0", null)).thenReturn(Either.left(baseType));
 
         // default test
-        result = Deencapsulation.invoke(testSubject, "fillImports", component, toscaTemplate);
+        result = Deencapsulation.invoke(testSubject, "fillImports", component, toscaTemplate, false);
         assertNotNull(result);
     }
 
@@ -588,7 +588,7 @@
         when(toscaOperationFacade.getToscaFullElement("modelName")).thenReturn(Either.left(new Service()));
 
         // default test
-        Deencapsulation.invoke(testSubject, "createDependency", componentCache, imports, dependecies, ci);
+        Deencapsulation.invoke(testSubject, "createDependency", componentCache, imports, dependecies, ci, false);
         assertFalse(componentCache.isEmpty());
     }
 
diff --git a/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/YamlUtil.java b/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/YamlUtil.java
index 45409c3..25407f1 100644
--- a/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/YamlUtil.java
+++ b/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/YamlUtil.java
@@ -87,7 +87,7 @@
         constructor.setPropertyUtils(getPropertyUtils());
         TypeDescription yamlFileDescription = new TypeDescription(typClass);
         constructor.addTypeDescription(yamlFileDescription);
-        T yamlObj = new Yaml(constructor, new Representer(), new DumperOptions(), getLoaderOptions()).load(yamlContent);
+        T yamlObj = new Yaml(constructor, new Representer(new DumperOptions()), new DumperOptions(), getLoaderOptions()).load(yamlContent);
 
         //noinspection ResultOfMethodCallIgnored
         yamlObj.toString();
@@ -114,7 +114,7 @@
             TypeDescription yamlFileDescription = new TypeDescription(typClass);
             constructor.addTypeDescription(yamlFileDescription);
             //No Yaml Constructor takes only Constructor and LoaderOptions, that is why I had to pass anonymous Representer and DumperOptions objects
-            T yamlObj = new Yaml(constructor, new Representer(), new DumperOptions(), getLoaderOptions()).load(yamlContent);
+            T yamlObj = new Yaml(constructor, new Representer(new DumperOptions()), new DumperOptions(), getLoaderOptions()).load(yamlContent);
             if (yamlObj != null) {
                 //noinspection ResultOfMethodCallIgnored
                 yamlObj.toString();
