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.manifestFileName;
27 import static org.openecomp.core.converter.datatypes.Constants.metadataFile;
28 import static org.openecomp.core.converter.datatypes.Constants.nodeType;
29 import static org.openecomp.core.converter.datatypes.Constants.openecompHeatIndex;
30 import static org.openecomp.core.converter.datatypes.Constants.outputs;
31 import static org.openecomp.core.converter.datatypes.Constants.requirements;
32 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME;
33 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.HEAT_INDEX_IMPORT_FILE;
34 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.ONAP_INDEX_IMPORT_FILE;
36 import org.apache.commons.collections.MapUtils;
37 import org.openecomp.core.converter.ServiceTemplateReaderService;
38 import org.openecomp.core.converter.ToscaConverter;
39 import org.openecomp.core.converter.datatypes.Constants;
40 import org.openecomp.core.converter.datatypes.CsarFileTypes;
41 import org.openecomp.core.converter.errors.SubstitutionMappingsConverterErrorBuilder;
42 import org.openecomp.core.impl.services.ServiceTemplateReaderServiceImpl;
43 import org.openecomp.core.utilities.file.FileContentHandler;
44 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
45 import org.openecomp.sdc.common.errors.CoreException;
46 import org.openecomp.sdc.common.errors.ErrorCategory;
47 import org.openecomp.sdc.common.errors.ErrorCode;
48 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
49 import org.openecomp.sdc.tosca.datatypes.model.ArtifactDefinition;
50 import org.openecomp.sdc.tosca.datatypes.model.CapabilityAssignment;
51 import org.openecomp.sdc.tosca.datatypes.model.Import;
52 import org.openecomp.sdc.tosca.datatypes.model.InterfaceDefinition;
53 import org.openecomp.sdc.tosca.datatypes.model.NodeFilter;
54 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
55 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
56 import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
57 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
58 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
59 import org.openecomp.sdc.tosca.datatypes.model.SubstitutionMapping;
60 import org.openecomp.sdc.tosca.services.DataModelUtil;
61 import org.openecomp.sdc.tosca.services.ToscaUtil;
62 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
63 import org.yaml.snakeyaml.error.YAMLException;
65 import java.io.ByteArrayInputStream;
67 import java.io.IOException;
68 import java.util.ArrayList;
69 import java.util.Collection;
70 import java.util.Collections;
71 import java.util.HashMap;
72 import java.util.List;
74 import java.util.Objects;
75 import java.util.Optional;
76 import java.util.jar.Manifest;
77 import java.util.regex.Pattern;
79 public class ToscaConverterImpl implements ToscaConverter {
81 private static final String ORIGINAL = ".original";
84 public ToscaServiceModel convert(FileContentHandler fileContentHandler)
86 Map<String, byte[]> csarFiles = new HashMap<>(fileContentHandler.getFiles());
87 ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
88 Map<String, ServiceTemplate> serviceTemplates = new HashMap<>();
89 FileContentHandler artifacts = new FileContentHandler();
90 GlobalSubstitutionServiceTemplate gsst = new GlobalSubstitutionServiceTemplate();
91 for (Map.Entry<String, byte[]> fileEntry : csarFiles.entrySet()) {
92 CsarFileTypes fileType = getFileType(fileEntry.getKey());
94 case mainServiceTemplate:
95 handleServiceTemplate(mainStName, fileEntry.getKey(), csarFiles, serviceTemplates);
98 case globalServiceTemplate:
99 handleServiceTemplate(globalStName, fileEntry.getKey(), csarFiles, serviceTemplates);
104 getConcreteArtifactFileName(fileEntry.getKey()), fileEntry.getValue());
107 case definitionsFile:
108 handleDefintionTemplate(fileEntry.getKey(), csarFiles, gsst);
115 handleMetadataFile(csarFiles);
116 updateToscaServiceModel(toscaServiceModel, serviceTemplates, artifacts, gsst, csarFiles);
117 return toscaServiceModel;
120 private void handleMetadataFile(Map<String, byte[]> csarFiles) {
121 byte[] bytes = csarFiles.remove(metadataFile);
123 csarFiles.put(metadataFile + ORIGINAL, bytes);
127 private void handleDefintionTemplate(String key, Map<String, byte[]> csarFiles,
128 GlobalSubstitutionServiceTemplate gsst) {
130 ServiceTemplateReaderService readerService = new ServiceTemplateReaderServiceImpl(csarFiles.get(key));
131 Object nodeTypes = readerService.getNodeTypes();
132 if (nodeTypes instanceof Map) {
133 Map<String, NodeType> nodeTypeMap = (Map<String, NodeType>) nodeTypes;
134 gsst.appendNodes(nodeTypeMap);
136 } catch (YAMLException ye) {
137 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
138 .withMessage("Invalid YAML content in file " + key)
139 .withCategory(ErrorCategory.APPLICATION).build(), ye);
143 private String getConcreteArtifactFileName(String fileName){
144 int artifactIndex = fileName.indexOf(CsarFileTypes.Artifacts.name());
145 if(artifactIndex < 0){
149 int artifactDirectoryIndex =
150 artifactIndex + CsarFileTypes.Artifacts.name().length() + 1;
151 return fileName.substring(artifactDirectoryIndex);
154 private void updateToscaServiceModel(ToscaServiceModel toscaServiceModel,
155 Map<String, ServiceTemplate> serviceTemplates,
156 FileContentHandler externalFilesHandler,
157 GlobalSubstitutionServiceTemplate globalSubstitutionServiceTemplate,
158 Map<String, byte[]> csarFiles) {
159 Collection<ServiceTemplate> globalServiceTemplates =
160 GlobalTypesGenerator.getGlobalTypesServiceTemplate(OnboardingTypesEnum.CSAR).values();
161 addGlobalServiceTemplates(globalServiceTemplates, serviceTemplates);
162 toscaServiceModel.setEntryDefinitionServiceTemplate(mainStName);
163 toscaServiceModel.setServiceTemplates(serviceTemplates);
164 externalFilesHandler.addFile(metadataFile + ORIGINAL,
165 csarFiles.get(metadataFile + ORIGINAL));
166 toscaServiceModel.setArtifactFiles(externalFilesHandler);
168 if(MapUtils.isNotEmpty(globalSubstitutionServiceTemplate.getNode_types())) {
170 .put(GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME, globalSubstitutionServiceTemplate);
174 private void addGlobalServiceTemplates(Collection<ServiceTemplate> globalServiceTemplates,
175 Map<String, ServiceTemplate> serviceTemplates) {
176 for (ServiceTemplate serviceTemplate : globalServiceTemplates) {
177 serviceTemplates.put(ToscaUtil.getServiceTemplateFileName(serviceTemplate), serviceTemplate);
181 private void handleServiceTemplate(String serviceTemplateName,
182 String fileName, Map<String, byte[]> csarFiles,
183 Map<String, ServiceTemplate> serviceTemplates) {
184 Optional<ServiceTemplate> serviceTemplate =
185 getServiceTemplateFromCsar(fileName, csarFiles);
186 serviceTemplate.ifPresent(
187 serviceTemplateValue -> addServiceTemplate(serviceTemplateName, serviceTemplateValue,
191 private void addServiceTemplate(String serviceTemplateName,
192 ServiceTemplate serviceTemplate,
193 Map<String, ServiceTemplate> serviceTemplates) {
194 serviceTemplates.put(serviceTemplateName, serviceTemplate);
197 private Optional<byte[]> getManifestContent(Map<String, byte[]> csarFiles) {
198 for (Map.Entry<String, byte[]> csarFileEntry : csarFiles.entrySet()) {
199 if (csarFileEntry.getKey().contains(manifestFileName)) {
200 return Optional.of(csarFileEntry.getValue());
204 return Optional.empty();
207 private Optional<ServiceTemplate> getServiceTemplateFromCsar(String fileName,
208 Map<String, byte[]> csarFiles) {
209 byte[] fileContent = csarFiles.get(fileName);
210 ServiceTemplate serviceTemplate = convertServiceTemplate(fileName, fileContent);
212 return Optional.of(serviceTemplate);
215 private ServiceTemplate convertServiceTemplate(String serviceTemplateName,
216 byte[] fileContent) {
217 ServiceTemplate serviceTemplate = new ServiceTemplate();
219 ServiceTemplateReaderService readerService =
220 new ServiceTemplateReaderServiceImpl(fileContent);
221 convertMetadata(serviceTemplateName, serviceTemplate, readerService);
222 convertToscaVersion(serviceTemplate, readerService);
223 convertImports(serviceTemplate);
224 convertNodeTypes(serviceTemplate, readerService);
225 convertTopologyTemplate(serviceTemplate, readerService);
227 } catch (YAMLException ye) {
228 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
229 .withMessage("Invalid YAML content in file" + serviceTemplateName)
230 .withCategory(ErrorCategory.APPLICATION).build(), ye);
234 return serviceTemplate;
237 private void convertToscaVersion(ServiceTemplate serviceTemplate,
238 ServiceTemplateReaderService readerService) {
239 Object toscaVersion = readerService.getToscaVersion();
240 serviceTemplate.setTosca_definitions_version((String) toscaVersion);
243 private void convertImports(ServiceTemplate serviceTemplate) {
244 serviceTemplate.setImports(new ArrayList<>());
245 serviceTemplate.getImports()
246 .add(createImportMap(openecompHeatIndex, HEAT_INDEX_IMPORT_FILE));
247 serviceTemplate.getImports().add(createImportMap(ONAP_INDEX, ONAP_INDEX_IMPORT_FILE));
248 serviceTemplate.getImports().add(createImportMap(globalSubstitution, globalStName));
252 private Map<String, Import> createImportMap(String key, String fileName) {
253 Map<String, Import> importMap = new HashMap<>();
254 Import anImport = new Import();
255 anImport.setFile(fileName);
256 importMap.put(key, anImport);
261 private void convertMetadata(String serviceTemplateName,
262 ServiceTemplate serviceTemplate,
263 ServiceTemplateReaderService readerService) {
264 Map<String, Object> metadataToConvert = (Map<String, Object>) readerService.getMetadata();
265 Map<String, String> finalMetadata = new HashMap<>();
267 if (MapUtils.isNotEmpty(metadataToConvert)) {
268 for (Map.Entry<String, Object> metadataEntry : metadataToConvert.entrySet()) {
269 if (Objects.isNull(metadataEntry.getValue()) ||
270 !(metadataEntry.getValue() instanceof String)) {
273 finalMetadata.put(metadataEntry.getKey(), (String) metadataEntry.getValue());
277 finalMetadata.put("template_name", getTemplateNameFromStName(serviceTemplateName));
278 serviceTemplate.setMetadata(finalMetadata);
281 private void convertNodeTypes(ServiceTemplate serviceTemplate, ServiceTemplateReaderService readerService) {
282 Map<String, Object> nodeTypes = readerService.getNodeTypes();
283 if (MapUtils.isEmpty(nodeTypes)) {
287 for (Map.Entry<String, Object> nodeTypeEntry : nodeTypes.entrySet()) {
288 Optional<NodeType> nodeType = ToscaConverterUtil
289 .createObjectFromClass(nodeTypeEntry.getKey(), nodeTypeEntry.getValue(),
292 nodeType.ifPresent(nodeTypeValue -> DataModelUtil
293 .addNodeType(serviceTemplate, nodeTypeEntry.getKey(), nodeTypeValue));
297 private void convertTopologyTemplate(ServiceTemplate serviceTemplate,
298 ServiceTemplateReaderService readerService) {
300 convertInputs(serviceTemplate, readerService);
301 convertNodeTemplates(serviceTemplate, readerService);
302 convertOutputs(serviceTemplate, readerService);
303 convertSubstitutionMappings(serviceTemplate, readerService);
306 private void convertInputs(ServiceTemplate serviceTemplate,
307 ServiceTemplateReaderService readerService) {
308 Map<String, Object> inputs = readerService.getInputs();
309 addInputsOrOutputsToServiceTemplate(serviceTemplate, inputs, Constants.inputs);
312 private void convertOutputs(ServiceTemplate serviceTemplate,
313 ServiceTemplateReaderService readerService) {
314 Map<String, Object> outputs = readerService.getOutputs();
315 addInputsOrOutputsToServiceTemplate(serviceTemplate, outputs, Constants.outputs);
318 private void addInputsOrOutputsToServiceTemplate(ServiceTemplate serviceTemplate,
319 Map<String, Object> mapToConvert,
320 String inputsOrOutputs) {
321 if (MapUtils.isEmpty(mapToConvert)) {
325 for (Map.Entry<String, Object> entry : mapToConvert.entrySet()) {
326 Optional<ParameterDefinition> parameterDefinition =
327 ToscaConverterUtil.createObjectFromClass(
328 entry.getKey(), entry.getValue(), ParameterDefinition.class);
330 parameterDefinition.ifPresent(parameterDefinitionValue -> {
331 Optional<Object> defaultValue =
332 ToscaConverterUtil.getDefaultValue(entry.getValue(), parameterDefinition.get());
333 defaultValue.ifPresent(parameterDefinitionValue::set_default);
334 addToServiceTemplateAccordingToSection(
335 serviceTemplate, inputsOrOutputs, entry.getKey(), parameterDefinition.get());
340 private void addToServiceTemplateAccordingToSection(ServiceTemplate serviceTemplate,
341 String inputsOrOutputs,
343 ParameterDefinition parameterDefinition) {
344 if (inputsOrOutputs.equals(inputs)) {
346 .addInputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
347 } else if (inputsOrOutputs.equals(outputs)) {
349 .addOutputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
353 private void convertNodeTemplates(ServiceTemplate serviceTemplate,
354 ServiceTemplateReaderService readerService) {
355 Map<String, Object> nodeTemplates = readerService.getNodeTemplates();
356 if (MapUtils.isEmpty(nodeTemplates)) {
360 for (Map.Entry<String, Object> nodeTemplateEntry : nodeTemplates.entrySet()) {
361 NodeTemplate nodeTemplate = convertNodeTemplate(nodeTemplateEntry.getValue());
362 DataModelUtil.addNodeTemplate(serviceTemplate, nodeTemplateEntry.getKey(), nodeTemplate);
366 private void convertSubstitutionMappings(ServiceTemplate serviceTemplate,
367 ServiceTemplateReaderService readerService) {
368 Map<String, Object> substitutionMappings = readerService.getSubstitutionMappings();
369 if (MapUtils.isEmpty(substitutionMappings)) {
372 SubstitutionMapping substitutionMapping = convertSubstitutionMappings(substitutionMappings);
373 DataModelUtil.addSubstitutionMapping(serviceTemplate, substitutionMapping);
376 private SubstitutionMapping convertSubstitutionMappings(Map<String, Object> substitutionMappings) {
377 SubstitutionMapping substitutionMapping = new SubstitutionMapping();
379 substitutionMapping.setNode_type((String) substitutionMappings.get(nodeType));
380 substitutionMapping.setCapabilities(
381 convertSubstitutionMappingsSections(capabilities, substitutionMappings.get(capabilities)));
382 substitutionMapping.setRequirements(
383 convertSubstitutionMappingsSections(requirements, substitutionMappings.get(requirements)));
385 return substitutionMapping;
388 private Map<String, List<String>> convertSubstitutionMappingsSections(String sectionName,
389 Object sectionToConvert) {
391 if(Objects.isNull(sectionToConvert)){
395 if(!(sectionToConvert instanceof Map)) {
396 throw new CoreException(
397 new SubstitutionMappingsConverterErrorBuilder(
398 sectionName, sectionToConvert.getClass().getSimpleName()).build());
401 return convertSection(sectionToConvert);
404 private Map<String, List<String>> convertSection(Object sectionToConvert) {
406 Map<String, Object> sectionAsMap = (Map<String, Object>)sectionToConvert;
407 Map<String, List<String>> convertedSection = new HashMap<>();
409 if (MapUtils.isEmpty(sectionAsMap)) {
413 for (Map.Entry<String, Object> entry : sectionAsMap.entrySet()) {
414 if (entry.getValue() instanceof List) {
415 convertedSection.put(entry.getKey(), (List<String>) entry.getValue());
419 return convertedSection;
422 private CsarFileTypes getFileType(String fileName) {
423 if (isMainServiceTemplate(fileName)) {
424 return CsarFileTypes.mainServiceTemplate;
425 } else if (isGlobalServiceTemplate(fileName)) {
426 return CsarFileTypes.globalServiceTemplate;
427 } else if (isDefinitions(fileName)) {
428 return CsarFileTypes.definitionsFile;
429 } else if (isMetadataFile(fileName)) {
430 return CsarFileTypes.toscaMetadata;
432 return CsarFileTypes.externalFile;
435 private Optional<Manifest> getCsarManifest(Map<String, byte[]> csarFiles) throws IOException {
436 Optional<byte[]> manifestContent = getManifestContent(csarFiles);
438 if (manifestContent.isPresent()) {
439 ByteArrayInputStream byteInputStream = new ByteArrayInputStream(manifestContent.get());
441 return Optional.of(new Manifest(byteInputStream));
444 return Optional.empty();
447 private NodeTemplate convertNodeTemplate(Object candidateNodeTemplate) {
448 NodeTemplate nodeTemplate = new NodeTemplate();
450 Map<String, Object> nodeTemplateAsMap = (Map<String, Object>) candidateNodeTemplate;
451 nodeTemplate.setArtifacts((Map<String, ArtifactDefinition>) nodeTemplateAsMap.get("artifacts"));
452 nodeTemplate.setAttributes((Map<String, Object>) nodeTemplateAsMap.get("attributes"));
453 nodeTemplate.setCopy((String) nodeTemplateAsMap.get("copy"));
454 nodeTemplate.setDescription((String) nodeTemplateAsMap.get("description"));
455 nodeTemplate.setDirectives((List<String>) nodeTemplateAsMap.get("directives"));
456 nodeTemplate.setInterfaces(
457 (Map<String, InterfaceDefinition>) nodeTemplateAsMap.get("interfaces"));
458 nodeTemplate.setNode_filter((NodeFilter) nodeTemplateAsMap.get("node_filter"));
459 nodeTemplate.setProperties((Map<String, Object>) nodeTemplateAsMap.get("properties"));
460 nodeTemplate.setRequirements(
461 (List<Map<String, RequirementAssignment>>) nodeTemplateAsMap.get("requirements"));
462 nodeTemplate.setType((String) nodeTemplateAsMap.get("type"));
463 nodeTemplate.setCapabilities(
464 convertCapabilities((Map<String, Object>) nodeTemplateAsMap.get("capabilities")));
469 private List<Map<String, CapabilityAssignment>> convertCapabilities(Map<String, Object> capabilities) {
470 List<Map<String, CapabilityAssignment>> convertedCapabilities = new ArrayList<>();
471 if (MapUtils.isEmpty(capabilities)) {
474 for (Map.Entry<String, Object> capabilityAssignmentEntry : capabilities.entrySet()) {
475 Map<String, CapabilityAssignment> tempMap = new HashMap<>();
476 Optional<CapabilityAssignment> capabilityAssignment = ToscaConverterUtil.createObjectFromClass
477 (capabilityAssignmentEntry.getKey(), capabilityAssignmentEntry.getValue(),
478 CapabilityAssignment.class);
480 capabilityAssignment.ifPresent(capabilityAssignmentValue -> {
481 tempMap.put(capabilityAssignmentEntry.getKey(), capabilityAssignmentValue);
482 convertedCapabilities.add(tempMap);
487 return convertedCapabilities;
491 private boolean isMainServiceTemplate(String fileName) {
492 return fileName.endsWith(mainStName);
495 private boolean isMetadataFile(String fileName) {
496 return fileName.equals(metadataFile);
499 private boolean isGlobalServiceTemplate(String fileName) {
500 return fileName.endsWith(globalStName);
503 private boolean isDefinitions(String fileName) {
504 return fileName.startsWith(definitionsDir);
507 private String getTemplateNameFromStName(String serviceTemplateName) {
508 String fileNameWithoutDirectories;
509 fileNameWithoutDirectories = getFileNameWithoutDirectories(serviceTemplateName);
510 return fileNameWithoutDirectories.split("ServiceTemplate")[0];
513 private String getFileNameWithoutDirectories(String serviceTemplateName) {
514 String fileNameWithoutDirectories;
515 if (serviceTemplateName.contains("/")) {
516 String[] split = serviceTemplateName.split("/");
517 fileNameWithoutDirectories = split[split.length - 1];
518 } else if (serviceTemplateName.contains(File.separator)) {
519 String[] split = serviceTemplateName.split(Pattern.quote(File.separator));
520 fileNameWithoutDirectories = split[split.length - 1];
522 fileNameWithoutDirectories = serviceTemplateName;
524 return fileNameWithoutDirectories;