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