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 / impl / ResourceTranslationResourceGroupImpl.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.impl;
22
23 import org.openecomp.sdc.common.errors.CoreException;
24 import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes;
25 import org.openecomp.sdc.heat.datatypes.model.Resource;
26 import org.openecomp.sdc.heat.services.HeatConstants;
27 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
28 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
29 import org.openecomp.sdc.tosca.services.DataModelUtil;
30 import org.openecomp.sdc.tosca.services.ToscaConstants;
31 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
32 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
33 import org.openecomp.sdc.translator.services.heattotosca.ResourceTranslationFactory;
34 import org.openecomp.sdc.translator.services.heattotosca.errors.InvalidPropertyValueErrorBuilder;
35 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaPropertyConverter;
36
37 import java.util.ArrayList;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Optional;
42
43 public class ResourceTranslationResourceGroupImpl extends ResourceTranslationBase {
44
45   @Override
46   protected void translate(TranslateTo translateTo) {
47     final String heatFileName = translateTo.getHeatFileName();
48     Object resourceDef =
49         translateTo.getResource().getProperties().get(HeatConstants.RESOURCE_DEF_PROPERTY_NAME);
50     Resource nestedResource = new Resource();
51     Object typeDefinition = ((Map) resourceDef).get("type");
52     if (!(typeDefinition instanceof String)) {
53       logger.warn("Resource '" + translateTo.getResourceId() + "' of type'"
54           + HeatResourcesTypes.RESOURCE_GROUP_RESOURCE_TYPE.getHeatResource()
55           + "' with resourceDef which is not pointing to nested heat file "
56           +   "is not supported and will be ignored in the translation ");
57       return;
58     }
59     String type = (String) typeDefinition;
60     if (!HeatToToscaUtil.isYmlFileType(type)) {
61       logger.warn("Resource '" + translateTo.getResourceId() + "' of type'"
62           + HeatResourcesTypes.RESOURCE_GROUP_RESOURCE_TYPE.getHeatResource()
63           + "' with resourceDef which is not pointing to nested heat "
64           +   "file is not supported and will be ignored in the translation ");
65       return;
66     }
67
68     nestedResource.setType(type);
69     nestedResource.setProperties((Map<String, Object>) ((Map) resourceDef).get("properties"));
70     nestedResource.setMetadata(((Map) resourceDef).get("metadata"));
71
72     Optional<String> substitutionNodeTemplateId =
73         ResourceTranslationFactory.getInstance(nestedResource)
74             .translateResource(heatFileName, translateTo.getServiceTemplate(),
75                 translateTo.getHeatOrchestrationTemplate(), nestedResource,
76                 translateTo.getResourceId(), translateTo.getContext());
77     if (substitutionNodeTemplateId.isPresent()) {
78       NodeTemplate substitutionNodeTemplate = DataModelUtil
79           .getNodeTemplate(translateTo.getServiceTemplate(), substitutionNodeTemplateId.get());
80       Map serviceTemplateFilter = (Map<String, Object>) substitutionNodeTemplate.getProperties()
81           .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
82
83       populateServiceTemplateFilterProperties(translateTo, substitutionNodeTemplate,
84           serviceTemplateFilter);
85       handlingIndexVar(translateTo, substitutionNodeTemplate);
86       DataModelUtil
87           .addNodeTemplate(translateTo.getServiceTemplate(), substitutionNodeTemplateId.get(),
88               substitutionNodeTemplate);
89     }
90
91   }
92
93   private void handlingIndexVar(TranslateTo translateTo, NodeTemplate substitutionNodeTemplate) {
94     String indexVarValue = getIndexVarValue(translateTo);
95     replacePropertiesIndexVarValue(indexVarValue, substitutionNodeTemplate.getProperties());
96   }
97
98   private Map<String, List> getNewIndexVarValue() {
99     final Map<String, List> newIndexVarValue = new HashMap<>();
100     List indexVarValList = new ArrayList<>();
101     indexVarValList.add(ToscaConstants.MODELABLE_ENTITY_NAME_SELF);
102     indexVarValList.add(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
103     indexVarValList.add(ToscaConstants.INDEX_VALUE_PROPERTY_NAME);
104     newIndexVarValue.put(ToscaFunctions.GET_PROPERTY.getDisplayName(), indexVarValList);
105     return newIndexVarValue;
106   }
107
108   private void replacePropertiesIndexVarValue(String indexVarValue,
109                                               Map<String, Object> properties) {
110     if (properties == null || properties.isEmpty()) {
111       return;
112     }
113
114     for (Map.Entry<String, Object> propertyEntry : properties.entrySet()) {
115       Object propertyValue = propertyEntry.getValue();
116       Object newPropertyValue = getUpdatedPropertyValueWithIndex(indexVarValue, propertyValue);
117       if (newPropertyValue != null) {
118         properties.put(propertyEntry.getKey(), newPropertyValue);
119       }
120     }
121   }
122
123   private Object getUpdatedPropertyValueWithIndex(String indexVarValue, Object propertyValue) {
124     if (propertyValue instanceof String && propertyValue != null) {
125       if (propertyValue.equals(indexVarValue)) {
126         return getNewIndexVarValue();
127       }
128       if (((String) propertyValue).contains(indexVarValue)) {
129         Map<String, List<Object>> concatMap = new HashMap<>();
130         List<Object> concatList = new ArrayList<>();
131         String value = (String) propertyValue;
132
133         while (value.contains(indexVarValue)) {
134           if (value.indexOf(indexVarValue) == 0) {
135             concatList.add(getNewIndexVarValue());
136             value = value.substring(indexVarValue.length());
137           } else {
138             int end = value.indexOf(indexVarValue);
139             concatList.add(value.substring(0, end));
140             value = value.substring(end);
141           }
142         }
143         if (!value.isEmpty()) {
144           concatList.add(value);
145         }
146
147         concatMap.put(ToscaFunctions.CONCAT.getDisplayName(), concatList);
148         return concatMap;
149       }
150       return propertyValue; //no update is needed
151     } else if (propertyValue instanceof Map && !((Map) propertyValue).isEmpty()) {
152       replacePropertiesIndexVarValue(indexVarValue, (Map<String, Object>) propertyValue);
153       return propertyValue;
154     } else if (propertyValue instanceof List && !((List) propertyValue).isEmpty()) {
155       List newPropertyValueList = new ArrayList<>();
156       for (Object entry : ((List) propertyValue)) {
157         newPropertyValueList.add(getUpdatedPropertyValueWithIndex(indexVarValue, entry));
158       }
159       return newPropertyValueList;
160     }
161     return propertyValue;
162   }
163
164   private String getIndexVarValue(TranslateTo translateTo) {
165     Object indexVar =
166         translateTo.getResource().getProperties().get(HeatConstants.INDEX_PROPERTY_NAME);
167     if (indexVar == null) {
168       return HeatConstants.RESOURCE_GROUP_INDEX_VAR_DEFAULT_VALUE;
169     }
170
171     if (indexVar instanceof String) {
172       return (String) indexVar;
173     } else {
174       throw new CoreException(
175           new InvalidPropertyValueErrorBuilder("index_var", indexVar.toString(), "String").build());
176     }
177   }
178
179   private void populateServiceTemplateFilterProperties(TranslateTo translateTo,
180                                                        NodeTemplate substitutionNodeTemplate,
181                                                        Map serviceTemplateFilter) {
182     boolean mandatory = false;
183     Object countValue = TranslatorHeatToToscaPropertyConverter
184         .getToscaPropertyValue(ToscaConstants.COUNT_PROPERTY_NAME,
185             translateTo.getResource().getProperties().get(ToscaConstants.COUNT_PROPERTY_NAME), null,
186             translateTo.getHeatFileName(), translateTo.getHeatOrchestrationTemplate(),
187             substitutionNodeTemplate, translateTo.getContext());
188
189     if (countValue != null) {
190       serviceTemplateFilter.put(ToscaConstants.COUNT_PROPERTY_NAME, countValue);
191     } else {
192       serviceTemplateFilter.put(ToscaConstants.COUNT_PROPERTY_NAME, 1);
193     }
194     if (countValue instanceof Integer && (Integer) countValue > 0) {
195       mandatory = true;
196     }
197     if (countValue == null) {
198       mandatory = true;
199     }
200     serviceTemplateFilter.put("mandatory", mandatory);
201   }
202 }