e7ff3aa8ee1be9c9ba40dc556a3c9f2b44a672c1
[sdc.git] /
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.converter.errors.SubstitutionMappingsConverterErrorBuilder;
9 import org.openecomp.core.impl.services.ServiceTemplateReaderServiceImpl;
10 import org.openecomp.core.utilities.file.FileContentHandler;
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(
58                         getConcreteArtifactFileName(fileEntry.getKey()), fileEntry.getValue());
59                     break;
60
61                 case definitionsFile:
62                     handleDefintionTemplate(fileEntry.getKey(), csarFiles, gsst);
63                     break;
64             }
65         }
66         handleMetadataFile(csarFiles);
67         updateToscaServiceModel(toscaServiceModel, serviceTemplates, artifacts, gsst, csarFiles);
68         return toscaServiceModel;
69     }
70
71     private void handleMetadataFile(Map<String, byte[]> csarFiles) {
72         byte[] bytes = csarFiles.remove(metadataFile);
73         if (bytes != null) {
74             csarFiles.put(metadataFile + ".original", bytes);
75         }
76     }
77
78     private void handleDefintionTemplate(String key, Map<String, byte[]> csarFiles,
79                                          GlobalSubstitutionServiceTemplate gsst) {
80         try {
81             ServiceTemplateReaderService readerService = new ServiceTemplateReaderServiceImpl(csarFiles.get(key));
82             if (readerService == null) {
83                 return;
84             }
85             Object nodeTypes = readerService.getNodeTypes();
86             if (nodeTypes instanceof Map) {
87                 Map<String, NodeType> nodeTypeMap = (Map<String, NodeType>) nodeTypes;
88                 gsst.appendNodes(nodeTypeMap);
89             }
90         } catch (YAMLException ye) {
91             throw new CoreException(new ErrorCode.ErrorCodeBuilder()
92                 .withMessage("Invalid YAML content in file " + key + ". reason - "
93                     + ye.getMessage())
94                 .withCategory(ErrorCategory.APPLICATION).build());
95         }
96     }
97
98     private String getConcreteArtifactFileName(String fileName){
99         int artifactIndex = fileName.indexOf(CsarFileTypes.Artifacts.name());
100         if(artifactIndex < 0){
101             return fileName;
102         }
103
104         int artifactDirectoryIndex =
105             artifactIndex + CsarFileTypes.Artifacts.name().length() + 1;
106         return fileName.substring(artifactDirectoryIndex);
107     }
108
109     private void updateToscaServiceModel(ToscaServiceModel toscaServiceModel,
110                                          Map<String, ServiceTemplate> serviceTemplates,
111                                          FileContentHandler externalFilesHandler,
112                                          GlobalSubstitutionServiceTemplate globalSubstitutionServiceTemplate,
113                                          Map<String, byte[]> csarFiles) {
114         Collection<ServiceTemplate> globalServiceTemplates =
115             GlobalTypesGenerator.getGlobalTypesServiceTemplate().values();
116         addGlobalServiceTemplates(globalServiceTemplates, serviceTemplates);
117         toscaServiceModel.setEntryDefinitionServiceTemplate(mainStName);
118         toscaServiceModel.setServiceTemplates(serviceTemplates);
119         externalFilesHandler.addFile(metadataFile + ".original",
120             csarFiles.get(metadataFile + ".original"));
121         toscaServiceModel.setArtifactFiles(externalFilesHandler);
122
123         if(MapUtils.isNotEmpty(globalSubstitutionServiceTemplate.getNode_types())) {
124             serviceTemplates
125                 .put(GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME, globalSubstitutionServiceTemplate);
126         }
127     }
128
129     private void addGlobalServiceTemplates(Collection<ServiceTemplate> globalServiceTemplates,
130                                            Map<String, ServiceTemplate> serviceTemplates) {
131         for (ServiceTemplate serviceTemplate : globalServiceTemplates) {
132             serviceTemplates.put(ToscaUtil.getServiceTemplateFileName(serviceTemplate), serviceTemplate);
133         }
134     }
135
136     private void handleServiceTemplate(String serviceTemplateName,
137                                        String fileName, Map<String, byte[]> csarFiles,
138                                        Map<String, ServiceTemplate> serviceTemplates) {
139         Optional<ServiceTemplate> serviceTemplate =
140             getServiceTemplateFromCsar(fileName, csarFiles);
141         serviceTemplate.ifPresent(
142             serviceTemplateValue -> addServiceTemplate(serviceTemplateName, serviceTemplateValue,
143                 serviceTemplates));
144     }
145
146     private void addServiceTemplate(String serviceTemplateName,
147                                     ServiceTemplate serviceTemplate,
148                                     Map<String, ServiceTemplate> serviceTemplates) {
149         serviceTemplates.put(serviceTemplateName, serviceTemplate);
150     }
151
152     private Optional<byte[]> getManifestContent(Map<String, byte[]> csarFiles) {
153         for (Map.Entry<String, byte[]> csarFileEntry : csarFiles.entrySet()) {
154             if (csarFileEntry.getKey().contains(manifestFileName)) {
155                 return Optional.of(csarFileEntry.getValue());
156             }
157         }
158
159         return Optional.empty();
160     }
161
162     private Optional<ServiceTemplate> getServiceTemplateFromCsar(String fileName,
163                                                                  Map<String, byte[]> csarFiles) {
164         byte[] fileContent = csarFiles.get(fileName);
165         ServiceTemplate serviceTemplate = convertServiceTemplate(fileName, fileContent);
166
167         return Optional.of(serviceTemplate);
168     }
169
170     private ServiceTemplate convertServiceTemplate(String serviceTemplateName,
171                                                    byte[] fileContent) {
172         ServiceTemplate serviceTemplate = new ServiceTemplate();
173         try {
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);
181
182         } catch (YAMLException ye) {
183             throw new CoreException(new ErrorCode.ErrorCodeBuilder()
184                 .withMessage("Invalid YAML content in file" + serviceTemplateName + ". reason - "
185                     + ye.getMessage())
186                 .withCategory(ErrorCategory.APPLICATION).build());
187         }
188
189
190         return serviceTemplate;
191     }
192
193     private void convertToscaVersion(ServiceTemplate serviceTemplate,
194                                      ServiceTemplateReaderService readerService) {
195         Object toscaVersion = readerService.getToscaVersion();
196         serviceTemplate.setTosca_definitions_version((String) toscaVersion);
197     }
198
199     private void convertImports(ServiceTemplate serviceTemplate) {
200         serviceTemplate.setImports(new ArrayList<>());
201         serviceTemplate.getImports()
202             .add(createImportMap(openecompHeatIndex, "openecomp-heat/_index.yml"));
203         serviceTemplate.getImports().add(createImportMap(globalSubstitution, globalStName));
204
205     }
206
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);
212
213         return importMap;
214     }
215
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<>();
221
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)) {
226                     continue;
227                 }
228                 finalMetadata.put(metadataEntry.getKey(), (String) metadataEntry.getValue());
229             }
230         }
231
232         finalMetadata.put("template_name", getTemplateNameFromStName(serviceTemplateName));
233         serviceTemplate.setMetadata(finalMetadata);
234     }
235
236     private void convertNodeTypes(ServiceTemplate serviceTemplate, ServiceTemplateReaderService readerService) {
237         Map<String, Object> nodeTypes = (Map<String, Object>) readerService.getNodeTypes();
238         if (MapUtils.isEmpty(nodeTypes)) {
239             return;
240         }
241
242         for (Map.Entry<String, Object> nodeTypeEntry : nodeTypes.entrySet()) {
243             Optional<NodeType> nodeType = ToscaConverterUtil
244                 .createObjectFromClass(nodeTypeEntry.getKey(), nodeTypeEntry.getValue(),
245                     NodeType.class);
246
247             nodeType.ifPresent(nodeTypeValue -> DataModelUtil
248                 .addNodeType(serviceTemplate, nodeTypeEntry.getKey(), nodeTypeValue));
249         }
250     }
251
252     private void convertTopologyTemplate(ServiceTemplate serviceTemplate,
253                                          ServiceTemplateReaderService readerService) {
254
255         convertInputs(serviceTemplate, readerService);
256         convertNodeTemplates(serviceTemplate, readerService);
257         convertOutputs(serviceTemplate, readerService);
258         convertSubstitutionMappings(serviceTemplate, readerService);
259     }
260
261     private void convertInputs(ServiceTemplate serviceTemplate,
262                                ServiceTemplateReaderService readerService) {
263         Map<String, Object> inputs = readerService.getInputs();
264         addInputsOrOutputsToServiceTemplate(serviceTemplate, inputs, Constants.inputs);
265     }
266
267     private void convertOutputs(ServiceTemplate serviceTemplate,
268                                 ServiceTemplateReaderService readerService) {
269         Map<String, Object> outputs = readerService.getOutputs();
270         addInputsOrOutputsToServiceTemplate(serviceTemplate, outputs, Constants.outputs);
271     }
272
273     private void addInputsOrOutputsToServiceTemplate(ServiceTemplate serviceTemplate,
274                                                      Map<String, Object> mapToConvert,
275                                                      String inputsOrOutputs) {
276         if (MapUtils.isEmpty(mapToConvert)) {
277             return;
278         }
279
280         for (Map.Entry<String, Object> entry : mapToConvert.entrySet()) {
281             Optional<ParameterDefinition> parameterDefinition =
282                 ToscaConverterUtil.createObjectFromClass(
283                     entry.getKey(), entry.getValue(), ParameterDefinition.class);
284
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());
291             } );
292         }
293     }
294
295     private void addToServiceTemplateAccordingToSection(ServiceTemplate serviceTemplate,
296                                                         String inputsOrOutputs,
297                                                         String parameterId,
298                                                         ParameterDefinition parameterDefinition) {
299         switch (inputsOrOutputs) {
300             case inputs:
301                 DataModelUtil
302                     .addInputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
303                 break;
304             case outputs:
305                 DataModelUtil
306                     .addOutputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
307         }
308     }
309
310     private void convertNodeTemplates(ServiceTemplate serviceTemplate,
311                                       ServiceTemplateReaderService readerService) {
312         Map<String, Object> nodeTemplates = readerService.getNodeTemplates();
313         if (MapUtils.isEmpty(nodeTemplates)) {
314             return;
315         }
316
317         for (Map.Entry<String, Object> nodeTemplateEntry : nodeTemplates.entrySet()) {
318             NodeTemplate nodeTemplate = convertNodeTemplate(nodeTemplateEntry.getValue());
319             DataModelUtil.addNodeTemplate(serviceTemplate, nodeTemplateEntry.getKey(), nodeTemplate);
320         }
321     }
322
323     private void convertSubstitutionMappings(ServiceTemplate serviceTemplate,
324                                              ServiceTemplateReaderService readerService) {
325         Map<String, Object> substitutionMappings = readerService.getSubstitutionMappings();
326         if (MapUtils.isEmpty(substitutionMappings)) {
327             return;
328         }
329         SubstitutionMapping substitutionMapping = convertSubstitutionMappings(substitutionMappings);
330         DataModelUtil.addSubstitutionMapping(serviceTemplate, substitutionMapping);
331     }
332
333     private SubstitutionMapping convertSubstitutionMappings(Map<String, Object> substitutionMappings) {
334         SubstitutionMapping substitutionMapping = new SubstitutionMapping();
335
336         substitutionMapping.setNode_type((String) substitutionMappings.get(nodeType));
337         substitutionMapping.setCapabilities(
338             convertSubstitutionMappingsSections(capabilities, substitutionMappings.get(capabilities)));
339         substitutionMapping.setRequirements(
340             convertSubstitutionMappingsSections(requirements, substitutionMappings.get(requirements)));
341
342         return substitutionMapping;
343     }
344
345     private Map<String, List<String>> convertSubstitutionMappingsSections(String sectionName,
346                                                                           Object sectionToConvert) {
347
348         if(Objects.isNull(sectionToConvert)){
349             return null;
350         }
351
352         if(!(sectionToConvert instanceof Map)) {
353             throw new CoreException(
354                 new SubstitutionMappingsConverterErrorBuilder(
355                     sectionName, sectionToConvert.getClass().getSimpleName()).build());
356         }
357
358         return convertSection(sectionToConvert);
359     }
360
361     private Map<String, List<String>> convertSection(Object sectionToConvert) {
362
363         Map<String, Object> sectionAsMap = (Map<String, Object>)sectionToConvert;
364         Map<String, List<String>> convertedSection = new HashMap<>();
365
366         if (MapUtils.isEmpty(sectionAsMap)) {
367             return null;
368         }
369
370         for (Map.Entry<String, Object> entry : sectionAsMap.entrySet()) {
371             if (entry.getValue() instanceof List) {
372                 convertedSection.put(entry.getKey(), (List<String>) entry.getValue());
373             }
374         }
375
376         return convertedSection;
377     }
378
379     private CsarFileTypes getFileType(String fileName) {
380         if (isMainServiceTemplate(fileName)) {
381             return CsarFileTypes.mainServiceTemplate;
382         } else if (isGlobalServiceTemplate(fileName)) {
383             return CsarFileTypes.globalServiceTemplate;
384         } else if (isDefinitions(fileName)) {
385             return CsarFileTypes.definitionsFile;
386         } else if (isMetadataFile(fileName)) {
387             return CsarFileTypes.toscaMetadata;
388         }
389         return CsarFileTypes.externalFile;
390     }
391
392     private Optional<Manifest> getCsarManifest(Map<String, byte[]> csarFiles) throws IOException {
393         Optional<byte[]> manifestContent = getManifestContent(csarFiles);
394
395         if (manifestContent.isPresent()) {
396             ByteArrayInputStream byteInputStream = new ByteArrayInputStream(manifestContent.get());
397
398             return Optional.of(new Manifest(byteInputStream));
399         }
400
401         return Optional.empty();
402     }
403
404     private NodeTemplate convertNodeTemplate(Object candidateNodeTemplate) {
405         NodeTemplate nodeTemplate = new NodeTemplate();
406
407         Map<String, Object> nodeTemplateAsMap = (Map<String, Object>) candidateNodeTemplate;
408         nodeTemplate.setArtifacts((Map<String, ArtifactDefinition>) nodeTemplateAsMap.get("artifacts"));
409         nodeTemplate.setAttributes((Map<String, Object>) nodeTemplateAsMap.get("attributes"));
410         nodeTemplate.setCopy((String) nodeTemplateAsMap.get("copy"));
411         nodeTemplate.setDescription((String) nodeTemplateAsMap.get("description"));
412         nodeTemplate.setDirectives((List<String>) nodeTemplateAsMap.get("directives"));
413         nodeTemplate.setInterfaces(
414             (Map<String, InterfaceDefinition>) nodeTemplateAsMap.get("interfaces"));
415         nodeTemplate.setNode_filter((NodeFilter) nodeTemplateAsMap.get("node_filter"));
416         nodeTemplate.setProperties((Map<String, Object>) nodeTemplateAsMap.get("properties"));
417         nodeTemplate.setRequirements(
418             (List<Map<String, RequirementAssignment>>) nodeTemplateAsMap.get("requirements"));
419         nodeTemplate.setType((String) nodeTemplateAsMap.get("type"));
420         nodeTemplate.setCapabilities(
421             convertCapabilities((Map<String, Object>) nodeTemplateAsMap.get("capabilities")));
422
423         return nodeTemplate;
424     }
425
426     private List<Map<String, CapabilityAssignment>> convertCapabilities(Map<String, Object> capabilities) {
427         List<Map<String, CapabilityAssignment>> convertedCapabilities = new ArrayList<>();
428         if (MapUtils.isEmpty(capabilities)) {
429             return null;
430         }
431         for (Map.Entry<String, Object> capabilityAssignmentEntry : capabilities.entrySet()) {
432             Map<String, CapabilityAssignment> tempMap = new HashMap<>();
433             Optional<CapabilityAssignment> capabilityAssignment = ToscaConverterUtil.createObjectFromClass
434                 (capabilityAssignmentEntry.getKey(), capabilityAssignmentEntry.getValue(),
435                     CapabilityAssignment.class);
436
437             capabilityAssignment.ifPresent(capabilityAssignmentValue -> {
438                 tempMap.put(capabilityAssignmentEntry.getKey(), capabilityAssignmentValue);
439                 convertedCapabilities.add(tempMap);
440                 }
441             );
442
443         }
444         return convertedCapabilities;
445     }
446
447
448     private boolean isMainServiceTemplate(String fileName) {
449         return fileName.endsWith(mainStName);
450     }
451
452     private boolean isMetadataFile(String fileName) {
453         return fileName.equals(metadataFile);
454     }
455
456     private boolean isGlobalServiceTemplate(String fileName) {
457         return fileName.endsWith(globalStName);
458     }
459
460     private boolean isDefinitions(String fileName) {
461         return fileName.startsWith(definitionsDir);
462     }
463
464     private String getTemplateNameFromStName(String serviceTemplateName) {
465         String fileNameWithoutDirectories;
466         fileNameWithoutDirectories = getFileNameWithoutDirectories(serviceTemplateName);
467         return fileNameWithoutDirectories.split("ServiceTemplate")[0];
468     }
469
470     private String getFileNameWithoutDirectories(String serviceTemplateName) {
471         String fileNameWithoutDirectories;
472         if (serviceTemplateName.contains("/")) {
473             String[] split = serviceTemplateName.split("/");
474             fileNameWithoutDirectories = split[split.length - 1];
475         } else if (serviceTemplateName.contains(File.separator)) {
476             String[] split = serviceTemplateName.split(Pattern.quote(File.separator));
477             fileNameWithoutDirectories = split[split.length - 1];
478         } else {
479             fileNameWithoutDirectories = serviceTemplateName;
480         }
481         return fileNameWithoutDirectories;
482     }
483 }