Support functions in TOSCA Simple Profile in YAML
[sdc.git] / openecomp-be / lib / openecomp-sdc-translator-lib / openecomp-sdc-translator-core / src / main / java / org / openecomp / sdc / translator / services / heattotosca / impl / functiontranslation / FunctionTranslationGetAttrImpl.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.translator.services.heattotosca.impl.functiontranslation;
18
19 import static org.openecomp.sdc.translator.services.heattotosca.ConfigConstants.TRANS_MAPPING_DELIMITER_CHAR;
20
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Objects;
27 import java.util.Optional;
28 import java.util.Set;
29
30 import org.apache.commons.lang3.StringUtils;
31 import org.onap.sdc.tosca.services.YamlUtil;
32 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
33 import org.openecomp.sdc.heat.datatypes.model.Resource;
34 import org.openecomp.sdc.heat.services.HeatConstants;
35 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
36 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
37 import org.openecomp.sdc.translator.services.heattotosca.ConsolidationDataUtil;
38 import org.openecomp.sdc.translator.services.heattotosca.Constants;
39 import org.openecomp.sdc.translator.services.heattotosca.FunctionTranslation;
40 import org.openecomp.sdc.translator.services.heattotosca.FunctionTranslationFactory;
41 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
42 import org.openecomp.sdc.translator.services.heattotosca.impl.resourcetranslation.ResourceTranslationBase;
43
44 public class FunctionTranslationGetAttrImpl implements FunctionTranslation {
45
46     private static List<Object> translateGetAttributeFunctionExpression(FunctionTranslator functionTranslator) {
47
48         List<Object> attributeParamList = (List) functionTranslator.getFunctionValue();
49         List<Object> toscaAttributeParamList = new ArrayList<>();
50
51         Optional<String> targetResourceTranslatedId = Optional.empty();
52         String targetResourceId = null;
53         if (attributeParamList.get(0) instanceof String) {
54             targetResourceId = (String) attributeParamList.get(0);
55             targetResourceTranslatedId = handleResourceName(targetResourceId, functionTranslator.getHeatFileName(),
56                     functionTranslator.getHeatOrchestrationTemplate(), functionTranslator.getContext());
57         }
58         if (!targetResourceTranslatedId.isPresent()) {
59             //unsupported resource
60             toscaAttributeParamList.add(functionTranslator.getUnsupportedResourcePrefix() + attributeParamList.get(0));
61             return toscaAttributeParamList;
62         }
63         toscaAttributeParamList.add(targetResourceTranslatedId.get());
64         Optional<List<Object>> toscaAttList = handleAttributeName(attributeParamList, functionTranslator);
65         if (!toscaAttList.isPresent()) {
66             //Unsupported attribute
67             toscaAttributeParamList.clear();
68             toscaAttributeParamList.add(functionTranslator.getUnsupportedAttributePrefix()
69                     + attributeParamList.get(0) + "." + attributeParamList.get(1));
70             return toscaAttributeParamList;
71         }
72         toscaAttributeParamList.addAll(toscaAttList.get());
73         handleGetAttrConsolidationData(functionTranslator, targetResourceId, targetResourceTranslatedId.get(),
74                 toscaAttList.get());
75
76         String resourceType = HeatToToscaUtil.getResourceType((String) attributeParamList.get(0), functionTranslator
77                 .getHeatOrchestrationTemplate(), functionTranslator.getHeatFileName());
78         Optional<List<Object>> toscaIndexOrKey = handleAttributeIndexOrKey(functionTranslator, resourceType,
79                 attributeParamList);
80         toscaIndexOrKey.ifPresent(toscaAttributeParamList::addAll);
81         return toscaAttributeParamList;
82     }
83
84     private static void handleGetAttrConsolidationData(FunctionTranslator functionTranslator,
85                                                        String targetResourceId,
86                                                        String targetResourceTranslatedId,
87                                                        List<Object> toscaAttList) {
88         Optional<String> resourceTranslatedId;
89         String resourceId = functionTranslator.getResourceId();
90         String resourceTranslatedIdValue = null;
91         if (resourceId != null) {
92             resourceTranslatedId = handleResourceName(resourceId, functionTranslator.getHeatFileName(),
93                     functionTranslator.getHeatOrchestrationTemplate(), functionTranslator.getContext());
94             if (resourceTranslatedId.isPresent()) {
95                 resourceTranslatedIdValue = resourceTranslatedId.get();
96                 handleGetAttrOutConsolidationData(functionTranslator, targetResourceTranslatedId,
97                         resourceTranslatedIdValue, toscaAttList);
98             }
99         }
100         handleGetAttrInConsolidationData(functionTranslator, resourceTranslatedIdValue,
101                 targetResourceId, targetResourceTranslatedId, toscaAttList);
102     }
103
104     private static void handleGetAttrOutConsolidationData(FunctionTranslator functionTranslator,
105                                                           String targetTranslatedResourceId,
106                                                           String resourceTranslatedId,
107                                                           List<Object> toscaAttList) {
108         if (functionTranslator.getServiceTemplate() == null) {
109             return;
110         }
111
112         String attName = (String) toscaAttList.get(0);
113         ConsolidationDataUtil.updateNodeGetAttributeOut(functionTranslator, targetTranslatedResourceId,
114                 resourceTranslatedId, attName);
115
116     }
117
118     private static void handleGetAttrInConsolidationData(FunctionTranslator functionTranslator,
119                                                          String resourceTranslatedId,
120                                                          String targetResourceId,
121                                                          String targetResourceTranslatedId,
122                                                          List<Object> toscaAttList) {
123         if (functionTranslator.getServiceTemplate() == null) {
124             return;
125         }
126         String attName = (String) toscaAttList.get(0);
127         if (Objects.nonNull(resourceTranslatedId)) {
128             ConsolidationDataUtil.updateNodeGetAttributeIn(functionTranslator, resourceTranslatedId,
129                     targetResourceId, targetResourceTranslatedId, attName);
130         } else {
131             ConsolidationDataUtil.updateOutputParamGetAttrIn(functionTranslator, targetResourceId,
132                     targetResourceTranslatedId, functionTranslator.getPropertyName(), attName);
133         }
134     }
135
136     private static Optional<List<Object>> handleAttributeIndexOrKey(FunctionTranslator functionTranslator,
137                                                                     String resourceType,
138                                                                     List<Object> attributeParamList) {
139
140         List<Object> attributeIndexOrKey = new ArrayList<>();
141         if (attributeParamList.size() < 3) {
142             return Optional.empty();
143         }
144
145         for (int i = 2; i < attributeParamList.size(); i++) {
146             if (isInteger(attributeParamList.get(i))) {
147                 attributeIndexOrKey.add(attributeParamList.get(i));
148             } else if (attributeParamList.get(i) instanceof Map) {
149                 attributeIndexOrKey.add(getToscaAttributeValue(functionTranslator, attributeParamList.get(i)));
150             } else {
151                 Object toscaAttributeName = resourceType == null ? null : functionTranslator.getContext()
152                         .getElementMapping(resourceType, Constants.ATTR, getAttributeFullPath(attributeParamList, i));
153                 if (toscaAttributeName == null) {
154                     toscaAttributeName = attributeParamList.get(i);
155                 }
156                 attributeIndexOrKey.add(toscaAttributeName);
157             }
158         }
159
160         return Optional.of(attributeIndexOrKey);
161     }
162
163     private static String getAttributeFullPath(List<Object> attributeParamList, int attributeIndex) {
164         if (attributeParamList.size() < 3) {
165             return null;
166         }
167         StringBuilder attributeFullPath = new StringBuilder();
168         attributeFullPath.append(attributeParamList.get(1));
169         for (int j = 2; j <= attributeIndex; j++) {
170             if (isInteger(attributeParamList.get(j))) {
171                 continue;
172             }
173             attributeFullPath.append(TRANS_MAPPING_DELIMITER_CHAR);
174             attributeFullPath.append(attributeParamList.get(j));
175         }
176         return attributeFullPath.toString();
177     }
178
179     private static boolean isInteger(Object inputNumber) {
180         if (inputNumber == null) {
181             return false;
182         }
183         return StringUtils.isNumeric(String.valueOf(inputNumber));
184     }
185
186     private static Optional<String> handleResourceName(String resourceId, String heatFileName,
187                                                        HeatOrchestrationTemplate heatOrchestrationTemplate,
188                                                        TranslationContext context) {
189         return ResourceTranslationBase
190                 .getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, resourceId, context);
191     }
192
193     private static Optional<List<Object>> handleAttributeName(List<Object> attributeParamList,
194                                                               FunctionTranslator functionTranslator) {
195         String resourceId = (String) attributeParamList.get(0);
196         Resource resource = HeatToToscaUtil.getResource(functionTranslator.getHeatOrchestrationTemplate(),
197                 resourceId, functionTranslator.getHeatFileName());
198         if (attributeParamList.size() == 1) {
199             return getResourceTranslatedAttributesList(resource, functionTranslator.getContext());
200         }
201         if (!(attributeParamList.get(1) instanceof String)) {
202             return Optional.empty();
203         }
204         if (HeatToToscaUtil.isNestedResource(resource)) {
205             return getNestedResourceTranslatedAttribute((String) attributeParamList.get(1));
206         } else {
207             return getResourceTranslatedAttribute(resource, (String) attributeParamList.get(1), functionTranslator
208                     .getContext());
209         }
210     }
211
212     private static Optional<List<Object>> getNestedResourceTranslatedAttribute(String attributeName) {
213         List<Object> translatedAttributesList = new ArrayList<>();
214         if (attributeName.startsWith(HeatConstants.GET_ATTR_FROM_RESOURCE_GROUP_PREFIX)) {
215             String[] attributeSplit = attributeName.split("\\.");
216             if (attributeSplit.length == 2) {
217                 translatedAttributesList.add(attributeSplit[1]);
218             } else if (attributeSplit.length == 3) {
219                 translatedAttributesList.add(attributeSplit[2]);
220                 translatedAttributesList.add(Integer.valueOf(attributeSplit[1]));
221             } else {
222                 return Optional.empty();
223             }
224         } else {
225             translatedAttributesList.add(attributeName);
226         }
227         return Optional.of(translatedAttributesList);
228     }
229
230     private static Optional<List<Object>> getResourceTranslatedAttributesList(Resource resource,
231                                                                               TranslationContext context) {
232         List<Object> translatedAttributes = new ArrayList<>();
233         if (HeatToToscaUtil.isNestedResource(resource)) {
234             Optional<String> nestedFile = HeatToToscaUtil.getNestedFile(resource);
235             if (!nestedFile.isPresent()) {
236                 return Optional.empty();
237             }
238             HeatOrchestrationTemplate nestedHeatOrchestrationTemplate = new YamlUtil()
239                     .yamlToObject(context.getFiles().getFileContentAsStream(nestedFile.get()), HeatOrchestrationTemplate.class);
240             translatedAttributes.addAll(nestedHeatOrchestrationTemplate.getOutputs().keySet());
241             return Optional.of(translatedAttributes);
242
243         } else {
244             Map<String, String> resourceMappingAttributes =
245                     context.getElementMapping(resource.getType(), Constants.ATTR);
246             if (resourceMappingAttributes == null) {
247                 return Optional.empty();
248             }
249             Set<String> mappingAttributes = new HashSet<>(new ArrayList<>(resourceMappingAttributes.values()));
250             translatedAttributes.addAll(mappingAttributes);
251             return Optional.of(translatedAttributes);
252         }
253     }
254
255     private static Optional<List<Object>> getResourceTranslatedAttribute(Resource resource,
256                                                                          String attributeName,
257                                                                          TranslationContext context) {
258         List<Object> translatedAttributesList = new ArrayList<>();
259         String translatedAttribute = context.getElementMapping(resource.getType(), Constants.ATTR, attributeName);
260         if (translatedAttribute != null) {
261             translatedAttributesList.add(translatedAttribute);
262             return Optional.of(translatedAttributesList);
263         } else {   //unsupported attribute
264             return Optional.empty();
265         }
266     }
267
268     private static Object getToscaAttributeValue(FunctionTranslator functionTranslator,
269                                                  Object attributeVal) {
270         if (attributeVal instanceof Map && !((Map) attributeVal).isEmpty()) {
271             Map.Entry<String, Object> functionMapEntry =
272                     (Map.Entry<String, Object>) ((Map) attributeVal).entrySet().iterator().next();
273             Optional<FunctionTranslation> functionTranslationInstance =
274                     FunctionTranslationFactory.getInstance(functionMapEntry.getKey());
275             if (functionTranslationInstance.isPresent()) {
276                 functionTranslator.setFunctionValue(functionMapEntry.getValue());
277                 return functionTranslationInstance.get().translateFunction(functionTranslator);
278             }
279             Map<String, Object> attrValueMap = new HashMap<>();
280             for (Map.Entry<String, Object> entry : ((Map<String, Object>) attributeVal).entrySet()) {
281                 attrValueMap.put(entry.getKey(), getToscaAttributeValue(functionTranslator, entry.getValue()));
282             }
283             return attrValueMap;
284         } else if (attributeVal instanceof List && !((List) attributeVal).isEmpty()) {
285             List<Object> propertyValueArray = new ArrayList<>();
286             for (int i = 0; i < ((List) attributeVal).size(); i++) {
287                 propertyValueArray.add(getToscaAttributeValue(functionTranslator, ((List) attributeVal).get(i)));
288             }
289             return propertyValueArray;
290         }
291         return attributeVal;
292     }
293
294     @Override
295     public Object translateFunction(FunctionTranslator functionTranslator) {
296         Object returnValue;
297         List<Object> attributeFunctionExpression = translateGetAttributeFunctionExpression(functionTranslator);
298         if (functionTranslator.isResourceSupported(attributeFunctionExpression.get(0).toString())
299                 && functionTranslator.isAttributeSupported(attributeFunctionExpression.get(0).toString())) {
300             Map<String, Object> getAttrValue = new HashMap<>();
301             getAttrValue.put(ToscaFunctions.GET_ATTRIBUTE.getFunctionName(), attributeFunctionExpression);
302             returnValue = getAttrValue;
303         } else {
304             returnValue = attributeFunctionExpression;
305         }
306         return returnValue;
307     }
308 }