Remove generation of csar.meta
[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 package org.openecomp.sdc.be.tosca;
21
22 import fj.F;
23 import fj.data.Either;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.EnumMap;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Map.Entry;
33 import java.util.Optional;
34 import java.util.Set;
35 import java.util.regex.Pattern;
36 import java.util.zip.ZipOutputStream;
37 import lombok.Getter;
38 import lombok.Setter;
39 import org.apache.commons.codec.binary.Base64;
40 import org.apache.commons.collections.MapUtils;
41 import org.apache.commons.io.output.ByteArrayOutputStream;
42 import org.apache.commons.lang3.tuple.ImmutablePair;
43 import org.openecomp.sdc.be.components.impl.ImportUtils;
44 import org.openecomp.sdc.be.config.ArtifactConfigManager;
45 import org.openecomp.sdc.be.config.ArtifactConfiguration;
46 import org.openecomp.sdc.be.config.ComponentType;
47 import org.openecomp.sdc.be.dao.api.ActionStatus;
48 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
49 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
50 import org.openecomp.sdc.be.impl.ComponentsUtils;
51 import org.openecomp.sdc.be.model.ArtifactDefinition;
52 import org.openecomp.sdc.be.model.Component;
53 import org.openecomp.sdc.be.model.ComponentInstance;
54 import org.openecomp.sdc.be.model.Service;
55 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
56 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
57 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
58 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
59 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
60 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
61 import org.openecomp.sdc.common.log.enums.StatusCode;
62 import org.openecomp.sdc.common.log.wrappers.Logger;
63 import org.openecomp.sdc.common.util.GeneralUtility;
64 import org.openecomp.sdc.common.util.ValidationUtils;
65 import org.openecomp.sdc.exception.ResponseFormat;
66 import org.springframework.beans.factory.annotation.Autowired;
67
68 @org.springframework.stereotype.Component("csar-utils")
69 public class CsarUtils {
70
71     public static final String ARTIFACTS_PATH = "Artifacts/";
72     public static final String ARTIFACTS = "Artifacts";
73     public static final String ARTIFACT_CREATED_FROM_CSAR = "Artifact created from csar";
74     private static final Logger log = Logger.getLogger(CsarUtils.class);
75     private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(CsarUtils.class.getName());
76     private static final String PATH_DELIMITER = "/";
77     private static final String DEFINITION = "Definitions";
78     private static final String DEL_PATTERN = "([/\\\\]+)";
79     private static final String WORD_PATTERN = "\\w\\_\\@\\-\\.\\s]+)";
80     public static final String VALID_ENGLISH_ARTIFACT_NAME = "([" + WORD_PATTERN;
81     public static final String VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN = ARTIFACTS + DEL_PATTERN +
82         // Artifact Group (i.e Deployment/Informational)
83         VALID_ENGLISH_ARTIFACT_NAME + DEL_PATTERN +
84         // Artifact Type
85         VALID_ENGLISH_ARTIFACT_NAME + DEL_PATTERN +
86         // Artifact Any File Name
87         ".+";
88     public static final String SERVICE_TEMPLATE_PATH_PATTERN = DEFINITION + DEL_PATTERN +
89         // Service Template File Name
90         VALID_ENGLISH_ARTIFACT_NAME;
91     private static final String VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS = "([\\d" + WORD_PATTERN;
92     private static final String VFC_NODE_TYPE_ARTIFACTS_PATH_PATTERN =
93         ARTIFACTS + DEL_PATTERN + ImportUtils.Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS + DEL_PATTERN
94             + VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS + DEL_PATTERN + VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS + DEL_PATTERN
95             + VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS;
96
97     private final ToscaOperationFacade toscaOperationFacade;
98     private final ComponentsUtils componentsUtils;
99     private final MapFromModelCsarGeneratorService mapFromModelCsarGeneratorService;
100
101     @Autowired
102     public CsarUtils(final ToscaOperationFacade toscaOperationFacade,
103                      final ComponentsUtils componentsUtils,
104                      final MapFromModelCsarGeneratorService mapFromModelCsarGeneratorService) {
105         this.toscaOperationFacade = toscaOperationFacade;
106         this.componentsUtils = componentsUtils;
107         this.mapFromModelCsarGeneratorService = mapFromModelCsarGeneratorService;
108     }
109
110     /**
111      * Extracts artifacts of VFCs from CSAR
112      *
113      * @param csar
114      * @return Map of <String, List<ArtifactDefinition>> the contains Lists of artifacts according vfcToscaNamespace
115      */
116     public static Map<String, List<ArtifactDefinition>> extractVfcsArtifactsFromCsar(Map<String, byte[]> csar) {
117         Map<String, List<ArtifactDefinition>> artifacts = new HashMap<>();
118         if (csar != null) {
119             log.debug("************* Going to extract VFCs artifacts from Csar. ");
120             Map<String, Set<List<String>>> collectedWarningMessages = new HashMap<>();
121             csar.entrySet().stream()
122                 // filter CSAR entry by node type artifact path
123                 .filter(e -> Pattern.compile(VFC_NODE_TYPE_ARTIFACTS_PATH_PATTERN).matcher(e.getKey()).matches())
124                 // extract ArtifactDefinition from CSAR entry for each entry with matching artifact path
125                 .forEach(e -> extractVfcArtifact(e, collectedWarningMessages).ifPresent(ip -> addExtractedVfcArtifact(ip, artifacts)));
126             // add counter suffix to artifact labels
127             handleWarningMessages(collectedWarningMessages);
128         }
129         return artifacts;
130     }
131
132     /**
133      * Print warnings to log
134      *
135      * @param collectedWarningMessages
136      */
137     public static void handleWarningMessages(Map<String, Set<List<String>>> collectedWarningMessages) {
138         collectedWarningMessages.entrySet().stream()
139             // for each vfc
140             .forEach(e -> e.getValue().stream()
141                 // add each warning message to log
142                 .forEach(args -> log.warn(e.getKey(), args.toArray())));
143     }
144
145     private static void addExtractedVfcArtifact(ImmutablePair<String, ArtifactDefinition> extractedVfcArtifact,
146                                                 Map<String, List<ArtifactDefinition>> artifacts) {
147         String vfcToscaNamespace = extractedVfcArtifact.getKey();
148         artifacts.computeIfAbsent(vfcToscaNamespace, k -> new ArrayList<>());
149         artifacts.get(vfcToscaNamespace).add(extractedVfcArtifact.getValue());
150     }
151
152     private static Optional<ImmutablePair<String, ArtifactDefinition>> extractVfcArtifact(Entry<String, byte[]> entry,
153                                                                                           Map<String, Set<List<String>>> collectedWarningMessages) {
154         String[] parsedCsarArtifactPath = entry.getKey().split(PATH_DELIMITER);
155         String groupType = parsedCsarArtifactPath[2].toUpperCase();
156         return detectArtifactGroupType(groupType, collectedWarningMessages).left()
157             .map(buildArtifactDefinitionFromCsarArtifactPath(entry, collectedWarningMessages, parsedCsarArtifactPath))
158             .either(ad -> Optional.of(new ImmutablePair<>(parsedCsarArtifactPath[1], ad)), b -> Optional.empty());
159     }
160
161     private static Either<ArtifactGroupTypeEnum, Boolean> detectArtifactGroupType(String groupType,
162                                                                                   Map<String, Set<List<String>>> collectedWarningMessages) {
163         Either<ArtifactGroupTypeEnum, Boolean> result;
164         try {
165             ArtifactGroupTypeEnum artifactGroupType = ArtifactGroupTypeEnum.findType(groupType.toUpperCase());
166             if (artifactGroupType == null || (artifactGroupType != ArtifactGroupTypeEnum.INFORMATIONAL
167                 && artifactGroupType != ArtifactGroupTypeEnum.DEPLOYMENT)) {
168                 String warningMessage = "Warning - unrecognized artifact group type {} was received.";
169                 List<String> messageArguments = new ArrayList<>();
170                 messageArguments.add(groupType);
171                 if (!collectedWarningMessages.containsKey(warningMessage)) {
172                     Set<List<String>> messageArgumentLists = new HashSet<>();
173                     messageArgumentLists.add(messageArguments);
174                     collectedWarningMessages.put(warningMessage, messageArgumentLists);
175                 } else {
176                     collectedWarningMessages.get(warningMessage).add(messageArguments);
177                 }
178                 result = Either.right(false);
179             } else {
180                 result = Either.left(artifactGroupType);
181             }
182         } catch (Exception e) {
183             log.debug("detectArtifactGroupType failed with exception", e);
184             result = Either.right(false);
185         }
186         return result;
187     }
188
189     private static F<ArtifactGroupTypeEnum, ArtifactDefinition> buildArtifactDefinitionFromCsarArtifactPath(Entry<String, byte[]> entry,
190                                                                                                             Map<String, Set<List<String>>> collectedWarningMessages,
191                                                                                                             String[] parsedCsarArtifactPath) {
192         return artifactGroupType -> {
193             ArtifactDefinition artifact;
194             artifact = new ArtifactDefinition();
195             artifact.setArtifactGroupType(artifactGroupType);
196             artifact.setArtifactType(
197                 detectArtifactTypeVFC(artifactGroupType, parsedCsarArtifactPath[3], parsedCsarArtifactPath[1], collectedWarningMessages));
198             artifact.setArtifactName(ValidationUtils.normalizeFileName(parsedCsarArtifactPath[parsedCsarArtifactPath.length - 1]));
199             artifact.setPayloadData(Base64.encodeBase64String(entry.getValue()));
200             artifact.setArtifactDisplayName(
201                 artifact.getArtifactName().lastIndexOf('.') > 0 ? artifact.getArtifactName().substring(0, artifact.getArtifactName().lastIndexOf('.'))
202                     : artifact.getArtifactName());
203             artifact.setArtifactLabel(ValidationUtils.normalizeArtifactLabel(artifact.getArtifactName()));
204             artifact.setDescription(ARTIFACT_CREATED_FROM_CSAR);
205             artifact.setIsFromCsar(true);
206             artifact.setArtifactChecksum(GeneralUtility.calculateMD5Base64EncodedByByteArray(entry.getValue()));
207             return artifact;
208         };
209     }
210
211     /**
212      * This method checks the artifact GroupType & Artifact Type. <br> if there is any problem warning messages are added to collectedWarningMessages
213      *
214      * @param artifactPath
215      * @param collectedWarningMessages
216      * @return
217      */
218     public static Either<NonMetaArtifactInfo, Boolean> validateNonMetaArtifact(String artifactPath, byte[] payloadData,
219                                                                                Map<String, Set<List<String>>> collectedWarningMessages) {
220         try {
221             String[] parsedArtifactPath = artifactPath.split(PATH_DELIMITER);
222             String groupType = parsedArtifactPath[1];
223             String receivedTypeName = parsedArtifactPath[2];
224             String artifactFileNameType = parsedArtifactPath[3];
225             return detectArtifactGroupType(groupType, collectedWarningMessages).left().bind(artifactGroupType -> {
226                 String artifactType = detectArtifactTypeVF(artifactGroupType, receivedTypeName, collectedWarningMessages);
227                 return Either
228                     .left(new NonMetaArtifactInfo(artifactFileNameType, artifactPath, artifactType, artifactGroupType, payloadData, null, true));
229             });
230         } catch (Exception e) {
231             log.debug("detectArtifactGroupType failed with exception", e);
232             return Either.right(false);
233         }
234     }
235
236     private static String detectArtifactTypeVFC(ArtifactGroupTypeEnum artifactGroupType, String receivedTypeName, String parentVfName,
237                                                 Map<String, Set<List<String>>> collectedWarningMessages) {
238         String warningMessage = "Warning - artifact type {} that was provided for VFC {} is not recognized.";
239         return detectArtifactType(artifactGroupType, receivedTypeName, warningMessage, collectedWarningMessages, parentVfName);
240     }
241
242     private static String detectArtifactTypeVF(ArtifactGroupTypeEnum artifactGroupType, String receivedTypeName,
243                                                Map<String, Set<List<String>>> collectedWarningMessages) {
244         String warningMessage = "Warning - artifact type {} that was provided for VF is not recognized.";
245         return detectArtifactType(artifactGroupType, receivedTypeName, warningMessage, collectedWarningMessages);
246     }
247
248     private static String detectArtifactType(final ArtifactGroupTypeEnum artifactGroupType, final String receivedTypeName,
249                                              final String warningMessage, final Map<String, Set<List<String>>> collectedWarningMessages,
250                                              final String... arguments) {
251         final ArtifactConfiguration artifactConfiguration = ArtifactConfigManager.getInstance()
252             .find(receivedTypeName, artifactGroupType, ComponentType.RESOURCE).orElse(null);
253         if (artifactConfiguration == null) {
254             final List<String> messageArguments = new ArrayList<>();
255             messageArguments.add(receivedTypeName);
256             messageArguments.addAll(Arrays.asList(arguments));
257             if (!collectedWarningMessages.containsKey(warningMessage)) {
258                 final Set<List<String>> messageArgumentLists = new HashSet<>();
259                 messageArgumentLists.add(messageArguments);
260                 collectedWarningMessages.put(warningMessage, messageArgumentLists);
261             } else {
262                 collectedWarningMessages.get(warningMessage).add(messageArguments);
263             }
264         }
265         return artifactConfiguration == null ? ArtifactTypeEnum.OTHER.getType() : receivedTypeName;
266     }
267
268     /**
269      * @param component
270      * @param getFromCS
271      * @param isInCertificationRequest
272      * @return
273      */
274     public Either<byte[], ResponseFormat> createCsar(final Component component, final boolean getFromCS, final boolean isInCertificationRequest) {
275         loggerSupportability
276             .log(LoggerSupportabilityActions.GENERATE_CSAR, StatusCode.STARTED, "Starting to create Csar for component {} ", component.getName());
277
278         return generateCsarZip(isAsdPackage(component), component, getFromCS, isInCertificationRequest).left().map(responseFormat -> {
279             loggerSupportability
280                 .log(LoggerSupportabilityActions.GENERATE_CSAR, StatusCode.COMPLETE, "Ended create Csar for component {} ", component.getName());
281             return responseFormat;
282         });
283     }
284
285     private boolean isAsdPackage(final Component component) {
286         final Either<CsarDefinition, ResponseFormat> collectedComponentCsarDefinition = collectComponentCsarDefinition(component);
287         if (collectedComponentCsarDefinition.isLeft()) {
288             final ComponentArtifacts componentArtifacts = collectedComponentCsarDefinition.left().value().getComponentArtifacts();
289             if (componentArtifacts != null) {
290                 final ComponentTypeArtifacts mainTypeAndCIArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
291                 if (mainTypeAndCIArtifacts != null) {
292                     final ArtifactsInfo artifactsInfo = mainTypeAndCIArtifacts.getComponentArtifacts();
293                     if (artifactsInfo != null) {
294                         final Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactsInfosMap = artifactsInfo.getArtifactsInfo();
295                         if (MapUtils.isNotEmpty(artifactsInfosMap) && artifactsInfosMap.containsKey(ArtifactGroupTypeEnum.DEPLOYMENT)) {
296                             return artifactsInfosMap.get(ArtifactGroupTypeEnum.DEPLOYMENT).containsKey(ArtifactTypeEnum.ASD_PACKAGE.getType());
297                         }
298                     }
299                 }
300             }
301         }
302         return false;
303     }
304
305     private Either<byte[], ResponseFormat> generateCsarZip(boolean isAsdPackage,
306                                                            Component component,
307                                                            boolean getFromCS,
308                                                            boolean isInCertificationRequest) {
309         try (final ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out)) {
310             Either<ZipOutputStream, ResponseFormat> populateZip = mapFromModelCsarGeneratorService.generateCsarZip(
311                 component, getFromCS, zip, isInCertificationRequest, isAsdPackage);
312             if (populateZip.isRight()) {
313                 log.debug("Failed to populate CSAR zip file {}. Please fix DB table accordingly ", populateZip.right().value());
314                 return Either.right(populateZip.right().value());
315             }
316             zip.finish();
317             return Either.left(out.toByteArray());
318         } catch (IOException e) {
319             log.debug("Failed with IOexception to create CSAR zip for component {}. Please fix DB table accordingly ", component.getUniqueId(), e);
320             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
321             return Either.right(responseFormat);
322         }
323     }
324
325     /************************************ Artifacts Structure END******************************************************************/
326
327     private Either<CsarDefinition, ResponseFormat> collectComponentCsarDefinition(Component component) {
328         ComponentArtifacts componentArtifacts = new ComponentArtifacts();
329         Component updatedComponent = component;
330
331         //get service to receive the AII artifacts uploaded to the service
332         if (updatedComponent.getComponentType() == ComponentTypeEnum.SERVICE) {
333             Either<Service, StorageOperationStatus> getServiceResponse = toscaOperationFacade.getToscaElement(updatedComponent.getUniqueId());
334
335             if (getServiceResponse.isRight()) {
336                 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getServiceResponse.right().value());
337                 return Either.right(componentsUtils.getResponseFormat(actionStatus));
338             }
339
340             updatedComponent = getServiceResponse.left().value();
341         }
342
343         //find the artifacts of the main component, it would have its composed instances artifacts in a separate folder
344         ComponentTypeArtifacts componentInstanceArtifacts = new ComponentTypeArtifacts();
345         ArtifactsInfo artifactsInfo = collectComponentArtifacts(updatedComponent);
346         componentInstanceArtifacts.setComponentArtifacts(artifactsInfo);
347         componentArtifacts.setMainTypeAndCIArtifacts(componentInstanceArtifacts);
348
349         Map<String, ComponentTypeArtifacts> resourceTypeArtifacts = componentArtifacts
350             .getComponentTypeArtifacts();    //artifacts mapped by the component type(tosca name+version)
351         //get the component instances
352         List<ComponentInstance> componentInstances = updatedComponent.getComponentInstances();
353         if (componentInstances != null) {
354             for (ComponentInstance componentInstance : componentInstances) {
355                 //call recursive to find artifacts for all the path
356                 Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts = collectComponentInstanceArtifacts(
357                     updatedComponent, componentInstance, resourceTypeArtifacts, componentInstanceArtifacts);
358                 if (collectComponentInstanceArtifacts.isRight()) {
359                     return Either.right(collectComponentInstanceArtifacts.right().value());
360                 }
361             }
362         }
363
364         if (log.isDebugEnabled()) {
365             printResult(componentArtifacts, updatedComponent.getName());
366         }
367
368         return Either.left(new CsarDefinition(componentArtifacts));
369     }
370
371     private void printResult(ComponentArtifacts componentArtifacts, String name) {
372         StringBuilder result = new StringBuilder();
373         result.append("Artifacts of main component " + name + "\n");
374         ComponentTypeArtifacts componentInstanceArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
375         printArtifacts(componentInstanceArtifacts);
376         result.append("Type Artifacts\n");
377         for (Entry<String, ComponentTypeArtifacts> typeArtifacts : componentArtifacts.getComponentTypeArtifacts().entrySet()) {
378             result.append("Folder " + typeArtifacts.getKey() + "\n");
379             result.append(printArtifacts(typeArtifacts.getValue()));
380         }
381
382         if (log.isDebugEnabled()) {
383             log.debug(result.toString());
384         }
385     }
386
387     /************************************ Artifacts Structure ******************************************************************/
388
389     private String printArtifacts(ComponentTypeArtifacts componentInstanceArtifacts) {
390         StringBuilder result = new StringBuilder();
391         ArtifactsInfo artifactsInfo = componentInstanceArtifacts.getComponentArtifacts();
392         Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componentArtifacts = artifactsInfo.getArtifactsInfo();
393         printArtifacts(componentArtifacts);
394         result = result.append("Resources\n");
395         for (Entry<String, ArtifactsInfo> resourceInstance : componentInstanceArtifacts.getComponentInstancesArtifacts().entrySet()) {
396             result.append("Folder" + resourceInstance.getKey() + "\n");
397             result.append(printArtifacts(resourceInstance.getValue().getArtifactsInfo()));
398         }
399
400         return result.toString();
401     }
402
403     private String printArtifacts(Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componetArtifacts) {
404         StringBuilder result = new StringBuilder();
405         for (Entry<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactGroup : componetArtifacts.entrySet()) {
406             result.append("    " + artifactGroup.getKey().getType());
407             for (Entry<String, List<ArtifactDefinition>> groupArtifacts : artifactGroup.getValue().entrySet()) {
408                 result.append("        " + groupArtifacts.getKey());
409                 for (ArtifactDefinition artifact : groupArtifacts.getValue()) {
410                     result.append("            " + artifact.getArtifactDisplayName());
411                 }
412             }
413         }
414
415         return result.toString();
416     }
417
418     private ComponentTypeArtifacts collectComponentTypeArtifacts(Component fetchedComponent) {
419         ArtifactsInfo componentArtifacts = collectComponentArtifacts(fetchedComponent);
420         ComponentTypeArtifacts componentArtifactsInfo = new ComponentTypeArtifacts();
421         if (componentArtifacts.isNotEmpty()) {
422             componentArtifactsInfo.setComponentArtifacts(componentArtifacts);
423         }
424         return componentArtifactsInfo;
425     }
426
427     private Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts(Component parentComponent, ComponentInstance componentInstance,
428                                                                               Map<String, ComponentTypeArtifacts> resourcesTypeArtifacts,
429                                                                               ComponentTypeArtifacts instanceArtifactsLocation) {
430         //1. get the component instance component
431         String componentUid;
432         if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
433             componentUid = componentInstance.getSourceModelUid();
434         } else {
435             componentUid = componentInstance.getComponentUid();
436         }
437         Either<Component, StorageOperationStatus> component = toscaOperationFacade.getToscaElement(componentUid);
438         if (component.isRight()) {
439             log.error("Failed to fetch resource with id {} for instance {}", componentUid, parentComponent.getUUID());
440             return Either.right(componentsUtils.getResponseFormat(ActionStatus.ASSET_NOT_FOUND_DURING_CSAR_CREATION,
441                 parentComponent.getComponentType().getValue(), parentComponent.getUUID(),
442                 componentInstance.getOriginType().getComponentType().getValue(), componentUid));
443         }
444         Component fetchedComponent = component.left().value();
445
446         //2. fill the artifacts for the current component parent type
447         String toscaComponentName =
448             componentInstance.getToscaComponentName() + "_v" + componentInstance.getComponentVersion();
449
450         // if there are no artifacts for this component type we need to fetch and build them
451         ComponentTypeArtifacts componentParentArtifacts = Optional
452             .ofNullable(resourcesTypeArtifacts.get(toscaComponentName))
453             .orElseGet(() -> collectComponentTypeArtifacts(fetchedComponent));
454
455         if (componentParentArtifacts.getComponentArtifacts().isNotEmpty()) {
456             resourcesTypeArtifacts.put(toscaComponentName, componentParentArtifacts);
457         }
458
459         //3. find the artifacts specific to the instance
460         Map<String, List<ArtifactDefinition>> componentInstanceSpecificInformationalArtifacts =
461             getComponentInstanceSpecificArtifacts(componentInstance.getArtifacts(),
462                 componentParentArtifacts.getComponentArtifacts().getArtifactsInfo(), ArtifactGroupTypeEnum.INFORMATIONAL);
463         Map<String, List<ArtifactDefinition>> componentInstanceSpecificDeploymentArtifacts =
464             getComponentInstanceSpecificArtifacts(componentInstance.getDeploymentArtifacts(),
465                 componentParentArtifacts.getComponentArtifacts().getArtifactsInfo(), ArtifactGroupTypeEnum.DEPLOYMENT);
466
467         //4. add the instances artifacts to the component type
468         ArtifactsInfo artifactsInfo = new ArtifactsInfo();
469         if (!componentInstanceSpecificInformationalArtifacts.isEmpty()) {
470             artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.INFORMATIONAL, componentInstanceSpecificInformationalArtifacts);
471         }
472         if (!componentInstanceSpecificDeploymentArtifacts.isEmpty()) {
473             artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.DEPLOYMENT, componentInstanceSpecificDeploymentArtifacts);
474         }
475         if (!artifactsInfo.isEmpty()) {
476             instanceArtifactsLocation.addComponentInstancesArtifacts(componentInstance.getNormalizedName(), artifactsInfo);
477         }
478
479         //5. do the same for all the component instances
480         List<ComponentInstance> componentInstances = fetchedComponent.getComponentInstances();
481         if (componentInstances != null) {
482             for (ComponentInstance childComponentInstance : componentInstances) {
483                 Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts = collectComponentInstanceArtifacts(
484                     fetchedComponent, childComponentInstance, resourcesTypeArtifacts, componentParentArtifacts);
485                 if (collectComponentInstanceArtifacts.isRight()) {
486                     return collectComponentInstanceArtifacts;
487                 }
488             }
489         }
490
491         return Either.left(true);
492     }
493
494     private Map<String, List<ArtifactDefinition>> getComponentInstanceSpecificArtifacts(Map<String, ArtifactDefinition> componentArtifacts,
495                                                                                         Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componentTypeArtifacts,
496                                                                                         ArtifactGroupTypeEnum artifactGroupTypeEnum) {
497         Map<String, List<ArtifactDefinition>> parentArtifacts = componentTypeArtifacts
498             .get(artifactGroupTypeEnum);    //the artfiacts of the component itself and not the instance
499
500         Map<String, List<ArtifactDefinition>> artifactsByTypeOfComponentInstance = new HashMap<>();
501         if (componentArtifacts != null) {
502             for (ArtifactDefinition artifact : componentArtifacts.values()) {
503                 List<ArtifactDefinition> parentArtifactsByType = null;
504                 if (parentArtifacts != null) {
505                     parentArtifactsByType = parentArtifacts.get(artifact.getArtifactType());
506                 }
507                 //the artifact is of instance
508                 if (parentArtifactsByType == null || !parentArtifactsByType.contains(artifact)) {
509                     List<ArtifactDefinition> typeArtifacts = artifactsByTypeOfComponentInstance.get(artifact.getArtifactType());
510                     if (typeArtifacts == null) {
511                         typeArtifacts = new ArrayList<>();
512                         artifactsByTypeOfComponentInstance.put(artifact.getArtifactType(), typeArtifacts);
513                     }
514                     typeArtifacts.add(artifact);
515                 }
516             }
517         }
518
519         return artifactsByTypeOfComponentInstance;
520     }
521
522     private ArtifactsInfo collectComponentArtifacts(Component component) {
523         Map<String, ArtifactDefinition> informationalArtifacts = component.getArtifacts();
524         Map<String, List<ArtifactDefinition>> informationalArtifactsByType = collectGroupArtifacts(informationalArtifacts);
525         Map<String, ArtifactDefinition> deploymentArtifacts = component.getDeploymentArtifacts();
526         Map<String, List<ArtifactDefinition>> deploymentArtifactsByType = collectGroupArtifacts(deploymentArtifacts);
527         ArtifactsInfo artifactsInfo = new ArtifactsInfo();
528         if (!informationalArtifactsByType.isEmpty()) {
529             artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.INFORMATIONAL, informationalArtifactsByType);
530         }
531         if (!deploymentArtifactsByType.isEmpty()) {
532             artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.DEPLOYMENT, deploymentArtifactsByType);
533         }
534
535         return artifactsInfo;
536     }
537
538     private Map<String, List<ArtifactDefinition>> collectGroupArtifacts(
539         final Map<String, ArtifactDefinition> componentArtifacts) {
540         final Map<String, List<ArtifactDefinition>> artifactsByType = new HashMap<>();
541         for (final ArtifactDefinition artifact : componentArtifacts.values()) {
542             if (artifact.getArtifactUUID() != null) {
543                 artifactsByType.putIfAbsent(artifact.getArtifactType(), new ArrayList<>());
544                 final List<ArtifactDefinition> typeArtifacts = artifactsByType.get(artifact.getArtifactType());
545                 typeArtifacts.add(artifact);
546             }
547         }
548         return artifactsByType;
549     }
550
551
552     @Getter
553     public static final class NonMetaArtifactInfo {
554
555         private final String path;
556         private final String artifactName;
557         private final String displayName;
558         private final String artifactLabel;
559         private final String artifactType;
560         private final ArtifactGroupTypeEnum artifactGroupType;
561         private final String payloadData;
562         private final String artifactChecksum;
563         private final boolean isFromCsar;
564         @Setter
565         private String artifactUniqueId;
566
567         public NonMetaArtifactInfo(final String artifactName, final String path, final String artifactType,
568                                    final ArtifactGroupTypeEnum artifactGroupType, final byte[] payloadData, final String artifactUniqueId,
569                                    final boolean isFromCsar) {
570             this.path = path;
571             this.isFromCsar = isFromCsar;
572             this.artifactName = ValidationUtils.normalizeFileName(artifactName);
573             this.artifactType = artifactType;
574             this.artifactGroupType = artifactGroupType;
575             final int pointIndex = artifactName.lastIndexOf('.');
576             if (pointIndex > 0) {
577                 displayName = artifactName.substring(0, pointIndex);
578             } else {
579                 displayName = artifactName;
580             }
581             this.artifactLabel = ValidationUtils.normalizeArtifactLabel(artifactName);
582             if (payloadData == null) {
583                 this.payloadData = null;
584                 this.artifactChecksum = null;
585             } else {
586                 this.payloadData = Base64.encodeBase64String(payloadData);
587                 this.artifactChecksum = GeneralUtility.calculateMD5Base64EncodedByByteArray(payloadData);
588             }
589             this.artifactUniqueId = artifactUniqueId;
590         }
591     }
592
593     /**
594      * The artifacts Definition saved by their structure
595      */
596     private class ArtifactsInfo {
597         //Key is the type of artifacts(Informational/Deployment)
598
599         //Value is a map between an artifact type and a list of all artifacts of this type
600         private Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactsInfoField;
601
602         public ArtifactsInfo() {
603             this.artifactsInfoField = new EnumMap<>(ArtifactGroupTypeEnum.class);
604         }
605
606         public Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> getArtifactsInfo() {
607             return artifactsInfoField;
608         }
609
610         public void addArtifactsToGroup(ArtifactGroupTypeEnum artifactGroup, Map<String, List<ArtifactDefinition>> artifactsDefinition) {
611             if (artifactsInfoField.get(artifactGroup) == null) {
612                 artifactsInfoField.put(artifactGroup, artifactsDefinition);
613             } else {
614                 Map<String, List<ArtifactDefinition>> artifactTypeEnumListMap = artifactsInfoField.get(artifactGroup);
615                 artifactTypeEnumListMap.putAll(artifactsDefinition);
616                 artifactsInfoField.put(artifactGroup, artifactTypeEnumListMap);
617             }
618         }
619
620         public boolean isEmpty() {
621             return artifactsInfoField.isEmpty();
622         }
623
624         public boolean isNotEmpty() {
625             return !isEmpty();
626         }
627     }
628
629     /**
630      * The artifacts of the component and of all its composed instances
631      */
632     private class ComponentTypeArtifacts {
633
634         private ArtifactsInfo componentArtifacts;    //component artifacts (describes the Informational Deployment folders)
635
636         private Map<String, ArtifactsInfo> componentInstancesArtifacts;        //artifacts of the composed instances mapped by the resourceInstance normalized name (describes the Resources folder)
637
638         public ComponentTypeArtifacts() {
639             componentArtifacts = new ArtifactsInfo();
640             componentInstancesArtifacts = new HashMap<>();
641         }
642
643         public ArtifactsInfo getComponentArtifacts() {
644             return componentArtifacts;
645         }
646
647         public void setComponentArtifacts(ArtifactsInfo artifactsInfo) {
648             this.componentArtifacts = artifactsInfo;
649         }
650
651         public Map<String, ArtifactsInfo> getComponentInstancesArtifacts() {
652             return componentInstancesArtifacts;
653         }
654
655         public void addComponentInstancesArtifacts(String normalizedName, ArtifactsInfo artifactsInfo) {
656             componentInstancesArtifacts.put(normalizedName, artifactsInfo);
657         }
658     }
659
660     private class ComponentArtifacts {
661
662         //artifacts of the component and CI's artifacts contained in it's composition (represents Informational, Deployment & Resource folders of main component)
663         private ComponentTypeArtifacts mainTypeAndCIArtifacts;
664         //artifacts of all component types mapped by their tosca name
665         private Map<String, ComponentTypeArtifacts> componentTypeArtifacts;
666
667         public ComponentArtifacts() {
668             mainTypeAndCIArtifacts = new ComponentTypeArtifacts();
669             componentTypeArtifacts = new HashMap<>();
670         }
671
672         public ComponentTypeArtifacts getMainTypeAndCIArtifacts() {
673             return mainTypeAndCIArtifacts;
674         }
675
676         public void setMainTypeAndCIArtifacts(ComponentTypeArtifacts componentInstanceArtifacts) {
677             this.mainTypeAndCIArtifacts = componentInstanceArtifacts;
678         }
679
680         public Map<String, ComponentTypeArtifacts> getComponentTypeArtifacts() {
681             return componentTypeArtifacts;
682         }
683     }
684
685     private class CsarDefinition {
686
687         private ComponentArtifacts componentArtifacts;
688
689         // add list of tosca artifacts and meta describes CSAR zip root
690         public CsarDefinition(ComponentArtifacts componentArtifacts) {
691             this.componentArtifacts = componentArtifacts;
692         }
693
694         public ComponentArtifacts getComponentArtifacts() {
695             return componentArtifacts;
696         }
697     }
698 }
699