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 / mapping / TranslatorHeatToToscaFunctionConverter.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.mapping;
22
23 import org.openecomp.core.utilities.yaml.YamlUtil;
24 import org.openecomp.sdc.heat.datatypes.HeatBoolean;
25 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
26 import org.openecomp.sdc.heat.datatypes.model.Resource;
27 import org.openecomp.sdc.heat.services.HeatConstants;
28 import org.openecomp.sdc.tosca.datatypes.ToscaArtifactType;
29 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
30 import org.openecomp.sdc.tosca.datatypes.model.ArtifactDefinition;
31 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
32 import org.openecomp.sdc.tosca.datatypes.model.Template;
33 import org.openecomp.sdc.tosca.services.ToscaConstants;
34 import org.openecomp.sdc.tosca.services.ToscaFileOutputService;
35 import org.openecomp.sdc.tosca.services.impl.ToscaFileOutputServiceCsarImpl;
36 import org.openecomp.sdc.translator.services.heattotosca.Constants;
37 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
38 import org.openecomp.sdc.translator.services.heattotosca.TranslationContext;
39 import org.openecomp.sdc.translator.services.heattotosca.impl.ResourceTranslationBase;
40
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.Optional;
47 import java.util.Set;
48 import java.util.stream.Collectors;
49
50
51 public class TranslatorHeatToToscaFunctionConverter {
52   private static final String UNSUPPORTED_RESOURCE = "UNSUPPORTED_RESOURCE_";
53   private static final String UNSUPPORTED_ATTRIBUTE = "UNSUPPORTED_ATTRIBUTE_";
54
55   protected static Set<String> functionNameSet;
56
57   static {
58     functionNameSet = new HashSet<>();
59     functionNameSet.add("get_param");
60     functionNameSet.add("get_attr");
61     functionNameSet.add("get_resource");
62     functionNameSet.add("get_file");
63   }
64
65   /**
66    * Gets tosca function.
67    *
68    * @param functionName              the function name
69    * @param function                  the function
70    * @param heatFileName              the heat file name
71    * @param heatOrchestrationTemplate the heat orchestration template
72    * @param template                  the template
73    * @param context                   the context
74    * @return the tosca function
75    */
76   public static Object getToscaFunction(String functionName, Object function, String heatFileName,
77                                         HeatOrchestrationTemplate heatOrchestrationTemplate,
78                                         Template template, TranslationContext context) {
79     Object returnValue = null;
80     if ("get_param".equals(functionName)) {
81       returnValue =
82           handleGetParamFunction(function, heatFileName, heatOrchestrationTemplate, context);
83     } else if ("get_attr".equals(functionName)) {
84       returnValue =
85           handleGetAttrFunction(function, heatFileName, heatOrchestrationTemplate, context);
86     } else if ("get_resource".equals(functionName)) {
87       returnValue =
88           handleGetResourceFunction(function, heatFileName, heatOrchestrationTemplate, context);
89     } else if ("get_file".equals(functionName)) {
90       returnValue = handleGetFileFunction(function, template);
91     }
92     return returnValue;
93   }
94
95   private static Object handleGetFileFunction(Object function, Template template) {
96     String file = ((String) function).replace("file:///", "");
97     Object returnValue;
98     final String artifactId = file.split("\\.")[0];
99
100     returnValue = new HashMap<>();
101     List artifactParameters = new ArrayList();
102     artifactParameters.add(0, ToscaConstants.MODELABLE_ENTITY_NAME_SELF);
103     ((Map) returnValue).put(ToscaFunctions.GET_ARTIFACT.getDisplayName(), artifactParameters);
104     artifactParameters.add(1, artifactId);
105
106     ToscaFileOutputService toscaFileOutputService = new ToscaFileOutputServiceCsarImpl();
107     if (template != null) {
108       if (template instanceof NodeTemplate) {
109         NodeTemplate nodeTemplate = (NodeTemplate) template;
110         ArtifactDefinition artifactDefinition =
111             createArtifactDefinition(file, toscaFileOutputService);
112         if (nodeTemplate.getArtifacts() == null) {
113           nodeTemplate.setArtifacts(new HashMap<>());
114         }
115         nodeTemplate.getArtifacts().put(artifactId, artifactDefinition);
116       }
117     }
118     return returnValue;
119   }
120
121   private static Object handleGetResourceFunction(Object function, String heatFileName,
122                                                   HeatOrchestrationTemplate
123                                                           heatOrchestrationTemplate,
124                                                   TranslationContext context) {
125     Object returnValue;
126     Optional<String> resourceTranslatedId = ResourceTranslationBase
127         .getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, (String) function,
128             context);
129     if (resourceTranslatedId.isPresent()) {
130       returnValue = resourceTranslatedId.get();
131     } else {
132       returnValue = UNSUPPORTED_RESOURCE + function;
133     }
134     return returnValue;
135   }
136
137   private static Object handleGetAttrFunction(Object function, String heatFileName,
138                                               HeatOrchestrationTemplate heatOrchestrationTemplate,
139                                               TranslationContext context) {
140     Object returnValue = new HashMap<>();
141     List<Object> attributeFunctionExpression =
142         translateGetAttributeFunctionExpression(function, heatFileName, heatOrchestrationTemplate,
143             context);
144     if (isResourceSupported(attributeFunctionExpression.get(0).toString())
145         && isAttributeSupported(attributeFunctionExpression.get(0).toString())) {
146       ((Map) returnValue)
147           .put(ToscaFunctions.GET_ATTRIBUTE.getDisplayName(), attributeFunctionExpression);
148     } else {
149       returnValue = attributeFunctionExpression;
150     }
151     return returnValue;
152   }
153
154   private static Object handleGetParamFunction(Object function, String heatFileName,
155                                                HeatOrchestrationTemplate heatOrchestrationTemplate,
156                                                TranslationContext context) {
157     Map returnValue = new HashMap<>();
158     returnValue.put(ToscaFunctions.GET_INPUT.getDisplayName(),
159         translateGetParamFunctionExpression(function, heatFileName, heatOrchestrationTemplate,
160             context));
161     return returnValue;
162   }
163
164   private static ArtifactDefinition createArtifactDefinition(Object function,
165                                                              ToscaFileOutputService
166                                                                      toscaFileOutputService) {
167     ArtifactDefinition artifactDefinition = new ArtifactDefinition();
168     artifactDefinition.setType(ToscaArtifactType.DEPLOYMENT.getDisplayName());
169     artifactDefinition
170         .setFile("../" + toscaFileOutputService.getArtifactsFolderName() + "/" + function);
171     return artifactDefinition;
172   }
173
174   private static Object translateGetParamFunctionExpression(Object function, String heatFileName,
175                                                             HeatOrchestrationTemplate
176                                                                     heatOrchestrationTemplate,
177                                                             TranslationContext context) {
178     Object returnValue = null;
179     if (function instanceof String) {
180       returnValue = function;
181     } else {
182       if (function instanceof List) {
183         returnValue = new ArrayList<>();
184         for (int i = 0; i < ((List) function).size(); i++) {
185           Object paramValue = ((List) function).get(i);
186           if ((paramValue instanceof Map && !((Map) paramValue).isEmpty())) {
187             Map<String, Object> paramMap = (Map) paramValue;
188             Map.Entry<String, Object> entry = paramMap.entrySet().iterator().next();
189             ((List) returnValue).add(
190                 getToscaFunction(entry.getKey(), entry.getValue(), heatFileName,
191                     heatOrchestrationTemplate, null, context));
192           } else {
193             ((List) returnValue).add(paramValue);
194           }
195         }
196       }
197     }
198
199     return returnValue;
200   }
201
202   private static List<Object> translateGetAttributeFunctionExpression(
203           Object function,String heatFileName,
204           HeatOrchestrationTemplate heatOrchestrationTemplate,
205           TranslationContext context) {
206     List<String> attributeParamList = (List) function;
207     List<Object> toscaAttributeParamList = new ArrayList<>();
208
209     Optional<String> resourceTranslatedId =
210         handleResourceName(attributeParamList.get(0), heatFileName, heatOrchestrationTemplate,
211             context);
212     if (!resourceTranslatedId.isPresent()) {
213       //unsupported resource
214       toscaAttributeParamList.add(UNSUPPORTED_RESOURCE + attributeParamList.get(0));
215       return toscaAttributeParamList;
216     } else {
217       toscaAttributeParamList.add(resourceTranslatedId.get());
218     }
219
220     Optional<List<Object>> toscaAttList =
221         handleAttributeName(attributeParamList, heatOrchestrationTemplate, heatFileName, context);
222     if (!toscaAttList.isPresent()) {
223       //Unsupported attribute
224       toscaAttributeParamList.clear();
225       toscaAttributeParamList
226           .add(UNSUPPORTED_ATTRIBUTE + attributeParamList.get(0) + "." + attributeParamList.get(1));
227       return toscaAttributeParamList;
228     } else {
229       toscaAttributeParamList.addAll(toscaAttList.get());
230     }
231
232     Optional<List<String>> toscaIndexOrKey = handleAttributeIndexOrKey(attributeParamList);
233     if (toscaIndexOrKey.isPresent()) {
234       toscaAttributeParamList.addAll(toscaIndexOrKey.get());
235     }
236
237     return toscaAttributeParamList;
238   }
239
240   private static Optional<List<String>> handleAttributeIndexOrKey(List<String> attributeParamList) {
241     List<String> attributeIndexOrKey = new ArrayList<>();
242     if (attributeParamList.size() < 2) {
243       return Optional.empty();
244     }
245
246     for (int i = 2; i < attributeParamList.size(); i++) {
247       attributeIndexOrKey.add(attributeParamList.get(i));
248     }
249
250     return Optional.of(attributeIndexOrKey);
251   }
252
253   private static Optional<List<Object>> handleAttributeName(List<String> attributeParamList,
254                                                             HeatOrchestrationTemplate
255                                                                     heatOrchestrationTemplate,
256                                                             String heatFileName,
257                                                             TranslationContext context) {
258     String resourceId = attributeParamList.get(0);
259     Resource resource =
260         HeatToToscaUtil.getResource(heatOrchestrationTemplate, resourceId, heatFileName);
261
262     if (attributeParamList.size() == 1) {
263       return getResourceTranslatedAttributesList(resource, context);
264     }
265
266     if (HeatToToscaUtil.isNestedResource(resource)) {
267       return getNestedResourceTranslatedAttribute(attributeParamList.get(1));
268     } else {
269       return getResourceTranslatedAttribute(resource, attributeParamList.get(1), context);
270     }
271   }
272
273   private static Optional<List<Object>> getResourceTranslatedAttribute(Resource resource,
274                                                                        String attributeName,
275                                                                        TranslationContext context) {
276     List<Object> translatedAttributesList = new ArrayList<>();
277     String translatedAttribute =
278         context.getElementMapping(resource.getType(), Constants.ATTR, attributeName);
279     if (translatedAttribute != null) {
280       translatedAttributesList.add(translatedAttribute);
281       return Optional.of(translatedAttributesList);
282     } else {   //unsupported attribute
283       return Optional.empty();
284     }
285   }
286
287   private static Optional<List<Object>> getNestedResourceTranslatedAttribute(String attributeName) {
288     List<Object> translatedAttributesList = new ArrayList<>();
289
290     if (attributeName.startsWith(HeatConstants.GET_ATT_FROM_RESOURCE_GROUP_PREFIX)) {
291       String[] attributeSplit = attributeName.split("\\.");
292       if (attributeSplit.length == 2) {
293         translatedAttributesList.add(attributeSplit[1]);
294       } else if (attributeSplit.length == 3) {
295         translatedAttributesList.add(attributeSplit[2]);
296         translatedAttributesList.add(Integer.valueOf(attributeSplit[1]));
297       } else {
298         return Optional.empty();
299       }
300     } else {
301       translatedAttributesList.add(attributeName);
302     }
303     return Optional.of(translatedAttributesList);
304   }
305
306   private static Optional<List<Object>> getResourceTranslatedAttributesList(Resource resource,
307                                                                             TranslationContext
308                                                                                     context) {
309     List<Object> translatedAttributes = new ArrayList<>();
310     if (HeatToToscaUtil.isNestedResource(resource)) {
311       Optional<String> nestedFile = HeatToToscaUtil.getNestedFile(resource);
312       if (!nestedFile.isPresent()) {
313         return Optional.empty();
314       }
315       HeatOrchestrationTemplate nestedHeatOrchestrationTemplate = new YamlUtil()
316           .yamlToObject(context.getFiles().getFileContent(nestedFile.get()),
317               HeatOrchestrationTemplate.class);
318       translatedAttributes.addAll(nestedHeatOrchestrationTemplate.getOutputs().keySet());
319       return Optional.of(translatedAttributes);
320
321     } else {
322       Map<String, String> resourceMappingAttributes =
323           context.getElementMapping(resource.getType(), Constants.ATTR);
324       Set<String> mappingAttributes = new HashSet<>();
325       mappingAttributes
326           .addAll(resourceMappingAttributes.values().stream().collect(Collectors.toList()));
327       translatedAttributes.addAll(mappingAttributes);
328       return Optional.of(translatedAttributes);
329     }
330   }
331
332   private static Optional<String> handleResourceName(String resourceId, String heatFileName,
333                                                      HeatOrchestrationTemplate
334                                                              heatOrchestrationTemplate,
335                                                      TranslationContext context) {
336     return ResourceTranslationBase
337         .getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, resourceId, context);
338   }
339
340   public static boolean isResourceSupported(String translatedResourceId) {
341     return !translatedResourceId.startsWith(UNSUPPORTED_RESOURCE);
342   }
343
344   public static boolean isAttributeSupported(String translatedAttName) {
345     return !translatedAttName.startsWith(UNSUPPORTED_ATTRIBUTE);
346   }
347
348   /**
349    * Translate fn split function optional.
350    *
351    * @param propertyValue       the property value
352    * @param listSize            the list size
353    * @param includeBooleanValue the include boolean value
354    * @return the optional
355    */
356   public static Optional<List<Map<String, List>>> translateFnSplitFunction(
357           Object propertyValue,int listSize,
358           boolean includeBooleanValue) {
359     List<Map<String, List>> tokenPropertyValueList = new ArrayList<>();
360
361     if (propertyValue instanceof Map && !((Map) propertyValue).isEmpty()) {
362       Map<String, Object> propMap = (Map) propertyValue;
363       Map.Entry<String, Object> entry = propMap.entrySet().iterator().next();
364       Object entity = entry.getValue();
365       String key = entry.getKey();
366       String tokenChar;
367
368       if (key.equals("Fn::Split") && entity instanceof List) {
369         tokenChar = (String) ((List) entity).get(0);
370         Object refParameter = ((List) entity).get(1);
371
372         for (int substringIndex = 0; substringIndex < listSize; substringIndex++) {
373           Map<String, List> tokenPropertyValue = new HashMap<>();
374           tokenPropertyValue.put("token", new ArrayList<>());
375
376           if (refParameter instanceof Map && ((Map) refParameter).get("Ref") != null) {
377             Map<String, String> stringWithToken = new HashMap<>();
378             ((Map) stringWithToken)
379                 .put(ToscaFunctions.GET_INPUT.getDisplayName(), ((Map) refParameter).get("Ref"));
380             tokenPropertyValue.get("token").add(stringWithToken);
381           } else if (refParameter instanceof String) {
382             if (includeBooleanValue) {
383               StringBuffer booleanBuffer = new StringBuffer();
384               String[] booleanValueList = ((String) refParameter).split(tokenChar);
385               for (int i = 0; i < booleanValueList.length; i++) {
386                 if (i == 0) {
387                   booleanBuffer.append(HeatBoolean.eval(booleanValueList[i]));
388                 } else {
389                   booleanBuffer.append(tokenChar);
390                   booleanBuffer.append(HeatBoolean.eval(booleanValueList[i]));
391                 }
392               }
393               tokenPropertyValue.get("token").add(booleanBuffer.toString());
394             } else {
395               tokenPropertyValue.get("token").add(refParameter);
396             }
397           }
398           tokenPropertyValue.get("token").add(tokenChar);
399           tokenPropertyValue.get("token").add(substringIndex);
400           tokenPropertyValueList.add(tokenPropertyValue);
401         }
402
403         return Optional.of(tokenPropertyValueList);
404
405       }
406     }
407
408     return Optional.empty();
409   }
410 }