f533353d1895047024c7d7a0acf7b35a456f855a
[sdc.git] /
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.datatypes.model.ServiceTemplate;
32 import org.onap.sdc.tosca.services.YamlUtil;
33 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
34 import org.openecomp.sdc.heat.datatypes.model.Resource;
35 import org.openecomp.sdc.heat.services.HeatConstants;
36 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
37 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
38 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
39 import org.openecomp.sdc.translator.datatypes.heattotosca.unifiedmodel.consolidation.EntityConsolidationData;
40 import org.openecomp.sdc.translator.datatypes.heattotosca.unifiedmodel.consolidation.SubInterfaceTemplateConsolidationData;
41 import org.openecomp.sdc.translator.services.heattotosca.ConsolidationDataUtil;
42 import org.openecomp.sdc.translator.services.heattotosca.Constants;
43 import org.openecomp.sdc.translator.services.heattotosca.FunctionTranslation;
44 import org.openecomp.sdc.translator.services.heattotosca.FunctionTranslationFactory;
45 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
46 import org.openecomp.sdc.translator.services.heattotosca.NameExtractor;
47 import org.openecomp.sdc.translator.services.heattotosca.impl.resourcetranslation.ResourceTranslationBase;
48
49 public class FunctionTranslationGetAttrImpl implements FunctionTranslation {
50
51     private static List<Object> translateGetAttributeFunctionExpression(FunctionTranslator functionTranslator) {
52
53         List<Object> attributeParamList = (List) functionTranslator.getFunctionValue();
54         List<Object> toscaAttributeParamList = new ArrayList<>();
55
56         Optional<String> targetResourceTranslatedId = Optional.empty();
57         String targetResourceId = null;
58         if (attributeParamList.get(0) instanceof String) {
59             targetResourceId = (String) attributeParamList.get(0);
60             targetResourceTranslatedId = handleResourceName(targetResourceId, functionTranslator.getHeatFileName(),
61                     functionTranslator.getHeatOrchestrationTemplate(), functionTranslator.getContext());
62         }
63         if (!targetResourceTranslatedId.isPresent()) {
64             //unsupported resource
65             toscaAttributeParamList.add(functionTranslator.getUnsupportedResourcePrefix() + attributeParamList.get(0));
66             return toscaAttributeParamList;
67         }
68         toscaAttributeParamList.add(targetResourceTranslatedId.get());
69         Optional<List<Object>> toscaAttList = handleAttributeName(attributeParamList, functionTranslator);
70         if (!toscaAttList.isPresent()) {
71             //Unsupported attribute
72             toscaAttributeParamList.clear();
73             toscaAttributeParamList.add(functionTranslator.getUnsupportedAttributePrefix()
74                     + attributeParamList.get(0) + "." + attributeParamList.get(1));
75             return toscaAttributeParamList;
76         }
77         toscaAttributeParamList.addAll(toscaAttList.get());
78         handleGetAttrConsolidationData(functionTranslator, targetResourceId, targetResourceTranslatedId.get(),
79                 toscaAttList.get());
80
81         String resourceType = HeatToToscaUtil.getResourceType((String) attributeParamList.get(0), functionTranslator
82                 .getHeatOrchestrationTemplate(), functionTranslator.getHeatFileName());
83         Optional<List<Object>> toscaIndexOrKey = handleAttributeIndexOrKey(functionTranslator, resourceType,
84                 attributeParamList);
85         toscaIndexOrKey.ifPresent(toscaAttributeParamList::addAll);
86         return toscaAttributeParamList;
87     }
88
89     private static void handleGetAttrConsolidationData(FunctionTranslator functionTranslator,
90                                                        String targetResourceId,
91                                                        String targetResourceTranslatedId,
92                                                        List<Object> toscaAttList) {
93
94         Optional<String> resourceTranslatedId;
95         String resourceId = functionTranslator.getResourceId();
96         String resourceTranslatedIdValue = null;
97         if (resourceId != null) {
98             resourceTranslatedId = handleResourceName(resourceId, functionTranslator.getHeatFileName(),
99                     functionTranslator.getHeatOrchestrationTemplate(), functionTranslator.getContext());
100             if (resourceTranslatedId.isPresent()) {
101                 resourceTranslatedIdValue = resourceTranslatedId.get();
102                 handleGetAttrOutConsolidationData(functionTranslator, targetResourceTranslatedId,
103                         resourceTranslatedIdValue, toscaAttList);
104             }
105         }
106         handleGetAttrInConsolidationData(functionTranslator, resourceTranslatedIdValue, targetResourceId,
107                 targetResourceTranslatedId, toscaAttList);
108     }
109
110     private static void handleGetAttrOutConsolidationData(FunctionTranslator functionTranslator,
111                                                           String targetTranslatedResourceId,
112                                                           String resourceTranslatedId,
113                                                           List<Object> toscaAttList) {
114         if (functionTranslator.getServiceTemplate() == null) {
115             return;
116         }
117         Optional<EntityConsolidationData> entityConsolidationData = getEntityConsolidationData(functionTranslator,
118                 functionTranslator.getResourceId(), resourceTranslatedId);
119         if (entityConsolidationData.isPresent()) {
120             String attName = (String) toscaAttList.get(0);
121             handleNodeGetAttrOut(targetTranslatedResourceId, functionTranslator, entityConsolidationData.get(),
122                     attName);
123         }
124     }
125
126     private static void handleGetAttrInConsolidationData(FunctionTranslator functionTranslator,
127                                                          String resourceTranslatedId,
128                                                          String targetResourceId,
129                                                          String targetResourceTranslatedId,
130                                                          List<Object> toscaAttList) {
131         if (functionTranslator.getServiceTemplate() == null) {
132             return;
133         }
134         Optional<EntityConsolidationData> entityConsolidationData = getEntityConsolidationData(functionTranslator,
135                 targetResourceId, targetResourceTranslatedId);
136         if (!entityConsolidationData.isPresent()) {
137             return;
138         }
139         String attName = (String) toscaAttList.get(0);
140         if (Objects.nonNull(resourceTranslatedId)) {
141             handleNodeGetAttrIn(resourceTranslatedId, functionTranslator, entityConsolidationData.get(), attName);
142         } else {
143             ConsolidationDataUtil.updateOutputGetAttributeInConsolidationData(entityConsolidationData.get(),
144                     functionTranslator.getPropertyName(), attName);
145         }
146     }
147
148     private static void handleNodeGetAttrOut(String nodeTemplateId, FunctionTranslator functionTranslator,
149                                              EntityConsolidationData entityConsolidationData,
150                                              String attName) {
151         Resource resource = functionTranslator.getHeatOrchestrationTemplate().getResources().get(functionTranslator
152                 .getResourceId());
153         boolean isNestedResource = HeatToToscaUtil.isNestedResource(resource);
154         String toscaPropertyName = functionTranslator.getPropertyName();
155         if (!isNestedResource) {
156             toscaPropertyName = HeatToToscaUtil.getToscaPropertyName(functionTranslator.getContext(), resource
157                     .getType(), functionTranslator.getPropertyName());
158         }
159         ConsolidationDataUtil.updateNodeGetAttributeOut(entityConsolidationData, nodeTemplateId, toscaPropertyName,
160                 attName);
161     }
162
163     private static void handleNodeGetAttrIn(String nodeTemplateId, FunctionTranslator functionTranslator,
164                                             EntityConsolidationData entityConsolidationData,
165                                             String attName) {
166         Resource resource = functionTranslator.getHeatOrchestrationTemplate().getResources().get(functionTranslator
167                 .getResourceId());
168         boolean isNestedResource = HeatToToscaUtil.isNestedResource(resource);
169         String propertyName = functionTranslator.getPropertyName();
170         String heatPropertyName = propertyName;
171         String toscaPropertyName = propertyName;
172         //For handling get_attr in inner levels for complex properties
173         if (propertyName.contains(TRANS_MAPPING_DELIMITER_CHAR)) {
174             heatPropertyName = propertyName.substring(0, propertyName.indexOf(TRANS_MAPPING_DELIMITER_CHAR));
175         }
176         if (!isNestedResource) {
177             toscaPropertyName = HeatToToscaUtil.getToscaPropertyName(functionTranslator.getContext(), resource
178                     .getType(), heatPropertyName);
179         }
180         ConsolidationDataUtil.updateNodeGetAttributeIn(entityConsolidationData, nodeTemplateId, toscaPropertyName,
181                 attName);
182     }
183
184     private static Optional<EntityConsolidationData> getEntityConsolidationData(FunctionTranslator functionTranslator,
185                                                                                 String resourceId,
186                                                                                 String resourceTranslatedId) {
187         HeatOrchestrationTemplate heatOrchestrationTemplate = functionTranslator.getHeatOrchestrationTemplate();
188         TranslationContext context = functionTranslator.getContext();
189         ServiceTemplate serviceTemplate = functionTranslator.getServiceTemplate();
190         String heatFileName = functionTranslator.getHeatFileName();
191
192         Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
193         if (ConsolidationDataUtil.isComputeResource(heatOrchestrationTemplate, resourceId)) {
194             String resourceType = heatOrchestrationTemplate.getResources().get(resourceId).getType();
195             NameExtractor nodeTypeNameExtractor = TranslationContext.getNameExtractorImpl(resourceType);
196             String computeType = nodeTypeNameExtractor.extractNodeTypeName(resource, resourceId, context
197                     .getTranslatedIds().get(heatFileName).get(resourceId));
198
199             return Optional.of(ConsolidationDataUtil.getComputeTemplateConsolidationData(context, serviceTemplate,
200                     computeType, resourceTranslatedId));
201         } else if (ConsolidationDataUtil.isPortResource(heatOrchestrationTemplate, resourceId)) {
202             return Optional.of(ConsolidationDataUtil
203                     .getPortTemplateConsolidationData(context, serviceTemplate, resourceId, resource.getType(),
204                             resourceTranslatedId));
205         } else if (HeatToToscaUtil.isSubInterfaceResource(resource, context)) {
206             TranslateTo subInterfaceTo = new TranslateTo(heatFileName, serviceTemplate, heatOrchestrationTemplate,
207                     resource, resourceId, resourceTranslatedId, context);
208             Optional<SubInterfaceTemplateConsolidationData> subInterfaceTemplateConsolidationData =
209                     ConsolidationDataUtil.getSubInterfaceTemplateConsolidationData(subInterfaceTo,
210                             resourceTranslatedId);
211             if (subInterfaceTemplateConsolidationData.isPresent()) {
212                 return Optional.of(subInterfaceTemplateConsolidationData.get());
213             }
214         } else if (HeatToToscaUtil.isNestedResource(resource)) {
215             return Optional.ofNullable(ConsolidationDataUtil
216                     .getNestedTemplateConsolidationData(context, serviceTemplate, heatFileName, resourceTranslatedId));
217         }
218         return Optional.empty();
219     }
220
221     private static Optional<List<Object>> handleAttributeIndexOrKey(FunctionTranslator functionTranslator,
222                                                                     String resourceType,
223                                                                     List<Object> attributeParamList) {
224
225         List<Object> attributeIndexOrKey = new ArrayList<>();
226         if (attributeParamList.size() < 3) {
227             return Optional.empty();
228         }
229
230         for (int i = 2; i < attributeParamList.size(); i++) {
231             if (isInteger(attributeParamList.get(i))) {
232                 attributeIndexOrKey.add(attributeParamList.get(i));
233             } else if (attributeParamList.get(i) instanceof Map) {
234                 attributeIndexOrKey.add(getToscaAttributeValue(functionTranslator, attributeParamList.get(i)));
235             } else {
236                 Object toscaAttributeName = resourceType == null ? null : functionTranslator.getContext()
237                         .getElementMapping(resourceType, Constants.ATTR, getAttributeFullPath(attributeParamList, i));
238                 if (toscaAttributeName == null) {
239                     toscaAttributeName = attributeParamList.get(i);
240                 }
241                 attributeIndexOrKey.add(toscaAttributeName);
242             }
243         }
244
245         return Optional.of(attributeIndexOrKey);
246     }
247
248     private static String getAttributeFullPath(List<Object> attributeParamList, int attributeIndex) {
249         if (attributeParamList.size() < 3) {
250             return null;
251         }
252         StringBuilder attributeFullPath = new StringBuilder();
253         attributeFullPath.append(attributeParamList.get(1));
254         for (int j = 2; j <= attributeIndex; j++) {
255             if (isInteger(attributeParamList.get(j))) {
256                 continue;
257             }
258             attributeFullPath.append(TRANS_MAPPING_DELIMITER_CHAR);
259             attributeFullPath.append(attributeParamList.get(j));
260         }
261         return attributeFullPath.toString();
262     }
263
264     private static boolean isInteger(Object inputNumber) {
265         if (inputNumber == null) {
266             return false;
267         }
268         return StringUtils.isNumeric(String.valueOf(inputNumber));
269     }
270
271     private static Optional<String> handleResourceName(String resourceId, String heatFileName,
272                                                        HeatOrchestrationTemplate heatOrchestrationTemplate,
273                                                        TranslationContext context) {
274         return ResourceTranslationBase
275                 .getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, resourceId, context);
276     }
277
278     private static Optional<List<Object>> handleAttributeName(List<Object> attributeParamList,
279                                                               FunctionTranslator functionTranslator) {
280         String resourceId = (String) attributeParamList.get(0);
281         Resource resource = HeatToToscaUtil.getResource(functionTranslator.getHeatOrchestrationTemplate(),
282                 resourceId, functionTranslator.getHeatFileName());
283         if (attributeParamList.size() == 1) {
284             return getResourceTranslatedAttributesList(resource, functionTranslator.getContext());
285         }
286         if (!(attributeParamList.get(1) instanceof String)) {
287             return Optional.empty();
288         }
289         if (HeatToToscaUtil.isNestedResource(resource)) {
290             return getNestedResourceTranslatedAttribute((String) attributeParamList.get(1));
291         } else {
292             return getResourceTranslatedAttribute(resource, (String) attributeParamList.get(1), functionTranslator
293                     .getContext());
294         }
295     }
296
297     private static Optional<List<Object>> getNestedResourceTranslatedAttribute(String attributeName) {
298         List<Object> translatedAttributesList = new ArrayList<>();
299         if (attributeName.startsWith(HeatConstants.GET_ATTR_FROM_RESOURCE_GROUP_PREFIX)) {
300             String[] attributeSplit = attributeName.split("\\.");
301             if (attributeSplit.length == 2) {
302                 translatedAttributesList.add(attributeSplit[1]);
303             } else if (attributeSplit.length == 3) {
304                 translatedAttributesList.add(attributeSplit[2]);
305                 translatedAttributesList.add(Integer.valueOf(attributeSplit[1]));
306             } else {
307                 return Optional.empty();
308             }
309         } else {
310             translatedAttributesList.add(attributeName);
311         }
312         return Optional.of(translatedAttributesList);
313     }
314
315     private static Optional<List<Object>> getResourceTranslatedAttributesList(Resource resource,
316                                                                               TranslationContext context) {
317         List<Object> translatedAttributes = new ArrayList<>();
318         if (HeatToToscaUtil.isNestedResource(resource)) {
319             Optional<String> nestedFile = HeatToToscaUtil.getNestedFile(resource);
320             if (!nestedFile.isPresent()) {
321                 return Optional.empty();
322             }
323             HeatOrchestrationTemplate nestedHeatOrchestrationTemplate = new YamlUtil()
324                     .yamlToObject(context.getFiles().getFileContent(nestedFile.get()), HeatOrchestrationTemplate.class);
325             translatedAttributes.addAll(nestedHeatOrchestrationTemplate.getOutputs().keySet());
326             return Optional.of(translatedAttributes);
327
328         } else {
329             Map<String, String> resourceMappingAttributes =
330                     context.getElementMapping(resource.getType(), Constants.ATTR);
331             if (resourceMappingAttributes == null) {
332                 return Optional.empty();
333             }
334             Set<String> mappingAttributes = new HashSet<>(new ArrayList<>(resourceMappingAttributes.values()));
335             translatedAttributes.addAll(mappingAttributes);
336             return Optional.of(translatedAttributes);
337         }
338     }
339
340     private static Optional<List<Object>> getResourceTranslatedAttribute(Resource resource,
341                                                                          String attributeName,
342                                                                          TranslationContext context) {
343         List<Object> translatedAttributesList = new ArrayList<>();
344         String translatedAttribute = context.getElementMapping(resource.getType(), Constants.ATTR, attributeName);
345         if (translatedAttribute != null) {
346             translatedAttributesList.add(translatedAttribute);
347             return Optional.of(translatedAttributesList);
348         } else {   //unsupported attribute
349             return Optional.empty();
350         }
351     }
352
353     private static Object getToscaAttributeValue(FunctionTranslator functionTranslator,
354                                                  Object attributeVal) {
355         if (attributeVal instanceof Map && !((Map) attributeVal).isEmpty()) {
356             Map.Entry<String, Object> functionMapEntry =
357                     (Map.Entry<String, Object>) ((Map) attributeVal).entrySet().iterator().next();
358             Optional<FunctionTranslation> functionTranslationInstance =
359                     FunctionTranslationFactory.getInstance(functionMapEntry.getKey());
360             if (functionTranslationInstance.isPresent()) {
361                 functionTranslator.setFunctionValue(functionMapEntry.getValue());
362                 return functionTranslationInstance.get().translateFunction(functionTranslator);
363             }
364             Map<String, Object> attrValueMap = new HashMap<>();
365             for (Map.Entry<String, Object> entry : ((Map<String, Object>) attributeVal).entrySet()) {
366                 attrValueMap.put(entry.getKey(), getToscaAttributeValue(functionTranslator, entry.getValue()));
367             }
368             return attrValueMap;
369         } else if (attributeVal instanceof List && !((List) attributeVal).isEmpty()) {
370             List<Object> propertyValueArray = new ArrayList<>();
371             for (int i = 0; i < ((List) attributeVal).size(); i++) {
372                 propertyValueArray.add(getToscaAttributeValue(functionTranslator, ((List) attributeVal).get(i)));
373             }
374             return propertyValueArray;
375         }
376         return attributeVal;
377     }
378
379     @Override
380     public Object translateFunction(FunctionTranslator functionTranslator) {
381         Object returnValue;
382         List<Object> attributeFunctionExpression = translateGetAttributeFunctionExpression(functionTranslator);
383         if (functionTranslator.isResourceSupported(attributeFunctionExpression.get(0).toString())
384                 && functionTranslator.isAttributeSupported(attributeFunctionExpression.get(0).toString())) {
385             Map<String, Object> getAttrValue = new HashMap<>();
386             getAttrValue.put(ToscaFunctions.GET_ATTRIBUTE.getDisplayName(), attributeFunctionExpression);
387             returnValue = getAttrValue;
388         } else {
389             returnValue = attributeFunctionExpression;
390         }
391         return returnValue;
392     }
393
394
395 }