2 * Copyright © 2016-2017 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.core.impl;
19 import org.apache.commons.collections.MapUtils;
20 import org.onap.sdc.tosca.datatypes.model.ArtifactDefinition;
21 import org.onap.sdc.tosca.datatypes.model.CapabilityAssignment;
22 import org.onap.sdc.tosca.datatypes.model.Import;
23 import org.onap.sdc.tosca.datatypes.model.NodeFilter;
24 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
25 import org.onap.sdc.tosca.datatypes.model.NodeType;
26 import org.onap.sdc.tosca.datatypes.model.ParameterDefinition;
27 import org.onap.sdc.tosca.datatypes.model.RequirementAssignment;
28 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
29 import org.onap.sdc.tosca.datatypes.model.SubstitutionMapping;
30 import org.openecomp.core.converter.ServiceTemplateReaderService;
31 import org.openecomp.core.converter.ToscaConverter;
32 import org.openecomp.core.converter.datatypes.Constants;
33 import org.openecomp.core.converter.datatypes.CsarFileTypes;
34 import org.openecomp.core.converter.errors.SubstitutionMappingsConverterErrorBuilder;
35 import org.openecomp.core.impl.services.ServiceTemplateReaderServiceImpl;
36 import org.openecomp.core.utilities.file.FileContentHandler;
37 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
38 import org.openecomp.sdc.common.errors.CoreException;
39 import org.openecomp.sdc.common.errors.ErrorCategory;
40 import org.openecomp.sdc.common.errors.ErrorCode;
41 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
42 import org.openecomp.sdc.tosca.services.DataModelUtil;
43 import org.openecomp.sdc.tosca.services.ToscaUtil;
44 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
45 import org.yaml.snakeyaml.error.YAMLException;
48 import java.util.ArrayList;
49 import java.util.Collection;
50 import java.util.HashMap;
51 import java.util.List;
53 import java.util.Objects;
54 import java.util.Optional;
55 import java.util.regex.Pattern;
57 import static org.openecomp.core.converter.datatypes.Constants.ONAP_INDEX;
58 import static org.openecomp.core.converter.datatypes.Constants.capabilities;
59 import static org.openecomp.core.converter.datatypes.Constants.inputs;
60 import static org.openecomp.core.converter.datatypes.Constants.nodeType;
61 import static org.openecomp.core.converter.datatypes.Constants.definitionsDir;
62 import static org.openecomp.core.converter.datatypes.Constants.globalStName;
63 import static org.openecomp.core.converter.datatypes.Constants.globalSubstitution;
64 import static org.openecomp.core.converter.datatypes.Constants.mainStName;
65 import static org.openecomp.core.converter.datatypes.Constants.openecompHeatIndex;
66 import static org.openecomp.core.converter.datatypes.Constants.outputs;
67 import static org.openecomp.core.converter.datatypes.Constants.requirements;
68 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME;
69 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.HEAT_INDEX_IMPORT_FILE;
70 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.ONAP_INDEX_IMPORT_FILE;
71 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ORIG_PATH_FILE_NAME;
72 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_PATH_FILE_NAME;
74 public class ToscaConverterImpl implements ToscaConverter {
77 public ToscaServiceModel convert(FileContentHandler fileContentHandler) {
78 Map<String, byte[]> csarFiles = new HashMap<>(fileContentHandler.getFiles());
79 ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
80 Map<String, ServiceTemplate> serviceTemplates = new HashMap<>();
81 FileContentHandler artifacts = new FileContentHandler();
82 GlobalSubstitutionServiceTemplate gsst = new GlobalSubstitutionServiceTemplate();
83 for (Map.Entry<String, byte[]> fileEntry : csarFiles.entrySet()) {
84 CsarFileTypes fileType = getFileType(fileEntry.getKey());
86 case mainServiceTemplate:
87 handleServiceTemplate(mainStName, fileEntry.getKey(), csarFiles, serviceTemplates);
90 case globalServiceTemplate:
91 handleServiceTemplate(globalStName, fileEntry.getKey(), csarFiles, serviceTemplates);
96 getConcreteArtifactFileName(fileEntry.getKey()), fileEntry.getValue());
100 handleDefintionTemplate(fileEntry.getKey(), csarFiles, gsst);
107 handleMetadataFile(csarFiles);
108 updateToscaServiceModel(toscaServiceModel, serviceTemplates, artifacts, gsst, csarFiles);
109 return toscaServiceModel;
112 private void handleMetadataFile(Map<String, byte[]> csarFiles) {
113 byte[] bytes = csarFiles.remove(TOSCA_META_PATH_FILE_NAME);
115 csarFiles.put(TOSCA_META_ORIG_PATH_FILE_NAME, bytes);
119 private void handleDefintionTemplate(String key, Map<String, byte[]> csarFiles,
120 GlobalSubstitutionServiceTemplate gsst) {
122 ServiceTemplateReaderService readerService = new ServiceTemplateReaderServiceImpl(csarFiles.get(key));
123 Object nodeTypes = readerService.getNodeTypes();
124 if (nodeTypes instanceof Map) {
125 Map<String, NodeType> nodeTypeMap = (Map<String, NodeType>) nodeTypes;
126 gsst.appendNodes(nodeTypeMap);
128 } catch (YAMLException ye) {
129 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
130 .withMessage("Invalid YAML content in file " + key)
131 .withCategory(ErrorCategory.APPLICATION).build(), ye);
135 private String getConcreteArtifactFileName(String fileName){
136 int artifactIndex = fileName.indexOf(CsarFileTypes.Artifacts.name());
137 if(artifactIndex < 0){
141 int artifactDirectoryIndex =
142 artifactIndex + CsarFileTypes.Artifacts.name().length() + 1;
143 return fileName.substring(artifactDirectoryIndex);
146 private void updateToscaServiceModel(ToscaServiceModel toscaServiceModel,
147 Map<String, ServiceTemplate> serviceTemplates,
148 FileContentHandler externalFilesHandler,
149 GlobalSubstitutionServiceTemplate globalSubstitutionServiceTemplate,
150 Map<String, byte[]> csarFiles) {
151 Collection<ServiceTemplate> globalServiceTemplates =
152 GlobalTypesGenerator.getGlobalTypesServiceTemplate(OnboardingTypesEnum.CSAR).values();
153 addGlobalServiceTemplates(globalServiceTemplates, serviceTemplates);
154 toscaServiceModel.setEntryDefinitionServiceTemplate(mainStName);
155 toscaServiceModel.setServiceTemplates(serviceTemplates);
156 externalFilesHandler.addFile(TOSCA_META_ORIG_PATH_FILE_NAME,
157 csarFiles.get(TOSCA_META_ORIG_PATH_FILE_NAME));
158 toscaServiceModel.setArtifactFiles(externalFilesHandler);
160 if(MapUtils.isNotEmpty(globalSubstitutionServiceTemplate.getNode_types())) {
162 .put(GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME, globalSubstitutionServiceTemplate);
166 private void addGlobalServiceTemplates(Collection<ServiceTemplate> globalServiceTemplates,
167 Map<String, ServiceTemplate> serviceTemplates) {
168 for (ServiceTemplate serviceTemplate : globalServiceTemplates) {
169 serviceTemplates.put(ToscaUtil.getServiceTemplateFileName(serviceTemplate), serviceTemplate);
173 private void handleServiceTemplate(String serviceTemplateName,
174 String fileName, Map<String, byte[]> csarFiles,
175 Map<String, ServiceTemplate> serviceTemplates) {
176 Optional<ServiceTemplate> serviceTemplate =
177 getServiceTemplateFromCsar(fileName, csarFiles);
178 serviceTemplate.ifPresent(
179 serviceTemplateValue -> addServiceTemplate(serviceTemplateName, serviceTemplateValue,
183 private void addServiceTemplate(String serviceTemplateName,
184 ServiceTemplate serviceTemplate,
185 Map<String, ServiceTemplate> serviceTemplates) {
186 serviceTemplates.put(serviceTemplateName, serviceTemplate);
189 private Optional<ServiceTemplate> getServiceTemplateFromCsar(String fileName,
190 Map<String, byte[]> csarFiles) {
191 byte[] fileContent = csarFiles.get(fileName);
192 ServiceTemplate serviceTemplate = convertServiceTemplate(fileName, fileContent);
194 return Optional.of(serviceTemplate);
197 private ServiceTemplate convertServiceTemplate(String serviceTemplateName,
198 byte[] fileContent) {
199 ServiceTemplate serviceTemplate = new ServiceTemplate();
201 ServiceTemplateReaderService readerService =
202 new ServiceTemplateReaderServiceImpl(fileContent);
203 convertMetadata(serviceTemplateName, serviceTemplate, readerService);
204 convertToscaVersion(serviceTemplate, readerService);
205 convertImports(serviceTemplate);
206 convertNodeTypes(serviceTemplate, readerService);
207 convertTopologyTemplate(serviceTemplate, readerService);
209 } catch (YAMLException ye) {
210 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
211 .withMessage("Invalid YAML content in file" + serviceTemplateName)
212 .withCategory(ErrorCategory.APPLICATION).build(), ye);
216 return serviceTemplate;
219 private void convertToscaVersion(ServiceTemplate serviceTemplate,
220 ServiceTemplateReaderService readerService) {
221 Object toscaVersion = readerService.getToscaVersion();
222 serviceTemplate.setTosca_definitions_version((String) toscaVersion);
225 private void convertImports(ServiceTemplate serviceTemplate) {
226 serviceTemplate.setImports(new ArrayList<>());
227 serviceTemplate.getImports()
228 .add(createImportMap(openecompHeatIndex, HEAT_INDEX_IMPORT_FILE));
229 serviceTemplate.getImports().add(createImportMap(ONAP_INDEX, ONAP_INDEX_IMPORT_FILE));
230 serviceTemplate.getImports().add(createImportMap(globalSubstitution, globalStName));
234 private Map<String, Import> createImportMap(String key, String fileName) {
235 Map<String, Import> importMap = new HashMap<>();
236 Import anImport = new Import();
237 anImport.setFile(fileName);
238 importMap.put(key, anImport);
243 private void convertMetadata(String serviceTemplateName,
244 ServiceTemplate serviceTemplate,
245 ServiceTemplateReaderService readerService) {
246 Map<String, Object> metadataToConvert = (Map<String, Object>) readerService.getMetadata();
247 Map<String, String> finalMetadata = new HashMap<>();
249 if (MapUtils.isNotEmpty(metadataToConvert)) {
250 for (Map.Entry<String, Object> metadataEntry : metadataToConvert.entrySet()) {
251 if (Objects.isNull(metadataEntry.getValue()) ||
252 !(metadataEntry.getValue() instanceof String)) {
255 finalMetadata.put(metadataEntry.getKey(), (String) metadataEntry.getValue());
259 finalMetadata.put("template_name", getTemplateNameFromStName(serviceTemplateName));
260 serviceTemplate.setMetadata(finalMetadata);
263 private void convertNodeTypes(ServiceTemplate serviceTemplate, ServiceTemplateReaderService readerService) {
264 Map<String, Object> nodeTypes = readerService.getNodeTypes();
265 if (MapUtils.isEmpty(nodeTypes)) {
269 for (Map.Entry<String, Object> nodeTypeEntry : nodeTypes.entrySet()) {
270 Optional<NodeType> nodeType = ToscaConverterUtil
271 .createObjectFromClass(nodeTypeEntry.getKey(), nodeTypeEntry.getValue(),
274 nodeType.ifPresent(nodeTypeValue -> DataModelUtil
275 .addNodeType(serviceTemplate, nodeTypeEntry.getKey(), nodeTypeValue));
279 private void convertTopologyTemplate(ServiceTemplate serviceTemplate,
280 ServiceTemplateReaderService readerService) {
282 convertInputs(serviceTemplate, readerService);
283 convertNodeTemplates(serviceTemplate, readerService);
284 convertOutputs(serviceTemplate, readerService);
285 convertSubstitutionMappings(serviceTemplate, readerService);
288 private void convertInputs(ServiceTemplate serviceTemplate,
289 ServiceTemplateReaderService readerService) {
290 Map<String, Object> inputs = readerService.getInputs();
291 addInputsOrOutputsToServiceTemplate(serviceTemplate, inputs, Constants.inputs);
294 private void convertOutputs(ServiceTemplate serviceTemplate,
295 ServiceTemplateReaderService readerService) {
296 Map<String, Object> outputs = readerService.getOutputs();
297 addInputsOrOutputsToServiceTemplate(serviceTemplate, outputs, Constants.outputs);
300 private void addInputsOrOutputsToServiceTemplate(ServiceTemplate serviceTemplate,
301 Map<String, Object> mapToConvert,
302 String inputsOrOutputs) {
303 if (MapUtils.isEmpty(mapToConvert)) {
307 for (Map.Entry<String, Object> entry : mapToConvert.entrySet()) {
308 Optional<ParameterDefinition> parameterDefinition =
309 ToscaConverterUtil.createObjectFromClass(
310 entry.getKey(), entry.getValue(), ParameterDefinition.class);
312 parameterDefinition.ifPresent(parameterDefinitionValue -> {
313 Optional<Object> defaultValue =
314 ToscaConverterUtil.getDefaultValue(entry.getValue(), parameterDefinition.get());
315 defaultValue.ifPresent(parameterDefinitionValue::set_default);
316 addToServiceTemplateAccordingToSection(
317 serviceTemplate, inputsOrOutputs, entry.getKey(), parameterDefinition.get());
322 private void addToServiceTemplateAccordingToSection(ServiceTemplate serviceTemplate,
323 String inputsOrOutputs,
325 ParameterDefinition parameterDefinition) {
326 if (inputsOrOutputs.equals(inputs)) {
328 .addInputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
329 } else if (inputsOrOutputs.equals(outputs)) {
331 .addOutputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
335 private void convertNodeTemplates(ServiceTemplate serviceTemplate,
336 ServiceTemplateReaderService readerService) {
337 Map<String, Object> nodeTemplates = readerService.getNodeTemplates();
338 if (MapUtils.isEmpty(nodeTemplates)) {
342 for (Map.Entry<String, Object> nodeTemplateEntry : nodeTemplates.entrySet()) {
343 NodeTemplate nodeTemplate = convertNodeTemplate(nodeTemplateEntry.getValue());
344 DataModelUtil.addNodeTemplate(serviceTemplate, nodeTemplateEntry.getKey(), nodeTemplate);
348 private void convertSubstitutionMappings(ServiceTemplate serviceTemplate,
349 ServiceTemplateReaderService readerService) {
350 Map<String, Object> substitutionMappings = readerService.getSubstitutionMappings();
351 if (MapUtils.isEmpty(substitutionMappings)) {
354 SubstitutionMapping substitutionMapping = convertSubstitutionMappings(substitutionMappings);
355 DataModelUtil.addSubstitutionMapping(serviceTemplate, substitutionMapping);
358 private SubstitutionMapping convertSubstitutionMappings(
359 Map<String, Object> substitutionMappings) {
360 SubstitutionMapping substitutionMapping = new SubstitutionMapping();
362 substitutionMapping.setNode_type((String) substitutionMappings.get(nodeType));
363 substitutionMapping.setCapabilities(
364 convertSubstitutionMappingsSections(capabilities, substitutionMappings.get(capabilities)));
365 substitutionMapping.setRequirements(
366 convertSubstitutionMappingsSections(requirements, substitutionMappings.get(requirements)));
368 return substitutionMapping;
371 private Map<String, List<String>> convertSubstitutionMappingsSections(String sectionName,
372 Object sectionToConvert) {
374 if (Objects.isNull(sectionToConvert)) {
378 if (!(sectionToConvert instanceof Map)) {
379 throw new CoreException(
380 new SubstitutionMappingsConverterErrorBuilder(
381 sectionName, sectionToConvert.getClass().getSimpleName()).build());
384 return convertSection(sectionToConvert);
387 private Map<String, List<String>> convertSection(Object sectionToConvert) {
389 Map<String, Object> sectionAsMap = (Map<String, Object>) sectionToConvert;
390 Map<String, List<String>> convertedSection = new HashMap<>();
392 if (MapUtils.isEmpty(sectionAsMap)) {
396 for (Map.Entry<String, Object> entry : sectionAsMap.entrySet()) {
397 if (entry.getValue() instanceof List) {
398 convertedSection.put(entry.getKey(), (List<String>) entry.getValue());
402 return convertedSection;
405 private CsarFileTypes getFileType(String fileName) {
406 if (isMainServiceTemplate(fileName)) {
407 return CsarFileTypes.mainServiceTemplate;
408 } else if (isGlobalServiceTemplate(fileName)) {
409 return CsarFileTypes.globalServiceTemplate;
410 } else if (isDefinitions(fileName)) {
411 return CsarFileTypes.definitionsFile;
412 } else if (isMetadataFile(fileName)) {
413 return CsarFileTypes.toscaMetadata;
415 return CsarFileTypes.externalFile;
418 private NodeTemplate convertNodeTemplate(Object candidateNodeTemplate) {
419 NodeTemplate nodeTemplate = new NodeTemplate();
421 Map<String, Object> nodeTemplateAsMap = (Map<String, Object>) candidateNodeTemplate;
422 nodeTemplate.setArtifacts((Map<String, ArtifactDefinition>) nodeTemplateAsMap.get("artifacts"));
423 nodeTemplate.setAttributes((Map<String, Object>) nodeTemplateAsMap.get("attributes"));
424 nodeTemplate.setCopy((String) nodeTemplateAsMap.get("copy"));
425 nodeTemplate.setDescription((String) nodeTemplateAsMap.get("description"));
426 nodeTemplate.setDirectives((List<String>) nodeTemplateAsMap.get("directives"));
427 nodeTemplate.setInterfaces(
428 (Map<String, Object>) nodeTemplateAsMap.get("interfaces"));
429 nodeTemplate.setNode_filter((NodeFilter) nodeTemplateAsMap.get("node_filter"));
430 nodeTemplate.setProperties((Map<String, Object>) nodeTemplateAsMap.get("properties"));
431 nodeTemplate.setRequirements(
432 (List<Map<String, RequirementAssignment>>) nodeTemplateAsMap.get("requirements"));
433 nodeTemplate.setType((String) nodeTemplateAsMap.get("type"));
434 nodeTemplate.setCapabilities(
435 convertCapabilities((Map<String, Object>) nodeTemplateAsMap.get("capabilities")));
440 private Map<String, CapabilityAssignment> convertCapabilities(Map<String, Object> capabilities) {
441 if (MapUtils.isEmpty(capabilities)) {
445 Map<String, CapabilityAssignment> convertedCapabilities = new HashMap<>();
446 for (Map.Entry<String, Object> capabilityAssignmentEntry : capabilities.entrySet()) {
447 Optional<CapabilityAssignment> capabilityAssignment = ToscaConverterUtil.createObjectFromClass
448 (capabilityAssignmentEntry.getKey(), capabilityAssignmentEntry.getValue(),
449 CapabilityAssignment.class);
451 capabilityAssignment.ifPresent(capabilityAssignmentValue ->
452 convertedCapabilities.put(capabilityAssignmentEntry.getKey(), capabilityAssignmentValue));
455 return convertedCapabilities;
459 private boolean isMainServiceTemplate(String fileName) {
460 return fileName.endsWith(mainStName);
463 private boolean isMetadataFile(String fileName) {
464 return fileName.equals(TOSCA_META_PATH_FILE_NAME);
467 private boolean isGlobalServiceTemplate(String fileName) {
468 return fileName.endsWith(globalStName);
471 private boolean isDefinitions(String fileName) {
472 return fileName.startsWith(definitionsDir);
475 private String getTemplateNameFromStName(String serviceTemplateName) {
476 String fileNameWithoutDirectories;
477 fileNameWithoutDirectories = getFileNameWithoutDirectories(serviceTemplateName);
478 return fileNameWithoutDirectories.split("ServiceTemplate")[0];
481 private String getFileNameWithoutDirectories(String serviceTemplateName) {
482 String fileNameWithoutDirectories;
483 if (serviceTemplateName.contains("/")) {
484 String[] split = serviceTemplateName.split("/");
485 fileNameWithoutDirectories = split[split.length - 1];
486 } else if (serviceTemplateName.contains(File.separator)) {
487 String[] split = serviceTemplateName.split(Pattern.quote(File.separator));
488 fileNameWithoutDirectories = split[split.length - 1];
490 fileNameWithoutDirectories = serviceTemplateName;
492 return fileNameWithoutDirectories;