386b2e1ea9c85a22e57e75017e96cee025e007dc
[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.mapping;
18
19 import static org.openecomp.sdc.translator.services.heattotosca.impl.functiontranslation.FunctionTranslator.getFunctionTranslateTo;
20
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Objects;
27 import java.util.Optional;
28 import org.apache.commons.collections4.MapUtils;
29 import org.apache.commons.lang3.StringUtils;
30 import org.onap.sdc.tosca.datatypes.model.Constraint;
31 import org.onap.sdc.tosca.datatypes.model.EntrySchema;
32 import org.onap.sdc.tosca.datatypes.model.ParameterDefinition;
33 import org.onap.sdc.tosca.datatypes.model.ScalarUnitValidator;
34 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
35 import org.onap.sdc.tosca.datatypes.model.heatextend.AnnotationDefinition;
36 import org.onap.sdc.tosca.datatypes.model.heatextend.ParameterDefinitionExt;
37 import org.openecomp.core.utilities.file.FileUtils;
38 import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes;
39 import org.openecomp.sdc.heat.datatypes.ToscaScalarUnitFrequency;
40 import org.openecomp.sdc.heat.datatypes.ToscaScalarUnitSize;
41 import org.openecomp.sdc.heat.datatypes.ToscaScalarUnitTime;
42 import org.openecomp.sdc.heat.datatypes.ToscaScalarUnitTypes;
43 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
44 import org.openecomp.sdc.heat.datatypes.model.Output;
45 import org.openecomp.sdc.heat.datatypes.model.Parameter;
46 import org.openecomp.sdc.tosca.datatypes.extend.ToscaAnnotationType;
47 import org.openecomp.sdc.tosca.services.ToscaConstants;
48 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
49 import org.openecomp.sdc.translator.services.heattotosca.FunctionTranslationFactory;
50 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
51 import org.openecomp.sdc.translator.services.heattotosca.impl.functiontranslation.FunctionTranslator;
52
53 public class TranslatorHeatToToscaParameterConverter {
54
55
56   private static Map<String, String> parameterTypeMapping;
57   private static Map<String, String> parameterEntrySchemaTypeMapping;
58   private static final String RANGE = "range";
59   private static final String LENGTH = "length";
60   private static final String MIN = "min";
61   private static final String MAX = "max";
62   private static final String ALLOWED_VALUES = "allowed_values";
63   private static final String ALLOWED_PATTERN = "allowed_pattern";
64
65
66   static {
67     parameterEntrySchemaTypeMapping = new HashMap<>();
68     parameterEntrySchemaTypeMapping.put("list", "string");
69   }
70
71   static {
72     parameterTypeMapping = new HashMap<>();
73     parameterTypeMapping.put("string", "string");
74     parameterTypeMapping.put("number", "float");
75     parameterTypeMapping.put("comma_delimited_list", "list");
76     parameterTypeMapping.put("json", "json");
77     parameterTypeMapping.put("boolean", "boolean");
78   }
79
80   /**
81    * Parameter converter map.
82    *
83    * @param parameters                the parameters
84    * @param heatOrchestrationTemplate the heat orchestration template
85    * @param heatFileName              the heat file name
86    * @param context                   the context
87    * @return the map
88    */
89   public static Map<String, ParameterDefinition> parameterConverter(ServiceTemplate serviceTemplate,
90                                                                     Map<String, Parameter> parameters,
91                                                                     HeatOrchestrationTemplate heatOrchestrationTemplate,
92                                                                     String heatFileName, String parentHeatFileName,
93                                                                     TranslationContext context,
94                                                                     Map<String, Object> heatEnvParameters) {
95     Map<String, ParameterDefinition> parameterDefinitionMap = new HashMap<>();
96     for (Map.Entry<String, Parameter> entry : parameters.entrySet()) {
97       String heatParamName = entry.getKey();
98       parameterDefinitionMap.put(heatParamName,
99           getToscaParameter(serviceTemplate,heatParamName, entry.getValue(), heatOrchestrationTemplate, heatFileName,
100               parentHeatFileName, context, heatEnvParameters));
101     }
102     return parameterDefinitionMap;
103   }
104
105   /**
106    * Parameter output converter map.
107    *
108    * @param parameters                the parameters
109    * @param heatOrchestrationTemplate the heat orchestration template
110    * @param heatFileName              the heat file name
111    * @param context                   the context
112    * @return the map
113    */
114   public static Map<String, ParameterDefinition> parameterOutputConverter(ServiceTemplate serviceTemplate,
115                                                                           Map<String, Output> parameters,
116                                                                           HeatOrchestrationTemplate heatOrchestrationTemplate,
117       String heatFileName, TranslationContext context) {
118     Map<String, ParameterDefinition> parameterDefinitionMap = new HashMap<>();
119     for (Map.Entry<String, Output> entry : parameters.entrySet()) {
120       parameterDefinitionMap.put(entry.getKey(),
121           getToscaOutputParameter(serviceTemplate,entry.getKey(),entry.getValue(),
122               heatOrchestrationTemplate,
123               heatFileName,
124               context));
125     }
126     return parameterDefinitionMap;
127   }
128
129   /**
130    * Gets tosca parameter.
131    *
132    * @param heatParameter             the heat parameter
133    * @param heatOrchestrationTemplate the heat orchestration template
134    * @param heatFileName              the heat file name
135    * @param context                   the context
136    * @return the tosca parameter
137    */
138   private static ParameterDefinitionExt getToscaParameter(ServiceTemplate serviceTemplate,
139                                                           String heatParameterName,
140                                                           Parameter heatParameter,
141                                                           HeatOrchestrationTemplate heatOrchestrationTemplate,
142                                                           String heatFileName,
143                                                           String parentHeatFileName,
144                                                           TranslationContext context,
145                                                           Map<String, Object> heatEnvParameters) {
146
147     ParameterDefinitionExt toscaParameter = new ParameterDefinitionExt();
148     toscaParameter.setType(getToscaParameterType(heatParameter.getType(), heatEnvParameters));
149     toscaParameter.setEntry_schema(getToscaParameterEntrySchema(toscaParameter.getType()));
150     toscaParameter.setLabel(heatParameter.getLabel());
151     toscaParameter.setDescription(heatParameter.getDescription());
152     toscaParameter.set_default(
153         getToscaParameterDefaultValue(serviceTemplate, heatParameterName, heatParameter.get_default(),
154             toscaParameter.getType(), heatFileName, heatOrchestrationTemplate, context));
155     toscaParameter.setHidden(heatParameter.isHidden());
156     toscaParameter.setImmutable(heatParameter.isImmutable());
157     toscaParameter.setConstraints(getToscaConstrains(heatParameter.getConstraints()));
158     Optional<Map<String, AnnotationDefinition>>  annotations = getToscaAnnotations(context, heatFileName, parentHeatFileName, heatParameterName);
159     annotations.ifPresent(ant->toscaParameter.setAnnotations(annotations.get()));
160
161
162     return toscaParameter;
163   }
164
165   private static Optional<Map<String, AnnotationDefinition> > getToscaAnnotations (TranslationContext context, String heatFileName, String parentHeatFileName, String heatParameterName){
166
167     if(parentHeatFileName != null){
168       heatFileName = parentHeatFileName;
169     }
170
171     if(!isAnnotationRequired(context, heatFileName)){
172       return Optional.empty();
173     }
174
175     AnnotationDefinition annotationDefinition = new AnnotationDefinition();
176     annotationDefinition.setType(ToscaAnnotationType.SOURCE);
177     annotationDefinition.setProperties(new HashMap<>());
178     List<String> vfModuleList = new ArrayList<>();
179     vfModuleList.add( FileUtils.getFileWithoutExtention(heatFileName));
180     annotationDefinition.getProperties().put(ToscaConstants.VF_MODULE_LABEL_PROPERTY_NAME, vfModuleList);
181     annotationDefinition.getProperties().put(ToscaConstants.SOURCE_TYPE_PROPERTY_NAME, ToscaConstants.HEAT_SOURCE_TYPE);
182     annotationDefinition.getProperties().put(ToscaConstants.PARAM_NAME_PROPERTY_NAME, heatParameterName);
183     Map<String, AnnotationDefinition> annotationMap = new HashMap<>();
184     annotationMap.put(ToscaConstants.SOURCE_ANNOTATION_ID, annotationDefinition);
185     return Optional.of(annotationMap);
186
187   }
188
189   private static boolean isAnnotationRequired(TranslationContext context, String heatFileName){
190     return !isNestedServiceTemplate(context, heatFileName);
191   }
192
193   private static boolean isNestedServiceTemplate(TranslationContext context, String heatFileName) {
194     return HeatToToscaUtil.isHeatFileNested(context, heatFileName);
195   }
196
197
198   /**
199    * Gets tosca output parameter.
200    *
201    * @param heatOutputParameter       the heat output parameter
202    * @param heatOrchestrationTemplate the heat orchestration template
203    * @param heatFileName              the heat file name
204    * @param context                   the context
205    * @return the tosca output parameter
206    */
207   private static ParameterDefinitionExt getToscaOutputParameter(ServiceTemplate serviceTemplate,
208                                                                String parameterName,
209                                                                Output heatOutputParameter,
210                                                                HeatOrchestrationTemplate
211                                                                    heatOrchestrationTemplate,
212                                                                String heatFileName,
213                                                                TranslationContext context) {
214
215     ParameterDefinitionExt toscaParameter = new ParameterDefinitionExt();
216     toscaParameter.setDescription(heatOutputParameter.getDescription());
217     toscaParameter.setValue(
218         getToscaParameterDefaultValue(serviceTemplate,parameterName,heatOutputParameter.getValue(),
219             toscaParameter.getType(),
220             heatFileName, heatOrchestrationTemplate, context));
221     return toscaParameter;
222   }
223
224   /**
225    * Gets tosca parameter default value.
226    *
227    * @param obj                       the a default
228    * @param type                      the type
229    * @param heatFileName              the heat file name
230    * @param heatOrchestrationTemplate the heat orchestration template
231    * @param context                   the context
232    * @return the tosca parameter default value
233    */
234   public static Object getToscaParameterDefaultValue(ServiceTemplate serviceTemplate,
235                                                      String parameterName,
236                                                      Object obj, String type,
237                                                      String heatFileName,
238                                                      HeatOrchestrationTemplate
239                                                          heatOrchestrationTemplate,
240                                                      TranslationContext context) {
241
242     if (obj == null) {
243       return null;
244     }
245     Object toscaDefaultValue = obj;
246     if ("list".equals(type)) {
247       if (obj instanceof String) {
248         return Arrays.asList(((String) obj).split(","));
249       } else {
250         return toscaDefaultValue;
251       }
252     }
253
254     return getToscaParameterValue(serviceTemplate,parameterName,toscaDefaultValue, heatFileName,
255         heatOrchestrationTemplate,
256         context);
257   }
258
259   private static Object getToscaParameterValue(ServiceTemplate serviceTemplate,
260                                                String parameterName,
261                                                Object paramValue, String heatFileName,
262                                                HeatOrchestrationTemplate heatOrchestrationTemplate,
263                                                TranslationContext context) {
264     if (paramValue instanceof Map) {
265       if(MapUtils.isEmpty((Map) paramValue)){
266         return new HashMap<>();
267       }
268       Map.Entry<String, Object> functionMapEntry =
269           (Map.Entry<String, Object>) ((Map) paramValue).entrySet().iterator().next();
270       if (FunctionTranslationFactory.getInstance(functionMapEntry.getKey()).isPresent()) {
271
272         FunctionTranslator functionTranslator = new FunctionTranslator(getFunctionTranslateTo(serviceTemplate, null,
273                 heatFileName, heatOrchestrationTemplate, context), parameterName,  functionMapEntry.getValue(), null);
274         return FunctionTranslationFactory.getInstance(functionMapEntry.getKey()).get()
275             .translateFunction(functionTranslator);
276       }
277     }
278
279     return paramValue;
280   }
281
282   private static List<Constraint> getToscaConstrains(List<Map<String, Object>> constraints) {
283     if (constraints == null) {
284       return null;
285     }
286
287     List<Constraint> constraintList = new ArrayList<>();
288
289     for (Map<String, Object> constraint : constraints) {
290       constraintList.addAll(getToscaParameterConstraint(constraint));
291     }
292
293     return constraintList;
294   }
295
296   private static List<Constraint> getToscaParameterConstraint(Map<String, Object> constraint) {
297     List<Constraint> convertedConstraintList = new ArrayList<>();
298     Constraint convertedConstraint;
299
300     if (constraint.containsKey(RANGE)) {
301       convertedConstraint = new Constraint();
302       convertedConstraintList.add(convertedConstraint);
303       Integer min = (Integer) ((Map) constraint.get(RANGE)).get(MIN);
304       Integer max = (Integer) ((Map) constraint.get(RANGE)).get(MAX);
305       convertedConstraint.setIn_range(new Integer[]{min, max});
306
307     } else if (constraint.containsKey(LENGTH)) {
308       Integer min = (Integer) ((Map) constraint.get(LENGTH)).get(MIN);
309       Integer max = (Integer) ((Map) constraint.get(LENGTH)).get(MAX);
310       if (max != null) {
311         convertedConstraint = new Constraint();
312         convertedConstraintList.add(convertedConstraint);
313         convertedConstraint.setMax_length(max);
314       }
315       if (min != null) {
316         convertedConstraint = new Constraint();
317         convertedConstraintList.add(convertedConstraint);
318         convertedConstraint.setMin_length(min);
319       }
320     } else if (constraint.containsKey(ALLOWED_VALUES)) {
321       convertedConstraint = new Constraint();
322       convertedConstraintList.add(convertedConstraint);
323       convertedConstraint.setValid_values((List) constraint.get(ALLOWED_VALUES));
324     } else if (constraint.containsKey(ALLOWED_PATTERN)) {
325       convertedConstraint = new Constraint();
326       convertedConstraintList.add(convertedConstraint);
327       convertedConstraint.setPattern(constraint.get(ALLOWED_PATTERN));
328     }
329
330     return convertedConstraintList;
331   }
332
333   private static EntrySchema getToscaParameterEntrySchema(String type) {
334
335     if (!parameterEntrySchemaTypeMapping.containsKey(type)) {
336       return null;
337     }
338
339     EntrySchema entrySchema = new EntrySchema();
340     entrySchema.setType(parameterEntrySchemaTypeMapping.get(type));
341     return entrySchema;
342   }
343
344   protected static String getToscaParameterType(final String heatParameterType,
345                                                 final Map<String, Object> heatEnvParameters) {
346     if (heatEnvParameters != null && DefinedHeatParameterTypes.NUMBER.getType().equals(heatParameterType)) {
347       if (getScalarUnitType(heatEnvParameters, ToscaScalarUnitSize.class) != null) {
348         return ToscaScalarUnitTypes.SCALAR_UNIT_SIZE.getType();
349       } else if (getScalarUnitType(heatEnvParameters, ToscaScalarUnitTime.class) != null) {
350         return ToscaScalarUnitTypes.SCALAR_UNIT_TIME.getType();
351       } else if (getScalarUnitType(heatEnvParameters, ToscaScalarUnitFrequency.class) != null) {
352         return ToscaScalarUnitTypes.SCALAR_UNIT_FREQUENCY.getType();
353       }
354     }
355
356     return parameterTypeMapping.get(heatParameterType);
357   }
358
359   private static <E extends Enum<E>> String getScalarUnitType(final Map<String, Object> heatEnvParameters,
360                                                               final Class<E> enumClass) {
361     final ScalarUnitValidator scalarUnitValidator = ScalarUnitValidator.getInstance();
362     if (Arrays.stream(enumClass.getEnumConstants()).anyMatch(unitType ->
363             heatEnvParameters.values().stream().filter(Objects::nonNull)
364                 .anyMatch(parameterValue -> scalarUnitValidator.isScalarUnit(parameterValue.toString()) &&
365                     Arrays.stream(StringUtils.split(parameterValue.toString()))
366                         .anyMatch(strParamValue -> strParamValue.equalsIgnoreCase(unitType.name()))))) {
367       return enumClass.getTypeName();
368     }
369     return null;
370   }
371
372 }