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 static org.openecomp.core.converter.datatypes.Constants.ONAP_INDEX;
20 import static org.openecomp.core.converter.datatypes.Constants.capabilities;
21 import static org.openecomp.core.converter.datatypes.Constants.definitionsDir;
22 import static org.openecomp.core.converter.datatypes.Constants.globalStName;
23 import static org.openecomp.core.converter.datatypes.Constants.globalSubstitution;
24 import static org.openecomp.core.converter.datatypes.Constants.inputs;
25 import static org.openecomp.core.converter.datatypes.Constants.mainStName;
26 import static org.openecomp.core.converter.datatypes.Constants.metadataFile;
27 import static org.openecomp.core.converter.datatypes.Constants.nodeType;
28 import static org.openecomp.core.converter.datatypes.Constants.openecompHeatIndex;
29 import static org.openecomp.core.converter.datatypes.Constants.outputs;
30 import static org.openecomp.core.converter.datatypes.Constants.requirements;
31 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME;
32 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.HEAT_INDEX_IMPORT_FILE;
33 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.ONAP_INDEX_IMPORT_FILE;
35 import org.apache.commons.collections.MapUtils;
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.onap.sdc.tosca.datatypes.model.ArtifactDefinition;
49 import org.onap.sdc.tosca.datatypes.model.CapabilityAssignment;
50 import org.onap.sdc.tosca.datatypes.model.Import;
51 import org.onap.sdc.tosca.datatypes.model.NodeFilter;
52 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
53 import org.onap.sdc.tosca.datatypes.model.NodeType;
54 import org.onap.sdc.tosca.datatypes.model.ParameterDefinition;
55 import org.onap.sdc.tosca.datatypes.model.RequirementAssignment;
56 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
57 import org.onap.sdc.tosca.datatypes.model.SubstitutionMapping;
58 import org.openecomp.sdc.tosca.services.DataModelUtil;
59 import org.openecomp.sdc.tosca.services.ToscaUtil;
60 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
61 import org.yaml.snakeyaml.error.YAMLException;
64 import java.util.ArrayList;
65 import java.util.Collection;
66 import java.util.HashMap;
67 import java.util.List;
69 import java.util.Objects;
70 import java.util.Optional;
71 import java.util.regex.Pattern;
73 public class ToscaConverterImpl implements ToscaConverter {
75 private static final String ORIGINAL = ".original";
76 public ToscaConverterImpl() {
81 public ToscaServiceModel convert(FileContentHandler fileContentHandler) {
82 Map<String, byte[]> csarFiles = new HashMap<>(fileContentHandler.getFiles());
83 ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
84 Map<String, ServiceTemplate> serviceTemplates = new HashMap<>();
85 FileContentHandler artifacts = new FileContentHandler();
86 GlobalSubstitutionServiceTemplate gsst = new GlobalSubstitutionServiceTemplate();
87 for (Map.Entry<String, byte[]> fileEntry : csarFiles.entrySet()) {
88 CsarFileTypes fileType = getFileType(fileEntry.getKey());
90 case mainServiceTemplate:
91 handleServiceTemplate(mainStName, fileEntry.getKey(), csarFiles, serviceTemplates);
94 case globalServiceTemplate:
95 handleServiceTemplate(globalStName, fileEntry.getKey(), csarFiles, serviceTemplates);
100 getConcreteArtifactFileName(fileEntry.getKey()), fileEntry.getValue());
103 case definitionsFile:
104 handleDefintionTemplate(fileEntry.getKey(), csarFiles, gsst);
111 handleMetadataFile(csarFiles);
112 updateToscaServiceModel(toscaServiceModel, serviceTemplates, artifacts, gsst, csarFiles);
113 return toscaServiceModel;
116 private void handleMetadataFile(Map<String, byte[]> csarFiles) {
117 byte[] bytes = csarFiles.remove(metadataFile);
119 csarFiles.put(metadataFile + ORIGINAL, bytes);
123 private void handleDefintionTemplate(String key, Map<String, byte[]> csarFiles,
124 GlobalSubstitutionServiceTemplate gsst) {
126 ServiceTemplateReaderService readerService = new ServiceTemplateReaderServiceImpl(csarFiles.get(key));
127 Object nodeTypes = readerService.getNodeTypes();
128 if (nodeTypes instanceof Map) {
129 Map<String, NodeType> nodeTypeMap = (Map<String, NodeType>) nodeTypes;
130 gsst.appendNodes(nodeTypeMap);
132 } catch (YAMLException ye) {
133 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
134 .withMessage("Invalid YAML content in file " + key)
135 .withCategory(ErrorCategory.APPLICATION).build(), ye);
139 private String getConcreteArtifactFileName(String fileName){
140 int artifactIndex = fileName.indexOf(CsarFileTypes.Artifacts.name());
141 if(artifactIndex < 0){
145 int artifactDirectoryIndex =
146 artifactIndex + CsarFileTypes.Artifacts.name().length() + 1;
147 return fileName.substring(artifactDirectoryIndex);
150 private void updateToscaServiceModel(ToscaServiceModel toscaServiceModel,
151 Map<String, ServiceTemplate> serviceTemplates,
152 FileContentHandler externalFilesHandler,
153 GlobalSubstitutionServiceTemplate globalSubstitutionServiceTemplate,
154 Map<String, byte[]> csarFiles) {
155 Collection<ServiceTemplate> globalServiceTemplates =
156 GlobalTypesGenerator.getGlobalTypesServiceTemplate(OnboardingTypesEnum.CSAR).values();
157 addGlobalServiceTemplates(globalServiceTemplates, serviceTemplates);
158 toscaServiceModel.setEntryDefinitionServiceTemplate(mainStName);
159 toscaServiceModel.setServiceTemplates(serviceTemplates);
160 externalFilesHandler.addFile(metadataFile + ORIGINAL,
161 csarFiles.get(metadataFile + ORIGINAL));
162 toscaServiceModel.setArtifactFiles(externalFilesHandler);
164 if(MapUtils.isNotEmpty(globalSubstitutionServiceTemplate.getNode_types())) {
166 .put(GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME, globalSubstitutionServiceTemplate);
170 private void addGlobalServiceTemplates(Collection<ServiceTemplate> globalServiceTemplates,
171 Map<String, ServiceTemplate> serviceTemplates) {
172 for (ServiceTemplate serviceTemplate : globalServiceTemplates) {
173 serviceTemplates.put(ToscaUtil.getServiceTemplateFileName(serviceTemplate), serviceTemplate);
177 private void handleServiceTemplate(String serviceTemplateName,
178 String fileName, Map<String, byte[]> csarFiles,
179 Map<String, ServiceTemplate> serviceTemplates) {
180 Optional<ServiceTemplate> serviceTemplate =
181 getServiceTemplateFromCsar(fileName, csarFiles);
182 serviceTemplate.ifPresent(
183 serviceTemplateValue -> addServiceTemplate(serviceTemplateName, serviceTemplateValue,
187 private void addServiceTemplate(String serviceTemplateName,
188 ServiceTemplate serviceTemplate,
189 Map<String, ServiceTemplate> serviceTemplates) {
190 serviceTemplates.put(serviceTemplateName, serviceTemplate);
193 private Optional<ServiceTemplate> getServiceTemplateFromCsar(String fileName,
194 Map<String, byte[]> csarFiles) {
195 byte[] fileContent = csarFiles.get(fileName);
196 ServiceTemplate serviceTemplate = convertServiceTemplate(fileName, fileContent);
198 return Optional.of(serviceTemplate);
201 private ServiceTemplate convertServiceTemplate(String serviceTemplateName,
202 byte[] fileContent) {
203 ServiceTemplate serviceTemplate = new ServiceTemplate();
205 ServiceTemplateReaderService readerService =
206 new ServiceTemplateReaderServiceImpl(fileContent);
207 convertMetadata(serviceTemplateName, serviceTemplate, readerService);
208 convertToscaVersion(serviceTemplate, readerService);
209 convertImports(serviceTemplate);
210 convertNodeTypes(serviceTemplate, readerService);
211 convertTopologyTemplate(serviceTemplate, readerService);
213 } catch (YAMLException ye) {
214 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
215 .withMessage("Invalid YAML content in file" + serviceTemplateName)
216 .withCategory(ErrorCategory.APPLICATION).build(), ye);
220 return serviceTemplate;
223 private void convertToscaVersion(ServiceTemplate serviceTemplate,
224 ServiceTemplateReaderService readerService) {
225 Object toscaVersion = readerService.getToscaVersion();
226 serviceTemplate.setTosca_definitions_version((String) toscaVersion);
229 private void convertImports(ServiceTemplate serviceTemplate) {
230 serviceTemplate.setImports(new ArrayList<>());
231 serviceTemplate.getImports()
232 .add(createImportMap(openecompHeatIndex, HEAT_INDEX_IMPORT_FILE));
233 serviceTemplate.getImports().add(createImportMap(ONAP_INDEX, ONAP_INDEX_IMPORT_FILE));
234 serviceTemplate.getImports().add(createImportMap(globalSubstitution, globalStName));
238 private Map<String, Import> createImportMap(String key, String fileName) {
239 Map<String, Import> importMap = new HashMap<>();
240 Import anImport = new Import();
241 anImport.setFile(fileName);
242 importMap.put(key, anImport);
247 private void convertMetadata(String serviceTemplateName,
248 ServiceTemplate serviceTemplate,
249 ServiceTemplateReaderService readerService) {
250 Map<String, Object> metadataToConvert = (Map<String, Object>) readerService.getMetadata();
251 Map<String, String> finalMetadata = new HashMap<>();
253 if (MapUtils.isNotEmpty(metadataToConvert)) {
254 for (Map.Entry<String, Object> metadataEntry : metadataToConvert.entrySet()) {
255 if (Objects.isNull(metadataEntry.getValue()) ||
256 !(metadataEntry.getValue() instanceof String)) {
259 finalMetadata.put(metadataEntry.getKey(), (String) metadataEntry.getValue());
263 finalMetadata.put("template_name", getTemplateNameFromStName(serviceTemplateName));
264 serviceTemplate.setMetadata(finalMetadata);
267 private void convertNodeTypes(ServiceTemplate serviceTemplate, ServiceTemplateReaderService readerService) {
268 Map<String, Object> nodeTypes = readerService.getNodeTypes();
269 if (MapUtils.isEmpty(nodeTypes)) {
273 for (Map.Entry<String, Object> nodeTypeEntry : nodeTypes.entrySet()) {
274 Optional<NodeType> nodeType = ToscaConverterUtil
275 .createObjectFromClass(nodeTypeEntry.getKey(), nodeTypeEntry.getValue(),
278 nodeType.ifPresent(nodeTypeValue -> DataModelUtil
279 .addNodeType(serviceTemplate, nodeTypeEntry.getKey(), nodeTypeValue));
283 private void convertTopologyTemplate(ServiceTemplate serviceTemplate,
284 ServiceTemplateReaderService readerService) {
286 convertInputs(serviceTemplate, readerService);
287 convertNodeTemplates(serviceTemplate, readerService);
288 convertOutputs(serviceTemplate, readerService);
289 convertSubstitutionMappings(serviceTemplate, readerService);
292 private void convertInputs(ServiceTemplate serviceTemplate,
293 ServiceTemplateReaderService readerService) {
294 Map<String, Object> inputs = readerService.getInputs();
295 addInputsOrOutputsToServiceTemplate(serviceTemplate, inputs, Constants.inputs);
298 private void convertOutputs(ServiceTemplate serviceTemplate,
299 ServiceTemplateReaderService readerService) {
300 Map<String, Object> outputs = readerService.getOutputs();
301 addInputsOrOutputsToServiceTemplate(serviceTemplate, outputs, Constants.outputs);
304 private void addInputsOrOutputsToServiceTemplate(ServiceTemplate serviceTemplate,
305 Map<String, Object> mapToConvert,
306 String inputsOrOutputs) {
307 if (MapUtils.isEmpty(mapToConvert)) {
311 for (Map.Entry<String, Object> entry : mapToConvert.entrySet()) {
312 Optional<ParameterDefinition> parameterDefinition =
313 ToscaConverterUtil.createObjectFromClass(
314 entry.getKey(), entry.getValue(), ParameterDefinition.class);
316 parameterDefinition.ifPresent(parameterDefinitionValue -> {
317 Optional<Object> defaultValue =
318 ToscaConverterUtil.getDefaultValue(entry.getValue(), parameterDefinition.get());
319 defaultValue.ifPresent(parameterDefinitionValue::set_default);
320 addToServiceTemplateAccordingToSection(
321 serviceTemplate, inputsOrOutputs, entry.getKey(), parameterDefinition.get());
326 private void addToServiceTemplateAccordingToSection(ServiceTemplate serviceTemplate,
327 String inputsOrOutputs,
329 ParameterDefinition parameterDefinition) {
330 if (inputsOrOutputs.equals(inputs)) {
332 .addInputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
333 } else if (inputsOrOutputs.equals(outputs)) {
335 .addOutputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
339 private void convertNodeTemplates(ServiceTemplate serviceTemplate,
340 ServiceTemplateReaderService readerService) {
341 Map<String, Object> nodeTemplates = readerService.getNodeTemplates();
342 if (MapUtils.isEmpty(nodeTemplates)) {
346 for (Map.Entry<String, Object> nodeTemplateEntry : nodeTemplates.entrySet()) {
347 NodeTemplate nodeTemplate = convertNodeTemplate(nodeTemplateEntry.getValue());
348 DataModelUtil.addNodeTemplate(serviceTemplate, nodeTemplateEntry.getKey(), nodeTemplate);
352 private void convertSubstitutionMappings(ServiceTemplate serviceTemplate,
353 ServiceTemplateReaderService readerService) {
354 Map<String, Object> substitutionMappings = readerService.getSubstitutionMappings();
355 if (MapUtils.isEmpty(substitutionMappings)) {
358 SubstitutionMapping substitutionMapping = convertSubstitutionMappings(substitutionMappings);
359 DataModelUtil.addSubstitutionMapping(serviceTemplate, substitutionMapping);
362 private SubstitutionMapping convertSubstitutionMappings(
363 Map<String, Object> substitutionMappings) {
364 SubstitutionMapping substitutionMapping = new SubstitutionMapping();
366 substitutionMapping.setNode_type((String) substitutionMappings.get(nodeType));
367 substitutionMapping.setCapabilities(
368 convertSubstitutionMappingsSections(capabilities, substitutionMappings.get(capabilities)));
369 substitutionMapping.setRequirements(
370 convertSubstitutionMappingsSections(requirements, substitutionMappings.get(requirements)));
372 return substitutionMapping;
375 private Map<String, List<String>> convertSubstitutionMappingsSections(String sectionName,
376 Object sectionToConvert) {
378 if (Objects.isNull(sectionToConvert)) {
382 if (!(sectionToConvert instanceof Map)) {
383 throw new CoreException(
384 new SubstitutionMappingsConverterErrorBuilder(
385 sectionName, sectionToConvert.getClass().getSimpleName()).build());
388 return convertSection(sectionToConvert);
391 private Map<String, List<String>> convertSection(Object sectionToConvert) {
393 Map<String, Object> sectionAsMap = (Map<String, Object>) sectionToConvert;
394 Map<String, List<String>> convertedSection = new HashMap<>();
396 if (MapUtils.isEmpty(sectionAsMap)) {
400 for (Map.Entry<String, Object> entry : sectionAsMap.entrySet()) {
401 if (entry.getValue() instanceof List) {
402 convertedSection.put(entry.getKey(), (List<String>) entry.getValue());
406 return convertedSection;
409 private CsarFileTypes getFileType(String fileName) {
410 if (isMainServiceTemplate(fileName)) {
411 return CsarFileTypes.mainServiceTemplate;
412 } else if (isGlobalServiceTemplate(fileName)) {
413 return CsarFileTypes.globalServiceTemplate;
414 } else if (isDefinitions(fileName)) {
415 return CsarFileTypes.definitionsFile;
416 } else if (isMetadataFile(fileName)) {
417 return CsarFileTypes.toscaMetadata;
419 return CsarFileTypes.externalFile;
422 private NodeTemplate convertNodeTemplate(Object candidateNodeTemplate) {
423 NodeTemplate nodeTemplate = new NodeTemplate();
425 Map<String, Object> nodeTemplateAsMap = (Map<String, Object>) candidateNodeTemplate;
426 nodeTemplate.setArtifacts((Map<String, ArtifactDefinition>) nodeTemplateAsMap.get("artifacts"));
427 nodeTemplate.setAttributes((Map<String, Object>) nodeTemplateAsMap.get("attributes"));
428 nodeTemplate.setCopy((String) nodeTemplateAsMap.get("copy"));
429 nodeTemplate.setDescription((String) nodeTemplateAsMap.get("description"));
430 nodeTemplate.setDirectives((List<String>) nodeTemplateAsMap.get("directives"));
431 nodeTemplate.setInterfaces(
432 (Map<String, Object>) nodeTemplateAsMap.get("interfaces"));
433 nodeTemplate.setNode_filter((NodeFilter) nodeTemplateAsMap.get("node_filter"));
434 nodeTemplate.setProperties((Map<String, Object>) nodeTemplateAsMap.get("properties"));
435 nodeTemplate.setRequirements(
436 (List<Map<String, RequirementAssignment>>) nodeTemplateAsMap.get("requirements"));
437 nodeTemplate.setType((String) nodeTemplateAsMap.get("type"));
438 nodeTemplate.setCapabilities(
439 convertCapabilities((Map<String, Object>) nodeTemplateAsMap.get("capabilities")));
444 private Map<String, CapabilityAssignment> convertCapabilities(Map<String, Object> capabilities) {
445 if (MapUtils.isEmpty(capabilities)) {
449 Map<String, CapabilityAssignment> convertedCapabilities = new HashMap<>();
450 for (Map.Entry<String, Object> capabilityAssignmentEntry : capabilities.entrySet()) {
451 Optional<CapabilityAssignment> capabilityAssignment = ToscaConverterUtil.createObjectFromClass
452 (capabilityAssignmentEntry.getKey(), capabilityAssignmentEntry.getValue(),
453 CapabilityAssignment.class);
455 capabilityAssignment.ifPresent(capabilityAssignmentValue ->
456 convertedCapabilities.put(capabilityAssignmentEntry.getKey(), capabilityAssignmentValue));
459 return convertedCapabilities;
463 private boolean isMainServiceTemplate(String fileName) {
464 return fileName.endsWith(mainStName);
467 private boolean isMetadataFile(String fileName) {
468 return fileName.equals(metadataFile);
471 private boolean isGlobalServiceTemplate(String fileName) {
472 return fileName.endsWith(globalStName);
475 private boolean isDefinitions(String fileName) {
476 return fileName.startsWith(definitionsDir);
479 private String getTemplateNameFromStName(String serviceTemplateName) {
480 String fileNameWithoutDirectories;
481 fileNameWithoutDirectories = getFileNameWithoutDirectories(serviceTemplateName);
482 return fileNameWithoutDirectories.split("ServiceTemplate")[0];
485 private String getFileNameWithoutDirectories(String serviceTemplateName) {
486 String fileNameWithoutDirectories;
487 if (serviceTemplateName.contains("/")) {
488 String[] split = serviceTemplateName.split("/");
489 fileNameWithoutDirectories = split[split.length - 1];
490 } else if (serviceTemplateName.contains(File.separator)) {
491 String[] split = serviceTemplateName.split(Pattern.quote(File.separator));
492 fileNameWithoutDirectories = split[split.length - 1];
494 fileNameWithoutDirectories = serviceTemplateName;
496 return fileNameWithoutDirectories;