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