Support unknown data types in service import
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / csar / ServiceCsarInfo.java
1 /*
2  * -
3  *  ============LICENSE_START=======================================================
4  *  Copyright (C) 2022 Nordix Foundation.
5  *  ================================================================================
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *       http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21
22 package org.openecomp.sdc.be.components.csar;
23
24 import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Map;
34 import org.apache.commons.collections.CollectionUtils;
35 import org.apache.commons.collections.MapUtils;
36 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
37 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
38 import org.openecomp.sdc.be.model.NodeTypeInfo;
39 import org.openecomp.sdc.be.model.User;
40 import org.openecomp.sdc.be.utils.TypeUtils;
41 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
42 import org.openecomp.sdc.common.log.wrappers.Logger;
43 import org.yaml.snakeyaml.Yaml;
44 import fj.data.Either;
45
46 /**
47  * Provides access to the contents of a Service CSAR
48  */
49 public class ServiceCsarInfo extends CsarInfo {
50
51     private Map<String, Map<String, Object>> mainTemplateImports;
52     private static final Logger log = Logger.getLogger(ServiceCsarInfo.class);
53
54     public ServiceCsarInfo(final User modifier, final String csarUUID, final Map<String, byte[]> csar, final String vfResourceName,
55             final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) {
56         super(modifier, csarUUID, csar, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate);
57
58         final Path mainTemplateDir = Paths.get(getMainTemplateName().substring(0, getMainTemplateName().lastIndexOf('/') + 1));
59         final Collection<Path> filesHandled = new HashSet<>();
60         filesHandled.add(Paths.get(mainTemplateName));
61         this.mainTemplateImports = getTemplateImports(csar, new Yaml().load(mainTemplateContent), mainTemplateDir, filesHandled);
62     }
63     
64     private Map<String, Map<String, Object>> getTemplateImports(final Map<String, byte[]> csar, Map<String, Object> mappedToscaMainTemplate,
65             final Path fileParentDir, final Collection<Path> filesHandled) {
66         final Map<String, Map<String, Object>> templateImports = new HashMap<>();
67
68         final List<Path> importFilePaths = getTempateImportFilePaths(mappedToscaMainTemplate, fileParentDir);
69
70         importFilePaths.stream().filter(path -> !filesHandled.contains(path)).forEach(
71                 importFilePath -> {
72                     byte[] importFile = csar.get(importFilePath.toString());
73                     if (importFile != null) {
74                         filesHandled.add(importFilePath);
75                         Map<String, Object> mappedImportFile = new Yaml().load(new String(csar.get(importFilePath.toString())));
76                         templateImports.put(importFilePath.toString(), mappedImportFile);
77                         
78                         templateImports.putAll(getTemplateImports(csar, mappedImportFile, importFilePath.getParent(), filesHandled));
79                         
80                     } else {
81                         log.info("Import {} cannot be found in CSAR", importFilePath.toString());
82                     }
83                 });
84
85         return templateImports;
86     }
87     
88     @SuppressWarnings({"unchecked", "rawtypes"})
89     private List<Path> getTempateImportFilePaths(final Map<String, Object> mappedToscaTemplate, final Path fileParentDir) {
90         final Either<Object, ResultStatusEnum> importsEither =
91                 findToscaElement(mappedToscaTemplate, ToscaTagNamesEnum.IMPORTS, ToscaElementTypeEnum.ALL);
92
93         if (importsEither.isLeft()) {
94             final List importsList = (List) importsEither.left().value();
95             if (CollectionUtils.isNotEmpty(importsList)) {
96                 if (importsList.get(0) instanceof String) {
97                     List<Path> importPaths = new ArrayList<>();
98                     importsList.stream().forEach(importPath -> importPaths.add(Paths.get((String)importPath)));
99                     return importPaths;
100                 } else if (importsList.get(0) instanceof Map) {
101                     return getTemplateImportFilePathsMultiLineGrammar(importsList, fileParentDir);
102                 }
103             }
104
105         }
106         return Collections.emptyList();
107     }
108
109     @SuppressWarnings("unchecked")
110     private List<Path> getTemplateImportFilePathsMultiLineGrammar(final List<Map<String, Object>> importsList, final Path fileParentDir) {
111         final List<Path> importFiles = new ArrayList<>();
112
113         for (Map<String, Object> importFileMultiLineGrammar : (List<Map<String, Object>>) importsList) {
114             if (MapUtils.isNotEmpty(importFileMultiLineGrammar)) {
115                 if (importFileMultiLineGrammar.values().iterator().next() instanceof String) {
116                     Path relativePath = Paths.get((String) importFileMultiLineGrammar.get("file"));
117                     Path absolutePath = fileParentDir.resolve(relativePath).normalize();
118                     importFiles.add(absolutePath);
119                 } else if (importFileMultiLineGrammar.values().iterator().next() instanceof Map) {
120                     importFileMultiLineGrammar.values().forEach(value -> {
121                         Path relativePath = Paths.get((String) ((Map<String, Object>) value).get("file"));
122                         Path absolutePath = fileParentDir == null ? relativePath : fileParentDir.resolve(relativePath).normalize();
123                         importFiles.add(absolutePath);
124                     });
125                 }
126             }
127         }
128         return importFiles;
129     }
130
131     @Override
132     public Map<String, NodeTypeInfo> extractTypesInfo() {
133         return Collections.emptyMap();
134     }
135
136     @Override
137     public Map<String, Object> getDataTypes() {
138         final Map<String, Object> definitions = new HashMap<>();
139         mainTemplateImports.entrySet().stream()
140                 .forEach(entry -> definitions.putAll(getTypesFromTemplate(entry.getValue(), TypeUtils.ToscaTagNamesEnum.DATA_TYPES)));
141         definitions.putAll(getTypesFromTemplate(getMappedToscaMainTemplate(), TypeUtils.ToscaTagNamesEnum.DATA_TYPES));
142         return definitions;
143     }
144
145 }