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