3 * * ============LICENSE_START=======================================================
4 * * Copyright (C) 2019 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=========================================================
23 package org.openecomp.core.impl;
25 import org.apache.commons.collections.MapUtils;
26 import org.onap.sdc.tosca.datatypes.model.ArtifactDefinition;
27 import org.onap.sdc.tosca.datatypes.model.CapabilityAssignment;
28 import org.onap.sdc.tosca.datatypes.model.Import;
29 import org.onap.sdc.tosca.datatypes.model.NodeFilter;
30 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
31 import org.onap.sdc.tosca.datatypes.model.NodeType;
32 import org.onap.sdc.tosca.datatypes.model.ParameterDefinition;
33 import org.onap.sdc.tosca.datatypes.model.RequirementAssignment;
34 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
35 import org.onap.sdc.tosca.datatypes.model.SubstitutionMapping;
36 import org.openecomp.core.converter.ServiceTemplateReaderService;
37 import org.openecomp.core.converter.ToscaConverter;
38 import org.openecomp.core.converter.datatypes.Constants;
39 import org.openecomp.core.converter.datatypes.CsarFileTypes;
40 import org.openecomp.core.converter.errors.SubstitutionMappingsConverterErrorBuilder;
41 import org.openecomp.core.impl.services.ServiceTemplateReaderServiceImpl;
42 import org.openecomp.core.utilities.file.FileContentHandler;
43 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
44 import org.openecomp.sdc.common.errors.CoreException;
45 import org.openecomp.sdc.common.errors.ErrorCategory;
46 import org.openecomp.sdc.common.errors.ErrorCode;
47 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
48 import org.openecomp.sdc.tosca.services.DataModelUtil;
49 import org.openecomp.sdc.tosca.services.ToscaUtil;
50 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
51 import org.yaml.snakeyaml.error.YAMLException;
53 import java.io.IOException;
54 import java.util.ArrayList;
55 import java.util.Collection;
56 import java.util.HashMap;
57 import java.util.List;
59 import java.util.Objects;
60 import java.util.Optional;
61 import java.util.regex.Pattern;
63 import static org.openecomp.core.converter.datatypes.Constants.ONAP_INDEX;
64 import static org.openecomp.core.converter.datatypes.Constants.capabilities;
65 import static org.openecomp.core.converter.datatypes.Constants.definitionsDir;
66 import static org.openecomp.core.converter.datatypes.Constants.globalStName;
67 import static org.openecomp.core.converter.datatypes.Constants.globalSubstitution;
68 import static org.openecomp.core.converter.datatypes.Constants.inputs;
69 import static org.openecomp.core.converter.datatypes.Constants.mainStName;
70 import static org.openecomp.core.converter.datatypes.Constants.nodeType;
71 import static org.openecomp.core.converter.datatypes.Constants.openecompHeatIndex;
72 import static org.openecomp.core.converter.datatypes.Constants.outputs;
73 import static org.openecomp.core.converter.datatypes.Constants.requirements;
74 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME;
75 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.HEAT_INDEX_IMPORT_FILE;
76 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.ONAP_INDEX_IMPORT_FILE;
77 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ORIG_PATH_FILE_NAME;
78 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_PATH_FILE_NAME;
80 public abstract class AbstractToscaConverter implements ToscaConverter {
83 public abstract ToscaServiceModel convert(FileContentHandler fileContentHandler) throws IOException;
85 protected void handleMetadataFile(Map<String, byte[]> csarFiles) {
86 byte[] bytes = csarFiles.remove(TOSCA_META_PATH_FILE_NAME);
88 csarFiles.put(TOSCA_META_ORIG_PATH_FILE_NAME, bytes);
92 protected void handleDefintionTemplate(String key, Map<String, byte[]> csarFiles,
93 GlobalSubstitutionServiceTemplate gsst) {
95 ServiceTemplateReaderService readerService = new ServiceTemplateReaderServiceImpl(csarFiles.get(key));
96 Object nodeTypes = readerService.getNodeTypes();
97 if (nodeTypes instanceof Map) {
98 Map<String, NodeType> nodeTypeMap = (Map<String, NodeType>) nodeTypes;
99 gsst.appendNodes(nodeTypeMap);
101 } catch (YAMLException ye) {
102 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
103 .withMessage("Invalid YAML content in file " + key)
104 .withCategory(ErrorCategory.APPLICATION).build(), ye);
108 protected String getConcreteArtifactFileName(String fileName){
109 int artifactIndex = fileName.indexOf(CsarFileTypes.Artifacts.name());
110 if(artifactIndex < 0){
114 int artifactDirectoryIndex =
115 artifactIndex + CsarFileTypes.Artifacts.name().length() + 1;
116 return fileName.substring(artifactDirectoryIndex);
119 protected void updateToscaServiceModel(ToscaServiceModel toscaServiceModel,
120 Map<String, ServiceTemplate> serviceTemplates,
121 FileContentHandler externalFilesHandler,
122 GlobalSubstitutionServiceTemplate globalSubstitutionServiceTemplate,
123 Map<String, byte[]> csarFiles, String entryDefinitionServiceTemplateName) {
124 Collection<ServiceTemplate> globalServiceTemplates =
125 GlobalTypesGenerator.getGlobalTypesServiceTemplate(OnboardingTypesEnum.CSAR).values();
126 addGlobalServiceTemplates(globalServiceTemplates, serviceTemplates);
127 toscaServiceModel.setServiceTemplates(serviceTemplates);
128 toscaServiceModel.setEntryDefinitionServiceTemplate(entryDefinitionServiceTemplateName);
129 externalFilesHandler.addFile(TOSCA_META_ORIG_PATH_FILE_NAME,
130 csarFiles.get(TOSCA_META_ORIG_PATH_FILE_NAME));
131 toscaServiceModel.setArtifactFiles(externalFilesHandler);
133 if(MapUtils.isNotEmpty(globalSubstitutionServiceTemplate.getNode_types())) {
135 .put(GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME, globalSubstitutionServiceTemplate);
139 private void addGlobalServiceTemplates(Collection<ServiceTemplate> globalServiceTemplates,
140 Map<String, ServiceTemplate> serviceTemplates) {
141 for (ServiceTemplate serviceTemplate : globalServiceTemplates) {
142 serviceTemplates.put(ToscaUtil.getServiceTemplateFileName(serviceTemplate), serviceTemplate);
146 protected void handleServiceTemplate(String serviceTemplateName,
147 String fileName, Map<String, byte[]> csarFiles,
148 Map<String, ServiceTemplate> serviceTemplates) {
149 Optional<ServiceTemplate> serviceTemplate =
150 getServiceTemplateFromCsar(fileName, csarFiles);
151 serviceTemplate.ifPresent(
152 serviceTemplateValue -> addServiceTemplate(serviceTemplateName, serviceTemplateValue,
156 private void addServiceTemplate(String serviceTemplateName,
157 ServiceTemplate serviceTemplate,
158 Map<String, ServiceTemplate> serviceTemplates) {
159 serviceTemplates.put(serviceTemplateName, serviceTemplate);
162 private Optional<ServiceTemplate> getServiceTemplateFromCsar(String fileName,
163 Map<String, byte[]> csarFiles) {
164 byte[] fileContent = csarFiles.get(fileName);
165 ServiceTemplate serviceTemplate = convertServiceTemplate(fileName, fileContent);
167 return Optional.of(serviceTemplate);
170 private ServiceTemplate convertServiceTemplate(String serviceTemplateName,
171 byte[] fileContent) {
172 ServiceTemplate serviceTemplate = new ServiceTemplate();
174 ServiceTemplateReaderService readerService =
175 new ServiceTemplateReaderServiceImpl(fileContent);
176 convertMetadata(serviceTemplateName, serviceTemplate, readerService);
177 convertToscaVersion(serviceTemplate, readerService);
178 convertImports(serviceTemplate);
179 convertNodeTypes(serviceTemplate, readerService);
180 convertTopologyTemplate(serviceTemplate, readerService);
182 } catch (YAMLException ye) {
183 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
184 .withMessage("Invalid YAML content in file" + serviceTemplateName)
185 .withCategory(ErrorCategory.APPLICATION).build(), ye);
189 return serviceTemplate;
192 private void convertToscaVersion(ServiceTemplate serviceTemplate,
193 ServiceTemplateReaderService readerService) {
194 Object toscaVersion = readerService.getToscaVersion();
195 serviceTemplate.setTosca_definitions_version((String) toscaVersion);
198 private void convertImports(ServiceTemplate serviceTemplate) {
199 serviceTemplate.setImports(new ArrayList<>());
200 serviceTemplate.getImports()
201 .add(createImportMap(openecompHeatIndex, HEAT_INDEX_IMPORT_FILE));
202 serviceTemplate.getImports().add(createImportMap(ONAP_INDEX, ONAP_INDEX_IMPORT_FILE));
203 serviceTemplate.getImports().add(createImportMap(globalSubstitution, globalStName));
207 private Map<String, Import> createImportMap(String key, String fileName) {
208 Map<String, Import> importMap = new HashMap<>();
209 Import anImport = new Import();
210 anImport.setFile(fileName);
211 importMap.put(key, anImport);
216 private void convertMetadata(String serviceTemplateName,
217 ServiceTemplate serviceTemplate,
218 ServiceTemplateReaderService readerService) {
219 Map<String, Object> metadataToConvert = (Map<String, Object>) readerService.getMetadata();
220 Map<String, String> finalMetadata = new HashMap<>();
222 if (MapUtils.isNotEmpty(metadataToConvert)) {
223 for (Map.Entry<String, Object> metadataEntry : metadataToConvert.entrySet()) {
224 if (Objects.isNull(metadataEntry.getValue()) ||
225 !(metadataEntry.getValue() instanceof String)) {
228 finalMetadata.put(metadataEntry.getKey(), (String) metadataEntry.getValue());
232 finalMetadata.put("template_name", getTemplateNameFromStName(serviceTemplateName));
233 serviceTemplate.setMetadata(finalMetadata);
236 private void convertNodeTypes(ServiceTemplate serviceTemplate, ServiceTemplateReaderService readerService) {
237 Map<String, Object> nodeTypes = readerService.getNodeTypes();
238 if (MapUtils.isEmpty(nodeTypes)) {
242 for (Map.Entry<String, Object> nodeTypeEntry : nodeTypes.entrySet()) {
243 Optional<NodeType> nodeType = ToscaConverterUtil
244 .createObjectFromClass(nodeTypeEntry.getKey(), nodeTypeEntry.getValue(),
247 nodeType.ifPresent(nodeTypeValue -> DataModelUtil
248 .addNodeType(serviceTemplate, nodeTypeEntry.getKey(), nodeTypeValue));
252 private void convertTopologyTemplate(ServiceTemplate serviceTemplate,
253 ServiceTemplateReaderService readerService) {
255 convertInputs(serviceTemplate, readerService);
256 convertNodeTemplates(serviceTemplate, readerService);
257 convertOutputs(serviceTemplate, readerService);
258 convertSubstitutionMappings(serviceTemplate, readerService);
261 private void convertInputs(ServiceTemplate serviceTemplate,
262 ServiceTemplateReaderService readerService) {
263 Map<String, Object> inputs = readerService.getInputs();
264 addInputsOrOutputsToServiceTemplate(serviceTemplate, inputs, Constants.inputs);
267 private void convertOutputs(ServiceTemplate serviceTemplate,
268 ServiceTemplateReaderService readerService) {
269 Map<String, Object> outputs = readerService.getOutputs();
270 addInputsOrOutputsToServiceTemplate(serviceTemplate, outputs, Constants.outputs);
273 private void addInputsOrOutputsToServiceTemplate(ServiceTemplate serviceTemplate,
274 Map<String, Object> mapToConvert,
275 String inputsOrOutputs) {
276 if (MapUtils.isEmpty(mapToConvert)) {
280 for (Map.Entry<String, Object> entry : mapToConvert.entrySet()) {
281 Optional<ParameterDefinition> parameterDefinition =
282 ToscaConverterUtil.createObjectFromClass(
283 entry.getKey(), entry.getValue(), ParameterDefinition.class);
285 parameterDefinition.ifPresent(parameterDefinitionValue -> {
286 Optional<Object> defaultValue =
287 ToscaConverterUtil.getDefaultValue(entry.getValue(), parameterDefinition.get());
288 defaultValue.ifPresent(parameterDefinitionValue::set_default);
289 addToServiceTemplateAccordingToSection(
290 serviceTemplate, inputsOrOutputs, entry.getKey(), parameterDefinition.get());
295 private void addToServiceTemplateAccordingToSection(ServiceTemplate serviceTemplate,
296 String inputsOrOutputs,
298 ParameterDefinition parameterDefinition) {
299 if (inputsOrOutputs.equals(inputs)) {
301 .addInputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
302 } else if (inputsOrOutputs.equals(outputs)) {
304 .addOutputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
308 private void convertNodeTemplates(ServiceTemplate serviceTemplate,
309 ServiceTemplateReaderService readerService) {
310 Map<String, Object> nodeTemplates = readerService.getNodeTemplates();
311 if (MapUtils.isEmpty(nodeTemplates)) {
315 for (Map.Entry<String, Object> nodeTemplateEntry : nodeTemplates.entrySet()) {
316 NodeTemplate nodeTemplate = convertNodeTemplate(nodeTemplateEntry.getValue());
317 DataModelUtil.addNodeTemplate(serviceTemplate, nodeTemplateEntry.getKey(), nodeTemplate);
321 private void convertSubstitutionMappings(ServiceTemplate serviceTemplate,
322 ServiceTemplateReaderService readerService) {
323 Map<String, Object> substitutionMappings = readerService.getSubstitutionMappings();
324 if (MapUtils.isEmpty(substitutionMappings)) {
327 SubstitutionMapping substitutionMapping = convertSubstitutionMappings(substitutionMappings);
328 DataModelUtil.addSubstitutionMapping(serviceTemplate, substitutionMapping);
331 private SubstitutionMapping convertSubstitutionMappings(
332 Map<String, Object> substitutionMappings) {
333 SubstitutionMapping substitutionMapping = new SubstitutionMapping();
335 substitutionMapping.setNode_type((String) substitutionMappings.get(nodeType));
336 substitutionMapping.setCapabilities(
337 convertSubstitutionMappingsSections(capabilities, substitutionMappings.get(capabilities)));
338 substitutionMapping.setRequirements(
339 convertSubstitutionMappingsSections(requirements, substitutionMappings.get(requirements)));
341 return substitutionMapping;
344 private Map<String, List<String>> convertSubstitutionMappingsSections(String sectionName,
345 Object sectionToConvert) {
347 if (Objects.isNull(sectionToConvert)) {
351 if (!(sectionToConvert instanceof Map)) {
352 throw new CoreException(
353 new SubstitutionMappingsConverterErrorBuilder(
354 sectionName, sectionToConvert.getClass().getSimpleName()).build());
357 return convertSection(sectionToConvert);
360 private Map<String, List<String>> convertSection(Object sectionToConvert) {
362 Map<String, Object> sectionAsMap = (Map<String, Object>) sectionToConvert;
363 Map<String, List<String>> convertedSection = new HashMap<>();
365 if (MapUtils.isEmpty(sectionAsMap)) {
369 for (Map.Entry<String, Object> entry : sectionAsMap.entrySet()) {
370 if (entry.getValue() instanceof List) {
371 convertedSection.put(entry.getKey(), (List<String>) entry.getValue());
375 return convertedSection;
378 protected CsarFileTypes getFileType(String fileName){
379 if (isMainServiceTemplate(fileName)) {
380 return CsarFileTypes.mainServiceTemplate;
381 } else if (isGlobalServiceTemplate(fileName)) {
382 return CsarFileTypes.globalServiceTemplate;
383 } else if (isDefinitions(fileName)) {
384 return CsarFileTypes.definitionsFile;
385 } else if (isMetadataFile(fileName)) {
386 return CsarFileTypes.toscaMetadata;
388 return CsarFileTypes.externalFile;
391 private NodeTemplate convertNodeTemplate(Object candidateNodeTemplate) {
392 NodeTemplate nodeTemplate = new NodeTemplate();
394 Map<String, Object> nodeTemplateAsMap = (Map<String, Object>) candidateNodeTemplate;
395 nodeTemplate.setArtifacts((Map<String, ArtifactDefinition>) nodeTemplateAsMap.get("artifacts"));
396 nodeTemplate.setAttributes((Map<String, Object>) nodeTemplateAsMap.get("attributes"));
397 nodeTemplate.setCopy((String) nodeTemplateAsMap.get("copy"));
398 nodeTemplate.setDescription((String) nodeTemplateAsMap.get("description"));
399 nodeTemplate.setDirectives((List<String>) nodeTemplateAsMap.get("directives"));
400 nodeTemplate.setInterfaces(
401 (Map<String, Object>) nodeTemplateAsMap.get("interfaces"));
402 nodeTemplate.setNode_filter((NodeFilter) nodeTemplateAsMap.get("node_filter"));
403 nodeTemplate.setProperties((Map<String, Object>) nodeTemplateAsMap.get("properties"));
404 nodeTemplate.setRequirements(
405 (List<Map<String, RequirementAssignment>>) nodeTemplateAsMap.get("requirements"));
406 nodeTemplate.setType((String) nodeTemplateAsMap.get("type"));
407 nodeTemplate.setCapabilities(
408 convertCapabilities((Map<String, Object>) nodeTemplateAsMap.get("capabilities")));
413 private Map<String, CapabilityAssignment> convertCapabilities(Map<String, Object> capabilities) {
414 if (MapUtils.isEmpty(capabilities)) {
418 Map<String, CapabilityAssignment> convertedCapabilities = new HashMap<>();
419 for (Map.Entry<String, Object> capabilityAssignmentEntry : capabilities.entrySet()) {
420 Optional<CapabilityAssignment> capabilityAssignment = ToscaConverterUtil.createObjectFromClass
421 (capabilityAssignmentEntry.getKey(), capabilityAssignmentEntry.getValue(),
422 CapabilityAssignment.class);
424 capabilityAssignment.ifPresent(capabilityAssignmentValue ->
425 convertedCapabilities.put(capabilityAssignmentEntry.getKey(), capabilityAssignmentValue));
428 return convertedCapabilities;
432 protected boolean isMainServiceTemplate(String fileName) {
433 return fileName.endsWith(mainStName);
436 protected boolean isMetadataFile(String fileName) {
437 return fileName.equals(TOSCA_META_PATH_FILE_NAME);
440 protected boolean isGlobalServiceTemplate(String fileName) {
441 return fileName.endsWith(globalStName);
444 protected boolean isDefinitions(String fileName) {
445 return fileName.startsWith(definitionsDir);
448 private String getTemplateNameFromStName(String serviceTemplateName) {
449 String fileNameWithoutDirectories = getFileNameWithoutDirectories(serviceTemplateName);
450 return fileNameWithoutDirectories.split("ServiceTemplate")[0];
453 private String getFileNameWithoutDirectories(String serviceTemplateName) {
454 String fileNameWithoutDirectories;
455 if (serviceTemplateName.contains("/")) {
456 String[] split = serviceTemplateName.split("/");
457 fileNameWithoutDirectories = split[split.length - 1];
458 } else if (serviceTemplateName.contains(File.separator)) {
459 String[] split = serviceTemplateName.split(Pattern.quote(File.separator));
460 fileNameWithoutDirectories = split[split.length - 1];
462 fileNameWithoutDirectories = serviceTemplateName;
464 return fileNameWithoutDirectories;