2  * Copyright © 2016-2018 European Support Limited
 
   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
 
   8  *      http://www.apache.org/licenses/LICENSE-2.0
 
  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.
 
  17 package org.openecomp.sdc.translator.services.heattotosca.impl.functiontranslation;
 
  19 import static org.openecomp.sdc.translator.services.heattotosca.ConfigConstants.TRANS_MAPPING_DELIMITER_CHAR;
 
  21 import org.apache.commons.lang3.StringUtils;
 
  22 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
 
  23 import org.openecomp.sdc.heat.datatypes.model.Resource;
 
  24 import org.openecomp.sdc.heat.services.HeatConstants;
 
  25 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
 
  26 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
 
  27 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
 
  28 import org.onap.sdc.tosca.datatypes.model.Template;
 
  29 import org.onap.sdc.tosca.services.YamlUtil;
 
  30 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
 
  31 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
 
  32 import org.openecomp.sdc.translator.datatypes.heattotosca.unifiedmodel.consolidation.EntityConsolidationData;
 
  33 import org.openecomp.sdc.translator.datatypes.heattotosca.unifiedmodel.consolidation.SubInterfaceTemplateConsolidationData;
 
  34 import org.openecomp.sdc.translator.services.heattotosca.ConsolidationDataUtil;
 
  35 import org.openecomp.sdc.translator.services.heattotosca.Constants;
 
  36 import org.openecomp.sdc.translator.services.heattotosca.FunctionTranslation;
 
  37 import org.openecomp.sdc.translator.services.heattotosca.FunctionTranslationFactory;
 
  38 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
 
  39 import org.openecomp.sdc.translator.services.heattotosca.NameExtractor;
 
  40 import org.openecomp.sdc.translator.services.heattotosca.helper.FunctionTranslationHelper;
 
  41 import org.openecomp.sdc.translator.services.heattotosca.impl.resourcetranslation.ResourceTranslationBase;
 
  43 import java.util.ArrayList;
 
  44 import java.util.HashMap;
 
  45 import java.util.HashSet;
 
  46 import java.util.List;
 
  48 import java.util.Optional;
 
  50 import java.util.stream.Collectors;
 
  52 public class FunctionTranslationGetAttrImpl implements FunctionTranslation {
 
  56   public Object translateFunction(ServiceTemplate serviceTemplate,
 
  57                                   String resourceId, String propertyName, String functionKey,
 
  58                                   Object functionValue, String heatFileName,
 
  59                                   HeatOrchestrationTemplate heatOrchestrationTemplate,
 
  60                                   Template toscaTemplate, TranslationContext context) {
 
  61     Object returnValue = new HashMap<>();
 
  62     List<Object> attributeFunctionExpression =
 
  63         translateGetAttributeFunctionExpression(serviceTemplate, resourceId, functionValue,
 
  64             propertyName, heatFileName, heatOrchestrationTemplate, (NodeTemplate) toscaTemplate,
 
  66     if (FunctionTranslationHelper.isResourceSupported(attributeFunctionExpression.get(0).toString())
 
  67         && FunctionTranslationHelper.isAttributeSupported(attributeFunctionExpression.get(0)
 
  70           .put(ToscaFunctions.GET_ATTRIBUTE.getDisplayName(), attributeFunctionExpression);
 
  72       returnValue = attributeFunctionExpression;
 
  78   private static List<Object> translateGetAttributeFunctionExpression(
 
  79       ServiceTemplate serviceTemplate,
 
  84       HeatOrchestrationTemplate heatOrchestrationTemplate,
 
  85       NodeTemplate nodeTemplate,
 
  86       TranslationContext context) {
 
  88     List<Object> attributeParamList = (List) functionValue;
 
  89     List<Object> toscaAttributeParamList = new ArrayList<>();
 
  91     Optional<String> targetResourceTranslatedId = Optional.empty();
 
  92     String targetResourceId = null;
 
  93     if( attributeParamList.get(0) instanceof String) {
 
  94       targetResourceId = (String) attributeParamList.get(0);
 
  95       targetResourceTranslatedId =
 
  96           handleResourceName(targetResourceId, heatFileName, heatOrchestrationTemplate,
 
  99     if (!targetResourceTranslatedId.isPresent()) {
 
 100       //unsupported resource
 
 101       toscaAttributeParamList
 
 103               FunctionTranslationHelper.getUnsupportedResourcePrefix() + attributeParamList.get(0));
 
 104       return toscaAttributeParamList;
 
 106       toscaAttributeParamList.add(targetResourceTranslatedId.get());
 
 109     Optional<List<Object>> toscaAttList =
 
 110         handleAttributeName(attributeParamList, heatOrchestrationTemplate, propertyName,
 
 111             heatFileName, serviceTemplate,
 
 113     if (!toscaAttList.isPresent()) {
 
 114       //Unsupported attribute
 
 115       toscaAttributeParamList.clear();
 
 116       toscaAttributeParamList
 
 117           .add(FunctionTranslationHelper.getUnsupportedAttributePrefix() + attributeParamList.get(0)
 
 118               + "." + attributeParamList.get(1));
 
 119       return toscaAttributeParamList;
 
 121       toscaAttributeParamList.addAll(toscaAttList.get());
 
 123       handleGetAttrConsolidationData(serviceTemplate, resourceId, propertyName, heatFileName,
 
 124           heatOrchestrationTemplate, context, targetResourceId,
 
 125           targetResourceTranslatedId,
 
 129     Optional<List<Object>> toscaIndexOrKey = handleAttributeIndexOrKey(serviceTemplate,
 
 130         resourceId, propertyName, HeatToToscaUtil
 
 131             .getResourceType((String) attributeParamList.get(0), heatOrchestrationTemplate,
 
 132                 heatFileName), attributeParamList, context, heatFileName,
 
 133         heatOrchestrationTemplate);
 
 134     toscaIndexOrKey.ifPresent(toscaAttributeParamList::addAll);
 
 136     return toscaAttributeParamList;
 
 139   private static void handleGetAttrConsolidationData(
 
 140       ServiceTemplate serviceTemplate,
 
 141       String resourceId, String propertyName,
 
 143       HeatOrchestrationTemplate heatOrchestrationTemplate,
 
 144       TranslationContext context,
 
 145       String targetResourceId,
 
 146       Optional<String> targetResourceTranslatedId,
 
 147       List<Object> toscaAttList) {
 
 149     Optional<String> resourceTranslatedId = Optional.empty();
 
 150     if (resourceId != null) {
 
 151       resourceTranslatedId =
 
 152           handleResourceName(resourceId, heatFileName, heatOrchestrationTemplate,
 
 155           .ifPresent(resourceTranslatedIdValue -> handleGetAttrOutConsolidationData(serviceTemplate,
 
 157               heatOrchestrationTemplate, context, resourceId, targetResourceTranslatedId.get(),
 
 158               resourceTranslatedIdValue, toscaAttList, heatFileName));
 
 161     if (targetResourceTranslatedId.isPresent()) {
 
 162       handleGetAttrInConsolidationData(serviceTemplate, resourceId, resourceTranslatedId,
 
 163           propertyName, heatOrchestrationTemplate, context, targetResourceId,
 
 164           targetResourceTranslatedId.get(), toscaAttList, heatFileName);
 
 168   private static void handleGetAttrOutConsolidationData(
 
 169       ServiceTemplate serviceTemplate,
 
 171       HeatOrchestrationTemplate heatOrchestrationTemplate,
 
 172       TranslationContext context,
 
 174       String targetTranslatedResourceId,
 
 175       String resourceTranslatedId,
 
 176       List<Object> toscaAttList,
 
 177       String heatFileName) {
 
 178     if (serviceTemplate != null) {
 
 179       Optional<EntityConsolidationData> entityConsolidationData =
 
 180           getEntityConsolidationData(serviceTemplate, heatOrchestrationTemplate, context,
 
 181               resourceId, resourceTranslatedId, heatFileName);
 
 182       if (entityConsolidationData.isPresent()) {
 
 183         String attName = (String) toscaAttList.get(0);
 
 184         handleNodeGetAttrOut(targetTranslatedResourceId, propertyName, heatOrchestrationTemplate,
 
 185             context, resourceId, entityConsolidationData.get(), attName);
 
 190   private static void handleGetAttrInConsolidationData(
 
 191       ServiceTemplate serviceTemplate,
 
 193       Optional<String> resourceTranslatedId,
 
 195       HeatOrchestrationTemplate heatOrchestrationTemplate,
 
 196       TranslationContext context,
 
 197       String targetResourceId,
 
 198       String targetResourceTranslatedId,
 
 199       List<Object> toscaAttList,
 
 200       String  heatFileName) {
 
 202     if (serviceTemplate != null) {
 
 203       Optional<EntityConsolidationData> entityConsolidationData =
 
 204           getEntityConsolidationData(serviceTemplate, heatOrchestrationTemplate, context,
 
 205               targetResourceId, targetResourceTranslatedId, heatFileName);
 
 206       if (entityConsolidationData.isPresent()) {
 
 207         String attName = (String) toscaAttList.get(0);
 
 208         if (resourceTranslatedId.isPresent()) {
 
 209           handleNodeGetAttrIn(resourceTranslatedId.get(), propertyName, heatOrchestrationTemplate,
 
 211               resourceId, entityConsolidationData.get(), attName);
 
 213           ConsolidationDataUtil
 
 214               .updateOutputGetAttributeInConsolidationData(entityConsolidationData.get(),
 
 215                   propertyName, attName);
 
 221   private static void handleNodeGetAttrOut(String nodeTemplateId, String propertyName,
 
 222                                            HeatOrchestrationTemplate heatOrchestrationTemplate,
 
 223                                            TranslationContext context, String resourceId,
 
 224                                            EntityConsolidationData entityConsolidationData,
 
 226     Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
 
 227     boolean isNestedResource = HeatToToscaUtil.isNestedResource(resource);
 
 228     String toscaPropertyName = propertyName;
 
 229     if (!isNestedResource) {
 
 230       toscaPropertyName = HeatToToscaUtil.getToscaPropertyName(context, resource
 
 231           .getType(), propertyName);
 
 233     ConsolidationDataUtil
 
 234         .updateNodeGetAttributeOut(entityConsolidationData,
 
 235             nodeTemplateId, toscaPropertyName, attName);
 
 238   private static void handleNodeGetAttrIn(String nodeTemplateId, String propertyName,
 
 239                                           HeatOrchestrationTemplate heatOrchestrationTemplate,
 
 240                                           TranslationContext context, String resourceId,
 
 241                                           EntityConsolidationData entityConsolidationData,
 
 243     Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
 
 244     boolean isNestedResource = HeatToToscaUtil.isNestedResource(resource);
 
 245     String heatPropertyName = propertyName;
 
 246     String toscaPropertyName = propertyName;
 
 247     //For handling get_attr in inner levels for complex properties
 
 248     if (propertyName.contains(TRANS_MAPPING_DELIMITER_CHAR)) {
 
 249       heatPropertyName = propertyName.substring(0,
 
 250           propertyName.indexOf(TRANS_MAPPING_DELIMITER_CHAR));
 
 252     if (!isNestedResource) {
 
 253       toscaPropertyName = HeatToToscaUtil.getToscaPropertyName(context, resource
 
 254           .getType(), heatPropertyName);
 
 256     ConsolidationDataUtil
 
 257         .updateNodeGetAttributeIn(entityConsolidationData,
 
 258             nodeTemplateId, toscaPropertyName, attName);
 
 261   private static Optional<EntityConsolidationData> getEntityConsolidationData(
 
 262       ServiceTemplate serviceTemplate,
 
 263       HeatOrchestrationTemplate heatOrchestrationTemplate,
 
 264       TranslationContext context,
 
 266       String resourceTranslatedId,
 
 267       String heatFileName) {
 
 268     Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
 
 269     if (ConsolidationDataUtil.isComputeResource(heatOrchestrationTemplate, resourceId)) {
 
 270       String resourceType = heatOrchestrationTemplate.getResources().get(resourceId).getType();
 
 271       NameExtractor nodeTypeNameExtractor =
 
 272           context.getNameExtractorImpl(resourceType);
 
 274           nodeTypeNameExtractor.extractNodeTypeName(
 
 275               resource, resourceId, context.getTranslatedIds().get(heatFileName).get(resourceId));
 
 278           ConsolidationDataUtil.getComputeTemplateConsolidationData(context, serviceTemplate,
 
 279               computeType, resourceTranslatedId));
 
 280     } else if (ConsolidationDataUtil.isPortResource(heatOrchestrationTemplate, resourceId)) {
 
 281       return Optional.of(ConsolidationDataUtil
 
 282           .getPortTemplateConsolidationData(context, serviceTemplate, resourceId, resource.getType(),
 
 283               resourceTranslatedId));
 
 284     } else if (HeatToToscaUtil.isSubInterfaceResource(resource, context)) {
 
 285       TranslateTo subInterfaceTo = new TranslateTo(heatFileName, serviceTemplate, heatOrchestrationTemplate,
 
 286           resource, resourceId, resourceTranslatedId, context);
 
 287       Optional<SubInterfaceTemplateConsolidationData> subInterfaceTemplateConsolidationData =
 
 288           ConsolidationDataUtil.getSubInterfaceTemplateConsolidationData(subInterfaceTo, resourceTranslatedId);
 
 289       if (subInterfaceTemplateConsolidationData.isPresent()) {
 
 290         return Optional.of(subInterfaceTemplateConsolidationData.get());
 
 292     } else if (HeatToToscaUtil.isNestedResource(resource)) {
 
 293       return Optional.ofNullable(ConsolidationDataUtil
 
 294           .getNestedTemplateConsolidationData(context, serviceTemplate, heatFileName, resourceTranslatedId));
 
 296     return Optional.empty();
 
 299   private static Optional<List<Object>> handleAttributeIndexOrKey(
 
 300       ServiceTemplate serviceTemplate,
 
 301       String resourceId, String propertyName,
 
 303       List<Object> attributeParamList,
 
 304       TranslationContext context,
 
 306       HeatOrchestrationTemplate heatOrchestrationTemplate) {
 
 308     List<Object> attributeIndexOrKey = new ArrayList<>();
 
 309     if (attributeParamList.size() < 3) {
 
 310       return Optional.empty();
 
 313     Object attributeName = attributeParamList.get(1);
 
 314     for (int i = 2; i < attributeParamList.size(); i++) {
 
 316       if (isInteger(attributeParamList.get(i))) {
 
 317         attributeIndexOrKey.add(attributeParamList.get(i));
 
 318       } else if (attributeParamList.get(i) instanceof Map) {
 
 319         attributeIndexOrKey.add(getToscaAttributeValue(serviceTemplate, resourceId,
 
 320             propertyName, attributeParamList.get(i), resourceType, heatFileName,
 
 321             heatOrchestrationTemplate, null, context));
 
 324         Object toscaAttributeName = resourceType == null ? null : context
 
 325             .getElementMapping(resourceType, Constants.ATTR,
 
 326                 getAttributeFullPath(attributeParamList, i));
 
 327         if (toscaAttributeName == null) {
 
 328           toscaAttributeName = attributeParamList.get(i);
 
 330         attributeIndexOrKey.add(toscaAttributeName);
 
 334     return Optional.of(attributeIndexOrKey);
 
 337   private static String getAttributeFullPath(List<Object> attributeParamList, int attributeIndex) {
 
 338     if (attributeParamList.size() < 3) {
 
 341     StringBuilder attributeFullPath = new StringBuilder();
 
 342     attributeFullPath.append(attributeParamList.get(1));
 
 343     for (int j = 2; j <= attributeIndex; j++) {
 
 344       if (isInteger(attributeParamList.get(j))) {
 
 347       attributeFullPath.append(TRANS_MAPPING_DELIMITER_CHAR);
 
 348       attributeFullPath.append(attributeParamList.get(j));
 
 350     return attributeFullPath.toString();
 
 353   private static boolean isInteger(Object inputNumber) {
 
 354     if (inputNumber == null) {
 
 358     if (StringUtils.isNumeric(String.valueOf(inputNumber))){
 
 365   private static Optional<String> handleResourceName(String resourceId, String heatFileName,
 
 366                                                      HeatOrchestrationTemplate
 
 367                                                          heatOrchestrationTemplate,
 
 368                                                      TranslationContext context) {
 
 369     return ResourceTranslationBase
 
 370         .getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, resourceId, context);
 
 373   private static Optional<List<Object>> handleAttributeName(List<Object> attributeParamList,
 
 374                                                             HeatOrchestrationTemplate
 
 375                                                                 heatOrchestrationTemplate,
 
 378                                                             ServiceTemplate serviceTemplate,
 
 379                                                             TranslationContext context) {
 
 380     String resourceId = (String) attributeParamList.get(0);
 
 382         HeatToToscaUtil.getResource(heatOrchestrationTemplate, resourceId, heatFileName);
 
 384     if (attributeParamList.size() == 1) {
 
 385       return getResourceTranslatedAttributesList(resource, context);
 
 388     if (!(attributeParamList.get(1) instanceof String)) {
 
 389       return Optional.empty();
 
 392     if (HeatToToscaUtil.isNestedResource(resource)) {
 
 393       return getNestedResourceTranslatedAttribute((String) attributeParamList.get(1));
 
 395       return getResourceTranslatedAttribute(resource, (String) attributeParamList.get(1), context);
 
 399   private static Optional<List<Object>> getNestedResourceTranslatedAttribute(String attributeName) {
 
 400     List<Object> translatedAttributesList = new ArrayList<>();
 
 402     if (attributeName.startsWith(HeatConstants.GET_ATTR_FROM_RESOURCE_GROUP_PREFIX)) {
 
 403       String[] attributeSplit = attributeName.split("\\.");
 
 404       if (attributeSplit.length == 2) {
 
 405         translatedAttributesList.add(attributeSplit[1]);
 
 406       } else if (attributeSplit.length == 3) {
 
 407         translatedAttributesList.add(attributeSplit[2]);
 
 408         translatedAttributesList.add(Integer.valueOf(attributeSplit[1]));
 
 410         return Optional.empty();
 
 413       translatedAttributesList.add(attributeName);
 
 415     return Optional.of(translatedAttributesList);
 
 418   private static Optional<List<Object>> getResourceTranslatedAttributesList(Resource resource,
 
 421     List<Object> translatedAttributes = new ArrayList<>();
 
 422     if (HeatToToscaUtil.isNestedResource(resource)) {
 
 423       Optional<String> nestedFile = HeatToToscaUtil.getNestedFile(resource);
 
 424       if (!nestedFile.isPresent()) {
 
 425         return Optional.empty();
 
 427       HeatOrchestrationTemplate nestedHeatOrchestrationTemplate = new YamlUtil()
 
 428           .yamlToObject(context.getFiles().getFileContent(nestedFile.get()),
 
 429               HeatOrchestrationTemplate.class);
 
 430       translatedAttributes.addAll(nestedHeatOrchestrationTemplate.getOutputs().keySet());
 
 431       return Optional.of(translatedAttributes);
 
 434       Map<String, String> resourceMappingAttributes =
 
 435           context.getElementMapping(resource.getType(), Constants.ATTR);
 
 436       if (resourceMappingAttributes == null) {
 
 437         return Optional.empty();
 
 439       Set<String> mappingAttributes = new HashSet<>();
 
 441           .addAll(resourceMappingAttributes.values().stream().collect(Collectors.toList()));
 
 442       translatedAttributes.addAll(mappingAttributes);
 
 443       return Optional.of(translatedAttributes);
 
 447   private static Optional<List<Object>> getResourceTranslatedAttribute(Resource resource,
 
 448                                                                        String attributeName,
 
 449                                                                        TranslationContext context) {
 
 450     List<Object> translatedAttributesList = new ArrayList<>();
 
 451     String translatedAttribute =
 
 452         context.getElementMapping(resource.getType(), Constants.ATTR, attributeName);
 
 453     if (translatedAttribute != null) {
 
 454       translatedAttributesList.add(translatedAttribute);
 
 455       return Optional.of(translatedAttributesList);
 
 456     } else {   //unsupported attribute
 
 457       return Optional.empty();
 
 461   private static Object getToscaAttributeValue(ServiceTemplate serviceTemplate,
 
 462                                                String resourceId, String propertyName,
 
 463                                                Object attributeVal, String resourceType,
 
 465                                                HeatOrchestrationTemplate heatOrchestrationTemplate,
 
 466                                                Template template, TranslationContext context) {
 
 467     if (attributeVal instanceof Map && !((Map) attributeVal).isEmpty()) {
 
 468       Map.Entry<String, Object> functionMapEntry =
 
 469           (Map.Entry<String, Object>) ((Map) attributeVal).entrySet().iterator().next();
 
 470       if (FunctionTranslationFactory.getInstance(functionMapEntry.getKey()).isPresent()) {
 
 471         return FunctionTranslationFactory.getInstance(functionMapEntry.getKey()).get()
 
 472             .translateFunction(serviceTemplate, resourceId, propertyName,
 
 473                 functionMapEntry.getKey(), functionMapEntry
 
 474                     .getValue(), heatFileName, heatOrchestrationTemplate, template, context);
 
 476       Map<String, Object> attrValueMap = new HashMap<>();
 
 477       for (Map.Entry<String, Object> entry : ((Map<String, Object>) attributeVal).entrySet()) {
 
 478         attrValueMap.put(entry.getKey(),
 
 479             getToscaAttributeValue(serviceTemplate, resourceId, propertyName, entry.getValue(),
 
 480                 resourceType, heatFileName, heatOrchestrationTemplate, template, context));
 
 483     } else if (attributeVal instanceof List && !((List) attributeVal).isEmpty()) {
 
 484       List propertyValueArray = new ArrayList<>();
 
 485       for (int i = 0; i < ((List) attributeVal).size(); i++) {
 
 486         propertyValueArray.add(
 
 487             getToscaAttributeValue(serviceTemplate, resourceId, propertyName,
 
 488                 ((List) attributeVal).get(i), resourceType, heatFileName,
 
 489                 heatOrchestrationTemplate, template, context));
 
 491       return propertyValueArray;