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