85f64699d4f732951a81f0f5d9277e7234d5a892
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / csar / OnboardedCsarInfo.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.util.ArrayList;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.regex.Pattern;
33 import org.apache.commons.collections.CollectionUtils;
34 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
35 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
36 import org.openecomp.sdc.be.config.NonManoConfiguration;
37 import org.openecomp.sdc.be.model.NodeTypeInfo;
38 import org.openecomp.sdc.be.model.User;
39 import org.openecomp.sdc.be.tosca.CsarUtils;
40 import org.openecomp.sdc.be.utils.TypeUtils;
41 import org.openecomp.sdc.common.api.Constants;
42 import org.yaml.snakeyaml.Yaml;
43 import fj.data.Either;
44
45 /**
46  * Provides access to the contents of a CSAR which has been created through the SDC onboarding
47  * process
48  */
49 public class OnboardedCsarInfo extends CsarInfo {
50
51     private List<Map.Entry<String, byte[]>> globalSubstitutes;
52
53     OnboardedCsarInfo(NonManoConfiguration nonManoConfiguration) {
54         super(nonManoConfiguration);
55     }
56
57     public OnboardedCsarInfo(final User modifier, final String csarUUID, final Map<String, byte[]> csar, final String vfResourceName,
58             final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) {
59         super(modifier, csarUUID, csar, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate);
60         this.globalSubstitutes = getGlobalSubstitutes(csar);
61     }
62
63     public OnboardedCsarInfo(final User modifier, final String csarUUID, final String csarVersionId, final Map<String, byte[]> csarContent,
64             final String vfResourceName, final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) {
65         super(modifier, csarUUID, csarVersionId, csarContent, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate);
66         this.globalSubstitutes = getGlobalSubstitutes(csar);
67     }
68
69     private List<Map.Entry<String, byte[]>> getGlobalSubstitutes(final Map<String, byte[]> csar) {
70         final List<Map.Entry<String, byte[]>> globalSubstitutesInCsar = new ArrayList<>();
71         for (Map.Entry<String, byte[]> entry : csar.entrySet()) {
72             if (isAServiceTemplate(entry.getKey()) && isGlobalSubstitute(entry.getKey())) {
73                 globalSubstitutesInCsar.add(entry);
74             }
75         }
76         return globalSubstitutesInCsar;
77     }
78
79     public Map<String, NodeTypeInfo> extractTypesInfo() {
80         final Map<String, NodeTypeInfo> nodeTypesInfo = new HashMap<>();
81         final Set<String> nodeTypesUsedInNodeTemplates = new HashSet<>();
82         for (Map.Entry<String, byte[]> entry : getCsar().entrySet()) {
83             extractNodeTypeInfo(nodeTypesInfo, nodeTypesUsedInNodeTemplates, entry);
84         }
85         if (CollectionUtils.isNotEmpty(globalSubstitutes)) {
86             setDerivedFrom(nodeTypesInfo);
87             addGlobalSubstitutionsToNodeTypes(nodeTypesUsedInNodeTemplates, nodeTypesInfo);
88         }
89
90         markNestedVfc(getMappedToscaMainTemplate(), nodeTypesInfo);
91         return nodeTypesInfo;
92     }
93
94     @SuppressWarnings("unchecked")
95     private void extractNodeTypeInfo(final Map<String, NodeTypeInfo> nodeTypesInfo, final Set<String> nodeTypesUsedInNodeTemplates,
96             final Map.Entry<String, byte[]> entry) {
97         if (isAServiceTemplate(entry.getKey()) && !isGlobalSubstitute(entry.getKey())) {
98             final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(new String(entry.getValue()));
99             findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS, ToscaElementTypeEnum.MAP).right()
100                     .on(sub -> handleSubstitutionMappings(nodeTypesInfo, entry, mappedToscaTemplate, (Map<String, Object>) sub));
101             final Either<Object, ResultStatusEnum> nodeTypesEither =
102                     findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES, ToscaElementTypeEnum.MAP);
103             if (nodeTypesEither.isLeft()) {
104                 final Map<String, Map<String, Object>> nodeTemplates = (Map<String, Map<String, Object>>) nodeTypesEither.left().value();
105                 nodeTypesUsedInNodeTemplates.addAll(findNodeTypesUsedInNodeTemplates(nodeTemplates));
106             }
107         }
108     }
109
110     private boolean isAServiceTemplate(final String filePath) {
111         return Pattern.compile(CsarUtils.SERVICE_TEMPLATE_PATH_PATTERN).matcher(filePath).matches();
112     }
113
114     private boolean isGlobalSubstitute(final String fileName) {
115         return fileName.equalsIgnoreCase(Constants.GLOBAL_SUBSTITUTION_TYPES_SERVICE_TEMPLATE)
116                 || fileName.equalsIgnoreCase(Constants.ABSTRACT_SUBSTITUTE_GLOBAL_TYPES_SERVICE_TEMPLATE);
117     }
118
119
120     private ResultStatusEnum handleSubstitutionMappings(final Map<String, NodeTypeInfo> nodeTypesInfo, final Map.Entry<String, byte[]> entry,
121             final Map<String, Object> mappedToscaTemplate, final Map<String, Object> substitutionMappings) {
122         final Set<String> nodeTypesDefinedInTemplate = findNodeTypesDefinedInTemplate(mappedToscaTemplate);
123         if (substitutionMappings.containsKey(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName())
124                 && !nodeTypesDefinedInTemplate.contains(substitutionMappings.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()))) {
125             NodeTypeInfo nodeTypeInfo = new NodeTypeInfo();
126             nodeTypeInfo.setSubstitutionMapping(true);
127             nodeTypeInfo.setType((String) substitutionMappings.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()));
128             nodeTypeInfo.setTemplateFileName(entry.getKey());
129             nodeTypeInfo.setMappedToscaTemplate(mappedToscaTemplate);
130             nodeTypesInfo.put(nodeTypeInfo.getType(), nodeTypeInfo);
131         }
132         return ResultStatusEnum.OK;
133     }
134
135     @SuppressWarnings("unchecked")
136     private Set<String> findNodeTypesDefinedInTemplate(final Map<String, Object> mappedToscaTemplate) {
137         final Either<Object, ResultStatusEnum> nodeTypesEither =
138                 findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP);
139         if (nodeTypesEither.isLeft()) {
140             final Map<String, Object> nodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
141             return nodeTypes.keySet();
142         }
143         return Collections.emptySet();
144     }
145
146     @SuppressWarnings("unchecked")
147     private void setDerivedFrom(final Map<String, NodeTypeInfo> nodeTypesInfo) {
148         for (Map.Entry<String, byte[]> entry : globalSubstitutes) {
149             final String yamlFileContents = new String(entry.getValue());
150             final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(yamlFileContents);
151             Either<Object, ResultStatusEnum> nodeTypesEither =
152                     findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP);
153             if (nodeTypesEither.isLeft()) {
154                 Map<String, Object> nodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
155                 for (Map.Entry<String, Object> nodeType : nodeTypes.entrySet()) {
156                     processNodeType(nodeTypesInfo, nodeType);
157                 }
158             }
159         }
160     }
161
162     @SuppressWarnings("unchecked")
163     private void processNodeType(final Map<String, NodeTypeInfo> nodeTypesInfo, final Map.Entry<String, Object> nodeType) {
164         final Map<String, Object> nodeTypeMap = (Map<String, Object>) nodeType.getValue();
165         if (nodeTypeMap.containsKey(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()) && nodeTypesInfo.containsKey(nodeType.getKey())) {
166             final NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(nodeType.getKey());
167             final List<String> derivedFrom = new ArrayList<>();
168             derivedFrom.add((String) nodeTypeMap.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()));
169             nodeTypeInfo.setDerivedFrom(derivedFrom);
170         }
171     }
172
173     @SuppressWarnings("unchecked")
174     private void addGlobalSubstitutionsToNodeTypes(final Set<String> nodeTypesUsedInNodeTemplates, final Map<String, NodeTypeInfo> nodeTypesInfo) {
175         for (Map.Entry<String, byte[]> entry : globalSubstitutes) {
176             final String yamlFileContents = new String(entry.getValue());
177             final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(yamlFileContents);
178             final Either<Object, ResultStatusEnum> nodeTypesEither =
179                     findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP);
180             if (nodeTypesEither.isLeft()) {
181                 final Map<String, Object> nodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
182                 for (final Map.Entry<String, Object> nodeType : nodeTypes.entrySet()) {
183                     if (!nodeTypesInfo.containsKey(nodeType.getKey()) && nodeTypesUsedInNodeTemplates.contains(nodeType.getKey())) {
184                         nodeTypesInfo.put(nodeType.getKey(), buildNodeTypeInfo(nodeType, entry.getKey(), mappedToscaTemplate));
185                     }
186                 }
187             }
188         }
189     }
190
191     @Override
192     public Map<String, Object> getDataTypes() {
193         if (datatypeDefinitions == null) {
194             datatypeDefinitions = new HashMap<>();
195             for (Map.Entry<String, byte[]> entry : globalSubstitutes) {
196                 final String yamlFileContents = new String(entry.getValue());
197                 final Map<String, Object> mappedToscaTemplate = new Yaml().load(yamlFileContents);
198                 datatypeDefinitions.putAll(getTypesFromTemplate(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.DATA_TYPES));
199             }
200             datatypeDefinitions.putAll(getTypesFromTemplate(mappedToscaMainTemplate, TypeUtils.ToscaTagNamesEnum.DATA_TYPES));
201         }
202         return datatypeDefinitions;
203     }
204
205 }