2 * Copyright © 2016-2018 European Support Limited
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.openecomp.sdc.vendorsoftwareproduct.services.impl.filedatastructuremodule;
19 import static org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder.getErrorWithParameters;
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;
31 import java.util.Objects;
32 import java.util.Optional;
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.common.zip.ZipUtils;
48 import org.openecomp.sdc.common.zip.exception.ZipSlipException;
49 import org.openecomp.sdc.datatypes.error.ErrorLevel;
50 import org.openecomp.sdc.datatypes.error.ErrorMessage;
51 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
52 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
53 import org.openecomp.sdc.heat.datatypes.structure.Artifact;
54 import org.openecomp.sdc.heat.datatypes.structure.HeatStructureTree;
55 import org.openecomp.sdc.heat.datatypes.structure.ValidationStructureList;
56 import org.openecomp.sdc.vendorsoftwareproduct.dao.OrchestrationTemplateCandidateDao;
57 import org.openecomp.sdc.vendorsoftwareproduct.dao.OrchestrationTemplateCandidateDaoFactory;
58 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData;
59 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
60 import org.openecomp.sdc.vendorsoftwareproduct.errors.utils.ErrorsUtil;
61 import org.openecomp.sdc.vendorsoftwareproduct.services.HeatFileAnalyzer;
62 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.CandidateService;
63 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.ManifestCreator;
64 import org.openecomp.sdc.vendorsoftwareproduct.services.utils.CandidateServiceValidator;
65 import org.openecomp.sdc.vendorsoftwareproduct.types.CandidateDataEntityTo;
66 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.AnalyzedZipHeatFiles;
67 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
68 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Module;
69 import org.openecomp.sdc.versioning.dao.types.Version;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
73 public class CandidateServiceImpl implements CandidateService {
74 private static final Logger logger = LoggerFactory.getLogger(CandidateServiceImpl.class);
75 private CandidateServiceValidator candidateServiceValidator = new CandidateServiceValidator();
76 private ManifestCreator manifestCreator;
77 private OrchestrationTemplateCandidateDao orchestrationTemplateCandidateDao;
79 public CandidateServiceImpl(ManifestCreator manifestCreator,
80 OrchestrationTemplateCandidateDao orchestrationTemplateCandidateDao) {
81 this.manifestCreator = manifestCreator;
82 this.orchestrationTemplateCandidateDao = orchestrationTemplateCandidateDao;
85 public CandidateServiceImpl() {
89 public Optional<ErrorMessage> validateNonEmptyFileToUpload(InputStream fileToUpload,
92 getErrorWithParameters(Messages.NO_FILE_WAS_UPLOADED_OR_FILE_NOT_EXIST.getErrorMessage(),
95 if (Objects.isNull(fileToUpload)) {
96 return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
100 int available = fileToUpload.available();
101 if (available == 0) {
102 return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
105 } catch (IOException e) {
106 logger.debug(e.getMessage(), e);
107 return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
111 return Optional.empty();
115 public Optional<ErrorMessage> validateRawZipData(String fileSuffix,
116 byte[] uploadedFileData) {
117 if (Objects.isNull(uploadedFileData)) {
118 return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
119 getErrorWithParameters(Messages.NO_FILE_WAS_UPLOADED_OR_FILE_NOT_EXIST.getErrorMessage(),
122 return Optional.empty();
125 private String heatStructureTreeToFileDataStructure(HeatStructureTree tree,
126 FileContentHandler zipContentMap,
127 Map<String, List<ErrorMessage>> uploadErrors,
128 AnalyzedZipHeatFiles analyzedZipHeatFiles) {
129 FilesDataStructure structure = new FilesDataStructure();
130 Set<String> usedEnvFiles = new HashSet<>();
131 addHeatsToFileDataStructure(tree, usedEnvFiles, structure, uploadErrors,
132 analyzedZipHeatFiles);
133 handleOtherResources(tree, usedEnvFiles, structure);
134 FilesDataStructure fileDataStructureFromManifest =
135 createFileDataStructureFromManifest(zipContentMap.getFileContentAsStream(SdcCommon.MANIFEST_NAME));
136 List<String> structureArtifacts = structure.getArtifacts();
137 structureArtifacts.addAll(fileDataStructureFromManifest.getArtifacts().stream().filter
138 (artifact -> isNotStrctureArtifact(structureArtifacts, artifact))
139 .collect(Collectors.toList()));
140 handleArtifactsFromTree(tree, structure);
142 return JsonUtil.object2Json(structure);
145 private boolean isNotStrctureArtifact(List<String> structureArtifacts, String artifact) {
146 return !structureArtifacts.contains(artifact);
150 public OrchestrationTemplateCandidateData createCandidateDataEntity(
151 CandidateDataEntityTo candidateDataEntityTo, InputStream zipFileManifest,
152 AnalyzedZipHeatFiles analyzedZipHeatFiles) {
153 FileContentHandler zipContentMap = candidateDataEntityTo.getContentMap();
154 FilesDataStructure filesDataStructure;
155 String dataStructureJson;
157 if (zipFileManifest != null) {
158 // create data structure from manifest
159 filesDataStructure = createFileDataStructureFromManifest(zipFileManifest);
160 Set<String> zipFileList = zipContentMap.getFileList();
161 balanceManifestFilesWithZipFiles(filesDataStructure,
162 zipContentMap, analyzedZipHeatFiles);
163 Set<String> filesDataStructureFiles = getFlatFileNames(filesDataStructure);
164 filesDataStructure.getUnassigned().addAll(zipFileList.stream()
165 .filter(fileName -> (!filesDataStructureFiles.contains(fileName)
166 && !filesDataStructure.getNested().contains(fileName)
167 && !fileName.equals(SdcCommon.MANIFEST_NAME)))
168 .collect(Collectors.toList()));
169 dataStructureJson = JsonUtil.object2Json(filesDataStructure);
171 // create data structure from based on naming convention
173 heatStructureTreeToFileDataStructure(candidateDataEntityTo.getTree(), zipContentMap,
174 candidateDataEntityTo.getErrors(), analyzedZipHeatFiles);
177 OrchestrationTemplateCandidateData candidateData = new OrchestrationTemplateCandidateData();
178 candidateData.setContentData(ByteBuffer.wrap(candidateDataEntityTo.getUploadedFileData()));
179 candidateData.setFilesDataStructure(dataStructureJson);
180 return candidateData;
183 private void balanceManifestFilesWithZipFiles(
184 FilesDataStructure filesDataStructure,
185 FileContentHandler fileContentHandler, AnalyzedZipHeatFiles analyzedZipHeatFiles) {
186 Set<String> zipFileList = fileContentHandler.getFileList();
187 filesDataStructure.getNested().addAll(analyzedZipHeatFiles.getNestedFiles());
188 List<Module> modules = filesDataStructure.getModules();
189 if (CollectionUtils.isEmpty(modules)) {
193 for (int i = 0; i < modules.size(); i++) {
194 Module module = modules.get(i);
195 if (!isFileExistInZipContains(zipFileList, module.getYaml())) {
196 addFileToUnassigned(filesDataStructure, zipFileList, module.getEnv());
197 addFileToUnassigned(filesDataStructure, zipFileList, module.getVol());
198 addFileToUnassigned(filesDataStructure, zipFileList, module.getVolEnv());
200 } else if (Objects.nonNull(module.getVol()) && !zipFileList.contains(module.getVol())) {
203 .addIgnoreNull(filesDataStructure.getUnassigned(), module.getVolEnv());
205 if (filesDataStructure.getNested().contains(module.getYaml())) {
206 moveModuleFileToNested(filesDataStructure, i--, module);
212 private void addFileToUnassigned(FilesDataStructure filesDataStructure, Set<String> zipFileList,
214 if (isFileExistInZipContains(zipFileList, fileName)) {
215 filesDataStructure.getUnassigned().add(fileName);
219 private boolean isFileExistInZipContains(Set<String> zipFileList, String fileName) {
220 return Objects.nonNull(fileName) && zipFileList.contains(fileName);
223 private void moveModuleFileToNested(FilesDataStructure filesDataStructure, int i,
225 if (!filesDataStructure.getNested().contains(module.getYaml())) {
226 filesDataStructure.getNested().add(module.getYaml());
228 if (Objects.nonNull(module.getEnv())) {
229 filesDataStructure.getNested().add(module.getEnv());
231 if (Objects.nonNull(module.getVol())) {
232 filesDataStructure.getNested().add(module.getVol());
234 if (Objects.nonNull(module.getVolEnv())) {
235 filesDataStructure.getNested().add(module.getVolEnv());
237 filesDataStructure.getModules().remove(i);
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());
250 fileNames.addAll(filesDataStructure.getArtifacts());
251 fileNames.addAll(filesDataStructure.getNested());
252 fileNames.addAll(filesDataStructure.getUnassigned());
257 private FilesDataStructure createFileDataStructureFromManifest(InputStream isManifestContent) {
258 ManifestContent manifestContent =
259 JsonUtil.json2Object(isManifestContent, ManifestContent.class);
260 FilesDataStructure structure = new FilesDataStructure();
261 for (FileData fileData : manifestContent.getData()) {
262 if (Objects.nonNull(fileData.getType()) &&
263 fileData.getType().equals(FileData.Type.HEAT)) {
264 Module module = new Module();
265 module.setType(FileData.Type.HEAT);
266 module.setYaml(fileData.getFile());
267 module.setIsBase(fileData.getBase());
268 addHeatDependenciesToModule(module, fileData.getData());
269 structure.getModules().add(module);
270 }else if (Objects.nonNull(fileData.getType()) &&
271 fileData.getType().equals(FileData.Type.HELM)) {
272 Module module = new Module();
273 module.setType(FileData.Type.HELM);
274 module.setYaml(fileData.getFile());
275 module.setIsBase(fileData.getBase());
276 structure.getModules().add(module);
278 else if (HeatFileAnalyzer.isYamlOrEnvFile(fileData.getFile()) &&
279 !FileData.Type.isArtifact(fileData.getType())) {
280 structure.getUnassigned().add(fileData.getFile());
282 structure.getArtifacts().add(fileData.getFile());
288 private void addHeatDependenciesToModule(Module module, List<FileData> data) {
289 if (CollectionUtils.isEmpty(data)) {
293 for (FileData fileData : data) {
294 if (fileData.getType().equals(FileData.Type.HEAT_ENV)) {
295 module.setEnv(fileData.getFile());
296 } else if (fileData.getType().equals(FileData.Type.HEAT_VOL)) { // must be volume
297 module.setVol(fileData.getFile());
298 if (!CollectionUtils.isEmpty(fileData.getData())) {
299 FileData volEnv = fileData.getData().get(0);
300 if (volEnv.getType().equals(FileData.Type.HEAT_ENV)) {
301 module.setVolEnv(volEnv.getFile());
303 throw new CoreException((new ErrorCode.ErrorCodeBuilder())
304 .withMessage(Messages.ILLEGAL_MANIFEST.getErrorMessage())
305 .withId(Messages.ILLEGAL_MANIFEST.getErrorMessage())
306 .withCategory(ErrorCategory.APPLICATION).build());
310 throw new CoreException((new ErrorCode.ErrorCodeBuilder())
311 .withMessage(Messages.FILE_TYPE_NOT_LEGAL.getErrorMessage())
312 .withId(Messages.FILE_TYPE_NOT_LEGAL.getErrorMessage())
313 .withCategory(ErrorCategory.APPLICATION).build());
319 public void updateCandidateUploadData(final String vspId, final Version version,
320 final OrchestrationTemplateCandidateData uploadData) {
321 orchestrationTemplateCandidateDao.update(vspId, version, uploadData);
325 public Optional<FilesDataStructure> getOrchestrationTemplateCandidateFileDataStructure(
326 String vspId, Version version) {
327 Optional<String> jsonFileDataStructure =
328 orchestrationTemplateCandidateDao.getStructure(vspId, version);
330 if (jsonFileDataStructure.isPresent() && JsonUtil.isValidJson(jsonFileDataStructure.get())) {
332 .of(JsonUtil.json2Object(jsonFileDataStructure.get(), FilesDataStructure.class));
334 return Optional.empty();
339 public void updateOrchestrationTemplateCandidateFileDataStructure(String vspId, Version version,
340 FilesDataStructure fileDataStructure) {
341 OrchestrationTemplateCandidateDaoFactory.getInstance().createInterface()
342 .updateStructure(vspId, version, fileDataStructure);
346 public Optional<OrchestrationTemplateCandidateData> getOrchestrationTemplateCandidate(String vspId,
348 return orchestrationTemplateCandidateDao.get(vspId, version);
352 public Optional<OrchestrationTemplateCandidateData> getOrchestrationTemplateCandidateInfo(
355 return orchestrationTemplateCandidateDao.getInfo(vspId, version);
359 public String createManifest(VspDetails vspDetails, FilesDataStructure structure) {
360 return JsonUtil.object2Json(manifestCreator.createManifest(vspDetails, structure)
361 .orElseThrow(() -> new CoreException(new ErrorCode.ErrorCodeBuilder()
362 .withMessage(Messages.CREATE_MANIFEST_FROM_ZIP.getErrorMessage()).build())));
366 public Optional<ManifestContent> createManifest(VspDetails vspDetails,
367 FileContentHandler fileContentHandler,
368 AnalyzedZipHeatFiles analyzedZipHeatFiles) {
369 return manifestCreator.createManifest(vspDetails, fileContentHandler, analyzedZipHeatFiles);
373 public Optional<ByteArrayInputStream> fetchZipFileByteArrayInputStream(String vspId,
374 OrchestrationTemplateCandidateData candidateDataEntity,
376 OnboardingTypesEnum type,
377 Map<String, List<ErrorMessage>> uploadErrors) {
379 ByteArrayInputStream byteArrayInputStream = null;
381 file = replaceManifestInZip(candidateDataEntity.getContentData(), manifest, type);
382 byteArrayInputStream = new ByteArrayInputStream(
383 Objects.isNull(file) ? candidateDataEntity.getContentData().array()
385 } catch (IOException e) {
386 ErrorMessage errorMessage =
387 new ErrorMessage(ErrorLevel.ERROR,
388 Messages.CANDIDATE_PROCESS_FAILED.getErrorMessage());
389 logger.error(errorMessage.getMessage(), e);
391 .addStructureErrorToErrorMap(SdcCommon.UPLOAD_FILE, errorMessage, uploadErrors);
393 return Optional.ofNullable(byteArrayInputStream);
397 public byte[] replaceManifestInZip(ByteBuffer contentData, String manifest,
398 OnboardingTypesEnum type)
400 ByteArrayOutputStream baos = new ByteArrayOutputStream();
402 try (final ZipOutputStream zos = new ZipOutputStream(baos);
403 ZipInputStream zipStream = new ZipInputStream(
404 new ByteArrayInputStream(contentData.array()))) {
406 boolean manifestWritten = false;
407 while ((zipEntry = zipStream.getNextEntry()) != null) {
408 if (!zipEntry.getName().equalsIgnoreCase(SdcCommon.MANIFEST_NAME)) {
409 ZipEntry loc_ze = new ZipEntry(zipEntry.getName());
410 zos.putNextEntry(loc_ze);
411 byte[] buf = new byte[1024];
413 while ((len = zipStream.read(buf)) > 0) {
414 zos.write(buf, 0, (len < buf.length) ? len : buf.length);
417 manifestWritten = true;
418 writeManifest(manifest, type, zos);
422 if (!manifestWritten) {
423 writeManifest(manifest, type, zos);
427 return baos.toByteArray();
431 public byte[] getZipData(ByteBuffer contentData)
433 ByteArrayOutputStream baos = new ByteArrayOutputStream();
435 try (final ZipOutputStream zos = new ZipOutputStream(baos);
436 ZipInputStream zipStream = new ZipInputStream(
437 new ByteArrayInputStream(contentData.array()))) {
439 while ((zipEntry = zipStream.getNextEntry()) != null) {
441 ZipUtils.checkForZipSlipInRead(zipEntry);
442 } catch (ZipSlipException e) {
443 throw new IOException(e);
445 ZipEntry locZipEntry = new ZipEntry(zipEntry.getName());
446 zos.putNextEntry(locZipEntry);
447 byte[] buf = new byte[1024];
449 while ((len = zipStream.read(buf)) > 0) {
450 zos.write(buf, 0, (len < buf.length) ? len : buf.length);
455 return baos.toByteArray();
459 public Optional<List<ErrorMessage>> validateFileDataStructure(
460 FilesDataStructure filesDataStructure) {
461 return candidateServiceValidator.validateFileDataStructure(filesDataStructure);
465 public void deleteOrchestrationTemplateCandidate(String vspId, Version versionId) {
466 orchestrationTemplateCandidateDao.delete(vspId, versionId);
470 public void updateValidationData(String vspId, Version version, ValidationStructureList
472 orchestrationTemplateCandidateDao.updateValidationData(vspId, version, validationData);
475 private void writeManifest(String manifest,
476 OnboardingTypesEnum type,
477 ZipOutputStream zos) throws IOException {
479 if (isManifestNeedsToGetWritten(type)) {
483 zos.putNextEntry(new ZipEntry(SdcCommon.MANIFEST_NAME));
484 try (InputStream manifestStream = new ByteArrayInputStream(
485 manifest.getBytes(StandardCharsets.UTF_8))) {
486 byte[] buf = new byte[1024];
488 while ((len = (manifestStream.read(buf))) > 0) {
489 zos.write(buf, 0, (len < buf.length) ? len : buf.length);
494 private boolean isManifestNeedsToGetWritten(OnboardingTypesEnum type) {
495 return type.equals(OnboardingTypesEnum.CSAR);
498 private void handleArtifactsFromTree(HeatStructureTree tree, FilesDataStructure structure) {
500 if (Objects.isNull(tree) || Objects.isNull(tree.getArtifacts())) {
504 if (CollectionUtils.isNotEmpty(tree.getArtifacts())) {
505 structure.getArtifacts().addAll(
508 .map(Artifact::getFileName)
509 .filter(fileName -> !structure.getArtifacts().contains(fileName))
510 .collect(Collectors.toList()));
514 private void handleOtherResources(HeatStructureTree tree, Set<String> usedEnvFiles,
515 FilesDataStructure structure) {
516 Set<HeatStructureTree> others = tree.getOther();
517 if (Objects.isNull(others)) {
521 List<String> artifacts = new ArrayList<>();
522 List<String> unassigned = new ArrayList<>();
523 for (HeatStructureTree other : others) {
524 if (HeatFileAnalyzer.isYamlOrEnvFile(other.getFileName())) {
525 if (isEnvFileUsedByHeatFile(usedEnvFiles, other)) {
528 unassigned.add(other.getFileName());
530 artifacts.add(other.getFileName());
532 handleArtifactsFromTree(other, structure);
534 structure.getArtifacts().addAll(artifacts);
535 structure.getUnassigned().addAll(unassigned);
538 private boolean isEnvFileUsedByHeatFile(Set<String> usedEnvFiles, HeatStructureTree other) {
539 return HeatFileAnalyzer.isEnvFile(other.getFileName()) &&
540 usedEnvFiles.contains(other.getFileName());
543 private void addHeatsToFileDataStructure(HeatStructureTree tree, Set<String> usedEnvFiles,
544 FilesDataStructure structure,
545 Map<String, List<ErrorMessage>> uploadErrors,
546 AnalyzedZipHeatFiles analyzedZipHeatFiles) {
547 List<Module> modules = new ArrayList<>();
548 Set<HeatStructureTree> heatsSet = tree.getHeat();
549 if (Objects.isNull(heatsSet)) {
552 for (HeatStructureTree heat : heatsSet) {
553 if (isFileBaseFile(heat.getFileName())) {
554 handleSingleHeat(structure, modules, heat, uploadErrors);
555 } else if (isFileModuleFile(heat.getFileName(),
556 analyzedZipHeatFiles.getModuleFiles())) {
557 handleSingleHeat(structure, modules, heat, uploadErrors);
559 structure.getUnassigned().add(heat.getFileName());
560 addNestedToFileDataStructure(heat, structure);
562 if (!Objects.isNull(heat.getEnv())) {
563 usedEnvFiles.add(heat.getEnv() == null ? null : heat.getEnv().getFileName());
566 structure.setModules(modules);
570 private boolean isFileModuleFile(String fileName, Set<String> modulesFileNames) {
571 return modulesFileNames.contains(fileName);
574 private boolean isFileBaseFile(String fileName) {
575 return manifestCreator.isFileBaseFile(fileName);
578 private void handleSingleHeat(FilesDataStructure structure, List<Module> modules,
579 HeatStructureTree heat,
580 Map<String, List<ErrorMessage>> uploadErrors) {
581 Module module = new Module();
582 module.setYaml(heat.getFileName());
583 module.setIsBase(heat.getBase());
584 addNestedToFileDataStructure(heat, structure);
585 Set<HeatStructureTree> volumeSet = heat.getVolume();
587 if (Objects.nonNull(volumeSet)) {
588 handleVolumes(module, volumeSet, structure, inx, uploadErrors);
590 handleEnv(module, heat, false, structure);
594 private void handleVolumes(Module module, Set<HeatStructureTree> volumeSet,
595 FilesDataStructure structure, int inx,
596 Map<String, List<ErrorMessage>> uploadErrors) {
597 for (HeatStructureTree volume : volumeSet) {
598 Objects.requireNonNull(volume, "volume cannot be null!");
600 ErrorsUtil.addStructureErrorToErrorMap(SdcCommon.UPLOAD_FILE,
601 new ErrorMessage(ErrorLevel.WARNING,
602 Messages.MORE_THEN_ONE_VOL_FOR_HEAT.getErrorMessage()), uploadErrors);
605 handleArtifactsFromTree(volume, structure);
606 module.setVol(volume.getFileName());
607 handleEnv(module, volume, true, structure);
608 addNestedToFileDataStructure(volume, structure);
612 private void handleEnv(Module module, HeatStructureTree tree, boolean isVolEnv,
613 FilesDataStructure structure) {
614 if (Objects.nonNull(tree.getEnv())) {
616 module.setVolEnv(tree.getEnv().getFileName());
618 module.setEnv(tree.getEnv().getFileName());
620 handleArtifactsFromTree(tree.getEnv(), structure);
624 private void addNestedToFileDataStructure(HeatStructureTree heat,
625 FilesDataStructure structure) {
626 Set<HeatStructureTree> nestedSet = heat.getNested();
627 if (Objects.isNull(nestedSet)) {
630 for (HeatStructureTree nested : nestedSet) {
631 if (structure.getNested().contains(nested.getFileName())) {
634 structure.getNested().add(nested.getFileName());
635 if (CollectionUtils.isNotEmpty(nested.getArtifacts())) {
636 handleArtifactsFromTree(nested, structure);
638 addNestedToFileDataStructure(nested, structure);