43ae3c9f387e94e7015ec78174f44ea91334fc6c
[sdc.git] /
1 /*
2  * -
3  *  * ============LICENSE_START=======================================================
4  *  *  Copyright (C) 2019  Nordix Foundation.
5  *  * ================================================================================
6  *  * Licensed under the Apache License, Version 2.0 (the "License");
7  *  * you may not use this file except in compliance with the License.
8  *  * You may obtain a copy of the License at
9  *  *
10  *  *      http://www.apache.org/licenses/LICENSE-2.0
11  *  *
12  *  * Unless required by applicable law or agreed to in writing, software
13  *  * distributed under the License is distributed on an "AS IS" BASIS,
14  *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  * See the License for the specific language governing permissions and
16  *  * limitations under the License.
17  *  *
18  *  * SPDX-License-Identifier: Apache-2.0
19  *  * ============LICENSE_END=========================================================
20  *
21  */
22
23 package org.openecomp.core.impl;
24
25 import static org.openecomp.core.converter.datatypes.Constants.ONAP_INDEX;
26 import static org.openecomp.core.converter.datatypes.Constants.definitionsDir;
27 import static org.openecomp.core.converter.datatypes.Constants.globalStName;
28 import static org.openecomp.core.converter.datatypes.Constants.globalSubstitution;
29 import static org.openecomp.core.converter.datatypes.Constants.mainStName;
30 import static org.openecomp.core.converter.datatypes.Constants.openecompHeatIndex;
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;
34 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ORIG_PATH_FILE_NAME;
35 import static org.openecomp.sdc.tosca.csar.ToscaMetadataFileInfo.TOSCA_META_PATH_FILE_NAME;
36 import java.io.File;
37 import java.util.ArrayList;
38 import java.util.Collection;
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Objects;
43 import java.util.Optional;
44 import java.util.regex.Pattern;
45 import javax.validation.constraints.NotNull;
46 import org.apache.commons.collections.MapUtils;
47 import org.onap.sdc.tosca.datatypes.model.DataType;
48 import org.onap.sdc.tosca.datatypes.model.Import;
49 import org.onap.sdc.tosca.datatypes.model.NodeType;
50 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
51 import org.openecomp.core.converter.ServiceTemplateReaderService;
52 import org.openecomp.core.converter.ToscaConverter;
53 import org.openecomp.core.converter.datatypes.CsarFileTypes;
54 import org.openecomp.core.impl.services.ServiceTemplateReaderServiceImpl;
55 import org.openecomp.core.utilities.file.FileContentHandler;
56 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
57 import org.openecomp.sdc.common.errors.CoreException;
58 import org.openecomp.sdc.common.errors.ErrorCategory;
59 import org.openecomp.sdc.common.errors.ErrorCode;
60 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
61 import org.openecomp.sdc.tosca.services.DataModelUtil;
62 import org.openecomp.sdc.tosca.services.ToscaUtil;
63 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66 import org.yaml.snakeyaml.error.YAMLException;
67
68 public abstract class AbstractToscaConverter implements ToscaConverter {
69     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractToscaConverter.class);
70
71     public abstract void convertTopologyTemplate(@NotNull ServiceTemplate serviceTemplate,
72                                                  ServiceTemplateReaderService readerService);
73
74     protected void handleMetadataFile(Map<String, byte[]> csarFiles) {
75         byte[] bytes = csarFiles.remove(TOSCA_META_PATH_FILE_NAME);
76         if (bytes != null) {
77             csarFiles.put(TOSCA_META_ORIG_PATH_FILE_NAME, bytes);
78         }
79     }
80
81     protected void handleDefinitionTemplate(String key, Map<String, byte[]> csarFiles,
82                                             GlobalSubstitutionServiceTemplate gsst) {
83         try {
84             ServiceTemplateReaderService readerService = new ServiceTemplateReaderServiceImpl(csarFiles.get(key));
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             gsst.appendDataTypes((Map) readerService.getDataTypes());
91         } catch (YAMLException ye) {
92             throw new CoreException(new ErrorCode.ErrorCodeBuilder()
93                     .withMessage("Invalid YAML content in file " + key)
94                     .withCategory(ErrorCategory.APPLICATION).build(), ye);
95         }
96     }
97
98     protected 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     protected void updateToscaServiceModel(ToscaServiceModel toscaServiceModel,
110                                            Map<String, ServiceTemplate> serviceTemplates,
111                                            FileContentHandler externalFilesHandler,
112                                            GlobalSubstitutionServiceTemplate globalSubstitutionServiceTemplate,
113                                            Map<String, byte[]> csarFiles, String entryDefinitionServiceTemplateName) {
114         Collection<ServiceTemplate> globalServiceTemplates =
115                 GlobalTypesGenerator.getGlobalTypesServiceTemplate(OnboardingTypesEnum.CSAR).values();
116         addGlobalServiceTemplates(globalServiceTemplates, serviceTemplates);
117         toscaServiceModel.setServiceTemplates(serviceTemplates);
118         toscaServiceModel.setEntryDefinitionServiceTemplate(entryDefinitionServiceTemplateName);
119         externalFilesHandler.addFile(TOSCA_META_ORIG_PATH_FILE_NAME,
120                 csarFiles.get(TOSCA_META_ORIG_PATH_FILE_NAME));
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     protected void handleServiceTemplate(String serviceTemplateName,
137                                          String fileName, Map<String, byte[]> csarFiles,
138                                          Map<String, ServiceTemplate> serviceTemplates) {
139         final byte[] inputServiceTemplate = getServiceTemplateFromCsar(fileName, csarFiles);
140         Optional<ServiceTemplate> serviceTemplate = convertServiceTemplate(fileName, inputServiceTemplate);
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 byte[] getServiceTemplateFromCsar(String fileName, Map<String, byte[]> csarFiles) {
153         return csarFiles.get(fileName);
154     }
155
156     private Optional<ServiceTemplate> convertServiceTemplate(String serviceTemplateName,
157                                                              byte[] fileContent) {
158         ServiceTemplate serviceTemplate = new ServiceTemplate();
159         try {
160             ServiceTemplateReaderService readerService =
161                     new ServiceTemplateReaderServiceImpl(fileContent);
162             convertMetadata(serviceTemplateName, serviceTemplate, readerService);
163             convertToscaVersion(serviceTemplate, readerService);
164             convertImports(serviceTemplate);
165             convertNodeTypes(serviceTemplate, readerService);
166             convertDataTypes(serviceTemplate, readerService);
167             convertTopologyTemplate(serviceTemplate, readerService);
168         } catch (YAMLException ye) {
169             throw new CoreException(new ErrorCode.ErrorCodeBuilder()
170                     .withMessage("Invalid YAML content in file" + serviceTemplateName)
171                     .withCategory(ErrorCategory.APPLICATION).build(), ye);
172         }
173
174
175         return Optional.of(serviceTemplate);
176     }
177
178     private void convertToscaVersion(ServiceTemplate serviceTemplate,
179                                      ServiceTemplateReaderService readerService) {
180         Object toscaVersion = readerService.getToscaVersion();
181         serviceTemplate.setTosca_definitions_version((String) toscaVersion);
182     }
183
184     private void convertImports(ServiceTemplate serviceTemplate) {
185         List<Map<String, Import>> imports = new ArrayList<>();
186         imports.add(createImportMap(openecompHeatIndex, HEAT_INDEX_IMPORT_FILE));
187         imports.add(createImportMap(ONAP_INDEX, ONAP_INDEX_IMPORT_FILE));
188         imports.add(createImportMap(globalSubstitution, globalStName));
189         serviceTemplate.setImports(imports);
190     }
191
192     private Map<String, Import> createImportMap(String key, String fileName) {
193         Map<String, Import> importMap = new HashMap<>();
194         Import anImport = new Import();
195         anImport.setFile(fileName);
196         importMap.put(key, anImport);
197
198         return importMap;
199     }
200
201     private void convertMetadata(String serviceTemplateName,
202                                  ServiceTemplate serviceTemplate,
203                                  ServiceTemplateReaderService readerService) {
204         Map<String, Object> metadataToConvert = (Map<String, Object>) readerService.getMetadata();
205         Map<String, String> finalMetadata = new HashMap<>();
206
207         if (MapUtils.isNotEmpty(metadataToConvert)) {
208             for (Map.Entry<String, Object> metadataEntry : metadataToConvert.entrySet()) {
209                 if (Objects.isNull(metadataEntry.getValue()) ||
210                         !(metadataEntry.getValue() instanceof String)) {
211                     continue;
212                 }
213                 finalMetadata.put(metadataEntry.getKey(), (String) metadataEntry.getValue());
214             }
215         }
216
217         finalMetadata.put("template_name", getTemplateNameFromStName(serviceTemplateName));
218         serviceTemplate.setMetadata(finalMetadata);
219     }
220
221     protected void convertNodeTypes(ServiceTemplate serviceTemplate, ServiceTemplateReaderService readerService) {
222         Map<String, Object> nodeTypes = readerService.getNodeTypes();
223         if (MapUtils.isEmpty(nodeTypes)) {
224             return;
225         }
226
227         for (Map.Entry<String, Object> nodeTypeEntry : nodeTypes.entrySet()) {
228             Optional<NodeType> nodeType = ToscaConverterUtil
229                     .createObjectFromClass(nodeTypeEntry.getKey(), nodeTypeEntry.getValue(),
230                             NodeType.class);
231
232             nodeType.ifPresent(nodeTypeValue -> DataModelUtil
233                     .addNodeType(serviceTemplate, nodeTypeEntry.getKey(), nodeTypeValue));
234         }
235     }
236
237     protected void convertDataTypes(final ServiceTemplate serviceTemplate,
238                                     final ServiceTemplateReaderService readerService) {
239         try {
240             final Map<String, Object> dataTypes = readerService.getDataTypes();
241             for (final Map.Entry<String, Object> entry : dataTypes.entrySet()) {
242                 final Optional<DataType> dataType =
243                         ToscaConverterUtil.createObjectFromClass(entry.getKey(), entry.getValue(), DataType.class);
244
245                 dataType.ifPresent(
246                         nodeTypeValue -> DataModelUtil.addDataType(serviceTemplate, entry.getKey(), nodeTypeValue));
247             }
248         } catch (final Exception ex) {
249             LOGGER.error("Unable to process data types: ", ex);
250         }
251     }
252
253     protected CsarFileTypes getFileType(String fileName) {
254         if (isMainServiceTemplate(fileName)) {
255             return CsarFileTypes.mainServiceTemplate;
256         } else if (isGlobalServiceTemplate(fileName)) {
257             return CsarFileTypes.globalServiceTemplate;
258         } else if (isDefinitions(fileName)) {
259             return CsarFileTypes.definitionsFile;
260         } else if (isMetadataFile(fileName)) {
261             return CsarFileTypes.toscaMetadata;
262         }
263         return CsarFileTypes.externalFile;
264     }
265
266     protected boolean isMainServiceTemplate(String fileName) {
267         return fileName.endsWith(mainStName);
268     }
269
270     protected boolean isMetadataFile(String fileName) {
271         return fileName.equals(TOSCA_META_PATH_FILE_NAME);
272     }
273
274     protected boolean isGlobalServiceTemplate(String fileName) {
275         return fileName.endsWith(globalStName);
276     }
277
278     protected boolean isDefinitions(String fileName) {
279         return fileName.startsWith(definitionsDir);
280     }
281
282     private String getTemplateNameFromStName(String serviceTemplateName) {
283         String fileNameWithoutDirectories = getFileNameWithoutDirectories(serviceTemplateName);
284         return fileNameWithoutDirectories.split("ServiceTemplate")[0];
285     }
286
287     private String getFileNameWithoutDirectories(String serviceTemplateName) {
288         String fileNameWithoutDirectories;
289         if (serviceTemplateName.contains("/")) {
290             String[] split = serviceTemplateName.split("/");
291             fileNameWithoutDirectories = split[split.length - 1];
292         } else if (serviceTemplateName.contains(File.separator)) {
293             String[] split = serviceTemplateName.split(Pattern.quote(File.separator));
294             fileNameWithoutDirectories = split[split.length - 1];
295         } else {
296             fileNameWithoutDirectories = serviceTemplateName;
297         }
298         return fileNameWithoutDirectories;
299     }
300 }