Release version 1.13.7
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / datamodel / utils / PropertyValueConstraintValidationUtil.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 package org.openecomp.sdc.be.datamodel.utils;
17
18 import com.fasterxml.jackson.core.JsonProcessingException;
19 import com.fasterxml.jackson.core.type.TypeReference;
20 import com.fasterxml.jackson.databind.ObjectMapper;
21 import fj.data.Either;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Objects;
29 import org.apache.commons.collections4.CollectionUtils;
30 import org.apache.commons.collections4.ListUtils;
31 import org.apache.commons.collections4.MapUtils;
32 import org.apache.commons.lang3.ArrayUtils;
33 import org.apache.commons.lang3.StringUtils;
34 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
35 import org.openecomp.sdc.be.dao.api.ActionStatus;
36 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
37 import org.openecomp.sdc.be.datatypes.elements.SubPropertyToscaFunction;
38 import org.openecomp.sdc.be.model.ComponentInstanceInput;
39 import org.openecomp.sdc.be.model.DataTypeDefinition;
40 import org.openecomp.sdc.be.model.InputDefinition;
41 import org.openecomp.sdc.be.model.PropertyConstraint;
42 import org.openecomp.sdc.be.model.PropertyDefinition;
43 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
44 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
45 import org.openecomp.sdc.be.model.tosca.ToscaType;
46 import org.openecomp.sdc.be.model.tosca.constraints.ConstraintUtil;
47 import org.openecomp.sdc.be.model.tosca.constraints.LengthConstraint;
48 import org.openecomp.sdc.be.model.tosca.constraints.MaxLengthConstraint;
49 import org.openecomp.sdc.be.model.tosca.constraints.MinLengthConstraint;
50 import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException;
51 import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException;
52 import org.openecomp.sdc.exception.ResponseFormat;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 public class PropertyValueConstraintValidationUtil {
57
58     private static final String UNDERSCORE = "_";
59     private static final String VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY = "%nValue provided in invalid format for %s property";
60     private static final Logger logger = LoggerFactory.getLogger(PropertyValueConstraintValidationUtil.class);
61     private static final String IGNORE_PROPERTY_VALUE_START_WITH_INPUT = "{\"get_input\":";
62     private static final String IGNORE_PROPERTY_VALUE_START_WITH_PROPERTY = "{\"get_property\":";
63     private static final String IGNORE_PROPERTY_VALUE_START_WITH_ATTRIBUTE = "{\"get_attribute\":";
64     private static final String IGNORE_PROPERTY_VALUE_INPUT = "{get_input=";
65     private static final String IGNORE_PROPERTY_VALUE_PROPERTY = "{get_property=";
66     private static final String IGNORE_PROPERTY_VALUE_ATTRIBUTE = "{get_attribute=";
67     private Map<String, DataTypeDefinition> dataTypeDefinitionCache;
68     private final ObjectMapper objectMapper = new ObjectMapper();
69     private final List<String> errorMessages = new ArrayList<>();
70     private StringBuilder completePropertyName;
71     private String completeInputName;
72
73     public Either<Boolean, ResponseFormat> validatePropertyConstraints(final Collection<? extends PropertyDefinition> propertyDefinitionList,
74                                                                        final ApplicationDataTypeCache applicationDataTypeCache,
75                                                                        final String model) {
76
77         dataTypeDefinitionCache = applicationDataTypeCache.getAll(model).left().value();
78         CollectionUtils.emptyIfNull(propertyDefinitionList).stream()
79             .filter(this::isNonToscaFunctionValuePresent)
80             .forEach(this::evaluatePropertyTypeForConstraintValidation);
81         if (CollectionUtils.isNotEmpty(errorMessages)) {
82             final String errorMsgAsString = String.join(",", errorMessages);
83             logger.debug("Properties with Invalid Data: {}", errorMsgAsString);
84             return Either.right(getResponseFormatManager().getResponseFormat(ActionStatus.INVALID_PROPERTY_VALUES, errorMsgAsString));
85         }
86         return Either.left(Boolean.TRUE);
87     }
88
89     private boolean isNonToscaFunctionValuePresent(PropertyDefinition propertyDefinition) {
90         if (isValueAToscaFunction(propertyDefinition)) {
91             return false;
92         }
93         if (propertyDefinition instanceof ComponentInstanceInput) {
94             return StringUtils.isNotEmpty(propertyDefinition.getValue());
95         }
96         if (propertyDefinition instanceof InputDefinition) {
97             return StringUtils.isNotEmpty(propertyDefinition.getDefaultValue());
98         }
99         return StringUtils.isNotEmpty(propertyDefinition.getValue() != null ? propertyDefinition.getValue() : propertyDefinition.getDefaultValue());
100     }
101
102     private void evaluatePropertyTypeForConstraintValidation(PropertyDefinition propertyDefinition) {
103         if (propertyDefinition == null || propertyDefinition.getType() == null || !dataTypeDefinitionCache.containsKey(
104             propertyDefinition.getType())) {
105             errorMessages.add("\nUnsupported datatype found for property " + getCompletePropertyName(propertyDefinition));
106             return;
107         }
108         completeInputName = "";
109         completePropertyName = new StringBuilder();
110         if (propertyDefinition instanceof ComponentInstanceInput) {
111             setCompletePropertyName(propertyDefinition);
112             evaluateComplexTypeProperties(propertyDefinition);
113             return;
114         }
115         if (propertyDefinition instanceof InputDefinition) {
116             completeInputName = propertyDefinition.getName();
117             propertyDefinition = getPropertyDefinitionObjectFromInputs(propertyDefinition);
118         }
119         if (propertyDefinition != null) {
120             List<PropertyConstraint> propertyConstraints =
121                 dataTypeDefinitionCache.get(propertyDefinition.getType()).safeGetConstraints();
122             if (ToscaType.isPrimitiveType(propertyDefinition.getType())) {
123                 propertyDefinition.setConstraints(org.openecomp.sdc.be.dao.utils.CollectionUtils.merge(propertyDefinition.safeGetConstraints(),
124                     propertyConstraints.isEmpty() ? new ArrayList<>() : propertyConstraints));
125                 evaluateConstraintsOnProperty(propertyDefinition);
126             } else if (ToscaType.isCollectionType(propertyDefinition.getType())) {
127                 propertyDefinition.setConstraints(org.openecomp.sdc.be.dao.utils.CollectionUtils.merge(propertyDefinition.safeGetConstraints(),
128                     propertyConstraints.isEmpty() ? new ArrayList<>() : propertyConstraints));
129                 evaluateConstraintsOnProperty(propertyDefinition);
130                 evaluateCollectionTypeProperties(propertyDefinition);
131             } else {
132                 setCompletePropertyName(propertyDefinition);
133                 evaluateComplexTypeProperties(propertyDefinition);
134             }
135         }
136     }
137
138     private void setCompletePropertyName(PropertyDefinition propertyDefinition) {
139         if (StringUtils.isNotBlank(propertyDefinition.getUniqueId())) {
140             completePropertyName.append(propertyDefinition.getUniqueId().substring(propertyDefinition.getUniqueId().lastIndexOf('.') + 1));
141         }
142     }
143
144     private void evaluateConstraintsOnProperty(PropertyDefinition propertyDefinition) {
145         ToscaType toscaType = ToscaType.isValidType(propertyDefinition.getType());
146         String value = propertyDefinition.getValue() != null ? propertyDefinition.getValue() : propertyDefinition.getDefaultValue();
147         if (!isValueAToscaFunction(propertyDefinition) && CollectionUtils.isNotEmpty(propertyDefinition.getConstraints())) {
148             for (PropertyConstraint propertyConstraint : propertyDefinition.getConstraints()) {
149                 try {
150                     propertyConstraint.initialize(toscaType, propertyDefinition.getSchema());
151                     propertyConstraint.validate(propertyDefinition);
152                 } catch (ConstraintValueDoNotMatchPropertyTypeException | ConstraintViolationException exception) {
153                     errorMessages.add(propertyConstraint.getErrorMessage(toscaType, exception, getCompletePropertyName(propertyDefinition)));
154                 } catch (IllegalArgumentException ie) {
155                     errorMessages.add(ie.getMessage());
156                 }
157             }
158         } else if (!isValueAToscaFunction(propertyDefinition) && ToscaType.isPrimitiveType(propertyDefinition.getType())
159                 && !propertyDefinition.isToscaFunction() && !toscaType.isValidValue(value)) {
160             errorMessages.add(String.format("Unsupported value provided for %s property supported value type is %s.",
161                 getCompletePropertyName(propertyDefinition), toscaType.getType()));
162         } else if (propertyDefinition.isRequired() && StringUtils.isEmpty(value)) {
163             errorMessages.add(String.format("Property %s is required. Please enter a value.", getCompletePropertyName(propertyDefinition)));
164         }
165     }
166
167     private boolean isValueAToscaFunction(PropertyDefinition propertyDefinition) {
168         return (propertyDefinition.getToscaFunction() != null)  || (propertyDefinition.getValue() != null
169             && ((propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_START_WITH_INPUT) || propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_START_WITH_PROPERTY)
170             || propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_START_WITH_ATTRIBUTE) || propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_ATTRIBUTE)
171             || propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_PROPERTY) || propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_INPUT))));
172     }
173
174     private void checkAndEvaluatePrimitiveProperty(PropertyDefinition propertyDefinition, DataTypeDefinition dataTypeDefinition) {
175         if (ToscaType.isPrimitiveType(dataTypeDefinition.getName()) && CollectionUtils.isNotEmpty(dataTypeDefinition.getConstraints())) {
176             PropertyDefinition definition = new PropertyDefinition();
177             definition.setValue(propertyDefinition.getValue());
178             definition.setType(dataTypeDefinition.getName());
179             definition.setConstraints(dataTypeDefinition.getConstraints());
180             evaluateConstraintsOnProperty(propertyDefinition);
181         }
182     }
183
184     private void evaluateComplexTypeProperties(PropertyDefinition propertyDefinition) {
185         List<PropertyDefinition> propertyDefinitions = dataTypeDefinitionCache.get(propertyDefinition.getType()).getProperties();
186         try {
187             Map<String, Object> valueMap = MapUtils
188                 .emptyIfNull(ConstraintUtil.parseToCollection(null != propertyDefinition.getValue() ?
189                     propertyDefinition.getValue() : propertyDefinition.getDefaultValue(), new TypeReference<>() {
190                 }));
191             if (CollectionUtils.isEmpty(propertyDefinitions)) {
192                 checkAndEvaluatePrimitiveProperty(propertyDefinition, dataTypeDefinitionCache.get(propertyDefinition.getType()));
193             } else {
194                 ListUtils.emptyIfNull(propertyDefinitions).forEach(prop -> evaluateRegularComplexType(propertyDefinition, prop, valueMap));
195             }
196         } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
197             logger.debug(e.getMessage(), e);
198             errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, getCompletePropertyName(propertyDefinition)));
199         }
200     }
201
202     private void evaluateRegularComplexType(PropertyDefinition propertyDefinition, PropertyDefinition prop, Map<String, Object> valueMap) {
203         try {
204             PropertyDefinition newPropertyWithValue;
205             if (valueMap.containsKey(prop.getName())) {
206                 if (propertyDefinition.getSubPropertyToscaFunctions() != null) {
207                     for (SubPropertyToscaFunction subPropertyToscaFunction : propertyDefinition.getSubPropertyToscaFunctions()) {
208                         final List<String> path = subPropertyToscaFunction.getSubPropertyPath();
209                         if (path.size() == 1 && path.get(0).equals(prop.getName())) {
210                             return;
211                         }
212                         if (path.size() > 1) {
213                             if (path.get(0).equals(propertyDefinition.getToscaSubPath()) && path.get(1).equals(prop.getName())) {
214                                 return;
215                             }
216                         }
217                     }
218                 }
219                 if (ToscaType.isPrimitiveType(prop.getType())) {
220                     String value = valueMap.get(prop.getName()) == null ? null : String.valueOf(valueMap.get(prop.getName()));
221                     newPropertyWithValue = copyPropertyWithNewValue(prop, value, prop.getName());
222                     if (isPropertyToEvaluate(newPropertyWithValue)) {
223                         evaluateConstraintsOnProperty(newPropertyWithValue);
224                     }
225                 } else if (ToscaType.isCollectionType(prop.getType())) {
226                     newPropertyWithValue =
227                         copyPropertyWithNewValue(prop,
228                             objectMapper.writeValueAsString(valueMap.get(prop.getName())), prop.getName());
229                     if (isPropertyToEvaluate(newPropertyWithValue)) {
230                         evaluateCollectionTypeProperties(newPropertyWithValue);
231                     }
232                 } else {
233                     newPropertyWithValue =
234                         copyPropertyWithNewValue(prop,
235                             objectMapper.writeValueAsString(valueMap.get(prop.getName())), prop.getName());
236                     if (isPropertyToEvaluate(newPropertyWithValue)) {
237                         evaluateComplexTypeProperties(newPropertyWithValue);
238                     }
239                 }
240             }
241         } catch (IOException | ConstraintValueDoNotMatchPropertyTypeException e) {
242             logger.error(e.getMessage(), e);
243             errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, getCompletePropertyName(propertyDefinition)));
244         }
245     }
246
247     private boolean isPropertyToEvaluate(PropertyDefinition propertyDefinition) throws ConstraintValueDoNotMatchPropertyTypeException {
248         if (Boolean.FALSE.equals(propertyDefinition.isRequired())) {
249             if (!ToscaType.isCollectionType(propertyDefinition.getType())) {
250                 return StringUtils.isNotEmpty(propertyDefinition.getValue()) &&
251                     !"null".equals(propertyDefinition.getValue());
252             } else if (ToscaType.LIST == ToscaType.isValidType(propertyDefinition.getType())) {
253                 Collection<?> list = ConstraintUtil.parseToCollection(null != propertyDefinition.getValue() ?
254                     propertyDefinition.getValue() : propertyDefinition.getDefaultValue(), new TypeReference<List<?>>() {
255                 });
256                 return CollectionUtils.isNotEmpty(list);
257             } else {
258                 Map<String, Object> valueMap = MapUtils
259                     .emptyIfNull(ConstraintUtil.parseToCollection(null != propertyDefinition.getValue() ?
260                         propertyDefinition.getValue() : propertyDefinition.getDefaultValue(), new TypeReference<>() {
261                     }));
262                 return MapUtils.isNotEmpty(valueMap);
263             }
264         } else {
265             return true;
266         }
267     }
268
269     private void evaluateCollectionTypeProperties(PropertyDefinition propertyDefinition) {
270         ToscaType toscaPropertyType = ToscaType.isValidType(propertyDefinition.getType());
271         try {
272             if (isPropertyToEvaluate(propertyDefinition)) {
273                 evaluateCollectionConstraints(propertyDefinition, toscaPropertyType);
274             }
275         } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
276             logger.error(e.getMessage(), e);
277             errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, getCompletePropertyName(propertyDefinition)));
278         }
279         if (ToscaType.LIST == toscaPropertyType) {
280             evaluateListType(propertyDefinition);
281         } else if (ToscaType.MAP == toscaPropertyType) {
282             evaluateMapType(propertyDefinition);
283         }
284     }
285
286     private void evaluateCollectionConstraints(PropertyDefinition propertyDefinition, ToscaType toscaPropertyType) {
287         List<PropertyConstraint> constraintsList = propertyDefinition.getConstraints();
288
289         if (CollectionUtils.isEmpty(constraintsList)) {
290             return;
291         }
292         ToscaType toscaPropertyType1;
293         if (null == toscaPropertyType) {
294             toscaPropertyType1 = ToscaType.isValidType(propertyDefinition.getType());
295         } else {
296             toscaPropertyType1 = toscaPropertyType;
297         }
298         constraintsList.stream()
299             .filter(this::isACollectionConstraint)
300             .forEach(propertyConstraint -> {
301                 try {
302                     if (ToscaType.LIST == toscaPropertyType1) {
303                         Collection<Object> list = ConstraintUtil.parseToCollection(null != propertyDefinition.getValue() ? propertyDefinition.getValue() : propertyDefinition.getDefaultValue(), new TypeReference<>() {
304                         });
305                         propertyConstraint.validate(list);
306                     } else if (ToscaType.MAP == toscaPropertyType1) {
307                         final Map<String, Object> map = ConstraintUtil.parseToCollection(null != propertyDefinition.getValue() ? propertyDefinition.getValue() : propertyDefinition.getDefaultValue(), new TypeReference<>() {
308                         });
309                         propertyConstraint.validate(map);
310                     }
311                 } catch (ConstraintValueDoNotMatchPropertyTypeException | ConstraintViolationException exception) {
312                     errorMessages.add("\n" + propertyConstraint.getErrorMessage(toscaPropertyType1, exception,
313                         getCompletePropertyName(propertyDefinition)));
314                 }
315             });
316     }
317
318     private boolean isACollectionConstraint(PropertyConstraint constraint) {
319         if (constraint instanceof MaxLengthConstraint) {
320             return true;
321         }
322         if (constraint instanceof MinLengthConstraint) {
323             return true;
324         }
325         return constraint instanceof LengthConstraint;
326     }
327
328     private void evaluateListType(PropertyDefinition propertyDefinition) {
329         try {
330             if (propertyDefinition.getSchemaType() == null) {
331                 propertyDefinition.setSchema(createStringSchema());
332             }
333             Collection<?> list = ConstraintUtil.parseToCollection(null != propertyDefinition.getValue() ?
334                 propertyDefinition.getValue() : propertyDefinition.getDefaultValue(), new TypeReference<List<?>>() {});
335             final Map<String, Object> map = new HashMap<>();
336             int index = 0;
337             for (Object obj : list) {
338                 map.put(String.valueOf(index),obj);
339                 index++;
340             }
341             evaluateCollectionType(propertyDefinition, map);
342         } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
343             logger.debug(e.getMessage(), e);
344             errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, getCompletePropertyName(propertyDefinition)));
345         }
346     }
347
348     private SchemaDefinition createStringSchema() {
349         final SchemaDefinition schemaDefinition = new SchemaDefinition();
350         final PropertyDefinition schemaStringProperty = new PropertyDefinition();
351         schemaStringProperty.setType(ToscaType.STRING.getType());
352         schemaDefinition.setProperty(schemaStringProperty);
353         return schemaDefinition;
354     }
355
356     private void evaluateMapType(final PropertyDefinition propertyDefinition) {
357         try {
358             if (propertyDefinition.getSchemaType() == null) {
359                 propertyDefinition.setSchema(createStringSchema());
360             }
361             final Map<String, Object> map = ConstraintUtil.parseToCollection(null != propertyDefinition.getValue() ?
362                 propertyDefinition.getValue() : propertyDefinition.getDefaultValue(), new TypeReference<>() {
363             });
364             evaluateCollectionType(propertyDefinition, map);
365         } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
366             logger.debug(e.getMessage(), e);
367             errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, getCompletePropertyName(propertyDefinition)));
368         }
369     }
370
371     private void evaluateCollectionPrimitiveSchemaType(final PropertyDefinition propertyDefinition,
372                                                        final String schemaType) throws JsonProcessingException {
373         if (propertyDefinition.getSchema() != null && propertyDefinition.getSchema().getProperty() instanceof PropertyDefinition) {
374             propertyDefinition.setConstraints(((PropertyDefinition) propertyDefinition.getSchema().getProperty()).getConstraints());
375             propertyDefinition.setValue(objectMapper.readValue(propertyDefinition.getValue(), String.class));
376             propertyDefinition.setType(schemaType);
377             evaluateConstraintsOnProperty(propertyDefinition);
378         }
379     }
380
381     private void evaluateCollectionType(final PropertyDefinition propertyDefinition, final Map<String, Object> valueMap) {
382         final String schemaType = propertyDefinition.getSchemaType();
383         for (String mapKey : valueMap.keySet()) {
384             final Object value = valueMap.get(mapKey);
385             try {
386                 final PropertyDefinition propertyCopyWithNewValue = copyPropertyWithNewValue(propertyDefinition,
387                     objectMapper.writeValueAsString(value),mapKey);
388                 propertyCopyWithNewValue.setToscaSubPath(mapKey);
389                 if (!isValueAToscaFunction(propertyCopyWithNewValue)) {
390                     if (ToscaType.isPrimitiveType(schemaType)) {
391                         evaluateCollectionPrimitiveSchemaType(propertyCopyWithNewValue, schemaType);
392                     } else if (ToscaType.isCollectionType(schemaType)) {
393                         propertyCopyWithNewValue.setType(schemaType);
394                         propertyCopyWithNewValue.setSchemaType(propertyDefinition.getSchemaProperty().getSchemaType());
395                         evaluateCollectionTypeProperties(propertyCopyWithNewValue);
396                     } else {
397                         propertyCopyWithNewValue.setType(schemaType);
398                         completePropertyName.append(UNDERSCORE);
399                         completePropertyName.append(propertyCopyWithNewValue.getName());
400                         evaluateComplexTypeProperties(propertyCopyWithNewValue);
401                     }
402                 }
403             } catch (final Exception e) {
404                 logger.debug(e.getMessage(), e);
405                 errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, getCompletePropertyName(propertyDefinition)));
406             }
407         }
408     }
409
410     private String getCompletePropertyName(final PropertyDefinition propertyDefinition) {
411         if (StringUtils.isNotBlank(completeInputName)) {
412             return completeInputName;
413         }
414
415         final String propertyName = propertyDefinition == null ? "" : propertyDefinition.getName();
416         if (StringUtils.isNotBlank(completePropertyName)) {
417             return completePropertyName + UNDERSCORE + propertyName;
418         }
419
420         return propertyName;
421     }
422
423     private PropertyDefinition copyPropertyWithNewValue(final PropertyDefinition propertyToCopy, final String value, final String key) {
424         final var propertyDefinition = new PropertyDefinition(propertyToCopy);
425         if (key != null && propertyToCopy.getSubPropertyToscaFunctions() != null) {
426             propertyToCopy.getSubPropertyToscaFunctions().forEach(subPropertyToscaFunction -> {
427                 final List<String> subPropertyPath = subPropertyToscaFunction.getSubPropertyPath();
428                 if (subPropertyPath.get((subPropertyPath.size() - 1)).equals(key)) {
429                     propertyDefinition.setToscaFunction(subPropertyToscaFunction.getToscaFunction());
430                 }
431             });
432         }
433         propertyDefinition.setValue(value);
434         return propertyDefinition;
435     }
436
437     private PropertyDefinition getPropertyDefinitionObjectFromInputs(PropertyDefinition property) {
438         InputDefinition inputDefinition = (InputDefinition) property;
439         PropertyDefinition propertyDefinition = null;
440         if (CollectionUtils.isEmpty(inputDefinition.getProperties()) || ToscaType.isPrimitiveType(inputDefinition.getProperties().get(0).getType())) {
441             propertyDefinition = new PropertyDefinition();
442             propertyDefinition.setType(inputDefinition.getType());
443             propertyDefinition.setValue(inputDefinition.getDefaultValue());
444             propertyDefinition.setName(inputDefinition.getName());
445             propertyDefinition.setConstraints(inputDefinition.getConstraints());
446         } else if (Objects.nonNull(inputDefinition.getInputPath())) {
447             propertyDefinition = evaluateComplexTypeInputs(inputDefinition);
448             propertyDefinition.setConstraints(inputDefinition.getConstraints());
449         }
450         return propertyDefinition;
451     }
452
453     private PropertyDefinition evaluateComplexTypeInputs(InputDefinition inputDefinition) {
454         Map<String, Object> inputMap = new HashMap<>();
455         PropertyDefinition propertyDefinition = new PropertyDefinition();
456         String[] inputPathArr = inputDefinition.getInputPath().split("#");
457         if (inputPathArr.length > 1) {
458             inputPathArr = ArrayUtils.remove(inputPathArr, 0);
459         }
460         try {
461             Map<String, Object> presentMap = inputMap;
462             for (int i = 0; i < inputPathArr.length; i++) {
463                 if (i == inputPathArr.length - 1) {
464                     presentMap.computeIfAbsent(inputPathArr[i], k -> inputDefinition.getDefaultValue());
465                 } else {
466                     presentMap.computeIfAbsent(inputPathArr[i], k -> new HashMap<String, Object>());
467                     presentMap = (Map<String, Object>) presentMap.get(inputPathArr[i]);
468                 }
469             }
470             if (CollectionUtils.isNotEmpty(inputDefinition.getProperties())) {
471                 propertyDefinition.setType(inputDefinition.getProperties().get(0).getType());
472             }
473             propertyDefinition.setName(inputDefinition.getName());
474             propertyDefinition.setValue(objectMapper.writeValueAsString(inputMap));
475         } catch (IOException e) {
476             logger.error(e.getMessage(), e);
477             errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, inputDefinition.getName()));
478         }
479         return propertyDefinition;
480     }
481
482     protected ResponseFormatManager getResponseFormatManager() {
483         return ResponseFormatManager.getInstance();
484     }
485 }