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