f38d7f2b0609fde41233a613e3aba38591c9ea55
[sdc.git] / openecomp-be / lib / openecomp-tosca-converter-lib / openecomp-tosca-converter-core / src / main / java / org / openecomp / core / impl / ToscaConverterImpl.java
1 package org.openecomp.core.impl;
2
3 import org.apache.commons.collections.MapUtils;
4 import org.openecomp.core.converter.ServiceTemplateReaderService;
5 import org.openecomp.core.converter.ToscaConverter;
6 import org.openecomp.core.converter.datatypes.Constants;
7 import org.openecomp.core.converter.datatypes.CsarFileTypes;
8 import org.openecomp.core.impl.services.ServiceTemplateReaderServiceImpl;
9 import org.openecomp.core.utilities.file.FileContentHandler;
10 import org.openecomp.core.utilities.json.JsonUtil;
11 import org.openecomp.sdc.common.errors.CoreException;
12 import org.openecomp.sdc.common.errors.ErrorCategory;
13 import org.openecomp.sdc.common.errors.ErrorCode;
14 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
15 import org.openecomp.sdc.tosca.datatypes.model.*;
16 import org.openecomp.sdc.tosca.services.DataModelUtil;
17 import org.openecomp.sdc.tosca.services.ToscaUtil;
18 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
19 import org.yaml.snakeyaml.error.YAMLException;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.*;
25 import java.util.jar.Manifest;
26 import java.util.regex.Pattern;
27
28 import static org.openecomp.core.converter.datatypes.Constants.*;
29 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME;
30
31 public class ToscaConverterImpl implements ToscaConverter {
32
33     public ToscaConverterImpl() {
34
35     }
36
37     @Override
38     public ToscaServiceModel convert(FileContentHandler fileContentHandler)
39             throws IOException {
40         Map<String, byte[]> csarFiles = new HashMap<>(fileContentHandler.getFiles());
41         ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
42         Map<String, ServiceTemplate> serviceTemplates = new HashMap<>();
43         FileContentHandler artifacts = new FileContentHandler();
44         GlobalSubstitutionServiceTemplate gsst = new GlobalSubstitutionServiceTemplate();
45         for (Map.Entry<String, byte[]> fileEntry : csarFiles.entrySet()) {
46             CsarFileTypes fileType = getFileType(fileEntry.getKey());
47             switch (fileType) {
48                 case mainServiceTemplate:
49                     handleServiceTemplate(mainStName, fileEntry.getKey(), csarFiles, serviceTemplates);
50                     break;
51
52                 case globalServiceTemplate:
53                     handleServiceTemplate(globalStName, fileEntry.getKey(), csarFiles, serviceTemplates);
54                     break;
55
56                 case externalFile:
57                     artifacts.addFile(fileEntry.getKey(), fileEntry.getValue());
58                     break;
59
60                 case definitionsFile:
61                     handleDefintionTemplate(fileEntry.getKey(), csarFiles, gsst);
62                     break;
63             }
64         }
65         handleMetadataFile(csarFiles);
66         updateToscaServiceModel(toscaServiceModel, serviceTemplates, artifacts, gsst, csarFiles);
67         return toscaServiceModel;
68     }
69
70     private void handleMetadataFile(Map<String, byte[]> csarFiles) {
71         byte[] bytes = csarFiles.remove(metadataFile);
72         if (bytes != null) {
73             csarFiles.put(metadataFile + ".original", bytes);
74         }
75     }
76
77     private void handleDefintionTemplate(String key, Map<String, byte[]> csarFiles,
78                                          GlobalSubstitutionServiceTemplate gsst) {
79         try {
80             ServiceTemplateReaderService readerService = new ServiceTemplateReaderServiceImpl(csarFiles.get(key));
81             if (readerService == null) {
82                 return;
83             }
84             Object nodeTypes = readerService.getNodeTypes();
85             if (nodeTypes instanceof Map) {
86                 Map<String, NodeType> nodeTypeMap = (Map<String, NodeType>) nodeTypes;
87                 gsst.appendNodes(nodeTypeMap);
88             }
89         } catch (YAMLException ye) {
90             throw new CoreException(new ErrorCode.ErrorCodeBuilder()
91                     .withMessage("Invalid YAML content in file " + key + ". reason - "
92                             + ye.getMessage())
93                     .withCategory(ErrorCategory.APPLICATION).build());
94         }
95     }
96
97     private void updateToscaServiceModel(ToscaServiceModel toscaServiceModel,
98                                          Map<String, ServiceTemplate> serviceTemplates,
99                                          FileContentHandler externalFilesHandler,
100                                          GlobalSubstitutionServiceTemplate globalSubstitutionServiceTemplate,
101                                          Map<String, byte[]> csarFiles) {
102         Collection<ServiceTemplate> globalServiceTemplates =
103                 GlobalTypesGenerator.getGlobalTypesServiceTemplate().values();
104         addGlobalServiceTemplates(globalServiceTemplates, serviceTemplates);
105         toscaServiceModel.setEntryDefinitionServiceTemplate(mainStName);
106         toscaServiceModel.setServiceTemplates(serviceTemplates);
107         externalFilesHandler.addFile(metadataFile + ".original",
108             csarFiles.get(metadataFile + ".original"));
109         toscaServiceModel.setArtifactFiles(externalFilesHandler);
110
111         if(MapUtils.isNotEmpty(globalSubstitutionServiceTemplate.getNode_types())) {
112             serviceTemplates
113                 .put(GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME, globalSubstitutionServiceTemplate);
114         }
115     }
116
117     private void addGlobalServiceTemplates(Collection<ServiceTemplate> globalServiceTemplates,
118                                            Map<String, ServiceTemplate> serviceTemplates) {
119         for (ServiceTemplate serviceTemplate : globalServiceTemplates) {
120             serviceTemplates.put(ToscaUtil.getServiceTemplateFileName(serviceTemplate), serviceTemplate);
121         }
122     }
123
124     private void handleServiceTemplate(String serviceTemplateName,
125                                        String fileName, Map<String, byte[]> csarFiles,
126                                        Map<String, ServiceTemplate> serviceTemplates) {
127         Optional<ServiceTemplate> serviceTemplate =
128                 getServiceTemplateFromCsar(fileName, csarFiles);
129         serviceTemplate.ifPresent(
130                 serviceTemplate1 -> addServiceTemplate(serviceTemplateName, serviceTemplate1,
131                         serviceTemplates));
132     }
133
134     private void addServiceTemplate(String serviceTemplateName,
135                                     ServiceTemplate serviceTemplate,
136                                     Map<String, ServiceTemplate> serviceTemplates) {
137         serviceTemplates.put(serviceTemplateName, serviceTemplate);
138     }
139
140     private Optional<byte[]> getManifestContent(Map<String, byte[]> csarFiles) {
141         for (Map.Entry<String, byte[]> csarFileEntry : csarFiles.entrySet()) {
142             if (csarFileEntry.getKey().contains(manifestFileName)) {
143                 return Optional.of(csarFileEntry.getValue());
144             }
145         }
146
147         return Optional.empty();
148     }
149
150     private Optional<ServiceTemplate> getServiceTemplateFromCsar(String fileName,
151                                                                  Map<String, byte[]> csarFiles) {
152         byte[] fileContent = csarFiles.get(fileName);
153         ServiceTemplate serviceTemplate = convertServiceTemplate(fileName, fileContent);
154
155         return Optional.of(serviceTemplate);
156     }
157
158     private ServiceTemplate convertServiceTemplate(String serviceTemplateName,
159                                                    byte[] fileContent) {
160         ServiceTemplate serviceTemplate = new ServiceTemplate();
161         try {
162             ServiceTemplateReaderService readerService =
163                     new ServiceTemplateReaderServiceImpl(fileContent);
164             convertMetadata(serviceTemplateName, serviceTemplate, readerService);
165             convertToscaVersion(serviceTemplate, readerService);
166             convertImports(serviceTemplate);
167             convertNodeTypes(serviceTemplate, readerService);
168             convertTopologyTemplate(serviceTemplate, readerService);
169
170         } catch (YAMLException ye) {
171             throw new CoreException(new ErrorCode.ErrorCodeBuilder()
172                     .withMessage("Invalid YAML content in file" + serviceTemplateName + ". reason - "
173                             + ye.getMessage())
174                     .withCategory(ErrorCategory.APPLICATION).build());
175         }
176
177
178         return serviceTemplate;
179     }
180
181     private void convertToscaVersion(ServiceTemplate serviceTemplate,
182                                      ServiceTemplateReaderService readerService) {
183         Object toscaVersion = readerService.getToscaVersion();
184         serviceTemplate.setTosca_definitions_version((String) toscaVersion);
185     }
186
187     private void convertImports(ServiceTemplate serviceTemplate) {
188         serviceTemplate.setImports(new ArrayList<>());
189         serviceTemplate.getImports()
190                 .add(createImportMap(openecompHeatIndex, "openecomp-heat/_index.yml"));
191         serviceTemplate.getImports().add(createImportMap(globalSubstitution, globalStName));
192
193     }
194
195     private Map<String, Import> createImportMap(String key, String fileName) {
196         Map<String, Import> importMap = new HashMap<>();
197         Import anImport = new Import();
198         anImport.setFile(fileName);
199         importMap.put(key, anImport);
200
201         return importMap;
202     }
203
204     private void convertMetadata(String serviceTemplateName,
205                                  ServiceTemplate serviceTemplate,
206                                  ServiceTemplateReaderService readerService) {
207         Map<String, Object> metadataToConvert = (Map<String, Object>) readerService.getMetadata();
208         Map<String, String> finalMetadata = new HashMap<>();
209
210         if (MapUtils.isNotEmpty(metadataToConvert)) {
211             for (Map.Entry<String, Object> metadataEntry : metadataToConvert.entrySet()) {
212                 if (Objects.isNull(metadataEntry.getValue()) ||
213                         !(metadataEntry.getValue() instanceof String)) {
214                     continue;
215                 }
216                 finalMetadata.put(metadataEntry.getKey(), (String) metadataEntry.getValue());
217             }
218         }
219
220         finalMetadata.put("template_name", getTemplateNameFromStName(serviceTemplateName));
221         serviceTemplate.setMetadata(finalMetadata);
222     }
223
224     private void convertNodeTypes(ServiceTemplate serviceTemplate, ServiceTemplateReaderService readerService) {
225         Map<String, Object> nodeTypes = (Map<String, Object>) readerService.getNodeTypes();
226         if (MapUtils.isEmpty(nodeTypes)) {
227             return;
228         }
229
230         for (Map.Entry<String, Object> nodeTypeEntry : nodeTypes.entrySet()) {
231             DataModelUtil
232                     .addNodeType(serviceTemplate, nodeTypeEntry.getKey(),
233                             (NodeType) createObjectFromClass(nodeTypeEntry.getKey(), nodeTypeEntry.getValue(),
234                                     NodeType.class));
235         }
236     }
237
238     private void convertTopologyTemplate(ServiceTemplate serviceTemplate,
239                                          ServiceTemplateReaderService readerService) {
240
241         convertInputs(serviceTemplate, readerService);
242         convertNodeTemplates(serviceTemplate, readerService);
243         convertOutputs(serviceTemplate, readerService);
244         convertSubstitutionMappings(serviceTemplate, readerService);
245     }
246
247     private void convertInputs(ServiceTemplate serviceTemplate,
248                                ServiceTemplateReaderService readerService) {
249         Map<String, Object> inputs = readerService.getInputs();
250         addInputsOrOutputsToServiceTemplate(serviceTemplate, inputs, Constants.inputs);
251     }
252
253     private void convertOutputs(ServiceTemplate serviceTemplate,
254                                 ServiceTemplateReaderService readerService) {
255         Map<String, Object> outputs = readerService.getOutputs();
256         addInputsOrOutputsToServiceTemplate(serviceTemplate, outputs, Constants.outputs);
257     }
258
259     private void addInputsOrOutputsToServiceTemplate(ServiceTemplate serviceTemplate,
260                                                      Map<String, Object> mapToConvert,
261                                                      String inputsOrOutputs) {
262         if (MapUtils.isEmpty(mapToConvert)) {
263             return;
264         }
265
266         for (Map.Entry<String, Object> entry : mapToConvert.entrySet()) {
267             ParameterDefinition parameterDefinition =
268                     (ParameterDefinition) createObjectFromClass(
269                             entry.getKey(), entry.getValue(), ParameterDefinition.class);
270             addToServiceTemplateAccordingToSection(
271                     serviceTemplate, inputsOrOutputs, entry.getKey(), parameterDefinition);
272         }
273     }
274
275     private void addToServiceTemplateAccordingToSection(ServiceTemplate serviceTemplate,
276                                                         String inputsOrOutputs,
277                                                         String parameterId,
278                                                         ParameterDefinition parameterDefinition) {
279         switch (inputsOrOutputs) {
280             case inputs:
281                 DataModelUtil
282                         .addInputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
283                 break;
284             case outputs:
285                 DataModelUtil
286                         .addOutputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
287         }
288     }
289
290     private void convertNodeTemplates(ServiceTemplate serviceTemplate,
291                                       ServiceTemplateReaderService readerService) {
292         Map<String, Object> nodeTemplates = readerService.getNodeTemplates();
293         if (MapUtils.isEmpty(nodeTemplates)) {
294             return;
295         }
296
297         for (Map.Entry<String, Object> nodeTemplateEntry : nodeTemplates.entrySet()) {
298             NodeTemplate nodeTemplate = convertNodeTemplate(nodeTemplateEntry.getValue());
299             DataModelUtil.addNodeTemplate(serviceTemplate, nodeTemplateEntry.getKey(), nodeTemplate);
300         }
301     }
302
303     private void convertSubstitutionMappings(ServiceTemplate serviceTemplate,
304                                              ServiceTemplateReaderService readerService) {
305         Map<String, Object> substitutionMappings = readerService.getSubstitutionMappings();
306         if (MapUtils.isEmpty(substitutionMappings)) {
307             return;
308         }
309         SubstitutionMapping substitutionMapping = convertSubstitutionMappings(substitutionMappings);
310         DataModelUtil.addSubstitutionMapping(serviceTemplate, substitutionMapping);
311     }
312
313     private SubstitutionMapping convertSubstitutionMappings(Map<String, Object> substitutionMappings) {
314         SubstitutionMapping substitutionMapping = new SubstitutionMapping();
315
316         substitutionMapping.setNode_type((String) substitutionMappings.get(nodeType));
317         substitutionMapping.setCapabilities(
318                 convertSubstitutionMappingsSections((Map<String, Object>) substitutionMappings.get(capabilities)));
319         substitutionMapping.setRequirements(
320                 convertSubstitutionMappingsSections((Map<String, Object>) substitutionMappings.get(requirements)));
321
322         return substitutionMapping;
323     }
324
325     private Map<String, List<String>> convertSubstitutionMappingsSections(
326             Map<String, Object> sectionToConvert) {
327         Map<String, List<String>> convertedSection = new HashMap<>();
328         if (MapUtils.isEmpty(sectionToConvert)) {
329             return null;
330         }
331
332         for (Map.Entry<String, Object> entry : sectionToConvert.entrySet()) {
333             if (entry.getValue() instanceof List) {
334                 convertedSection.put(entry.getKey(), (List<String>) entry.getValue());
335             }
336         }
337
338         return convertedSection;
339     }
340
341     private CsarFileTypes getFileType(String fileName) {
342         if (isMainServiceTemplate(fileName)) {
343             return CsarFileTypes.mainServiceTemplate;
344         } else if (isGlobalServiceTemplate(fileName)) {
345             return CsarFileTypes.globalServiceTemplate;
346         } else if (isDefinitions(fileName)) {
347             return CsarFileTypes.definitionsFile;
348         } else if (isMetadataFile(fileName)) {
349             return CsarFileTypes.toscaMetadata;
350         }
351         return CsarFileTypes.externalFile;
352     }
353
354     private Optional<Manifest> getCsarManifest(Map<String, byte[]> csarFiles) throws IOException {
355         Optional<byte[]> manifestContent = getManifestContent(csarFiles);
356
357         if (manifestContent.isPresent()) {
358             ByteArrayInputStream byteInputStream = new ByteArrayInputStream(manifestContent.get());
359
360             return Optional.of(new Manifest(byteInputStream));
361         }
362
363         return Optional.empty();
364     }
365
366     private NodeTemplate convertNodeTemplate(Object candidateNodeTemplate) {
367         NodeTemplate nodeTemplate = new NodeTemplate();
368
369         Map<String, Object> nodeTemplateAsMap = (Map<String, Object>) candidateNodeTemplate;
370         nodeTemplate.setArtifacts((Map<String, ArtifactDefinition>) nodeTemplateAsMap.get("artifacts"));
371         nodeTemplate.setAttributes((Map<String, Object>) nodeTemplateAsMap.get("attributes"));
372         nodeTemplate.setCopy((String) nodeTemplateAsMap.get("copy"));
373         nodeTemplate.setDescription((String) nodeTemplateAsMap.get("description"));
374         nodeTemplate.setDirectives((List<String>) nodeTemplateAsMap.get("directives"));
375         nodeTemplate.setInterfaces(
376                 (Map<String, InterfaceDefinition>) nodeTemplateAsMap.get("interfaces"));
377         nodeTemplate.setNode_filter((NodeFilter) nodeTemplateAsMap.get("node_filter"));
378         nodeTemplate.setProperties((Map<String, Object>) nodeTemplateAsMap.get("properties"));
379         nodeTemplate.setRequirements(
380                 (List<Map<String, RequirementAssignment>>) nodeTemplateAsMap.get("requirements"));
381         nodeTemplate.setType((String) nodeTemplateAsMap.get("type"));
382         nodeTemplate.setCapabilities(
383                 convertCapabilities((Map<String, Object>) nodeTemplateAsMap.get("capabilities")));
384
385         return nodeTemplate;
386     }
387
388     private List<Map<String, CapabilityAssignment>> convertCapabilities(Map<String, Object> capabilities) {
389         List<Map<String, CapabilityAssignment>> convertedCapabilities = new ArrayList<>();
390         if (MapUtils.isEmpty(capabilities)) {
391             return null;
392         }
393         for (Map.Entry<String, Object> capabilityAssignmentEntry : capabilities.entrySet()) {
394             Map<String, CapabilityAssignment> tempMap = new HashMap<>();
395             tempMap.put(capabilityAssignmentEntry.getKey(),
396                     (CapabilityAssignment) createObjectFromClass
397                             (capabilityAssignmentEntry.getKey(), capabilityAssignmentEntry.getValue(), CapabilityAssignment.class));
398             convertedCapabilities.add(tempMap);
399         }
400         return convertedCapabilities;
401     }
402
403     private Object createObjectFromClass(String nodeTypeId,
404                                          Object objectCandidate,
405                                          Class classToCreate) {
406         try {
407             return JsonUtil.json2Object(objectCandidate.toString(), classToCreate);
408         } catch (Exception e) {
409             //todo - return error to user?
410             throw new CoreException(new ErrorCode.ErrorCodeBuilder()
411                     .withCategory(ErrorCategory.APPLICATION)
412                     .withMessage("Can't create " + classToCreate.getSimpleName() + " from " +
413                         nodeTypeId).build());
414         }
415     }
416
417     private boolean isMainServiceTemplate(String fileName) {
418         return fileName.endsWith(mainStName);
419     }
420
421     private boolean isMetadataFile(String fileName) {
422         return fileName.equals(metadataFile);
423     }
424
425     private boolean isGlobalServiceTemplate(String fileName) {
426         return fileName.endsWith(globalStName);
427     }
428
429     private boolean isDefinitions(String fileName) {
430         return fileName.startsWith(definitionsDir);
431     }
432
433     private String getTemplateNameFromStName(String serviceTemplateName) {
434         String fileNameWithoutDirectories;
435         fileNameWithoutDirectories = getFileNameWithoutDirectories(serviceTemplateName);
436         return fileNameWithoutDirectories.split("ServiceTemplate")[0];
437     }
438
439     private String getFileNameWithoutDirectories(String serviceTemplateName) {
440         String fileNameWithoutDirectories;
441         if (serviceTemplateName.contains("/")) {
442             String[] split = serviceTemplateName.split("/");
443             fileNameWithoutDirectories = split[split.length - 1];
444         } else if (serviceTemplateName.contains(File.separator)) {
445             String[] split = serviceTemplateName.split(Pattern.quote(File.separator));
446             fileNameWithoutDirectories = split[split.length - 1];
447         } else {
448             fileNameWithoutDirectories = serviceTemplateName;
449         }
450         return fileNameWithoutDirectories;
451     }
452 }