push addional code
[sdc.git] / openecomp-be / lib / openecomp-sdc-translator-lib / openecomp-sdc-translator-core / src / main / java / org / openecomp / sdc / translator / services / heattotosca / HeatToToscaUtil.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.translator.services.heattotosca;
22
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.openecomp.core.utilities.yaml.YamlUtil;
25 import org.openecomp.sdc.common.errors.CoreException;
26 import org.openecomp.sdc.heat.datatypes.HeatBoolean;
27 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
28 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
29 import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes;
30 import org.openecomp.sdc.heat.datatypes.model.Resource;
31 import org.openecomp.sdc.heat.services.HeatConstants;
32 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
33 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
34 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
35 import org.openecomp.sdc.tosca.services.ToscaUtil;
36 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
37 import org.openecomp.sdc.translator.datatypes.heattotosca.ResourceReferenceType;
38 import org.openecomp.sdc.translator.datatypes.heattotosca.to.FileDataCollection;
39 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
40 import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder;
41 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaFunctionConverter;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 import java.util.ArrayList;
46 import java.util.Collection;
47 import java.util.HashMap;
48 import java.util.HashSet;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.Objects;
52 import java.util.Optional;
53 import java.util.Set;
54 import java.util.stream.Collectors;
55
56 public class HeatToToscaUtil {
57
58   protected static Logger logger = LoggerFactory.getLogger(HeatToToscaUtil.class);
59
60
61   /**
62    * Build list of files to search optional.
63    *
64    * @param heatFileName  the heat file name
65    * @param filesDataList the files data list
66    * @param types         the types
67    * @return the optional
68    */
69   public static Optional<List<FileData>> buildListOfFilesToSearch(String heatFileName,
70                                                                   List<FileData> filesDataList,
71                                                                   FileData.Type... types) {
72     List<FileData> list = new ArrayList<>(filesDataList);
73     Optional<FileData> resourceFileData = HeatToToscaUtil.getFileData(heatFileName, filesDataList);
74     if (resourceFileData.isPresent() && Objects.nonNull(resourceFileData.get().getData())) {
75       list.addAll(resourceFileData.get().getData());
76     }
77     return Optional.ofNullable(HeatToToscaUtil.getFilteredListOfFileDataByTypes(list, types));
78   }
79
80   public static List<FileData> getFilteredListOfFileDataByTypes(List<FileData> filesToSearch,
81                                                                 FileData.Type... types) {
82     return filesToSearch.stream().filter(FileData.buildFileDataPredicateByType(types))
83         .collect(Collectors.toList());
84   }
85
86   /**
87    * Gets file data.
88    *
89    * @param heatFileName the heat file name
90    * @param fileDataList the file data list
91    * @return the file data
92    */
93   public static Optional<FileData> getFileData(String heatFileName,
94                                                Collection<FileData> fileDataList) {
95     for (FileData file : fileDataList) {
96       if (file.getFile().equals(heatFileName)) {
97         return Optional.of(file);
98       }
99     }
100     return Optional.empty();
101   }
102
103   static FileDataCollection getFileCollectionsByFilter(List<FileData> fileDataList,
104                                                        Set<FileData.Type> typeFilter,
105                                                        TranslationContext translationContext) {
106     FileDataCollection fileDataCollection = new FileDataCollection();
107     Map<String, FileData> filteredFiles = filterFileDataListByType(fileDataList, typeFilter);
108     Set<String> referenced = new HashSet<>();
109     List<String> filenames = extractFilenamesFromFileDataList(filteredFiles.values());
110
111     for (FileData fileData : filteredFiles.values()) {
112       String fileName = fileData.getFile();
113
114       if (FileData.isHeatFile(fileData.getType())) {
115         if (fileData.getBase() != null && fileData.getBase().equals(true)) {
116           fileDataCollection.addBaseFiles(fileData);
117         }
118         HeatOrchestrationTemplate heatOrchestrationTemplate = new YamlUtil()
119             .yamlToObject(translationContext.getFileContent(fileName),
120                 HeatOrchestrationTemplate.class);
121         for (Resource resource : heatOrchestrationTemplate.getResources().values()) {
122           if (filenames.contains(resource.getType())) {
123             handleNestedFile(translationContext, fileDataCollection, filteredFiles, referenced,
124                 resource.getType());
125           } else if (resource.getType()
126               .equals(HeatResourcesTypes.RESOURCE_GROUP_RESOURCE_TYPE.getHeatResource())) {
127             Object resourceDef =
128                 resource.getProperties().get(HeatConstants.RESOURCE_DEF_PROPERTY_NAME);
129             Object innerTypeDef = ((Map) resourceDef).get("type");
130             if (innerTypeDef instanceof String) {
131               String internalResourceType = (String) innerTypeDef;
132               if (filenames.contains(internalResourceType)) {
133                 handleNestedFile(translationContext, fileDataCollection, filteredFiles, referenced,
134                     internalResourceType);
135               }
136             }
137           }
138         }
139
140       } else {
141         fileDataCollection.addArtifactFiles(fileData);
142         filteredFiles.remove(fileData.getFile());
143       }
144     }
145
146     referenced.forEach(filteredFiles::remove);
147     if (!CollectionUtils.isEmpty(fileDataCollection.getBaseFile())) {
148       for (FileData fileData : fileDataCollection.getBaseFile()) {
149         filteredFiles.remove(fileData.getFile());
150       }
151     }
152     fileDataCollection.setAddOnFiles(filteredFiles.values());
153     return fileDataCollection;
154   }
155
156   private static void handleNestedFile(TranslationContext translationContext,
157                                        FileDataCollection fileDataCollection,
158                                        Map<String, FileData> filteredFiles, Set<String> referenced,
159                                        String nestedFileName) {
160     referenced.add(nestedFileName);
161     fileDataCollection.addNestedFiles(filteredFiles.get(nestedFileName));
162     translationContext.getNestedHeatsFiles().add(nestedFileName);
163   }
164
165   private static Map<String, FileData> filterFileDataListByType(List<FileData> fileDataList,
166                                                                 Set<FileData.Type> typesToGet) {
167     Map<String, FileData> filtered = new HashMap<>();
168     fileDataList.stream().filter(file -> typesToGet.contains(file.getType()))
169         .forEach(file -> filtered.put(file.getFile(), file));
170     return filtered;
171   }
172
173   private static List<String> extractFilenamesFromFileDataList(Collection<FileData> fileDataList) {
174     return fileDataList.stream().map(FileData::getFile).collect(Collectors.toList());
175   }
176
177   /**
178    * Extract attached resource id optional.
179    *
180    * @param translateTo  the translate to
181    * @param propertyName the property name
182    * @return the optional
183    */
184   public static Optional<AttachedResourceId> extractAttachedResourceId(TranslateTo translateTo,
185                                                                        String propertyName) {
186     Object propertyValue = translateTo.getResource().getProperties().get(propertyName);
187     if (propertyValue == null) {
188       return Optional.empty();
189     }
190     return extractAttachedResourceId(translateTo.getHeatFileName(),
191         translateTo.getHeatOrchestrationTemplate(), translateTo.getContext(), propertyValue);
192   }
193
194   /**
195    * Extract attached resource id optional.
196    *
197    * @param heatFileName              the heat file name
198    * @param heatOrchestrationTemplate the heat orchestration template
199    * @param context                   the context
200    * @param propertyValue             the property value
201    * @return the optional
202    */
203   public static Optional<AttachedResourceId> extractAttachedResourceId(String heatFileName,
204                                       HeatOrchestrationTemplate heatOrchestrationTemplate,
205                                       TranslationContext context,
206                                       Object propertyValue) {
207
208     Object entity;
209     Object translatedId;
210
211     if (Objects.isNull(propertyValue)) {
212       return Optional.empty();
213     }
214
215     ResourceReferenceType referenceType = ResourceReferenceType.OTHER;
216     if (propertyValue instanceof Map && !((Map) propertyValue).isEmpty()) {
217       Map<String, Object> propMap = (Map) propertyValue;
218       Map.Entry<String, Object> entry = propMap.entrySet().iterator().next();
219       entity = entry.getValue();
220       String key = entry.getKey();
221       switch (key) {
222         case "get_resource":
223           referenceType = ResourceReferenceType.GET_RESOURCE;
224           break;
225         case "get_param":
226           referenceType = ResourceReferenceType.GET_PARAM;
227           break;
228         case "get_attr":
229           referenceType = ResourceReferenceType.GET_ATTR;
230           break;
231         default:
232       }
233       translatedId = TranslatorHeatToToscaFunctionConverter
234           .getToscaFunction(entry.getKey(), entry.getValue(), heatFileName,
235               heatOrchestrationTemplate, null, context);
236       if (translatedId instanceof String
237           && !TranslatorHeatToToscaFunctionConverter.isResourceSupported((String) translatedId)) {
238         translatedId = null;
239       }
240
241     } else {
242       translatedId = propertyValue;
243       entity = propertyValue;
244     }
245
246     return Optional.of(new AttachedResourceId(translatedId, entity, referenceType));
247   }
248
249   /**
250    * Gets contrail attached heat resource id.
251    *
252    * @param attachedResource the attached resource
253    * @return the contrail attached heat resource id
254    */
255   public static Optional<String> getContrailAttachedHeatResourceId(
256       AttachedResourceId attachedResource) {
257     if (attachedResource == null) {
258       return Optional.empty();
259     }
260
261     if (attachedResource.isGetResource()) {
262       return Optional.of((String) attachedResource.getEntityId());
263     }
264     if (attachedResource.isGetAttr() && (attachedResource.getEntityId() instanceof List)
265         && ((List) attachedResource.getEntityId()).size() > 1
266         && ((List) attachedResource.getEntityId()).get(1).equals("fq_name")) {
267       return Optional.of((String) ((List) attachedResource.getEntityId()).get(0));
268     }
269
270     return Optional.empty();
271   }
272
273   /**
274    * Extract property optional.
275    *
276    * @param propertyValue the property value
277    * @return the optional
278    */
279   public static Optional<AttachedResourceId> extractProperty(Object propertyValue) {
280
281     Object entity;
282     if (Objects.isNull(propertyValue)) {
283       return Optional.empty();
284     }
285
286     ResourceReferenceType referenceType = ResourceReferenceType.OTHER;
287     if (propertyValue instanceof Map && !((Map) propertyValue).isEmpty()) {
288       Map<String, Object> propMap = (Map) propertyValue;
289       Map.Entry<String, Object> entry = propMap.entrySet().iterator().next();
290       entity = entry.getValue();
291       String key = entry.getKey();
292       switch (key) {
293         case "get_resource":
294           referenceType = ResourceReferenceType.GET_RESOURCE;
295           break;
296         case "get_param":
297           referenceType = ResourceReferenceType.GET_PARAM;
298           break;
299         case "get_attr":
300           referenceType = ResourceReferenceType.GET_ATTR;
301           break;
302         default:
303       }
304
305     } else {
306       entity = propertyValue;
307     }
308
309     return Optional.of(new AttachedResourceId(null, entity, referenceType));
310   }
311
312   /**
313    * Map boolean.
314    *
315    * @param nodeTemplate the node template
316    * @param propertyKey  the property key
317    */
318   public static void mapBoolean(NodeTemplate nodeTemplate, String propertyKey) {
319     Object value = nodeTemplate.getProperties().get(propertyKey);
320     if (value != null && !(value instanceof Map)) {
321       nodeTemplate.getProperties().put(propertyKey, HeatBoolean.eval(value));
322     }
323   }
324
325   /**
326    * Map boolean list.
327    *
328    * @param nodeTemplate    the node template
329    * @param propertyListKey the property list key
330    */
331   public static void mapBooleanList(NodeTemplate nodeTemplate, String propertyListKey) {
332     Object listValue = nodeTemplate.getProperties().get(propertyListKey);
333     if (listValue instanceof List) {
334       List booleanList = ((List) listValue);
335       for (int i = 0; i < booleanList.size(); i++) {
336         Object value = booleanList.get(i);
337         if (value != null && !(value instanceof Map)) {
338           booleanList.set(i, HeatBoolean.eval(value));
339         }
340       }
341     }
342   }
343
344
345   public static boolean isYmlFileType(String filename) {
346     return (filename.indexOf("yaml") > 0 || filename.indexOf("yml") > 0);
347   }
348
349   /**
350    * Is nested resource boolean.
351    *
352    * @param resource the resource
353    * @return the boolean
354    */
355   public static boolean isNestedResource(Resource resource) {
356     String resourceType = resource.getType();
357
358     if (resourceType.equals(HeatResourcesTypes.RESOURCE_GROUP_RESOURCE_TYPE.getHeatResource())) {
359       Object resourceDef = resource.getProperties().get(HeatConstants.RESOURCE_DEF_PROPERTY_NAME);
360       String internalResourceType = (String) ((Map) resourceDef).get("type");
361       if (isYamlFile(internalResourceType)) {
362         return true;
363       }
364     } else if (isYamlFile(resourceType)) {
365       return true;
366     }
367     return false;
368   }
369
370   /**
371    * Gets nested file.
372    *
373    * @param resource the resource
374    * @return the nested file
375    */
376   public static Optional<String> getNestedFile(Resource resource) {
377     if (!isNestedResource(resource)) {
378       return Optional.empty();
379     }
380     String resourceType = resource.getType();
381     if (resourceType.equals(HeatResourcesTypes.RESOURCE_GROUP_RESOURCE_TYPE.getHeatResource())) {
382       Object resourceDef = resource.getProperties().get(HeatConstants.RESOURCE_DEF_PROPERTY_NAME);
383       String internalResourceType = (String) ((Map) resourceDef).get("type");
384       return Optional.of(internalResourceType);
385     } else {
386       return Optional.of(resourceType);
387     }
388   }
389
390   private static boolean isYamlFile(String fileName) {
391     return fileName.endsWith(".yaml") || fileName.endsWith(".yml");
392   }
393
394   /**
395    * Gets resource.
396    *
397    * @param heatOrchestrationTemplate the heat orchestration template
398    * @param resourceId                the resource id
399    * @param heatFileName              the heat file name
400    * @return the resource
401    */
402   public static Resource getResource(HeatOrchestrationTemplate heatOrchestrationTemplate,
403                                      String resourceId, String heatFileName) {
404     Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
405     if (resource == null) {
406       throw new CoreException(
407           new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
408     }
409     return resource;
410   }
411
412   public static boolean isHeatFileNested(TranslateTo translateTo, String heatFileName) {
413     return translateTo.getContext().getNestedHeatsFiles().contains(heatFileName);
414   }
415
416   /**
417    * Extract contrail get resource attached heat resource id string.
418    *
419    * @param propertyValue the property value
420    * @return the string
421    */
422   public static String extractContrailGetResourceAttachedHeatResourceId(Object propertyValue) {
423     if (propertyValue == null) {
424       return null;
425     }
426
427     Object value;
428     if (propertyValue instanceof Map) {
429       if (((Map) propertyValue).containsKey("get_attr")) {
430         value = ((Map) propertyValue).get("get_attr");
431         if (value instanceof List) {
432           if (((List) value).size() == 2 && ((List) value).get(1).equals("fq_name")) {
433             if (((List) value).get(0) instanceof String) {
434               return (String) ((List) value).get(0);
435             } else {
436               logger.warn("invalid format of 'get_attr' function - " + propertyValue.toString());
437             }
438           }
439         }
440       } else if (((Map) propertyValue).containsKey("get_resource")) {
441         value = ((Map) propertyValue).get("get_resource");
442         if (value instanceof String) {
443           return (String) value;
444         } else {
445           logger.warn("invalid format of 'get_resource' function - " + propertyValue.toString());
446         }
447       } else {
448         Collection<Object> valCollection = ((Map) propertyValue).values();
449         for (Object entryValue : valCollection) {
450           String ret = extractContrailGetResourceAttachedHeatResourceId(entryValue);
451           if (ret != null) {
452             return ret;
453           }
454
455         }
456       }
457     } else if (propertyValue instanceof List) {
458       for (Object prop : (List) propertyValue) {
459         String ret = extractContrailGetResourceAttachedHeatResourceId(prop);
460         if (ret != null) {
461           return ret;
462         }
463       }
464     }
465     return null;
466   }
467
468   /**
469    * Gets tosca service model.
470    *
471    * @param translateTo the translate to
472    * @return the tosca service model
473    */
474   public static ToscaServiceModel getToscaServiceModel(TranslateTo translateTo) {
475     Map<String, ServiceTemplate> serviceTemplates =
476         new HashMap<>(translateTo.getContext().getGlobalServiceTemplates());
477     Collection<ServiceTemplate> tmpServiceTemplates =
478         translateTo.getContext().getTranslatedServiceTemplates().values();
479     for (ServiceTemplate serviceTemplate : tmpServiceTemplates) {
480       ToscaUtil.addServiceTemplateToMapWithKeyFileName(serviceTemplates, serviceTemplate);
481     }
482     return new ToscaServiceModel(null, serviceTemplates,
483         ToscaUtil.getServiceTemplateFileName(translateTo.getResource().getType()));
484   }
485
486   /**
487    * Gets service template from context.
488    *
489    * @param serviceTemplateFileName the service template file name
490    * @param context                 the context
491    * @return the service template from context
492    */
493   public static Optional<ServiceTemplate> getServiceTemplateFromContext(
494       String serviceTemplateFileName, TranslationContext context) {
495     for (ServiceTemplate serviceTemplate : context.getTranslatedServiceTemplates().values()) {
496       if (ToscaUtil.getServiceTemplateFileName(serviceTemplate).equals(serviceTemplateFileName)) {
497         return Optional.of(serviceTemplate);
498       }
499     }
500
501     return Optional.empty();
502   }
503 }