3c95539ec5211dd5f72024f662d87d0503f751c2
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / tosca / CsarUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.tosca;
22
23 import com.google.gson.Gson;
24 import fj.data.Either;
25 import java.io.BufferedOutputStream;
26 import java.io.ByteArrayInputStream;
27 import java.io.File;
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.EnumMap;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.LinkedList;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 import java.util.Objects;
39 import java.util.Set;
40 import java.util.regex.Matcher;
41 import java.util.regex.Pattern;
42 import java.util.stream.Collectors;
43 import java.util.zip.ZipEntry;
44 import java.util.zip.ZipInputStream;
45 import java.util.zip.ZipOutputStream;
46 import org.apache.commons.codec.binary.Base64;
47 import org.apache.commons.codec.digest.DigestUtils;
48 import org.apache.commons.io.output.ByteArrayOutputStream;
49 import org.apache.commons.lang.WordUtils;
50 import org.apache.commons.lang3.tuple.ImmutablePair;
51 import org.apache.commons.lang3.tuple.ImmutableTriple;
52 import org.apache.commons.lang3.tuple.Triple;
53 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic;
54 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum;
55 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationInfo;
56 import org.openecomp.sdc.be.components.impl.ImportUtils;
57 import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
58 import org.openecomp.sdc.be.config.Configuration.ArtifactTypeConfig;
59 import org.openecomp.sdc.be.config.ConfigurationManager;
60 import org.openecomp.sdc.be.dao.api.ActionStatus;
61 import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
62 import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
63 import org.openecomp.sdc.be.dao.cassandra.SdcSchemaFilesCassandraDao;
64 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
65 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
66 import org.openecomp.sdc.be.impl.ComponentsUtils;
67 import org.openecomp.sdc.be.model.ArtifactDefinition;
68 import org.openecomp.sdc.be.model.Component;
69 import org.openecomp.sdc.be.model.ComponentInstance;
70 import org.openecomp.sdc.be.model.InterfaceDefinition;
71 import org.openecomp.sdc.be.model.LifecycleStateEnum;
72 import org.openecomp.sdc.be.model.Operation;
73 import org.openecomp.sdc.be.model.Resource;
74 import org.openecomp.sdc.be.model.Service;
75 import org.openecomp.sdc.be.model.User;
76 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaElementLifecycleOperation;
77 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
78 import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter;
79 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
80 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
81 import org.openecomp.sdc.be.resources.data.ESArtifactData;
82 import org.openecomp.sdc.be.resources.data.SdcSchemaFilesData;
83 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
84 import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil;
85 import org.openecomp.sdc.be.utils.CommonBeUtils;
86 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
87 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
88 import org.openecomp.sdc.common.impl.ExternalConfiguration;
89 import org.openecomp.sdc.common.util.GeneralUtility;
90 import org.openecomp.sdc.common.util.ValidationUtils;
91 import org.openecomp.sdc.exception.ResponseFormat;
92 import org.onap.sdc.generator.data.AdditionalParams;
93 import org.onap.sdc.generator.data.Artifact;
94 import org.onap.sdc.generator.data.ArtifactType;
95 import org.onap.sdc.generator.data.GenerationData;
96 import org.onap.sdc.generator.impl.ArtifactGenerationServiceImpl;
97 import org.slf4j.Logger;
98 import org.slf4j.LoggerFactory;
99 import org.springframework.beans.factory.annotation.Autowired;
100
101
102 /**
103  * @author tg851x
104  *
105  */
106 @org.springframework.stereotype.Component("csar-utils")
107 public class CsarUtils {
108
109     private static final Logger log = LoggerFactory.getLogger(CsarUtils.class);
110
111     @Autowired
112     private SdcSchemaFilesCassandraDao sdcSchemaFilesCassandraDao;
113     @Autowired
114     private ArtifactCassandraDao artifactCassandraDao;
115     @Autowired
116     private ComponentsUtils componentsUtils;
117     @Autowired
118     private ToscaExportHandler toscaExportUtils;
119     @Autowired
120     private ArtifactsBusinessLogic artifactsBusinessLogic;
121     @Autowired
122     protected ToscaOperationFacade toscaOperationFacade;
123
124
125     @javax.annotation.Resource
126     private ServiceBusinessLogic serviceBusinessLogic;
127
128     private Gson gson = new Gson();
129
130     public static final String CONFORMANCE_LEVEL = ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel();
131     public static final String SDC_VERSION = ExternalConfiguration.getAppVersion();
132
133     public static final Pattern UUID_NORMATIVE_NEW_VERSION = Pattern.compile("^\\d{1,}.0");
134     public static final String ARTIFACTS_PATH = "Artifacts/";
135     public static final String RESOURCES_PATH = "Resources/";
136     public static final String INFORMATIONAL_ARTIFACTS = "Informational/";
137     public static final String DEPLOYMENT_ARTIFACTS = "Deployment/";
138     public static final String WORKFLOW_ARTIFACT_DIR = "Workflows"+File.separator+"BPMN"+File.separator;
139     public static final String DEPLOYMENT_ARTIFACTS_DIR = "Deployment"+File.separator;
140
141     public static final String DEFINITIONS_PATH = "Definitions/";
142     private static final String CSAR_META_VERSION = "1.0";
143     private static final String CSAR_META_PATH_FILE_NAME = "csar.meta";
144     private static final String TOSCA_META_PATH_FILE_NAME = "TOSCA-Metadata/TOSCA.meta";
145     private static final String TOSCA_META_VERSION = "1.0";
146     private static final String CSAR_VERSION = "1.1";
147     public static final String ARTIFACTS = "Artifacts";
148     public static final String DEFINITION = "Definitions";
149     public static final String DEL_PATTERN = "([/\\\\]+)";
150     private static String versionFirstThreeOctates;
151
152     public static final String VFC_NODE_TYPE_ARTIFACTS_PATH_PATTERN = ARTIFACTS + DEL_PATTERN +
153                                                                               ImportUtils.Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX +
154                                                                               "([\\d\\w\\_\\-\\.\\s]+)" + DEL_PATTERN +
155                                                                               "([\\d\\w\\_\\-\\.\\s]+)" + DEL_PATTERN +
156                                                                               "([\\d\\w\\_\\-\\.\\s]+)" + DEL_PATTERN +
157                                                                               "([\\d\\w\\_\\-\\.\\s]+)";
158
159     public static final String VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN = ARTIFACTS + DEL_PATTERN+
160                                                                              // Artifact Group (i.e Deployment/Informational)
161                                                                              "([\\w\\_\\-\\.\\s]+)" + DEL_PATTERN +
162                                                                              // Artifact Type
163                                                                              "([\\w\\_\\-\\.\\s]+)"  + DEL_PATTERN +
164                                                                              // Artifact Any File Name
165                                                                              ".+";
166     public static final String VALID_ENGLISH_ARTIFACT_NAME = "([\\w\\_\\-\\.\\s]+)";
167     public static final String SERVICE_TEMPLATE_PATH_PATTERN = DEFINITION + DEL_PATTERN+
168                                                                        // Service Template File Name
169                                                                        "([\\w\\_\\-\\.\\s]+)";
170
171     public static final String ARTIFACT_CREATED_FROM_CSAR = "Artifact created from csar";
172
173     public CsarUtils() {
174         if(SDC_VERSION != null && !SDC_VERSION.isEmpty()){
175             Matcher matcher = Pattern.compile("(?!\\.)(\\d+(\\.\\d+)+)(?![\\d\\.])").matcher(SDC_VERSION);
176             matcher.find();
177             versionFirstThreeOctates = matcher.group(0);
178         } else {
179             versionFirstThreeOctates = "";
180         }
181     }
182
183     /**
184      *
185      * @param component
186      * @param getFromCS
187      * @param isInCertificationRequest
188      * @return
189      */
190     public Either<byte[], ResponseFormat> createCsar(Component component, boolean getFromCS, boolean isInCertificationRequest) {
191         return createCsar(component, getFromCS, isInCertificationRequest, false);
192     }
193
194     private Either<byte[], ResponseFormat> createCsar(Component component, boolean getFromCS, boolean isInCertificationRequest, boolean mockGenerator) {
195         final String createdBy = component.getCreatorFullName();
196
197         String fileName;
198         Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
199         ArtifactDefinition artifactDefinition = toscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
200         fileName = artifactDefinition.getArtifactName();
201
202         String toscaConformanceLevel = ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel();
203         String csarBlock0 = createCsarBlock0(CSAR_META_VERSION, toscaConformanceLevel);
204         byte[] csarBlock0Byte = csarBlock0.getBytes();
205
206         final String toscaBlock0 = createToscaBlock0(TOSCA_META_VERSION, CSAR_VERSION, createdBy, fileName);
207         byte[] toscaBlock0Byte = toscaBlock0.getBytes();
208
209         Either<byte[], ResponseFormat> generateCsarZipResponse = generateCsarZip(csarBlock0Byte, toscaBlock0Byte, component, getFromCS, isInCertificationRequest, mockGenerator);
210
211         if (generateCsarZipResponse.isRight()) {
212             return Either.right(generateCsarZipResponse.right().value());
213         }
214
215         return Either.left(generateCsarZipResponse.left().value());
216     }
217
218     private Either<byte[], ResponseFormat> generateCsarZip(byte[] csarBlock0Byte, byte[] toscaBlock0Byte, Component component, boolean getFromCS, boolean isInCertificationRequest, boolean mockGenerator) {
219         try (
220                 ByteArrayOutputStream out = new ByteArrayOutputStream();
221                 ZipOutputStream zip = new ZipOutputStream(out);
222         ){
223             zip.putNextEntry(new ZipEntry(CSAR_META_PATH_FILE_NAME));
224             zip.write(csarBlock0Byte);
225             zip.putNextEntry(new ZipEntry(TOSCA_META_PATH_FILE_NAME));
226             zip.write(toscaBlock0Byte);
227             Either<ZipOutputStream, ResponseFormat> populateZip = populateZip(component, getFromCS, zip, isInCertificationRequest, mockGenerator);
228             if (populateZip.isRight()) {
229                 log.debug("Failed to populate CSAR zip file {}", populateZip.right().value());
230                 return Either.right(populateZip.right().value());
231             }
232
233             zip.finish();
234             byte[] byteArray = out.toByteArray();
235
236             return Either.left(byteArray);
237         } catch (IOException e) {
238             log.debug("Failed with IOexception to create CSAR zip for component {}", component.getUniqueId(), e);
239
240             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
241             return Either.right(responseFormat);
242         }
243     }
244
245     private Either<ZipOutputStream, ResponseFormat> populateZip(Component component, boolean getFromCS, ZipOutputStream zip, boolean isInCertificationRequest, boolean mockGenerator) throws IOException {
246
247         LifecycleStateEnum lifecycleState = component.getLifecycleState();
248         String componentYaml;
249         Either<ToscaRepresentation, ToscaError> exportComponent;
250         byte[] mainYaml;
251         // <file name, cassandraId, component>
252         List<Triple<String, String, Component>> dependencies = null;
253         List<ImmutablePair<Component, byte[]>> generatorInputs = new LinkedList<>();
254
255         Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
256         ArtifactDefinition artifactDefinition = toscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
257         String fileName = artifactDefinition.getArtifactName();
258
259         if (getFromCS || !(lifecycleState == LifecycleStateEnum.NOT_CERTIFIED_CHECKIN || lifecycleState == LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT)) {
260             String cassandraId = artifactDefinition.getEsId();
261             Either<byte[], ActionStatus> fromCassandra = getFromCassandra(cassandraId);
262             if (fromCassandra.isRight()) {
263                 log.debug("ArtifactName {}, unique ID {}", artifactDefinition.getArtifactName(), artifactDefinition.getUniqueId());
264                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(fromCassandra.right().value());
265                 return Either.right(responseFormat);
266             }
267             mainYaml = fromCassandra.left().value();
268
269         } else {
270             exportComponent = toscaExportUtils.exportComponent(component);
271             if (exportComponent.isRight()) {
272                 log.debug("exportComponent failed", exportComponent.right().value());
273                 ActionStatus convertedFromToscaError = componentsUtils.convertFromToscaError(exportComponent.right().value());
274                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(convertedFromToscaError);
275                 return Either.right(responseFormat);
276             }
277             ToscaRepresentation exportResult = exportComponent.left().value();
278             componentYaml = exportResult.getMainYaml();
279             mainYaml = componentYaml.getBytes();
280             dependencies = exportResult.getDependencies();
281         }
282
283         zip.putNextEntry(new ZipEntry(DEFINITIONS_PATH + fileName));
284         zip.write(mainYaml);
285         //US798487 - Abstraction of complex types
286         if (!ModelConverter.isAtomicComponent(component)){
287             log.debug("Component {} is complex - generating abstract type for it..", component.getName());
288             writeComponentInterface(component, zip, fileName);
289         }
290
291         generatorInputs.add(new ImmutablePair<Component, byte[]>(component, mainYaml));
292
293         if (dependencies == null) {
294             Either<ToscaTemplate, ToscaError> dependenciesRes = toscaExportUtils.getDependencies(component);
295             if (dependenciesRes.isRight()) {
296                 log.debug("Failed to retrieve dependencies for component {}, error {}", component.getUniqueId(),
297                         dependenciesRes.right().value());
298                 ActionStatus convertFromToscaError = componentsUtils.convertFromToscaError(dependenciesRes.right().value());
299                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(convertFromToscaError);
300                 return Either.right(responseFormat);
301             }
302             dependencies = dependenciesRes.left().value().getDependencies();
303         }
304
305         //UID <cassandraId,filename,component>
306         Map<String, ImmutableTriple<String,String, Component>> innerComponentsCache = new HashMap<>();
307
308         if (dependencies != null && !dependencies.isEmpty()) {
309             for (Triple<String, String, Component> d : dependencies) {
310                 String cassandraId = d.getMiddle();
311                 Component childComponent = d.getRight();
312                 Either<byte[], ActionStatus> entryData = getEntryData(cassandraId, childComponent);
313
314                 if (entryData.isRight()) {
315                     ResponseFormat responseFormat = componentsUtils.getResponseFormat(entryData.right().value());
316                     return Either.right(responseFormat);
317                 }
318
319                 //fill innerComponentsCache
320                 fileName = d.getLeft();
321                 addComponentToCache(innerComponentsCache, cassandraId, fileName, childComponent);
322                 addInnerComponentsToCache(innerComponentsCache, childComponent);
323
324                 byte[] content = entryData.left().value();
325                 generatorInputs.add(new ImmutablePair<Component, byte[]>(childComponent, content));
326             }
327
328             //add inner components to CSAR
329             for (Entry<String, ImmutableTriple<String, String, Component>> innerComponentTripleEntry : innerComponentsCache.entrySet()) {
330
331                 ImmutableTriple<String, String, Component> innerComponentTriple = innerComponentTripleEntry.getValue();
332
333                 Component innerComponent = innerComponentTriple.getRight();
334                 String icFileName = innerComponentTriple.getMiddle();
335
336                 // add component to zip
337                 Either<byte[], ActionStatus> entryData = getEntryData(innerComponentTriple.getLeft(), innerComponent);
338                 if (entryData.isRight()) {
339                     ResponseFormat responseFormat = componentsUtils.getResponseFormat(entryData.right().value());
340                     log.debug("Failed adding to zip component {}, error {}", innerComponentTriple.getLeft(),
341                             entryData.right().value());
342                     return Either.right(responseFormat);
343                 }
344                 byte[] content = entryData.left().value();
345                 zip.putNextEntry(new ZipEntry(DEFINITIONS_PATH + icFileName));
346                 zip.write(content);
347
348                 // add component interface to zip
349                 if (!ModelConverter.isAtomicComponent(innerComponent)) {
350                     writeComponentInterface(innerComponent, zip, icFileName);
351                 }
352             }
353         }
354
355         //retrieve SDC.zip from Cassandra
356         Either<byte[], ResponseFormat> latestSchemaFilesFromCassandra = getLatestSchemaFilesFromCassandra();
357
358         if(latestSchemaFilesFromCassandra.isRight()){
359             log.error("Error retrieving SDC Schema files from cassandra" );
360             return Either.right(latestSchemaFilesFromCassandra.right().value());
361         }
362
363         //add files from retireved SDC.zip to Definitions folder in CSAR
364         Either<ZipOutputStream, ResponseFormat> addSchemaFilesFromCassandra = addSchemaFilesFromCassandra(zip, latestSchemaFilesFromCassandra.left().value());
365
366         if(addSchemaFilesFromCassandra.isRight()){
367             return addSchemaFilesFromCassandra;
368         }
369
370         // Artifact Generation
371         if (component.getComponentType() == ComponentTypeEnum.SERVICE
372                     && isInCertificationRequest) {
373
374             List<ArtifactDefinition> aiiArtifactList;
375
376             Either<List<ArtifactDefinition>, ResponseFormat> handleAAIArtifacts = handleAAIArtifacts(component, mockGenerator, generatorInputs);
377
378             if (handleAAIArtifacts.isLeft()) {
379                 aiiArtifactList = handleAAIArtifacts.left().value();
380             } else {
381                 log.debug("AAI Artifacts handling failed");
382                 return Either.right(handleAAIArtifacts.right().value());
383             }
384
385             if (isInCertificationRequest) {
386                 Either<ActionStatus, ResponseFormat> handleAllAAIArtifactsInDataModel = handleAllAAIArtifactsInDataModel(
387                         component, aiiArtifactList, false, true);
388
389                 if (handleAllAAIArtifactsInDataModel.isRight()) {
390                     log.debug("AAI Artifacts handling (create, update, delete) failed");
391                     return Either.right(handleAllAAIArtifactsInDataModel.right().value());
392                 }
393             }
394
395         }
396
397         Either<CsarDefinition, ResponseFormat> collectedComponentCsarDefinition = collectComponentCsarDefinition(component);
398
399         if (collectedComponentCsarDefinition.isRight()) {
400             return Either.right(collectedComponentCsarDefinition.right().value());
401         }
402
403         return writeAllFilesToCsar(component, collectedComponentCsarDefinition.left().value(), zip, isInCertificationRequest);
404     }
405
406     private Either<ZipOutputStream, ResponseFormat> addSchemaFilesFromCassandra(ZipOutputStream zip, byte[] schemaFileZip){
407
408         final int initSize = 2048;
409
410         log.debug("Starting copy from Schema file zip to CSAR zip");
411
412         try (ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(schemaFileZip));
413              ByteArrayOutputStream out = new ByteArrayOutputStream();
414              BufferedOutputStream bos = new BufferedOutputStream(out, initSize);) {
415
416             ZipEntry entry = null;
417
418             while ((entry = zipStream.getNextEntry()) != null) {
419
420                 String entryName = entry.getName();
421                 int readSize = initSize;
422                 byte[] entryData = new byte[initSize];
423
424                 while ((readSize = zipStream.read(entryData, 0, readSize)) != -1) {
425                     bos.write(entryData, 0, readSize);
426                 }
427
428                 bos.flush();
429                 out.flush();
430                 zip.putNextEntry(new ZipEntry(DEFINITIONS_PATH + entryName));
431                 zip.write(out.toByteArray());
432                 zip.flush();
433                 out.reset();
434             }
435         } catch (IOException e) {
436             log.error("Error while writing the SDC schema file to the CSAR {}", e);
437             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
438         }
439
440         log.debug("Finished coppy from Schema file zip to CSAR zip");
441
442         return Either.left(zip);
443     }
444
445
446     private void addInnerComponentsToCache(Map<String, ImmutableTriple<String, String, Component>> componentCache,
447             Component childComponent) {
448
449         List<ComponentInstance> instances = childComponent.getComponentInstances();
450
451         if(instances != null) {
452             instances.forEach(ci -> {
453                 ImmutableTriple<String, String, Component> componentRecord = componentCache.get(ci.getComponentUid());
454                 if (componentRecord == null) {
455                     // all resource must be only once!
456                     Either<Resource, StorageOperationStatus> resource = toscaOperationFacade.getToscaElement(ci.getComponentUid());
457                     if (resource.isRight()) {
458                         log.debug("Failed to fetch resource with id {} for instance {}");
459                     }
460                     Component componentRI = resource.left().value();
461
462                     Map<String, ArtifactDefinition> childToscaArtifacts = componentRI.getToscaArtifacts();
463                     ArtifactDefinition childArtifactDefinition = childToscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
464                     if (childArtifactDefinition != null) {
465                         //add to cache
466                         addComponentToCache(componentCache, childArtifactDefinition.getEsId(), childArtifactDefinition.getArtifactName(), componentRI);
467                     }
468
469                     //if not atomic - insert inner components as well
470                     if(!ModelConverter.isAtomicComponent(componentRI)) {
471                         addInnerComponentsToCache(componentCache, componentRI);
472                     }
473                 }
474             });
475         }
476     }
477
478     private void addComponentToCache(Map<String, ImmutableTriple<String, String, Component>> componentCache,
479             String id, String fileName, Component component) {
480
481         ImmutableTriple<String, String, Component> cachedComponent = componentCache.get(component.getInvariantUUID());
482         if (cachedComponent == null || CommonBeUtils.compareAsdcComponentVersions(component.getVersion(), cachedComponent.getRight().getVersion())) {
483             componentCache.put(component.getInvariantUUID(),
484                     new ImmutableTriple<String, String, Component>(id, fileName, component));
485
486             if(cachedComponent != null) {
487                 //overwriting component with newer version
488                 log.warn("Overwriting component invariantID {} of version {} with a newer version {}", id, cachedComponent.getRight().getVersion(), component.getVersion());
489             }
490         }
491     }
492
493     private Either<ZipOutputStream, ResponseFormat> writeComponentInterface(Component component, ZipOutputStream zip, String fileName) {
494         try {
495             Either<ToscaRepresentation, ToscaError> componentInterface = toscaExportUtils.exportComponentInterface(component);
496             ToscaRepresentation componentInterfaceYaml = componentInterface.left().value();
497             String mainYaml = componentInterfaceYaml.getMainYaml();
498             String interfaceFileName = DEFINITIONS_PATH + ToscaExportHandler.getInterfaceFilename(fileName);
499
500             zip.putNextEntry(new ZipEntry(interfaceFileName));
501             zip.write(mainYaml.getBytes());
502
503         } catch (Exception e) {
504             log.error("#writeComponentInterface - zip writing failed with error: ", e);
505             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
506         }
507
508         return Either.left(zip);
509     }
510
511     private Either<List<ArtifactDefinition>, ResponseFormat> handleAAIArtifacts(Component component, boolean mockGenerator, List<ImmutablePair<Component, byte[]>> generatorInputs) {
512
513         ComponentTypeEnum componentType = component.getComponentType();
514         List<Artifact> generatedArtifacts;
515         List<ArtifactDefinition> aaiArtifacts = new LinkedList<>();
516
517         if (componentType == ComponentTypeEnum.SERVICE && !generatorInputs.isEmpty()) {
518             List<Artifact> convertedGeneratorInputs = convertToGeneratorArtifactsInput(generatorInputs);
519
520             Either<List<Artifact>, String> generatorResponse;
521
522             if (mockGenerator) {
523                 generatorResponse = artifactGenerator(convertedGeneratorInputs, ArtifactType.OTHER, component);
524             } else {
525                 generatorResponse = artifactGenerator(convertedGeneratorInputs, ArtifactType.AAI, component);
526             }
527
528             if (generatorResponse.isRight()) {
529                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.AAI_ARTIFACT_GENERATION_FAILED, component.getComponentType().getValue(), component.getName(), generatorResponse.right().value());
530                 return Either.right(responseFormat);
531             }
532
533             generatedArtifacts = generatorResponse.left().value();
534
535             aaiArtifacts = convertToArtifactDefinitionFromArtifactGeneratedData(generatedArtifacts);
536
537         }
538
539         return Either.left(aaiArtifacts);
540     }
541
542     private Either<ActionStatus, ResponseFormat> handleAllAAIArtifactsInDataModel(Component component, List<ArtifactDefinition> artifactsFromAAI, boolean shouldLock, boolean inTransaction) {
543
544         Either<ActionStatus, ResponseFormat> handleAAIArtifactsResponse;
545         User lastComponentUpdater;
546
547         List<ArtifactDefinition> aaiArtifatcsToCreate = getAAIArtifatcsForCreate(artifactsFromAAI, component);
548         List<ArtifactDefinition> aaiArtifatcsToDelete = getAAIArtifatcsForDelete(artifactsFromAAI, component);
549         List<ArtifactDefinition> aaiArtifatcsToUpdate = getAAIArtifatcsForUpdate(artifactsFromAAI, component);
550
551         String lastUpdaterUserId = component.getLastUpdaterUserId();
552         Either<User, ResponseFormat> validateUserExists = artifactsBusinessLogic.validateUserExists(lastUpdaterUserId, "CSAR creation util", true);
553
554         if (validateUserExists.isRight()) {
555             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.AAI_ARTIFACT_GENERATION_FAILED, component.getComponentType().getValue(), component.getName(), "User not found");
556             return Either.right(responseFormat);
557         }
558
559         lastComponentUpdater = validateUserExists.left().value();
560
561         handleAAIArtifactsResponse = handleAAIArtifactsInDataModelByOperationType(component, aaiArtifatcsToDelete, artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactOperationEnum.DELETE), lastComponentUpdater, shouldLock,
562                 inTransaction);
563
564         if (handleAAIArtifactsResponse.isRight()) {
565             return handleAAIArtifactsResponse;
566         }
567
568         handleAAIArtifactsResponse = handleAAIArtifactsInDataModelByOperationType(component, aaiArtifatcsToCreate, artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactOperationEnum.CREATE), lastComponentUpdater, shouldLock,
569                 inTransaction);
570
571         if (handleAAIArtifactsResponse.isRight()) {
572             return handleAAIArtifactsResponse;
573         }
574
575         return handleAAIArtifactsInDataModelByOperationType(component, aaiArtifatcsToUpdate, artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactOperationEnum.UPDATE), lastComponentUpdater, shouldLock, inTransaction);
576     }
577
578     private List<ArtifactDefinition> getAAIArtifatcsForUpdate(List<ArtifactDefinition> artifactsFromAAI, Component component) {
579
580         Set<String> componetDeploymentArtifactLables = component.getDeploymentArtifacts().keySet();
581         Set<String> componetInformationalArtifactLables = component.getArtifacts().keySet();
582
583         return artifactsFromAAI.stream()
584                                .filter(e -> componetDeploymentArtifactLables.contains(e.getArtifactLabel()) || componetInformationalArtifactLables.contains(e.getArtifactLabel()))
585                                .filter(e -> checkAaiForUpdate(component, e))
586                                .collect(Collectors.toList());
587     }
588
589     private boolean checkAaiForUpdate(Component component, ArtifactDefinition artifactDefinition) {
590         ArtifactDefinition artifactDefinitionComp = component.getDeploymentArtifacts().get(artifactDefinition.getArtifactLabel());
591
592         if (artifactDefinitionComp == null) {
593             log.warn("Failed to get {} artifact", artifactDefinition.getArtifactLabel());
594             return false;
595         }
596
597         // Old Artifacts before the generated flag introduction if contains "aai" ignore case prefix updated
598         if (artifactDefinitionComp.getGenerated() == null) {
599             if (artifactDefinitionComp.getArtifactLabel().toLowerCase().startsWith("aai")) {
600                 return true;
601             } else {
602                 log.warn("The artifact {} flag is null but AAI prefix is abssent Not updated", artifactDefinition.getArtifactLabel());
603             }
604         } else {
605             if (artifactDefinition.getGenerated()) {
606                 return true;
607             } else {
608                 log.warn("Generated artifact {} was already uploaded manually", artifactDefinition.getArtifactLabel());
609             }
610         }
611         return false;
612     }
613
614     private List<ArtifactDefinition> getAAIArtifatcsForDelete(List<ArtifactDefinition> artifactsFromAAI, Component component) {
615
616         Set<String> aaiLabels = artifactsFromAAI.stream()
617                                                 .map(ArtifactDefinition::getArtifactLabel)
618                                                 .collect(Collectors.toSet());
619
620         List<ArtifactDefinition> artifactsForDeleteDeployment = component.getDeploymentArtifacts().values().stream()
621                                                                          // Filter Out Artifacts that are not contained in artifacts returned
622                                                                          // from AAI API
623                                                                          .filter(e -> !aaiLabels.contains(e.getArtifactLabel()))
624                                                                          .collect(Collectors.toList());
625
626         List<ArtifactDefinition> artifactsForDeleteInformational = component.getArtifacts().values().stream()
627                                                                             // Filter Out Artifacts that are not contained in artifacts returned
628                                                                             // from AAI API
629                                                                             .filter(e -> !aaiLabels.contains(e.getArtifactLabel()))
630                                                                             .collect(Collectors.toList());
631
632         artifactsForDeleteDeployment.addAll(artifactsForDeleteInformational);
633
634         return artifactsForDeleteDeployment.stream()
635                                            .filter(e -> (e.getGenerated() != null && e.getGenerated().equals(Boolean.TRUE)) || (e.getGenerated() == null && e.getArtifactLabel().toLowerCase().startsWith("aai")))
636                                            .collect(Collectors.toList());
637     }
638
639     private List<ArtifactDefinition> getAAIArtifatcsForCreate(List<ArtifactDefinition> artifactsFromAAI, Component component) {
640
641         Set<String> componentDeploymentLabels = component.getDeploymentArtifacts().keySet();
642         Set<String> componentInfoLabels = component.getArtifacts().keySet();
643
644         // If the artifact label does not exist in the service -
645         // store the artifact (generate uuid and version, "generated" flag is TRUE)
646         return artifactsFromAAI.stream()
647                                .filter(e -> !componentDeploymentLabels.contains(e.getArtifactLabel()) && !componentInfoLabels.contains(e.getArtifactLabel()))
648                                .collect(Collectors.toList());
649     }
650
651     private Either<ActionStatus, ResponseFormat> handleAAIArtifactsInDataModelByOperationType(Component component, List<ArtifactDefinition> generatedArtifactsDefinitions, ArtifactOperationInfo operationType, User user, boolean shouldLock,
652             boolean inTransaction) {
653
654         String componentUniqueId = component.getUniqueId();
655         ComponentTypeEnum componentType = component.getComponentType();
656
657         for (ArtifactDefinition artDef : generatedArtifactsDefinitions) {
658             String data = gson.toJson(artDef);
659             String dataMD5 = GeneralUtility.calculateMD5Base64EncodedByString(data);
660             String artifactUniqueId = null;
661
662             if ((operationType.getArtifactOperationEnum() == ArtifactOperationEnum.UPDATE) || (operationType.getArtifactOperationEnum() == ArtifactOperationEnum.DELETE)) {
663                 String artifactLabel = artDef.getArtifactLabel();
664                 ArtifactDefinition artifactDefinition = component.getDeploymentArtifacts().get(artifactLabel);
665                 if (artifactDefinition != null) {
666                     artifactUniqueId = artifactDefinition.getUniqueId();
667                 }
668             }
669
670             Either<Either<ArtifactDefinition, Operation>, ResponseFormat> validateAndHandleArtifact = artifactsBusinessLogic.validateAndHandleArtifact(componentUniqueId, componentType, operationType, artifactUniqueId, artDef, dataMD5, data, null,
671                     null, user, component, shouldLock, inTransaction, false);
672
673             if (validateAndHandleArtifact.isRight()) {
674                 if (ArtifactOperationEnum.isCreateOrLink(operationType.getArtifactOperationEnum()) || ArtifactOperationEnum.UPDATE == operationType.getArtifactOperationEnum()) {
675                     ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.AAI_ARTIFACT_GENERATION_FAILED, componentType.getValue(), component.getName(), validateAndHandleArtifact.right().value().toString());
676
677                     Either.right(responseFormat);
678                 } else {
679                     log.warn("Generated artifact {} could not be deleted", artDef.getArtifactLabel());
680                 }
681             }
682         }
683
684         return Either.left(ActionStatus.OK);
685     }
686
687     private List<ArtifactDefinition> convertToArtifactDefinitionFromArtifactGeneratedData(List<Artifact> generatorOutput) {
688         List<ArtifactDefinition> artifactDefList = new LinkedList<>();
689
690         for (Artifact artifact : generatorOutput) {
691             ArtifactDefinition newEntry = new ArtifactDefinition();
692             newEntry.setArtifactName(artifact.getName());
693             newEntry.setArtifactType(artifact.getType());
694             newEntry.setArtifactGroupType(ArtifactGroupTypeEnum.findType(artifact.getGroupType()));
695             newEntry.setDescription(artifact.getDescription());
696
697             // Normalizing the artifact label to match those stored in DB
698             String normalizeArtifactLabel = ValidationUtils.normalizeArtifactLabel(artifact.getLabel());
699             newEntry.setArtifactLabel(normalizeArtifactLabel);
700             newEntry.setPayload(Base64.decodeBase64(artifact.getPayload()));
701             newEntry.setArtifactChecksum(artifact.getChecksum());
702             // Flag that set to true in case that the artifact is generated by AI&I generator
703             newEntry.setGenerated(Boolean.TRUE);
704
705             artifactDefList.add(newEntry);
706         }
707
708         return artifactDefList;
709     }
710
711     // List<ImmutablePair<Component, byte[] artifactBytes>>
712     // artifact stored by label
713     private List<Artifact> convertToGeneratorArtifactsInput(List<ImmutablePair<Component, byte[]>> inputs) {
714         List<Artifact> listOfArtifactsInput = new LinkedList<>();
715         for (ImmutablePair<Component, byte[]> triple : inputs) {
716             Component component = triple.getLeft();
717
718             Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
719             ArtifactDefinition artifactDefinition = toscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
720
721             String artifactName = artifactDefinition.getArtifactName();
722             String artifactType = artifactDefinition.getArtifactType();
723             String artifactGroupType = artifactDefinition.getArtifactGroupType().getType();
724             String artifactDescription = artifactDefinition.getDescription();
725             String artifactLabel = artifactDefinition.getArtifactLabel();
726             byte[] right = triple.getRight();
727             // The md5 calculated on the uncoded data
728             String md5Hex = DigestUtils.md5Hex(right);
729             byte[] payload = Base64.encodeBase64(right);
730             String artifactVersion = artifactDefinition.getArtifactVersion();
731
732             Artifact convertedArtifact = new Artifact(artifactType, artifactGroupType, md5Hex, payload);
733             convertedArtifact.setName(artifactName);
734             convertedArtifact.setDescription(artifactDescription);
735             convertedArtifact.setLabel(artifactLabel);
736             convertedArtifact.setVersion(artifactVersion);
737
738             listOfArtifactsInput.add(convertedArtifact);
739         }
740
741         return listOfArtifactsInput;
742     }
743
744     private Either<byte[], ActionStatus> getEntryData(String cassandraId, Component childComponent) {
745         byte[] content;
746         if (cassandraId == null || cassandraId.isEmpty()) {
747             Either<ToscaRepresentation, ToscaError> exportRes = toscaExportUtils.exportComponent(childComponent);
748             if (exportRes.isRight()) {
749                 log.debug("Failed to export tosca template for child component {} error {}", childComponent.getUniqueId(), exportRes.right().value());
750                 return Either.right(componentsUtils.convertFromToscaError(exportRes.right().value()));
751             }
752             content = exportRes.left().value().getMainYaml().getBytes();
753         } else {
754             Either<byte[], ActionStatus> fromCassandra = getFromCassandra(cassandraId);
755             if (fromCassandra.isRight()) {
756                 return Either.right(fromCassandra.right().value());
757             } else {
758                 content = fromCassandra.left().value();
759             }
760         }
761         return Either.left(content);
762     }
763
764     private Either<byte[], ResponseFormat> getLatestSchemaFilesFromCassandra() {
765         Either<List<SdcSchemaFilesData>, CassandraOperationStatus> specificSchemaFiles = sdcSchemaFilesCassandraDao.getSpecificSchemaFiles(versionFirstThreeOctates, CONFORMANCE_LEVEL);
766
767         if(specificSchemaFiles.isRight()){
768             log.debug("Failed to get the schema files SDC-Version: {} Conformance-Level {}", versionFirstThreeOctates, CONFORMANCE_LEVEL);
769             StorageOperationStatus storageStatus = DaoStatusConverter.convertCassandraStatusToStorageStatus(specificSchemaFiles.right().value());
770             ActionStatus convertedFromStorageResponse = componentsUtils.convertFromStorageResponse(storageStatus);
771             return Either.right(componentsUtils.getResponseFormat(convertedFromStorageResponse));
772         }
773
774         List<SdcSchemaFilesData> listOfSchemas = specificSchemaFiles.left().value();
775
776         if(listOfSchemas.isEmpty()){
777             log.debug("Failed to get the schema files SDC-Version: {} Conformance-Level {}", versionFirstThreeOctates, CONFORMANCE_LEVEL);
778             return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_SCHEMA_FILES_NOT_FOUND, versionFirstThreeOctates, CONFORMANCE_LEVEL));
779         }
780
781         SdcSchemaFilesData schemaFile = listOfSchemas.iterator().next();
782
783         return Either.left(schemaFile.getPayloadAsArray());
784     }
785
786     private Either<byte[], ActionStatus> getFromCassandra(String cassandraId) {
787         Either<ESArtifactData, CassandraOperationStatus> artifactResponse = artifactCassandraDao.getArtifact(cassandraId);
788
789         if (artifactResponse.isRight()) {
790             log.debug("Failed to fetch artifact from Cassandra by id {} error {} ", cassandraId, artifactResponse.right().value());
791
792             StorageOperationStatus storageStatus = DaoStatusConverter.convertCassandraStatusToStorageStatus(artifactResponse.right().value());
793             ActionStatus convertedFromStorageResponse = componentsUtils.convertFromStorageResponse(storageStatus);
794             return Either.right(convertedFromStorageResponse);
795         }
796         ESArtifactData artifactData = artifactResponse.left().value();
797         return Either.left(artifactData.getDataAsArray());
798     }
799
800     private String createCsarBlock0(String metaFileVersion, String toscaConformanceLevel) {
801         final String BLOCK_0_TEMPLATE =
802                 "SDC-TOSCA-Meta-File-Version: %s\nSDC-TOSCA-Definitions-Version: %s\n";
803         String readyBlock = String.format(BLOCK_0_TEMPLATE, metaFileVersion, toscaConformanceLevel);
804         return readyBlock;
805     }
806
807     private String createToscaBlock0(String metaFileVersion, String csarVersion, String createdBy, String entryDef) {
808         final String block0template = "TOSCA-Meta-File-Version: %s\nCSAR-Version: %s\nCreated-By: %s\nEntry-Definitions: Definitions/%s\n\nName: csar.meta\nContent-Type: text/plain\n";
809         return String.format(block0template, metaFileVersion, csarVersion, createdBy, entryDef);
810     }
811
812     private Either<List<Artifact>, String> artifactGenerator(List<Artifact> artifactList, ArtifactType type, Component component) {
813
814         ArtifactGenerationServiceImpl artifactGenerationServiceImpl = new ArtifactGenerationServiceImpl();
815         ArtifactTypes artifactTypes = new ArtifactTypes();
816         List<ArtifactType> artifactTypesList = new LinkedList<>();
817         ArtifactType otherType;
818
819         if (type == null) {
820             otherType = ArtifactType.OTHER;
821         } else {
822             otherType = type;
823         }
824
825         artifactTypesList.add(otherType);
826         artifactTypes.setArtifactTypes(artifactTypesList);
827
828         String configJson = gson.toJson(artifactTypes);
829         Map<String, String> additionalParams = new HashMap<>();
830         String version;
831
832         if (UUID_NORMATIVE_NEW_VERSION.matcher(component.getVersion()).matches() ) {
833             version = component.getVersion();
834         } else {
835             String[] versionParts = component.getVersion().split(ToscaElementLifecycleOperation.VERSION_DELIMETER_REGEXP);
836             Integer majorVersion = Integer.parseInt(versionParts[0]);
837
838             version = (majorVersion + 1) + ToscaElementLifecycleOperation.VERSION_DELIMETER + "0";
839         }
840
841         additionalParams.put(AdditionalParams.ServiceVersion.getName(), version);
842         GenerationData generatedArtifacts = artifactGenerationServiceImpl.generateArtifact(artifactList, configJson, additionalParams);
843
844         Map<String, List<String>> errorData = generatedArtifacts.getErrorData();
845
846         if (!errorData.isEmpty()) {
847             Set<String> keySet = errorData.keySet();
848             StringBuilder error = new StringBuilder();
849
850             for (String key : keySet) {
851                 List<String> errorList = errorData.get(key);
852                 log.debug("The Artifact Generator Failed - {} with following: {}", key, errorList);
853                 error.append(key + errorList);
854             }
855
856             return Either.right(error.toString());
857         }
858
859         return Either.left(generatedArtifacts.getResultData());
860     }
861
862     /**
863      * Extracts artifacts of VFCs from CSAR
864      *
865      * @param csar
866      * @return Map of <String, List<ArtifactDefinition>> the contains Lists of artifacts according vfcToscaNamespace
867      */
868     public static Map<String, List<ArtifactDefinition>> extractVfcsArtifactsFromCsar(Map<String, byte[]> csar) {
869
870         Map<String, List<ArtifactDefinition>> artifacts = new HashMap<>();
871         if (csar != null) {
872             log.debug("************* Going to extract VFCs artifacts from Csar. ");
873             Map<String, Set<List<String>>> collectedWarningMessages = new HashMap<>();
874             csar.entrySet().stream()
875                 // filter CSAR entry by node type artifact path
876                 .filter(e -> Pattern.compile(VFC_NODE_TYPE_ARTIFACTS_PATH_PATTERN).matcher(e.getKey()).matches())
877                 // extract ArtifactDefinition from CSAR entry for each entry with matching artifact path
878                 .forEach(e -> addExtractedVfcArtifact(extractVfcArtifact(e, collectedWarningMessages), artifacts));
879             // add counter suffix to artifact labels
880             handleWarningMessages(collectedWarningMessages);
881
882         }
883         return artifacts;
884     }
885
886     /**
887      * Print warnings to log
888      *
889      * @param collectedWarningMessages
890      */
891     public static void handleWarningMessages(Map<String, Set<List<String>>> collectedWarningMessages) {
892         collectedWarningMessages.entrySet().stream()
893                                 // for each vfc
894                                 .forEach(e -> e.getValue().stream()
895                                                // add each warning message to log
896                                                .forEach(args -> log.warn(e.getKey(), args.toArray())));
897
898     }
899
900     private static void addExtractedVfcArtifact(ImmutablePair<String, ArtifactDefinition> extractedVfcArtifact, Map<String, List<ArtifactDefinition>> artifacts) {
901         if (extractedVfcArtifact != null) {
902             List<ArtifactDefinition> currArtifactsList;
903             String vfcToscaNamespace = extractedVfcArtifact.getKey();
904             if (artifacts.containsKey(vfcToscaNamespace)) {
905                 currArtifactsList = artifacts.get(vfcToscaNamespace);
906             } else {
907                 currArtifactsList = new ArrayList<>();
908                 artifacts.put(vfcToscaNamespace, currArtifactsList);
909             }
910             currArtifactsList.add(extractedVfcArtifact.getValue());
911         }
912     }
913
914     private static ImmutablePair<String, ArtifactDefinition> extractVfcArtifact(Entry<String, byte[]> entry, Map<String, Set<List<String>>> collectedWarningMessages) {
915         ArtifactDefinition artifact;
916         String[] parsedCsarArtifactPath = entry.getKey().split("/");
917         Either<ArtifactGroupTypeEnum, Boolean> eitherArtifactGroupType = detectArtifactGroupType(parsedCsarArtifactPath[2].toUpperCase(), collectedWarningMessages);
918         if (eitherArtifactGroupType.isLeft()) {
919             artifact = buildArtifactDefinitionFromCsarArtifactPath(entry, collectedWarningMessages, parsedCsarArtifactPath, eitherArtifactGroupType.left().value());
920         } else {
921             return null;
922         }
923         return new ImmutablePair<>(parsedCsarArtifactPath[1], artifact);
924     }
925
926     private static Either<ArtifactGroupTypeEnum, Boolean> detectArtifactGroupType(String groupType, Map<String, Set<List<String>>> collectedWarningMessages) {
927         Either<ArtifactGroupTypeEnum, Boolean> result;
928         try {
929             ArtifactGroupTypeEnum artifactGroupType = ArtifactGroupTypeEnum.findType(groupType.toUpperCase());
930             if (artifactGroupType == null || (artifactGroupType != ArtifactGroupTypeEnum.INFORMATIONAL && artifactGroupType != ArtifactGroupTypeEnum.DEPLOYMENT)) {
931                 String warningMessage = "Warning - unrecognized artifact group type {} was received.";
932                 List<String> messageArguments = new ArrayList<>();
933                 messageArguments.add(groupType);
934                 if (!collectedWarningMessages.containsKey(warningMessage)) {
935                     Set<List<String>> messageArgumentLists = new HashSet<>();
936                     messageArgumentLists.add(messageArguments);
937                     collectedWarningMessages.put(warningMessage, messageArgumentLists);
938                 } else {
939                     collectedWarningMessages.get(warningMessage).add(messageArguments);
940                 }
941
942                 result = Either.right(false);
943             } else {
944
945                 result = Either.left(artifactGroupType);
946             }
947         } catch (Exception e) {
948             log.debug("detectArtifactGroupType failed with exception", e);
949             result = Either.right(false);
950         }
951         return result;
952     }
953
954     private static ArtifactDefinition buildArtifactDefinitionFromCsarArtifactPath(Entry<String, byte[]> entry, Map<String, Set<List<String>>> collectedWarningMessages, String[] parsedCsarArtifactPath, ArtifactGroupTypeEnum artifactGroupType) {
955         ArtifactDefinition artifact;
956         artifact = new ArtifactDefinition();
957         artifact.setArtifactGroupType(artifactGroupType);
958         artifact.setArtifactType(detectArtifactTypeVFC(artifactGroupType, parsedCsarArtifactPath[3], parsedCsarArtifactPath[1], collectedWarningMessages));
959         artifact.setArtifactName(ValidationUtils.normalizeFileName(parsedCsarArtifactPath[parsedCsarArtifactPath.length - 1]));
960         artifact.setPayloadData(Base64.encodeBase64String(entry.getValue()));
961         artifact.setArtifactDisplayName(artifact.getArtifactName().lastIndexOf('.') > 0 ? artifact.getArtifactName().substring(0, artifact.getArtifactName().lastIndexOf('.')) : artifact.getArtifactName());
962         artifact.setArtifactLabel(ValidationUtils.normalizeArtifactLabel(artifact.getArtifactName()));
963         artifact.setDescription(ARTIFACT_CREATED_FROM_CSAR);
964         artifact.setIsFromCsar(true);
965         artifact.setArtifactChecksum(GeneralUtility.calculateMD5Base64EncodedByByteArray(entry.getValue()));
966         return artifact;
967     }
968
969     public static final class NonMetaArtifactInfo {
970         private final String path;
971         private final String artifactName;
972         private final String displayName;
973         private final String artifactLabel;
974         private final ArtifactTypeEnum artifactType;
975         private final ArtifactGroupTypeEnum artifactGroupType;
976         private String payloadData;
977         private String artifactChecksum;
978         private String artifactUniqueId;
979         private final boolean isFromCsar;
980
981         public NonMetaArtifactInfo(String artifactName, String path, ArtifactTypeEnum artifactType, ArtifactGroupTypeEnum artifactGroupType, byte[] payloadData, String artifactUniqueId, boolean isFromCsar) {
982             super();
983             this.path = path;
984             this.isFromCsar = isFromCsar;
985             this.artifactName = ValidationUtils.normalizeFileName(artifactName);
986             this.artifactType = artifactType;
987             this.artifactGroupType = artifactGroupType;
988             final int pointIndex = artifactName.lastIndexOf('.');
989             if (pointIndex > 0) {
990                 displayName = artifactName.substring(0, pointIndex);
991             } else {
992                 displayName = artifactName;
993             }
994             this.artifactLabel = ValidationUtils.normalizeArtifactLabel(artifactName);
995             if (payloadData != null) {
996                 this.payloadData = Base64.encodeBase64String(payloadData);
997                 this.artifactChecksum = GeneralUtility.calculateMD5Base64EncodedByByteArray(payloadData);
998             }
999             this.artifactUniqueId = artifactUniqueId;
1000         }
1001
1002         public String getPath() {
1003             return path;
1004         }
1005
1006         public String getArtifactName() {
1007             return artifactName;
1008         }
1009
1010         public ArtifactTypeEnum getArtifactType() {
1011             return artifactType;
1012         }
1013
1014         public String getDisplayName() {
1015             return displayName;
1016         }
1017
1018         public ArtifactGroupTypeEnum getArtifactGroupType() {
1019             return artifactGroupType;
1020         }
1021
1022         public String getArtifactLabel() {
1023             return artifactLabel;
1024         }
1025
1026         public boolean isFromCsar(){
1027             return isFromCsar;
1028         }
1029
1030         public String getPayloadData() {
1031             return payloadData;
1032         }
1033
1034         public String getArtifactChecksum() {
1035             return artifactChecksum;
1036         }
1037
1038         public String getArtifactUniqueId() {
1039             return artifactUniqueId;
1040         }
1041
1042         public void setArtifactUniqueId(String artifactUniqueId) {
1043             this.artifactUniqueId = artifactUniqueId;
1044         }
1045
1046     }
1047
1048     /**
1049      * This method checks the artifact GroupType & Artifact Type. <br>
1050      * if there is any problem warning messages are added to collectedWarningMessages
1051      *
1052      * @param artifactPath
1053      * @param collectedWarningMessages
1054      * @return
1055      */
1056     public static Either<NonMetaArtifactInfo, Boolean> validateNonMetaArtifact(String artifactPath, byte[] payloadData, Map<String, Set<List<String>>> collectedWarningMessages) {
1057         Either<NonMetaArtifactInfo, Boolean> ret;
1058         try {
1059             String[] parsedArtifactPath = artifactPath.split("/");
1060             // Validate Artifact Group Type
1061             Either<ArtifactGroupTypeEnum, Boolean> eitherGroupType = detectArtifactGroupType(parsedArtifactPath[1], collectedWarningMessages);
1062             if (eitherGroupType.isLeft()) {
1063                 final ArtifactGroupTypeEnum groupTypeEnum = eitherGroupType.left().value();
1064
1065                 // Validate Artifact Type
1066                 String artifactType = parsedArtifactPath[2];
1067                 artifactType = detectArtifactTypeVF(groupTypeEnum, artifactType, collectedWarningMessages);
1068
1069                 String artifactFileNameType = parsedArtifactPath[3];
1070                 ret = Either.left(new NonMetaArtifactInfo(artifactFileNameType, artifactPath, ArtifactTypeEnum.findType(artifactType), groupTypeEnum, payloadData, null, true));
1071
1072             } else {
1073                 ret = Either.right(eitherGroupType.right().value());
1074             }
1075         } catch (Exception e) {
1076             log.debug("detectArtifactGroupType failed with exception", e);
1077             ret = Either.right(false);
1078         }
1079         return ret;
1080
1081     }
1082
1083     private static String detectArtifactTypeVFC(ArtifactGroupTypeEnum artifactGroupType, String receivedTypeName, String parentVfName, Map<String, Set<List<String>>> collectedWarningMessages) {
1084         String warningMessage = "Warning - artifact type {} that was provided for VFC {} is not recognized.";
1085         return detectArtifactType(artifactGroupType, receivedTypeName, warningMessage, collectedWarningMessages, parentVfName);
1086     }
1087
1088     private static String detectArtifactTypeVF(ArtifactGroupTypeEnum artifactGroupType, String receivedTypeName, Map<String, Set<List<String>>> collectedWarningMessages) {
1089         String warningMessage = "Warning - artifact type {} that was provided for VF is not recognized.";
1090         return detectArtifactType(artifactGroupType, receivedTypeName, warningMessage, collectedWarningMessages);
1091     }
1092
1093     private static String detectArtifactType(ArtifactGroupTypeEnum artifactGroupType, String receivedTypeName, String warningMessage, Map<String, Set<List<String>>> collectedWarningMessages, String... arguments) {
1094
1095         ArtifactTypeEnum artifactType = ArtifactTypeEnum.findType(receivedTypeName);
1096         Map<String, ArtifactTypeConfig> resourceValidTypeArtifacts = null;
1097
1098         if(artifactGroupType != null){
1099             switch (artifactGroupType) {
1100                 case INFORMATIONAL:
1101                     resourceValidTypeArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration()
1102                                                                      .getResourceInformationalArtifacts();
1103                     break;
1104                 case DEPLOYMENT:
1105                     resourceValidTypeArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration()
1106                                                                      .getResourceDeploymentArtifacts();
1107                     break;
1108                 default:
1109                     break;
1110             }
1111         }
1112
1113         Set<String> validArtifactTypes = null;
1114         if(resourceValidTypeArtifacts != null){
1115             validArtifactTypes = resourceValidTypeArtifacts.keySet();
1116         }
1117
1118         if (validArtifactTypes == null || artifactType == null || !validArtifactTypes.contains(artifactType.getType())) {
1119             List<String> messageArguments = new ArrayList<>();
1120             messageArguments.add(receivedTypeName);
1121             messageArguments.addAll(Arrays.asList(arguments));
1122             if (!collectedWarningMessages.containsKey(warningMessage)) {
1123                 Set<List<String>> messageArgumentLists = new HashSet<>();
1124                 messageArgumentLists.add(messageArguments);
1125                 collectedWarningMessages.put(warningMessage, messageArgumentLists);
1126             } else {
1127                 collectedWarningMessages.get(warningMessage).add(messageArguments);
1128             }
1129         }
1130
1131         return artifactType == null ? ArtifactTypeEnum.OTHER.getType() : artifactType.getType();
1132     }
1133
1134     private Either<ZipOutputStream, ResponseFormat> writeAllFilesToCsar(Component mainComponent, CsarDefinition csarDefinition, ZipOutputStream zipstream, boolean isInCertificationRequest) throws IOException{
1135         ComponentArtifacts componentArtifacts = csarDefinition.getComponentArtifacts();
1136
1137         Either<ZipOutputStream, ResponseFormat> writeComponentArtifactsToSpecifiedPath = writeComponentArtifactsToSpecifiedPath(mainComponent, componentArtifacts, zipstream, ARTIFACTS_PATH, isInCertificationRequest);
1138
1139         if(writeComponentArtifactsToSpecifiedPath.isRight()){
1140             return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
1141         }
1142
1143         ComponentTypeArtifacts mainTypeAndCIArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
1144         writeComponentArtifactsToSpecifiedPath = writeArtifactsInfoToSpecifiedtPath(mainComponent, mainTypeAndCIArtifacts.getComponentArtifacts(), zipstream, ARTIFACTS_PATH, isInCertificationRequest);
1145
1146         if(writeComponentArtifactsToSpecifiedPath.isRight()){
1147             return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
1148         }
1149
1150         Map<String, ArtifactsInfo> componentInstancesArtifacts = mainTypeAndCIArtifacts.getComponentInstancesArtifacts();
1151         Set<String> keySet = componentInstancesArtifacts.keySet();
1152
1153         String currentPath = ARTIFACTS_PATH + RESOURCES_PATH;
1154         for (String keyAssetName : keySet) {
1155             ArtifactsInfo artifactsInfo = componentInstancesArtifacts.get(keyAssetName);
1156             String pathWithAssetName = currentPath + keyAssetName + "/";
1157             writeComponentArtifactsToSpecifiedPath = writeArtifactsInfoToSpecifiedtPath(mainComponent, artifactsInfo, zipstream, pathWithAssetName, isInCertificationRequest);
1158
1159             if(writeComponentArtifactsToSpecifiedPath.isRight()){
1160                 return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
1161             }
1162         }
1163         writeComponentArtifactsToSpecifiedPath = writeOperationsArtifactsToCsar(mainComponent, zipstream);
1164
1165         if (writeComponentArtifactsToSpecifiedPath.isRight()) {
1166             return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
1167         }
1168         return Either.left(zipstream);
1169     }
1170
1171     private Either<ZipOutputStream, ResponseFormat> writeOperationsArtifactsToCsar(Component component,
1172             ZipOutputStream zipstream) {
1173         if (component instanceof Service ) {
1174             return Either.left(zipstream);
1175         }
1176         if (Objects.isNull(((Resource) component).getInterfaces())) {
1177             log.debug("Component Name {}- no interfaces found", component.getNormalizedName());
1178             return Either.left(zipstream);
1179         }
1180         final Map<String, InterfaceDefinition> interfaces = ((Resource) component).getInterfaces();
1181
1182         for (Map.Entry<String, InterfaceDefinition> interfaceEntry : interfaces.entrySet()) {
1183             for (OperationDataDefinition operation : interfaceEntry.getValue().getOperations().values()) {
1184                 try {
1185                     if (Objects.isNull(operation.getImplementation())) {
1186                         log.debug("Component Name {}, Interface Id {}, Operation Name {} - no Operation Implementation found",
1187                                 component.getNormalizedName(), interfaceEntry.getValue().getUniqueId(),
1188                                 operation.getName());
1189                         continue;
1190                     }
1191                     if (Objects.isNull(operation.getImplementation().getArtifactName())) {
1192                         log.debug("Component Name {}, Interface Id {}, Operation Name {} - no artifact found",
1193                                 component.getNormalizedName(), interfaceEntry.getValue().getUniqueId(),
1194                                 operation.getName());
1195                         continue;
1196                     }
1197
1198                     final String artifactUUID = operation.getImplementation().getArtifactUUID();
1199
1200                     final Either<byte[], ActionStatus> artifactFromCassandra = getFromCassandra(artifactUUID);
1201                     final String artifactName = operation.getImplementation().getArtifactName();
1202                     if (artifactFromCassandra.isRight()) {
1203                         log.error("ArtifactName {}, unique ID {}", artifactName, artifactUUID);
1204                         log.error("Failed to get {} payload from DB reason: {}", artifactName,
1205                                 artifactFromCassandra.right().value());
1206                         return Either.right(componentsUtils.getResponseFormat(
1207                                 ActionStatus.ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION, "Resource",
1208                                 component.getUniqueId(), artifactName, artifactUUID));
1209                     }
1210
1211                     final byte[] payloadData = artifactFromCassandra.left().value();
1212                     zipstream.putNextEntry(new ZipEntry(OperationArtifactUtil.createOperationArtifactPath(
1213                             component.getNormalizedName(), interfaceEntry.getValue().getToscaResourceName(), operation)));
1214                     zipstream.write(payloadData);
1215
1216                 } catch (IOException e) {
1217                     log.error("Component Name {},  Interface Name {}, Operation Name {}", component.getNormalizedName(),
1218                             interfaceEntry.getKey(), operation.getName());
1219                     log.error("Error while writing the operation's artifacts to the CSAR " + "{}", e);
1220                     return Either.right(componentsUtils
1221                                                 .getResponseFormat(ActionStatus.ERROR_DURING_CSAR_CREATION, "Resource",
1222                                                         component.getUniqueId()));
1223                 }
1224             }
1225         }
1226         return Either.left(zipstream);
1227
1228     }
1229
1230     private Either<ZipOutputStream, ResponseFormat> writeComponentArtifactsToSpecifiedPath(Component mainComponent, ComponentArtifacts componentArtifacts, ZipOutputStream zipstream,
1231             String currentPath, boolean isInCertificationRequest) throws IOException {
1232         Map<String, ComponentTypeArtifacts> componentTypeArtifacts = componentArtifacts.getComponentTypeArtifacts();
1233         //Keys are defined:
1234         //<Inner Asset TOSCA name (e.g. VFC name)> folder name: <Inner Asset TOSCA name (e.g. VFC name)>_v<version>.
1235         //E.g. "org.openecomp.resource.vf.vipr_atm_v1.0"
1236         Set<String> componentTypeArtifactsKeys = componentTypeArtifacts.keySet();
1237         for (String keyAssetName : componentTypeArtifactsKeys) {
1238             ComponentTypeArtifacts componentInstanceArtifacts = componentTypeArtifacts.get(keyAssetName);
1239             ArtifactsInfo componentArtifacts2 = componentInstanceArtifacts.getComponentArtifacts();
1240             String pathWithAssetName = currentPath + keyAssetName + "/";
1241             Either<ZipOutputStream, ResponseFormat> writeArtifactsInfoToSpecifiedtPath = writeArtifactsInfoToSpecifiedtPath(mainComponent, componentArtifacts2, zipstream, pathWithAssetName, isInCertificationRequest);
1242
1243             if(writeArtifactsInfoToSpecifiedtPath.isRight()){
1244                 return writeArtifactsInfoToSpecifiedtPath;
1245             }
1246         }
1247
1248         return Either.left(zipstream);
1249     }
1250
1251     private Either<ZipOutputStream, ResponseFormat> writeArtifactsInfoToSpecifiedtPath(Component mainComponent, ArtifactsInfo currArtifactsInfo, ZipOutputStream zip, String path, boolean isInCertificationRequest) throws IOException {
1252         Map<ArtifactGroupTypeEnum, Map<ArtifactTypeEnum, List<ArtifactDefinition>>> artifactsInfo = currArtifactsInfo
1253                                                                                                             .getArtifactsInfo();
1254         Set<ArtifactGroupTypeEnum> groupTypeEnumKeySet = artifactsInfo.keySet();
1255
1256         for (ArtifactGroupTypeEnum artifactGroupTypeEnum : groupTypeEnumKeySet) {
1257             String groupTypeFolder = path + WordUtils.capitalizeFully(artifactGroupTypeEnum.getType()) + "/";
1258
1259             Map<ArtifactTypeEnum, List<ArtifactDefinition>> artifactTypesMap = artifactsInfo.get(artifactGroupTypeEnum);
1260             Set<ArtifactTypeEnum> artifactTypeEnumKeySet = artifactTypesMap.keySet();
1261
1262             for (ArtifactTypeEnum artifactTypeEnum : artifactTypeEnumKeySet) {
1263                 List<ArtifactDefinition> artifactDefinitionList = artifactTypesMap.get(artifactTypeEnum);
1264                 String artifactTypeFolder = groupTypeFolder + artifactTypeEnum.toString() + "/";
1265
1266                 Either<ZipOutputStream, ResponseFormat> writeArtifactDefinition = writeArtifactDefinition(mainComponent, zip, artifactDefinitionList, artifactTypeFolder, isInCertificationRequest);
1267
1268                 if(writeArtifactDefinition.isRight()){
1269                     return writeArtifactDefinition;
1270                 }
1271             }
1272         }
1273
1274         return Either.left(zip);
1275     }
1276
1277     private Either<ZipOutputStream, ResponseFormat> writeArtifactDefinition(Component mainComponent, ZipOutputStream zip, List<ArtifactDefinition> artifactDefinitionList,
1278             String artifactPathAndFolder, boolean isInCertificationRequest) throws IOException {
1279
1280         ComponentTypeEnum componentType = mainComponent.getComponentType();
1281         String heatEnvType = ArtifactTypeEnum.HEAT_ENV.getType();
1282
1283         for (ArtifactDefinition artifactDefinition : artifactDefinitionList) {
1284             if (!isInCertificationRequest && componentType == ComponentTypeEnum.SERVICE
1285                         && artifactDefinition.getArtifactType().equals(heatEnvType) ||
1286                         //this is placeholder
1287                         (artifactDefinition.getEsId() == null && artifactDefinition.getMandatory())){
1288                 continue;
1289             }
1290
1291             byte[] payloadData = artifactDefinition.getPayloadData();
1292             String artifactFileName = artifactDefinition.getArtifactName();
1293
1294             if (payloadData == null) {
1295                 Either<byte[], ActionStatus> fromCassandra = getFromCassandra(artifactDefinition.getEsId());
1296
1297                 if (fromCassandra.isRight()) {
1298                     log.debug("ArtifactName {}, unique ID {}", artifactDefinition.getArtifactName(), artifactDefinition.getUniqueId());
1299                     log.debug("Failed to get {} payload from DB reason: {}", artifactFileName, fromCassandra.right().value());
1300                     continue;
1301                 }
1302                 payloadData = fromCassandra.left().value();
1303             }
1304             zip.putNextEntry(new ZipEntry(artifactPathAndFolder + artifactFileName));
1305             zip.write(payloadData);
1306         }
1307
1308         return Either.left(zip);
1309     }
1310
1311     /************************************ Artifacts Structure ******************************************************************/
1312     /**
1313      * The artifacts Definition saved by their structure
1314      */
1315     private class ArtifactsInfo {
1316         //Key is the type of artifacts(Informational/Deployment)
1317         //Value is a map between an artifact type and a list of all artifacts of this type
1318         private Map<ArtifactGroupTypeEnum, Map<ArtifactTypeEnum, List<ArtifactDefinition>>> artifactsInfoField;
1319
1320         public ArtifactsInfo() {
1321             this.artifactsInfoField = new EnumMap<>(ArtifactGroupTypeEnum.class);
1322         }
1323
1324         public Map<ArtifactGroupTypeEnum, Map<ArtifactTypeEnum, List<ArtifactDefinition>>> getArtifactsInfo() {
1325             return artifactsInfoField;
1326         }
1327
1328         public List<ArtifactDefinition> getFlatArtifactsListByType(ArtifactTypeEnum artifactType){
1329             List<ArtifactDefinition> artifacts = new ArrayList<>();
1330             for (List<ArtifactDefinition> artifactsByType:artifactsInfoField.get(artifactType).values()){
1331                 artifacts.addAll(artifactsByType);
1332             }
1333             return artifacts;
1334         }
1335
1336         public void addArtifactsToGroup(ArtifactGroupTypeEnum artifactGroup,Map<ArtifactTypeEnum, List<ArtifactDefinition>> artifactsDefinition){
1337             artifactsInfoField.put(artifactGroup, artifactsDefinition);
1338         }
1339
1340         public boolean isEmpty() {
1341             return artifactsInfoField.isEmpty();
1342         }
1343
1344     }
1345
1346     /**
1347      * The artifacts of the component and of all its composed instances
1348      *
1349      */
1350     private class ComponentTypeArtifacts {
1351         private ArtifactsInfo componentArtifacts;    //component artifacts (describes the Informational Deployment folders)
1352         private Map<String, ArtifactsInfo> componentInstancesArtifacts;        //artifacts of the composed instances mapped by the resourceInstance normalized name (describes the Resources folder)
1353
1354         public ComponentTypeArtifacts() {
1355             componentArtifacts = new ArtifactsInfo();
1356             componentInstancesArtifacts = new HashMap<>();
1357         }
1358
1359         public ArtifactsInfo getComponentArtifacts() {
1360             return componentArtifacts;
1361         }
1362         public void setComponentArtifacts(ArtifactsInfo artifactsInfo) {
1363             this.componentArtifacts = artifactsInfo;
1364         }
1365         public Map<String, ArtifactsInfo> getComponentInstancesArtifacts() {
1366             return componentInstancesArtifacts;
1367         }
1368         public void setComponentInstancesArtifacts(Map<String, ArtifactsInfo> componentInstancesArtifacts) {
1369             this.componentInstancesArtifacts = componentInstancesArtifacts;
1370         }
1371
1372         public void addComponentInstancesArtifacts(String normalizedName, ArtifactsInfo artifactsInfo) {
1373             componentInstancesArtifacts.put(normalizedName, artifactsInfo);
1374         }
1375
1376     }
1377
1378     private class ComponentArtifacts {
1379         //artifacts of the component and CI's artifacts contained in it's composition (represents Informational, Deployment & Resource folders of main component)
1380         private ComponentTypeArtifacts mainTypeAndCIArtifacts;
1381         //artifacts of all component types mapped by their tosca name
1382         private Map<String, ComponentTypeArtifacts> componentTypeArtifacts;
1383
1384         public ComponentArtifacts(){
1385             mainTypeAndCIArtifacts = new ComponentTypeArtifacts();
1386             componentTypeArtifacts = new HashMap<>();
1387         }
1388
1389         public ComponentTypeArtifacts getMainTypeAndCIArtifacts() {
1390             return mainTypeAndCIArtifacts;
1391         }
1392
1393         public void setMainTypeAndCIArtifacts(ComponentTypeArtifacts componentInstanceArtifacts) {
1394             this.mainTypeAndCIArtifacts = componentInstanceArtifacts;
1395         }
1396
1397         public Map<String, ComponentTypeArtifacts> getComponentTypeArtifacts() {
1398             return componentTypeArtifacts;
1399         }
1400
1401         public void setComponentTypeArtifacts(Map<String, ComponentTypeArtifacts> componentTypeArtifacts) {
1402             this.componentTypeArtifacts = componentTypeArtifacts;
1403         }
1404     }
1405
1406     private class CsarDefinition {
1407         private ComponentArtifacts componentArtifacts;
1408
1409         // add list of tosca artifacts and meta describes CSAR zip root
1410
1411         public CsarDefinition(ComponentArtifacts componentArtifacts) {
1412             this.componentArtifacts = componentArtifacts;
1413         }
1414
1415         public ComponentArtifacts getComponentArtifacts() {
1416             return componentArtifacts;
1417         }
1418     }
1419
1420     /************************************ Artifacts Structure END******************************************************************/
1421
1422     private Either<CsarDefinition,ResponseFormat> collectComponentCsarDefinition(Component component){
1423         ComponentArtifacts componentArtifacts = new ComponentArtifacts();
1424         Component updatedComponent = component;
1425
1426         //get service to receive the AII artifacts uploaded to the service
1427         if (updatedComponent.getComponentType() == ComponentTypeEnum.SERVICE) {
1428             Either<Service, StorageOperationStatus> getServiceResponse = toscaOperationFacade.getToscaElement(updatedComponent.getUniqueId());
1429
1430             if(getServiceResponse.isRight()){
1431                 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getServiceResponse.right().value());
1432                 return Either.right(componentsUtils.getResponseFormat(actionStatus));
1433             }
1434
1435             updatedComponent = getServiceResponse.left().value();
1436         }
1437
1438         //find the artifacts of the main component, it would have its composed instances artifacts in a separate folder
1439         ComponentTypeArtifacts componentInstanceArtifacts = new ComponentTypeArtifacts();
1440         ArtifactsInfo artifactsInfo = collectComponentArtifacts(updatedComponent);
1441         componentInstanceArtifacts.setComponentArtifacts(artifactsInfo);
1442         componentArtifacts.setMainTypeAndCIArtifacts(componentInstanceArtifacts);
1443
1444         Map<String,ComponentTypeArtifacts> resourceTypeArtifacts = componentArtifacts.getComponentTypeArtifacts();    //artifacts mapped by the component type(tosca name+version)
1445         //get the component instances
1446         List<ComponentInstance> componentInstances = updatedComponent.getComponentInstances();
1447         if (componentInstances!=null){
1448             for (ComponentInstance componentInstance:componentInstances){
1449                 //call recursive to find artifacts for all the path
1450                 Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts = collectComponentInstanceArtifacts(
1451                         updatedComponent, componentInstance, resourceTypeArtifacts, componentInstanceArtifacts);
1452                 if (collectComponentInstanceArtifacts.isRight()){
1453                     return Either.right(collectComponentInstanceArtifacts.right().value());
1454                 }
1455             }
1456         }
1457
1458         if(log.isDebugEnabled()){
1459             printResult(componentArtifacts,updatedComponent.getName());
1460         }
1461
1462         return Either.left(new CsarDefinition(componentArtifacts));
1463     }
1464
1465     private void printResult(ComponentArtifacts componentArtifacts, String name) {
1466         StringBuilder result = new StringBuilder();
1467         result.append("Artifacts of main component " + name + "\n");
1468         ComponentTypeArtifacts componentInstanceArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
1469         printArtifacts(componentInstanceArtifacts);
1470         result.append("Type Artifacts\n");
1471         for (Map.Entry<String, ComponentTypeArtifacts> typeArtifacts:componentArtifacts.getComponentTypeArtifacts().entrySet()){
1472             result.append("Folder " + typeArtifacts.getKey() + "\n");
1473             result.append(printArtifacts(typeArtifacts.getValue()));
1474         }
1475
1476         if(log.isDebugEnabled()){
1477             log.debug(result.toString());
1478         }
1479     }
1480
1481     private String printArtifacts(ComponentTypeArtifacts componentInstanceArtifacts) {
1482         StringBuilder result = new StringBuilder();
1483         ArtifactsInfo artifactsInfo = componentInstanceArtifacts.getComponentArtifacts();
1484         Map<ArtifactGroupTypeEnum, Map<ArtifactTypeEnum, List<ArtifactDefinition>>> componetArtifacts = artifactsInfo.getArtifactsInfo();
1485         printArtifacts(componetArtifacts);
1486         result = result.append("Resources\n");
1487         for (Map.Entry<String, ArtifactsInfo> resourceInstance:componentInstanceArtifacts.getComponentInstancesArtifacts().entrySet()){
1488             result.append("Folder" + resourceInstance.getKey() + "\n");
1489             result.append(printArtifacts(resourceInstance.getValue().getArtifactsInfo()));
1490         }
1491
1492         return result.toString();
1493     }
1494
1495     private String  printArtifacts(Map<ArtifactGroupTypeEnum, Map<ArtifactTypeEnum, List<ArtifactDefinition>>> componetArtifacts) {
1496         StringBuilder result = new StringBuilder();
1497         for (Map.Entry<ArtifactGroupTypeEnum, Map<ArtifactTypeEnum, List<ArtifactDefinition>>> artifactGroup:componetArtifacts.entrySet()){
1498             result.append("    " + artifactGroup.getKey().getType());
1499             for (Map.Entry<ArtifactTypeEnum, List<ArtifactDefinition>> groupArtifacts:artifactGroup.getValue().entrySet()){
1500                 result.append("        " + groupArtifacts.getKey().getType());
1501                 for (ArtifactDefinition artifact:groupArtifacts.getValue()){
1502                     result.append("            " + artifact.getArtifactDisplayName());
1503                 }
1504             }
1505         }
1506
1507         return result.toString();
1508     }
1509
1510     private ComponentTypeArtifacts collectComponentTypeArtifacts(Map<String, ComponentTypeArtifacts> resourcesArtifacts, ComponentInstance componentInstance,
1511             Resource fetchedComponent) {
1512         String toscaComponentName = componentInstance.getToscaComponentName() + "_v" + componentInstance.getComponentVersion();
1513
1514         ComponentTypeArtifacts componentArtifactsInfo = resourcesArtifacts.get(toscaComponentName);
1515         //if there are no artifacts for this component type we need to fetch and build them
1516         if (componentArtifactsInfo==null){
1517             ArtifactsInfo componentArtifacts = collectComponentArtifacts(fetchedComponent);
1518             componentArtifactsInfo = new ComponentTypeArtifacts();
1519             if (!componentArtifacts.isEmpty()){
1520                 componentArtifactsInfo.setComponentArtifacts(componentArtifacts);
1521                 resourcesArtifacts.put(toscaComponentName, componentArtifactsInfo);
1522             }
1523         }
1524         return componentArtifactsInfo;
1525     }
1526
1527     private Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts(Component parentComponent,ComponentInstance componentInstance,
1528             Map<String, ComponentTypeArtifacts> resourcesTypeArtifacts,ComponentTypeArtifacts instanceArtifactsLocation) {
1529         //1. get the component instance component
1530         String componentUid = componentInstance.getComponentUid();
1531         Either<Resource, StorageOperationStatus> resource = toscaOperationFacade.getToscaElement(componentUid);
1532         if (resource.isRight()) {
1533             log.error("Failed to fetch resource with id {} for instance {}",componentUid, parentComponent.getUUID());
1534             return Either.right(componentsUtils.getResponseFormat(ActionStatus.ASSET_NOT_FOUND_DURING_CSAR_CREATION,
1535                     parentComponent.getComponentType().getValue(), parentComponent.getUUID(),
1536                     componentInstance.getOriginType().getComponentType().getValue(), componentUid));
1537         }
1538         Resource fetchedComponent = resource.left().value();
1539
1540         //2. fill the artifacts for the current component parent type
1541         ComponentTypeArtifacts componentParentArtifacts = collectComponentTypeArtifacts(resourcesTypeArtifacts, componentInstance, fetchedComponent);
1542
1543         //3. find the artifacts specific to the instance
1544         Map<ArtifactTypeEnum, List<ArtifactDefinition>> componentInstanceSpecificInformationalArtifacts =
1545                 getComponentInstanceSpecificArtifacts(componentInstance.getArtifacts(),
1546                         componentParentArtifacts.getComponentArtifacts().getArtifactsInfo(), ArtifactGroupTypeEnum.INFORMATIONAL);
1547         Map<ArtifactTypeEnum, List<ArtifactDefinition>> componentInstanceSpecificDeploymentArtifacts =
1548                 getComponentInstanceSpecificArtifacts(componentInstance.getDeploymentArtifacts(),
1549                         componentParentArtifacts.getComponentArtifacts().getArtifactsInfo(), ArtifactGroupTypeEnum.DEPLOYMENT);
1550
1551         //4. add the instances artifacts to the component type
1552         ArtifactsInfo artifactsInfo = new ArtifactsInfo();
1553         if (!componentInstanceSpecificInformationalArtifacts.isEmpty()){
1554             artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.INFORMATIONAL, componentInstanceSpecificInformationalArtifacts);
1555         }
1556         if (!componentInstanceSpecificDeploymentArtifacts.isEmpty()){
1557             artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.DEPLOYMENT, componentInstanceSpecificDeploymentArtifacts);
1558         }
1559         if (!artifactsInfo.isEmpty()){
1560             instanceArtifactsLocation.addComponentInstancesArtifacts(componentInstance.getNormalizedName(), artifactsInfo);
1561         }
1562
1563         //5. do the same for all the component instances
1564         List<ComponentInstance> componentInstances = fetchedComponent.getComponentInstances();
1565         if (componentInstances!=null){
1566             for (ComponentInstance childComponentInstance:componentInstances){
1567                 Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts = collectComponentInstanceArtifacts(
1568                         fetchedComponent, childComponentInstance, resourcesTypeArtifacts, componentParentArtifacts);
1569                 if (collectComponentInstanceArtifacts.isRight()){
1570                     return collectComponentInstanceArtifacts;
1571                 }
1572             }
1573         }
1574
1575         return Either.left(true);
1576     }
1577
1578     private Map<ArtifactTypeEnum, List<ArtifactDefinition>> getComponentInstanceSpecificArtifacts(Map<String, ArtifactDefinition> componentArtifacts,
1579             Map<ArtifactGroupTypeEnum, Map<ArtifactTypeEnum, List<ArtifactDefinition>>> componentTypeArtifacts, ArtifactGroupTypeEnum artifactGroupTypeEnum) {
1580         Map<ArtifactTypeEnum, List<ArtifactDefinition>> parentArtifacts = componentTypeArtifacts.get(artifactGroupTypeEnum);    //the artfiacts of the component itself and not the instance
1581
1582         Map<ArtifactTypeEnum, List<ArtifactDefinition>> artifactsByTypeOfComponentInstance = new EnumMap<>(ArtifactTypeEnum.class);
1583         if (componentArtifacts!=null){
1584             for (ArtifactDefinition artifact:componentArtifacts.values()){
1585                 ArtifactTypeEnum artifactType = ArtifactTypeEnum.findType(artifact.getArtifactType());
1586                 List<ArtifactDefinition> parentArtifactsByType = null;
1587                 if (parentArtifacts!=null){
1588                     parentArtifactsByType = parentArtifacts.get(artifactType);
1589                 }
1590                 //the artifact is of instance
1591                 if (parentArtifactsByType == null || !parentArtifactsByType.contains(artifact)){
1592                     List<ArtifactDefinition> typeArtifacts = artifactsByTypeOfComponentInstance.get(artifactType);
1593                     if (typeArtifacts == null){
1594                         typeArtifacts = new ArrayList<>();
1595                         artifactsByTypeOfComponentInstance.put(artifactType, typeArtifacts);
1596                     }
1597                     typeArtifacts.add(artifact);
1598                 }
1599             }
1600         }
1601
1602         return artifactsByTypeOfComponentInstance;
1603     }
1604
1605     private ArtifactsInfo collectComponentArtifacts(Component component) {
1606         Map<String, ArtifactDefinition> informationalArtifacts = component.getArtifacts();
1607         Map<ArtifactTypeEnum, List<ArtifactDefinition>> informationalArtifactsByType = collectGroupArtifacts(informationalArtifacts);
1608         Map<String, ArtifactDefinition> deploymentArtifacts = component.getDeploymentArtifacts();
1609         Map<ArtifactTypeEnum, List<ArtifactDefinition>> deploymentArtifactsByType = collectGroupArtifacts(deploymentArtifacts);
1610         ArtifactsInfo artifactsInfo = new ArtifactsInfo();
1611         if (!informationalArtifactsByType.isEmpty()){
1612             artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.INFORMATIONAL, informationalArtifactsByType);
1613         }
1614         if (!deploymentArtifactsByType.isEmpty() ){
1615             artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.DEPLOYMENT, deploymentArtifactsByType);
1616         }
1617
1618         return artifactsInfo;
1619     }
1620
1621     private Map<ArtifactTypeEnum, List<ArtifactDefinition>> collectGroupArtifacts(Map<String, ArtifactDefinition> componentArtifacts) {
1622         Map<ArtifactTypeEnum, List<ArtifactDefinition>> artifactsByType = new EnumMap<>(ArtifactTypeEnum.class);
1623         for (ArtifactDefinition artifact:componentArtifacts.values()){
1624             if (artifact.getArtifactUUID()!=null){
1625                 ArtifactTypeEnum artifactType = ArtifactTypeEnum.findType(artifact.getArtifactType());
1626                 List<ArtifactDefinition> typeArtifacts = artifactsByType.get(artifactType);
1627                 if (typeArtifacts==null){
1628                     typeArtifacts = new ArrayList<>();
1629                     artifactsByType.put(artifactType, typeArtifacts);
1630                 }
1631                 typeArtifacts.add(artifact);
1632             }
1633         }
1634         return artifactsByType;
1635     }
1636 }