3255e186e417028845fc1806e4e1259c19d424b4
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.vendorsoftwareproduct.services.impl.filedatastructuremodule;
18
19 import static org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder.getErrorWithParameters;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.nio.ByteBuffer;
26 import java.nio.charset.StandardCharsets;
27 import java.util.ArrayList;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Objects;
32 import java.util.Optional;
33 import java.util.Set;
34 import java.util.stream.Collectors;
35 import java.util.zip.ZipEntry;
36 import java.util.zip.ZipInputStream;
37 import java.util.zip.ZipOutputStream;
38 import org.apache.commons.collections4.CollectionUtils;
39 import org.openecomp.core.utilities.file.FileContentHandler;
40 import org.openecomp.core.utilities.json.JsonUtil;
41 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
42 import org.openecomp.sdc.common.errors.CoreException;
43 import org.openecomp.sdc.common.errors.ErrorCategory;
44 import org.openecomp.sdc.common.errors.ErrorCode;
45 import org.openecomp.sdc.common.errors.Messages;
46 import org.openecomp.sdc.common.utils.SdcCommon;
47 import org.openecomp.sdc.datatypes.error.ErrorLevel;
48 import org.openecomp.sdc.datatypes.error.ErrorMessage;
49 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
50 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
51 import org.openecomp.sdc.heat.datatypes.structure.Artifact;
52 import org.openecomp.sdc.heat.datatypes.structure.HeatStructureTree;
53 import org.openecomp.sdc.heat.datatypes.structure.ValidationStructureList;
54 import org.openecomp.sdc.vendorsoftwareproduct.dao.OrchestrationTemplateCandidateDao;
55 import org.openecomp.sdc.vendorsoftwareproduct.dao.OrchestrationTemplateCandidateDaoFactory;
56 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData;
57 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
58 import org.openecomp.sdc.vendorsoftwareproduct.errors.utils.ErrorsUtil;
59 import org.openecomp.sdc.vendorsoftwareproduct.services.HeatFileAnalyzer;
60 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.CandidateService;
61 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.ManifestCreator;
62 import org.openecomp.sdc.vendorsoftwareproduct.services.utils.CandidateServiceValidator;
63 import org.openecomp.sdc.vendorsoftwareproduct.types.CandidateDataEntityTo;
64 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.AnalyzedZipHeatFiles;
65 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
66 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Module;
67 import org.openecomp.sdc.versioning.dao.types.Version;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71 public class CandidateServiceImpl implements CandidateService {
72   private static final Logger logger = LoggerFactory.getLogger(CandidateServiceImpl.class);
73   private CandidateServiceValidator candidateServiceValidator = new CandidateServiceValidator();
74   private ManifestCreator manifestCreator;
75   private OrchestrationTemplateCandidateDao orchestrationTemplateCandidateDao;
76
77   public CandidateServiceImpl(ManifestCreator manifestCreator,
78                               OrchestrationTemplateCandidateDao orchestrationTemplateCandidateDao) {
79     this.manifestCreator = manifestCreator;
80     this.orchestrationTemplateCandidateDao = orchestrationTemplateCandidateDao;
81   }
82
83   public CandidateServiceImpl() {
84   }
85
86   @Override
87   public Optional<ErrorMessage> validateNonEmptyFileToUpload(InputStream fileToUpload,
88                                                              String fileSuffix) {
89     String errorMessage =
90         getErrorWithParameters(Messages.NO_FILE_WAS_UPLOADED_OR_FILE_NOT_EXIST.getErrorMessage(),
91             fileSuffix);
92
93     if (Objects.isNull(fileToUpload)) {
94       return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
95           errorMessage));
96     } else {
97       try {
98         int available = fileToUpload.available();
99         if (available == 0) {
100           return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
101               errorMessage));
102         }
103       } catch (IOException e) {
104         logger.debug(e.getMessage(), e);
105         return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
106             errorMessage));
107       }
108     }
109     return Optional.empty();
110   }
111
112   @Override
113   public Optional<ErrorMessage> validateRawZipData(String fileSuffix,
114                                                    byte[] uploadedFileData) {
115     if (Objects.isNull(uploadedFileData)) {
116       return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
117           getErrorWithParameters(Messages.NO_FILE_WAS_UPLOADED_OR_FILE_NOT_EXIST.getErrorMessage(),
118               fileSuffix)));
119     }
120     return Optional.empty();
121   }
122
123   private String heatStructureTreeToFileDataStructure(HeatStructureTree tree,
124                                                       FileContentHandler zipContentMap,
125                                                       Map<String, List<ErrorMessage>> uploadErrors,
126                                                       AnalyzedZipHeatFiles analyzedZipHeatFiles) {
127     FilesDataStructure structure = new FilesDataStructure();
128     Set<String> usedEnvFiles = new HashSet<>();
129     addHeatsToFileDataStructure(tree, usedEnvFiles, structure, uploadErrors,
130         analyzedZipHeatFiles);
131     handleOtherResources(tree, usedEnvFiles, structure);
132     FilesDataStructure fileDataStructureFromManifest =
133         createFileDataStructureFromManifest(zipContentMap.getFileContent(SdcCommon.MANIFEST_NAME));
134     List<String> structureArtifacts = structure.getArtifacts();
135     structureArtifacts.addAll(fileDataStructureFromManifest.getArtifacts().stream().filter
136         (artifact -> isNotStrctureArtifact(structureArtifacts, artifact))
137         .collect(Collectors.toList()));
138     handleArtifactsFromTree(tree, structure);
139
140     return JsonUtil.object2Json(structure);
141   }
142
143   private boolean isNotStrctureArtifact(List<String> structureArtifacts, String artifact) {
144     return !structureArtifacts.contains(artifact);
145   }
146
147   @Override
148   public OrchestrationTemplateCandidateData createCandidateDataEntity(
149       CandidateDataEntityTo candidateDataEntityTo, InputStream zipFileManifest,
150       AnalyzedZipHeatFiles analyzedZipHeatFiles) {
151     FileContentHandler zipContentMap = candidateDataEntityTo.getContentMap();
152     FilesDataStructure filesDataStructure;
153     String dataStructureJson;
154
155     if (zipFileManifest != null) {
156       // create data structure from manifest
157       filesDataStructure = createFileDataStructureFromManifest(zipFileManifest);
158       Set<String> zipFileList = zipContentMap.getFileList();
159       balanceManifestFilesWithZipFiles(filesDataStructure,
160           zipContentMap, analyzedZipHeatFiles);
161       Set<String> filesDataStructureFiles = getFlatFileNames(filesDataStructure);
162       filesDataStructure.getUnassigned().addAll(zipFileList.stream()
163           .filter(fileName -> (!filesDataStructureFiles.contains(fileName)
164               && !filesDataStructure.getNested().contains(fileName)
165               && !fileName.equals(SdcCommon.MANIFEST_NAME)))
166           .collect(Collectors.toList()));
167       dataStructureJson = JsonUtil.object2Json(filesDataStructure);
168     } else {
169       // create data structure from based on naming convention
170       dataStructureJson =
171           heatStructureTreeToFileDataStructure(candidateDataEntityTo.getTree(), zipContentMap,
172               candidateDataEntityTo.getErrors(), analyzedZipHeatFiles);
173     }
174
175     OrchestrationTemplateCandidateData candidateData = new OrchestrationTemplateCandidateData();
176     candidateData.setContentData(ByteBuffer.wrap(candidateDataEntityTo.getUploadedFileData()));
177     candidateData.setFilesDataStructure(dataStructureJson);
178     return candidateData;
179   }
180
181   private void balanceManifestFilesWithZipFiles(
182       FilesDataStructure filesDataStructure,
183       FileContentHandler fileContentHandler, AnalyzedZipHeatFiles analyzedZipHeatFiles) {
184     Set<String> zipFileList = fileContentHandler.getFileList();
185     filesDataStructure.getNested().addAll(analyzedZipHeatFiles.getNestedFiles());
186     List<Module> modules = filesDataStructure.getModules();
187     if (CollectionUtils.isEmpty(modules)) {
188       return;
189     }
190
191     for (int i = 0; i < modules.size(); i++) {
192       Module module = modules.get(i);
193       if (!isFileExistInZipContains(zipFileList, module.getYaml())) {
194         addFileToUnassigned(filesDataStructure, zipFileList, module.getEnv());
195         addFileToUnassigned(filesDataStructure, zipFileList, module.getVol());
196         addFileToUnassigned(filesDataStructure, zipFileList, module.getVolEnv());
197         modules.remove(i--);
198       } else if (Objects.nonNull(module.getVol()) && !zipFileList.contains(module.getVol())) {
199         module.setVol(null);
200         CollectionUtils
201             .addIgnoreNull(filesDataStructure.getUnassigned(), module.getVolEnv());
202       } else {
203         if (filesDataStructure.getNested().contains(module.getYaml())) {
204           moveModuleFileToNested(filesDataStructure, i--, module);
205         }
206       }
207     }
208   }
209
210   private void addFileToUnassigned(FilesDataStructure filesDataStructure, Set<String> zipFileList,
211                                    String fileName) {
212     if (isFileExistInZipContains(zipFileList, fileName)) {
213       filesDataStructure.getUnassigned().add(fileName);
214     }
215   }
216
217   private boolean isFileExistInZipContains(Set<String> zipFileList, String fileName) {
218     return Objects.nonNull(fileName) && zipFileList.contains(fileName);
219   }
220
221   private void moveModuleFileToNested(FilesDataStructure filesDataStructure, int i,
222                                       Module module) {
223     if (!filesDataStructure.getNested().contains(module.getYaml())) {
224       filesDataStructure.getNested().add(module.getYaml());
225     }
226     if (Objects.nonNull(module.getEnv())) {
227       filesDataStructure.getNested().add(module.getEnv());
228     }
229     if (Objects.nonNull(module.getVol())) {
230       filesDataStructure.getNested().add(module.getVol());
231     }
232     if (Objects.nonNull(module.getVolEnv())) {
233       filesDataStructure.getNested().add(module.getVolEnv());
234     }
235     filesDataStructure.getModules().remove(i);
236   }
237
238   private Set<String> getFlatFileNames(FilesDataStructure filesDataStructure) {
239     Set<String> fileNames = new HashSet<>();
240     if (!CollectionUtils.isEmpty(filesDataStructure.getModules())) {
241       for (Module module : filesDataStructure.getModules()) {
242         CollectionUtils.addIgnoreNull(fileNames, module.getEnv());
243         CollectionUtils.addIgnoreNull(fileNames, module.getVol());
244         CollectionUtils.addIgnoreNull(fileNames, module.getVolEnv());
245         CollectionUtils.addIgnoreNull(fileNames, module.getYaml());
246       }
247     }
248     fileNames.addAll(filesDataStructure.getArtifacts());
249     fileNames.addAll(filesDataStructure.getNested());
250     fileNames.addAll(filesDataStructure.getUnassigned());
251
252     return fileNames;
253   }
254
255   private FilesDataStructure createFileDataStructureFromManifest(InputStream isManifestContent) {
256     ManifestContent manifestContent =
257         JsonUtil.json2Object(isManifestContent, ManifestContent.class);
258     FilesDataStructure structure = new FilesDataStructure();
259     for (FileData fileData : manifestContent.getData()) {
260       if (Objects.nonNull(fileData.getType()) &&
261           fileData.getType().equals(FileData.Type.HEAT)) {
262         Module module = new Module();
263         module.setYaml(fileData.getFile());
264         module.setIsBase(fileData.getBase());
265         addHeatDependenciesToModule(module, fileData.getData());
266         structure.getModules().add(module);
267       } else if (HeatFileAnalyzer.isYamlOrEnvFile(fileData.getFile()) &&
268           !FileData.Type.isArtifact(fileData.getType())) {
269         structure.getUnassigned().add(fileData.getFile());
270       } else {
271         structure.getArtifacts().add(fileData.getFile());
272       }
273     }
274     return structure;
275   }
276
277   private void addHeatDependenciesToModule(Module module, List<FileData> data) {
278     if (CollectionUtils.isEmpty(data)) {
279       return;
280     }
281
282     for (FileData fileData : data) {
283       if (fileData.getType().equals(FileData.Type.HEAT_ENV)) {
284         module.setEnv(fileData.getFile());
285       } else if (fileData.getType().equals(FileData.Type.HEAT_VOL)) { // must be volume
286         module.setVol(fileData.getFile());
287         if (!CollectionUtils.isEmpty(fileData.getData())) {
288           FileData volEnv = fileData.getData().get(0);
289           if (volEnv.getType().equals(FileData.Type.HEAT_ENV)) {
290             module.setVolEnv(volEnv.getFile());
291           } else {
292             throw new CoreException((new ErrorCode.ErrorCodeBuilder())
293                 .withMessage(Messages.ILLEGAL_MANIFEST.getErrorMessage())
294                 .withId(Messages.ILLEGAL_MANIFEST.getErrorMessage())
295                 .withCategory(ErrorCategory.APPLICATION).build());
296           }
297         }
298       } else {
299         throw new CoreException((new ErrorCode.ErrorCodeBuilder())
300             .withMessage(Messages.FILE_TYPE_NOT_LEGAL.getErrorMessage())
301             .withId(Messages.FILE_TYPE_NOT_LEGAL.getErrorMessage())
302             .withCategory(ErrorCategory.APPLICATION).build());
303       }
304     }
305   }
306
307   @Override
308   public void updateCandidateUploadData(final String vspId, final Version version,
309                                         final OrchestrationTemplateCandidateData uploadData) {
310     orchestrationTemplateCandidateDao.update(vspId, version, uploadData);
311   }
312
313   @Override
314   public Optional<FilesDataStructure> getOrchestrationTemplateCandidateFileDataStructure(
315       String vspId, Version version) {
316     Optional<String> jsonFileDataStructure =
317         orchestrationTemplateCandidateDao.getStructure(vspId, version);
318
319     if (jsonFileDataStructure.isPresent() && JsonUtil.isValidJson(jsonFileDataStructure.get())) {
320       return Optional
321           .of(JsonUtil.json2Object(jsonFileDataStructure.get(), FilesDataStructure.class));
322     } else {
323       return Optional.empty();
324     }
325   }
326
327   @Override
328   public void updateOrchestrationTemplateCandidateFileDataStructure(String vspId, Version version,
329                                                                     FilesDataStructure fileDataStructure) {
330     OrchestrationTemplateCandidateDaoFactory.getInstance().createInterface()
331         .updateStructure(vspId, version, fileDataStructure);
332   }
333
334   @Override
335   public Optional<OrchestrationTemplateCandidateData> getOrchestrationTemplateCandidate(String vspId,
336                                                                                         Version version) {
337     return orchestrationTemplateCandidateDao.get(vspId, version);
338   }
339
340   @Override
341   public Optional<OrchestrationTemplateCandidateData> getOrchestrationTemplateCandidateInfo(
342       String vspId,
343       Version version) {
344     return orchestrationTemplateCandidateDao.getInfo(vspId, version);
345   }
346
347   @Override
348   public String createManifest(VspDetails vspDetails, FilesDataStructure structure) {
349     return JsonUtil.object2Json(manifestCreator.createManifest(vspDetails, structure)
350         .orElseThrow(() -> new CoreException(new ErrorCode.ErrorCodeBuilder()
351             .withMessage(Messages.CREATE_MANIFEST_FROM_ZIP.getErrorMessage()).build())));
352   }
353
354   @Override
355   public Optional<ManifestContent> createManifest(VspDetails vspDetails,
356                                                   FileContentHandler fileContentHandler,
357                                                   AnalyzedZipHeatFiles analyzedZipHeatFiles) {
358     return manifestCreator.createManifest(vspDetails, fileContentHandler, analyzedZipHeatFiles);
359   }
360
361   @Override
362   public Optional<ByteArrayInputStream> fetchZipFileByteArrayInputStream(String vspId,
363                                                                          OrchestrationTemplateCandidateData candidateDataEntity,
364                                                                          String manifest,
365                                                                          OnboardingTypesEnum type,
366                                                                          Map<String, List<ErrorMessage>> uploadErrors) {
367     byte[] file;
368     ByteArrayInputStream byteArrayInputStream = null;
369     try {
370       file = replaceManifestInZip(candidateDataEntity.getContentData(), manifest, type);
371       byteArrayInputStream = new ByteArrayInputStream(
372           Objects.isNull(file) ? candidateDataEntity.getContentData().array()
373               : file);
374     } catch (IOException e) {
375       ErrorMessage errorMessage =
376           new ErrorMessage(ErrorLevel.ERROR,
377               Messages.CANDIDATE_PROCESS_FAILED.getErrorMessage());
378       logger.error(errorMessage.getMessage(), e);
379       ErrorsUtil
380           .addStructureErrorToErrorMap(SdcCommon.UPLOAD_FILE, errorMessage, uploadErrors);
381     }
382     return Optional.ofNullable(byteArrayInputStream);
383   }
384
385   @Override
386   public byte[] replaceManifestInZip(ByteBuffer contentData, String manifest,
387                                      OnboardingTypesEnum type)
388       throws IOException {
389     ByteArrayOutputStream baos = new ByteArrayOutputStream();
390
391     try (final ZipOutputStream zos = new ZipOutputStream(baos);
392          ZipInputStream zipStream = new ZipInputStream(
393              new ByteArrayInputStream(contentData.array()))) {
394       ZipEntry zipEntry;
395       boolean manifestWritten = false;
396       while ((zipEntry = zipStream.getNextEntry()) != null) {
397         if (!zipEntry.getName().equalsIgnoreCase(SdcCommon.MANIFEST_NAME)) {
398           ZipEntry loc_ze = new ZipEntry(zipEntry.getName());
399           zos.putNextEntry(loc_ze);
400           byte[] buf = new byte[1024];
401           int len;
402           while ((len = zipStream.read(buf)) > 0) {
403             zos.write(buf, 0, (len < buf.length) ? len : buf.length);
404           }
405         } else {
406           manifestWritten = true;
407           writeManifest(manifest, type, zos);
408         }
409         zos.closeEntry();
410       }
411       if (!manifestWritten) {
412         writeManifest(manifest, type, zos);
413         zos.closeEntry();
414       }
415     }
416     return baos.toByteArray();
417   }
418
419   @Override
420   public byte[] getZipData(ByteBuffer contentData)
421       throws IOException {
422     ByteArrayOutputStream baos = new ByteArrayOutputStream();
423
424     try (final ZipOutputStream zos = new ZipOutputStream(baos);
425          ZipInputStream zipStream = new ZipInputStream(
426              new ByteArrayInputStream(contentData.array()))) {
427       ZipEntry zipEntry;
428       while ((zipEntry = zipStream.getNextEntry()) != null) {
429         ZipEntry locZipEntry = new ZipEntry(zipEntry.getName());
430         zos.putNextEntry(locZipEntry);
431         byte[] buf = new byte[1024];
432         int len;
433         while ((len = zipStream.read(buf)) > 0) {
434           zos.write(buf, 0, (len < buf.length) ? len : buf.length);
435         }
436         zos.closeEntry();
437       }
438     }
439     return baos.toByteArray();
440   }
441
442   @Override
443   public Optional<List<ErrorMessage>> validateFileDataStructure(
444       FilesDataStructure filesDataStructure) {
445     return candidateServiceValidator.validateFileDataStructure(filesDataStructure);
446   }
447
448   @Override
449   public void deleteOrchestrationTemplateCandidate(String vspId, Version versionId) {
450     orchestrationTemplateCandidateDao.delete(vspId, versionId);
451   }
452
453   @Override
454   public void updateValidationData(String vspId, Version version, ValidationStructureList
455       validationData) {
456     orchestrationTemplateCandidateDao.updateValidationData(vspId, version, validationData);
457   }
458
459   private void writeManifest(String manifest,
460                              OnboardingTypesEnum type,
461                              ZipOutputStream zos) throws IOException {
462
463     if (isManifestNeedsToGetWritten(type)) {
464       return;
465     }
466
467     zos.putNextEntry(new ZipEntry(SdcCommon.MANIFEST_NAME));
468     try (InputStream manifestStream = new ByteArrayInputStream(
469         manifest.getBytes(StandardCharsets.UTF_8))) {
470       byte[] buf = new byte[1024];
471       int len;
472       while ((len = (manifestStream.read(buf))) > 0) {
473         zos.write(buf, 0, (len < buf.length) ? len : buf.length);
474       }
475     }
476   }
477
478   private boolean isManifestNeedsToGetWritten(OnboardingTypesEnum type) {
479     return type.equals(OnboardingTypesEnum.CSAR);
480   }
481
482   private void handleArtifactsFromTree(HeatStructureTree tree, FilesDataStructure structure) {
483
484     if (Objects.isNull(tree) || Objects.isNull(tree.getArtifacts())) {
485       return;
486     }
487
488     if (CollectionUtils.isNotEmpty(tree.getArtifacts())) {
489       structure.getArtifacts().addAll(
490           tree.getArtifacts()
491               .stream()
492               .map(Artifact::getFileName)
493               .filter(fileName -> !structure.getArtifacts().contains(fileName))
494               .collect(Collectors.toList()));
495     }
496   }
497
498   private void handleOtherResources(HeatStructureTree tree, Set<String> usedEnvFiles,
499                                     FilesDataStructure structure) {
500     Set<HeatStructureTree> others = tree.getOther();
501     if (Objects.isNull(others)) {
502       return;
503     }
504
505     List<String> artifacts = new ArrayList<>();
506     List<String> unassigned = new ArrayList<>();
507     for (HeatStructureTree other : others) {
508       if (HeatFileAnalyzer.isYamlOrEnvFile(other.getFileName())) {
509         if (isEnvFileUsedByHeatFile(usedEnvFiles, other)) {
510           continue;
511         }
512         unassigned.add(other.getFileName());
513       } else {
514         artifacts.add(other.getFileName());
515       }
516       handleArtifactsFromTree(other, structure);
517     }
518     structure.getArtifacts().addAll(artifacts);
519     structure.getUnassigned().addAll(unassigned);
520   }
521
522   private boolean isEnvFileUsedByHeatFile(Set<String> usedEnvFiles, HeatStructureTree other) {
523     return HeatFileAnalyzer.isEnvFile(other.getFileName()) &&
524         usedEnvFiles.contains(other.getFileName());
525   }
526
527   private void addHeatsToFileDataStructure(HeatStructureTree tree, Set<String> usedEnvFiles,
528                                            FilesDataStructure structure,
529                                            Map<String, List<ErrorMessage>> uploadErrors,
530                                            AnalyzedZipHeatFiles analyzedZipHeatFiles) {
531     List<Module> modules = new ArrayList<>();
532     Set<HeatStructureTree> heatsSet = tree.getHeat();
533     if (Objects.isNull(heatsSet)) {
534       return;
535     }
536     for (HeatStructureTree heat : heatsSet) {
537       if (isFileBaseFile(heat.getFileName())) {
538         handleSingleHeat(structure, modules, heat, uploadErrors);
539       } else if (isFileModuleFile(heat.getFileName(),
540           analyzedZipHeatFiles.getModuleFiles())) {
541         handleSingleHeat(structure, modules, heat, uploadErrors);
542       } else {
543         structure.getUnassigned().add(heat.getFileName());
544         addNestedToFileDataStructure(heat, structure);
545       }
546       if (!Objects.isNull(heat.getEnv())) {
547         usedEnvFiles.add(heat.getEnv() == null ? null : heat.getEnv().getFileName());
548       }
549     }
550     structure.setModules(modules);
551
552   }
553
554   private boolean isFileModuleFile(String fileName, Set<String> modulesFileNames) {
555     return modulesFileNames.contains(fileName);
556   }
557
558   private boolean isFileBaseFile(String fileName) {
559     return manifestCreator.isFileBaseFile(fileName);
560   }
561
562   private void handleSingleHeat(FilesDataStructure structure, List<Module> modules,
563                                 HeatStructureTree heat,
564                                 Map<String, List<ErrorMessage>> uploadErrors) {
565     Module module = new Module();
566     module.setYaml(heat.getFileName());
567     module.setIsBase(heat.getBase());
568     addNestedToFileDataStructure(heat, structure);
569     Set<HeatStructureTree> volumeSet = heat.getVolume();
570     int inx = 0;
571     if (Objects.nonNull(volumeSet)) {
572       handleVolumes(module, volumeSet, structure, inx, uploadErrors);
573     }
574     handleEnv(module, heat, false, structure);
575     modules.add(module);
576   }
577
578   private void handleVolumes(Module module, Set<HeatStructureTree> volumeSet,
579                              FilesDataStructure structure, int inx,
580                              Map<String, List<ErrorMessage>> uploadErrors) {
581     for (HeatStructureTree volume : volumeSet) {
582       Objects.requireNonNull(volume, "volume cannot be null!");
583       if (inx++ > 0) {
584         ErrorsUtil.addStructureErrorToErrorMap(SdcCommon.UPLOAD_FILE,
585             new ErrorMessage(ErrorLevel.WARNING,
586                 Messages.MORE_THEN_ONE_VOL_FOR_HEAT.getErrorMessage()), uploadErrors);
587         break;
588       }
589       handleArtifactsFromTree(volume, structure);
590       module.setVol(volume.getFileName());
591       handleEnv(module, volume, true, structure);
592       addNestedToFileDataStructure(volume, structure);
593     }
594   }
595
596   private void handleEnv(Module module, HeatStructureTree tree, boolean isVolEnv,
597                          FilesDataStructure structure) {
598     if (Objects.nonNull(tree.getEnv())) {
599       if (isVolEnv) {
600         module.setVolEnv(tree.getEnv().getFileName());
601       } else {
602         module.setEnv(tree.getEnv().getFileName());
603       }
604       handleArtifactsFromTree(tree.getEnv(), structure);
605     }
606   }
607
608   private void addNestedToFileDataStructure(HeatStructureTree heat,
609                                             FilesDataStructure structure) {
610     Set<HeatStructureTree> nestedSet = heat.getNested();
611     if (Objects.isNull(nestedSet)) {
612       return;
613     }
614     for (HeatStructureTree nested : nestedSet) {
615       if (structure.getNested().contains(nested.getFileName())) {
616         continue;
617       }
618       structure.getNested().add(nested.getFileName());
619       if (CollectionUtils.isNotEmpty(nested.getArtifacts())) {
620         handleArtifactsFromTree(nested, structure);
621       }
622       addNestedToFileDataStructure(nested, structure);
623     }
624   }
625 }