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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.openecomp.sdc.be.components.csar;
24 import static org.openecomp.sdc.be.components.impl.ImportUtils.Constants.DEFAULT_ICON;
25 import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement;
27 import fj.data.Either;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.List;
38 import org.apache.commons.collections.CollectionUtils;
39 import org.apache.commons.collections.MapUtils;
40 import org.openecomp.sdc.be.components.impl.ImportUtils;
41 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
42 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
43 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
44 import org.openecomp.sdc.be.model.NodeTypeDefinition;
45 import org.openecomp.sdc.be.model.NodeTypeInfo;
46 import org.openecomp.sdc.be.model.NodeTypeMetadata;
47 import org.openecomp.sdc.be.model.NullNodeTypeMetadata;
48 import org.openecomp.sdc.be.model.User;
49 import org.openecomp.sdc.be.model.category.CategoryDefinition;
50 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
51 import org.openecomp.sdc.be.utils.TypeUtils;
52 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
53 import org.openecomp.sdc.common.log.wrappers.Logger;
54 import org.yaml.snakeyaml.Yaml;
57 * Provides access to the contents of a Service CSAR
59 public class ServiceCsarInfo extends CsarInfo {
61 private static final Logger log = Logger.getLogger(ServiceCsarInfo.class);
62 private final Map<String, Map<String, Object>> mainTemplateImports;
63 private List<NodeTypeDefinition> nodeTypeDefinitions;
65 public ServiceCsarInfo(final User modifier, final String csarUUID, final Map<String, byte[]> csar, final String vfResourceName,
66 final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) {
67 super(modifier, csarUUID, csar, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate);
69 final Path mainTemplateDir = Paths.get(getMainTemplateName().substring(0, getMainTemplateName().lastIndexOf('/') + 1));
70 final Collection<Path> filesHandled = new HashSet<>();
71 filesHandled.add(Paths.get(mainTemplateName));
72 this.mainTemplateImports = getTemplateImports(csar, new Yaml().load(mainTemplateContent), mainTemplateDir, filesHandled);
75 private Map<String, Map<String, Object>> getTemplateImports(final Map<String, byte[]> csar, Map<String, Object> mappedToscaMainTemplate,
76 final Path fileParentDir, final Collection<Path> filesHandled) {
77 final Map<String, Map<String, Object>> templateImports = new HashMap<>();
79 final List<Path> importFilePaths = getTemplateImportFilePaths(mappedToscaMainTemplate, fileParentDir);
81 importFilePaths.stream().filter(path -> !filesHandled.contains(path)).forEach(
83 byte[] importFile = csar.get(importFilePath.toString());
84 if (importFile != null) {
85 filesHandled.add(importFilePath);
86 Map<String, Object> mappedImportFile = new Yaml().load(new String(csar.get(importFilePath.toString())));
87 templateImports.put(importFilePath.toString(), mappedImportFile);
88 templateImports.putAll(getTemplateImports(csar, mappedImportFile, importFilePath.getParent(), filesHandled));
90 log.info("Import {} cannot be found in CSAR", importFilePath.toString());
94 return templateImports;
97 @SuppressWarnings({"unchecked", "rawtypes"})
98 private List<Path> getTemplateImportFilePaths(final Map<String, Object> mappedToscaTemplate, final Path fileParentDir) {
99 final Either<Object, ResultStatusEnum> importsEither =
100 findToscaElement(mappedToscaTemplate, ToscaTagNamesEnum.IMPORTS, ToscaElementTypeEnum.ALL);
102 if (importsEither.isLeft()) {
103 final List importsList = (List) importsEither.left().value();
104 if (CollectionUtils.isNotEmpty(importsList)) {
105 if (importsList.get(0) instanceof String) {
106 List<Path> importPaths = new ArrayList<>();
108 .forEach(importPath -> importPaths.add(fileParentDir == null ? Paths.get((String) importPath)
109 : fileParentDir.resolve(Paths.get((String) importPath)).normalize()));
111 } else if (importsList.get(0) instanceof Map) {
112 return getTemplateImportFilePathsMultiLineGrammar(importsList, fileParentDir);
117 return Collections.emptyList();
120 @SuppressWarnings("unchecked")
121 private List<Path> getTemplateImportFilePathsMultiLineGrammar(final List<Map<String, Object>> importsList, final Path fileParentDir) {
122 final List<Path> importFiles = new ArrayList<>();
124 for (Map<String, Object> importFileMultiLineGrammar : importsList) {
125 if (MapUtils.isNotEmpty(importFileMultiLineGrammar)) {
126 if (importFileMultiLineGrammar.values().iterator().next() instanceof String) {
127 Path relativePath = Paths.get((String) importFileMultiLineGrammar.get("file"));
128 Path absolutePath = fileParentDir == null ? relativePath : fileParentDir.resolve(relativePath).normalize();
129 importFiles.add(absolutePath);
130 } else if (importFileMultiLineGrammar.values().iterator().next() instanceof Map) {
131 importFileMultiLineGrammar.values().forEach(value -> {
132 Path relativePath = Paths.get((String) ((Map<String, Object>) value).get("file"));
133 Path absolutePath = fileParentDir == null ? relativePath : fileParentDir.resolve(relativePath).normalize();
134 importFiles.add(absolutePath);
143 public Map<String, NodeTypeInfo> extractTypesInfo() {
144 return Collections.emptyMap();
148 public Map<String, Object> getDataTypes() {
149 return getTypes(ToscaTagNamesEnum.DATA_TYPES);
153 public Map<String, Object> getGroupTypes() {
154 return getTypes(ToscaTagNamesEnum.GROUP_TYPES);
158 public Map<String, Object> getCapabilityTypes() {
159 return getTypes(ToscaTagNamesEnum.CAPABILITY_TYPES);
162 private Map<String, Object> getTypes(ToscaTagNamesEnum toscaTag) {
163 final Map<String, Object> types = new HashMap<>();
164 mainTemplateImports.entrySet().stream().forEach(entry -> types.putAll(getTypesFromTemplate(entry.getValue(), toscaTag)));
165 types.putAll(getTypesFromTemplate(getMappedToscaMainTemplate(), toscaTag));
169 public Map<String, Object> getArtifactTypes() {
170 final Map<String, Object> artifactsTypes = new HashMap<>();
171 mainTemplateImports.entrySet().stream()
172 .forEach(entry -> artifactsTypes.putAll(getTypesFromTemplate(entry.getValue(), TypeUtils.ToscaTagNamesEnum.ARTIFACT_TYPES)));
173 artifactsTypes.putAll(getTypesFromTemplate(getMappedToscaMainTemplate(), TypeUtils.ToscaTagNamesEnum.ARTIFACT_TYPES));
174 return artifactsTypes;
177 public List<NodeTypeDefinition> getNodeTypesUsed() {
178 if (nodeTypeDefinitions == null) {
179 nodeTypeDefinitions = new ArrayList<>();
180 final Set<String> nodeTypesUsed = getNodeTypesUsedInToscaTemplate(getMappedToscaMainTemplate());
181 nodeTypeDefinitions.addAll(getNodeTypeDefinitions(nodeTypesUsed));
183 nodeTypeDefinitions = sortNodeTypesByDependencyOrder(nodeTypeDefinitions);
184 return nodeTypeDefinitions;
187 private List<NodeTypeDefinition> sortNodeTypesByDependencyOrder(final List<NodeTypeDefinition> nodeTypes) {
188 final List<NodeTypeDefinition> sortedNodeTypeDefinitions = new ArrayList<>();
189 final Map<String, NodeTypeDefinition> nodeTypeDefinitionsMap = new HashMap<>();
191 nodeTypes.forEach(nodeType -> {
192 int highestDependencyIndex = -1;
193 for (final String dependencyName : getDependencyTypes(nodeType, nodeTypes)) {
194 final NodeTypeDefinition dependency = nodeTypeDefinitionsMap.get(dependencyName);
195 final int indexOfDependency = sortedNodeTypeDefinitions.lastIndexOf(dependency);
196 highestDependencyIndex = indexOfDependency > highestDependencyIndex ? indexOfDependency : highestDependencyIndex;
198 sortedNodeTypeDefinitions.add(highestDependencyIndex + 1, nodeType);
199 nodeTypeDefinitionsMap.put(nodeType.getMappedNodeType().getKey(), nodeType);
201 return sortedNodeTypeDefinitions;
204 private Collection<String> getDependencyTypes(final NodeTypeDefinition nodeType, final List<NodeTypeDefinition> nodeTypes) {
205 final Set<String> dependencies = new HashSet<>();
206 Either<Object, ResultStatusEnum> derivedFromTypeEither = findToscaElement((Map<String, Object>) nodeType.getMappedNodeType().getValue(),
207 TypeUtils.ToscaTagNamesEnum.DERIVED_FROM, ToscaElementTypeEnum.STRING);
208 if (derivedFromTypeEither.isLeft() && derivedFromTypeEither.left().value() != null) {
209 final String derivedFrom = (String) derivedFromTypeEither.left().value();
210 dependencies.add(derivedFrom);
211 nodeTypes.stream().filter(derivedFromCandidate -> derivedFrom.contentEquals(derivedFromCandidate.getMappedNodeType().getKey()))
212 .forEach(derivedFromNodeType -> dependencies.addAll(getDependencyTypes(derivedFromNodeType, nodeTypes)));
217 private Set<NodeTypeDefinition> getNodeTypeDefinitions(final Set<String> nodeTypesToGet) {
218 final Set<NodeTypeDefinition> nodeTypesToReturn = new HashSet<>();
219 final Set<NodeTypeDefinition> foundNodeTypes = getTypes(nodeTypesToGet);
220 nodeTypesToReturn.addAll(foundNodeTypes);
221 final Set<String> recursiveNodeTypesToGet = new HashSet<>();
222 foundNodeTypes.stream().forEach(nodeTypeDef -> {
223 Either<Object, ResultStatusEnum> derivedFromTypeEither =
224 findToscaElement((Map<String, Object>) nodeTypeDef.getMappedNodeType().getValue(), TypeUtils.ToscaTagNamesEnum.DERIVED_FROM,
225 ToscaElementTypeEnum.STRING);
226 if (derivedFromTypeEither.isLeft()) {
227 recursiveNodeTypesToGet.add((String) derivedFromTypeEither.left().value());
230 recursiveNodeTypesToGet.removeAll(nodeTypesToGet);
231 if (CollectionUtils.isNotEmpty(recursiveNodeTypesToGet)) {
232 nodeTypesToReturn.addAll(getNodeTypeDefinitions(recursiveNodeTypesToGet));
234 return nodeTypesToReturn;
238 private Set<NodeTypeDefinition> getTypes(final Set<String> nodeTypes) {
239 Set<NodeTypeDefinition> nodeTypeDefinitionsLocal = new HashSet<>();
240 mainTemplateImports.entrySet().forEach(entry -> {
241 final Map<String, Object> types = getTypesFromTemplate(entry.getValue(), TypeUtils.ToscaTagNamesEnum.NODE_TYPES, nodeTypes);
242 if (MapUtils.isNotEmpty(types)) {
243 types.entrySet().stream().forEach(typesEntry -> {
244 final NodeTypeMetadata metadata =
245 getMetaDataFromTemplate(entry.getValue(), typesEntry.getKey());
246 nodeTypeDefinitionsLocal.add(new NodeTypeDefinition(typesEntry, metadata));
250 return nodeTypeDefinitionsLocal;
253 @SuppressWarnings("unchecked")
254 private Set<String> getNodeTypesUsedInToscaTemplate(Map<String, Object> mappedToscaTemplate) {
255 final Either<Object, ResultStatusEnum> nodeTemplatesEither = findToscaElement(mappedToscaTemplate,
256 TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES, ToscaElementTypeEnum.MAP);
257 final Set<String> nodeTypesUsedInNodeTemplates = new HashSet<>();
258 if (nodeTemplatesEither.isLeft()) {
259 final Map<String, Map<String, Object>> nodeTemplates =
260 (Map<String, Map<String, Object>>) nodeTemplatesEither.left().value();
261 nodeTypesUsedInNodeTemplates.addAll(findNodeTypesUsedInNodeTemplates(nodeTemplates));
263 return nodeTypesUsedInNodeTemplates;
266 private NodeTypeMetadata getMetaDataFromTemplate(Map<String, Object> mappedResourceTemplate, String nodeTemplateType) {
267 NodeTypeMetadata nodeTypeMetadata = new NodeTypeMetadata();
268 Either<Map<String, Object>, ImportUtils.ResultStatusEnum> metadataEither = ImportUtils.findFirstToscaMapElement(mappedResourceTemplate,
269 TypeUtils.ToscaTagNamesEnum.METADATA);
270 if (metadataEither.isLeft() && metadataEither.left().value().get("type").equals(ResourceTypeEnum.VFC.getValue())) {
271 Map<String, Object> metadata = metadataEither.left().value();
272 createMetadataFromTemplate(nodeTypeMetadata, metadata, nodeTemplateType);
274 nodeTypeMetadata = createDefaultMetadata(nodeTemplateType);
276 return nodeTypeMetadata;
279 private void createMetadataFromTemplate(NodeTypeMetadata nodeTypeMetadata, Map<String, Object> metadata, String nodeTemplateType) {
280 nodeTypeMetadata.setToscaName(nodeTemplateType);
281 nodeTypeMetadata.setContactId(getModifier().getUserId());
282 nodeTypeMetadata.setDescription((String) metadata.get("description"));
283 List<String> tags = new ArrayList<>();
284 tags.add((String) metadata.get("name"));
285 nodeTypeMetadata.setTags(tags);
286 SubCategoryDefinition subCategory = new SubCategoryDefinition();
287 subCategory.setName((String) metadata.get("subcategory"));
288 CategoryDefinition category = new CategoryDefinition();
289 category.setName((String) metadata.get("category"));
290 category.setNormalizedName(((String) metadata.get("category")).toLowerCase());
291 category.setIcons(List.of(DEFAULT_ICON));
292 category.setNormalizedName(((String) metadata.get("category")).toLowerCase());
293 category.addSubCategory(subCategory);
294 List<CategoryDefinition> categories = new ArrayList<>();
295 categories.add(category);
296 nodeTypeMetadata.setCategories(categories);
297 nodeTypeMetadata.setName((String) metadata.get("name"));
298 nodeTypeMetadata.setIcon("defaulticon");
299 nodeTypeMetadata.setResourceVendorModelNumber((String) metadata.get("resourceVendorModelNumber"));
300 nodeTypeMetadata.setResourceType((String) metadata.get("type"));
301 nodeTypeMetadata.setVendorName((String) metadata.get("resourceVendor"));
302 nodeTypeMetadata.setVendorRelease(String.valueOf(metadata.get("resourceVendorRelease")));
303 nodeTypeMetadata.setModel((String) metadata.get("model"));
304 nodeTypeMetadata.setNormative(false);
307 private NullNodeTypeMetadata createDefaultMetadata(String nodeTemplateType) {
308 NullNodeTypeMetadata nodeTypeMetadata = new NullNodeTypeMetadata();
309 nodeTypeMetadata.setToscaName(nodeTemplateType);
310 return nodeTypeMetadata;