import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
+import org.openecomp.sdc.be.datatypes.elements.SubPropertyToscaFunction;
import org.openecomp.sdc.be.model.ComponentInstanceInput;
import org.openecomp.sdc.be.model.DataTypeDefinition;
import org.openecomp.sdc.be.model.InputDefinition;
import org.openecomp.sdc.be.model.PropertyConstraint;
import org.openecomp.sdc.be.model.PropertyDefinition;
import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
+import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
import org.openecomp.sdc.be.model.tosca.ToscaType;
import org.openecomp.sdc.be.model.tosca.constraints.ConstraintUtil;
-import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
+import org.openecomp.sdc.be.model.tosca.constraints.LengthConstraint;
+import org.openecomp.sdc.be.model.tosca.constraints.MaxLengthConstraint;
+import org.openecomp.sdc.be.model.tosca.constraints.MinLengthConstraint;
import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException;
import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException;
import org.openecomp.sdc.exception.ResponseFormat;
private static final String UNDERSCORE = "_";
private static final String VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY = "%nValue provided in invalid format for %s property";
private static final Logger logger = LoggerFactory.getLogger(PropertyValueConstraintValidationUtil.class);
- private static final String IGNORE_PROPERTY_VALUE_START_WITH = "{\"get_input\":";
+ private static final String IGNORE_PROPERTY_VALUE_START_WITH_INPUT = "{\"get_input\":";
+ private static final String IGNORE_PROPERTY_VALUE_START_WITH_PROPERTY = "{\"get_property\":";
+ private static final String IGNORE_PROPERTY_VALUE_START_WITH_ATTRIBUTE = "{\"get_attribute\":";
+ private static final String IGNORE_PROPERTY_VALUE_INPUT = "{get_input=";
+ private static final String IGNORE_PROPERTY_VALUE_PROPERTY = "{get_property=";
+ private static final String IGNORE_PROPERTY_VALUE_ATTRIBUTE = "{get_attribute=";
private Map<String, DataTypeDefinition> dataTypeDefinitionCache;
private final ObjectMapper objectMapper = new ObjectMapper();
private final List<String> errorMessages = new ArrayList<>();
dataTypeDefinitionCache = applicationDataTypeCache.getAll(model).left().value();
CollectionUtils.emptyIfNull(propertyDefinitionList).stream()
- .filter(this::isValuePresent)
+ .filter(this::isNonToscaFunctionValuePresent)
.forEach(this::evaluatePropertyTypeForConstraintValidation);
if (CollectionUtils.isNotEmpty(errorMessages)) {
final String errorMsgAsString = String.join(",", errorMessages);
return Either.left(Boolean.TRUE);
}
- private boolean isValuePresent(PropertyDefinition propertyDefinition) {
+ private boolean isNonToscaFunctionValuePresent(PropertyDefinition propertyDefinition) {
+ if (isValueAToscaFunction(propertyDefinition)) {
+ return false;
+ }
if (propertyDefinition instanceof ComponentInstanceInput) {
return StringUtils.isNotEmpty(propertyDefinition.getValue());
}
if (propertyDefinition instanceof InputDefinition) {
return StringUtils.isNotEmpty(propertyDefinition.getDefaultValue());
}
- return StringUtils.isNotEmpty(propertyDefinition.getValue());
+ return StringUtils.isNotEmpty(propertyDefinition.getValue() != null ? propertyDefinition.getValue() : propertyDefinition.getDefaultValue());
}
private void evaluatePropertyTypeForConstraintValidation(PropertyDefinition propertyDefinition) {
- if (propertyDefinition == null || propertyDefinition.getType() == null || !dataTypeDefinitionCache.containsKey(propertyDefinition.getType())) {
+ if (propertyDefinition == null || propertyDefinition.getType() == null || !dataTypeDefinitionCache.containsKey(
+ propertyDefinition.getType())) {
errorMessages.add("\nUnsupported datatype found for property " + getCompletePropertyName(propertyDefinition));
return;
}
propertyDefinition = getPropertyDefinitionObjectFromInputs(propertyDefinition);
}
if (propertyDefinition != null) {
+ List<PropertyConstraint> propertyConstraints =
+ dataTypeDefinitionCache.get(propertyDefinition.getType()).safeGetConstraints();
if (ToscaType.isPrimitiveType(propertyDefinition.getType())) {
propertyDefinition.setConstraints(org.openecomp.sdc.be.dao.utils.CollectionUtils.merge(propertyDefinition.safeGetConstraints(),
- dataTypeDefinitionCache.get(propertyDefinition.getType()).safeGetConstraints()));
+ propertyConstraints.isEmpty() ? new ArrayList<>() : propertyConstraints));
evaluateConstraintsOnProperty(propertyDefinition);
} else if (ToscaType.isCollectionType(propertyDefinition.getType())) {
propertyDefinition.setConstraints(org.openecomp.sdc.be.dao.utils.CollectionUtils.merge(propertyDefinition.safeGetConstraints(),
- dataTypeDefinitionCache.get(propertyDefinition.getType()).safeGetConstraints()));
+ propertyConstraints.isEmpty() ? new ArrayList<>() : propertyConstraints));
evaluateConstraintsOnProperty(propertyDefinition);
evaluateCollectionTypeProperties(propertyDefinition);
} else {
private void evaluateConstraintsOnProperty(PropertyDefinition propertyDefinition) {
ToscaType toscaType = ToscaType.isValidType(propertyDefinition.getType());
- if (isPropertyNotMappedAsInput(propertyDefinition) && CollectionUtils.isNotEmpty(propertyDefinition.getConstraints())) {
+ if (!isValueAToscaFunction(propertyDefinition) && CollectionUtils.isNotEmpty(propertyDefinition.getConstraints())) {
for (PropertyConstraint propertyConstraint : propertyDefinition.getConstraints()) {
try {
- propertyConstraint.initialize(toscaType);
- propertyConstraint.validate(toscaType, propertyDefinition.getValue());
+ propertyConstraint.initialize(toscaType, propertyDefinition.getSchema());
+ propertyConstraint.validate(propertyDefinition);
} catch (ConstraintValueDoNotMatchPropertyTypeException | ConstraintViolationException exception) {
- errorMessages.add("\n" + propertyConstraint.getErrorMessage(toscaType, exception, getCompletePropertyName(propertyDefinition)));
+ errorMessages.add(propertyConstraint.getErrorMessage(toscaType, exception, getCompletePropertyName(propertyDefinition)));
+ } catch (IllegalArgumentException ie) {
+ errorMessages.add(ie.getMessage());
}
}
- } else if (isPropertyNotMappedAsInput(propertyDefinition) && ToscaType.isPrimitiveType(propertyDefinition.getType()) && !toscaType
- .isValidValue(propertyDefinition.getValue())) {
- errorMessages.add(String
- .format("\nUnsupported value provided for %s property supported value " + "type is %s.", getCompletePropertyName(propertyDefinition),
- toscaType.getType()));
+ } else if (!isValueAToscaFunction(propertyDefinition) && ToscaType.isPrimitiveType(propertyDefinition.getType())
+ && !propertyDefinition.isToscaFunction() && !toscaType.isValidValue(
+ propertyDefinition.getValue() != null ? propertyDefinition.getValue() : propertyDefinition.getDefaultValue())) {
+ errorMessages.add(String.format("Unsupported value provided for %s property supported value type is %s.",
+ getCompletePropertyName(propertyDefinition), toscaType.getType()));
}
}
- private boolean isPropertyNotMappedAsInput(PropertyDefinition propertyDefinition) {
- return !propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_START_WITH);
+ private boolean isValueAToscaFunction(PropertyDefinition propertyDefinition) {
+ return (propertyDefinition.getToscaFunction() != null) || (propertyDefinition.getValue() != null
+ && ((propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_START_WITH_INPUT) || propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_START_WITH_PROPERTY)
+ || propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_START_WITH_ATTRIBUTE) || propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_ATTRIBUTE)
+ || propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_PROPERTY) || propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_INPUT))));
}
private void checkAndEvaluatePrimitiveProperty(PropertyDefinition propertyDefinition, DataTypeDefinition dataTypeDefinition) {
private void evaluateRegularComplexType(PropertyDefinition propertyDefinition, PropertyDefinition prop, Map<String, Object> valueMap) {
try {
+ PropertyDefinition newPropertyWithValue;
if (valueMap.containsKey(prop.getName())) {
+ if (propertyDefinition.getSubPropertyToscaFunctions() != null) {
+ for (SubPropertyToscaFunction subPropertyToscaFunction : propertyDefinition.getSubPropertyToscaFunctions()) {
+ final List<String> path = subPropertyToscaFunction.getSubPropertyPath();
+ if (path.size() == 1 && path.get(0).equals(prop.getName())) {
+ return;
+ }
+ if (path.size() > 1) {
+ if (path.get(0).equals(propertyDefinition.getToscaSubPath()) && path.get(1).equals(prop.getName())) {
+ return;
+ }
+ }
+ }
+ }
if (ToscaType.isPrimitiveType(prop.getType())) {
- evaluateConstraintsOnProperty(copyPropertyWithNewValue(prop, String.valueOf(valueMap.get(prop.getName()))));
+ newPropertyWithValue = copyPropertyWithNewValue(prop, String.valueOf(valueMap.get(prop.getName())), prop.getName());
+ if (isPropertyToEvaluate(newPropertyWithValue)) {
+ evaluateConstraintsOnProperty(newPropertyWithValue);
+ }
} else if (ToscaType.isCollectionType(prop.getType())) {
- evaluateCollectionTypeProperties(copyPropertyWithNewValue(prop, objectMapper.writeValueAsString(valueMap.get(prop.getName()))));
+ newPropertyWithValue =
+ copyPropertyWithNewValue(prop,
+ objectMapper.writeValueAsString(valueMap.get(prop.getName())), prop.getName());
+ if (isPropertyToEvaluate(newPropertyWithValue)) {
+ evaluateCollectionTypeProperties(newPropertyWithValue);
+ }
} else {
- completePropertyName.append(UNDERSCORE);
- completePropertyName.append(prop.getName());
- evaluateComplexTypeProperties(copyPropertyWithNewValue(prop, objectMapper.writeValueAsString(valueMap.get(prop.getName()))));
+ newPropertyWithValue =
+ copyPropertyWithNewValue(prop,
+ objectMapper.writeValueAsString(valueMap.get(prop.getName())), prop.getName());
+ if (isPropertyToEvaluate(newPropertyWithValue)) {
+ evaluateComplexTypeProperties(newPropertyWithValue);
+ }
}
}
- } catch (IOException e) {
+ } catch (IOException | ConstraintValueDoNotMatchPropertyTypeException e) {
logger.error(e.getMessage(), e);
errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, getCompletePropertyName(propertyDefinition)));
}
}
+ private boolean isPropertyToEvaluate(PropertyDefinition propertyDefinition) throws ConstraintValueDoNotMatchPropertyTypeException {
+ if (Boolean.FALSE.equals(propertyDefinition.isRequired())) {
+ if (!ToscaType.isCollectionType(propertyDefinition.getType())) {
+ return StringUtils.isNotEmpty(propertyDefinition.getValue()) &&
+ !"null".equals(propertyDefinition.getValue());
+ } else if (ToscaType.LIST == ToscaType.isValidType(propertyDefinition.getType())) {
+ Collection<?> list = ConstraintUtil.parseToCollection(null != propertyDefinition.getValue() ?
+ propertyDefinition.getValue() : propertyDefinition.getDefaultValue(), new TypeReference<List<?>>() {
+ });
+ return CollectionUtils.isNotEmpty(list);
+ } else {
+ Map<String, Object> valueMap = MapUtils
+ .emptyIfNull(ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() {
+ }));
+ return MapUtils.isNotEmpty(valueMap);
+ }
+ } else {
+ return true;
+ }
+ }
+
private void evaluateCollectionTypeProperties(PropertyDefinition propertyDefinition) {
ToscaType toscaPropertyType = ToscaType.isValidType(propertyDefinition.getType());
+ try {
+ if (isPropertyToEvaluate(propertyDefinition)) {
+ evaluateCollectionConstraints(propertyDefinition, toscaPropertyType);
+ }
+ } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
+ logger.error(e.getMessage(), e);
+ errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, getCompletePropertyName(propertyDefinition)));
+ }
if (ToscaType.LIST == toscaPropertyType) {
evaluateListType(propertyDefinition);
} else if (ToscaType.MAP == toscaPropertyType) {
}
}
+ private void evaluateCollectionConstraints(PropertyDefinition propertyDefinition, ToscaType toscaPropertyType) {
+ List<PropertyConstraint> constraintsList = propertyDefinition.getConstraints();
+
+ if (CollectionUtils.isEmpty(constraintsList)) {
+ return;
+ }
+ ToscaType toscaPropertyType1;
+ if (null == toscaPropertyType) {
+ toscaPropertyType1 = ToscaType.isValidType(propertyDefinition.getType());
+ } else {
+ toscaPropertyType1 = toscaPropertyType;
+ }
+ constraintsList.stream()
+ .filter(this::isACollectionConstraint)
+ .forEach(propertyConstraint -> {
+ try {
+ if (ToscaType.LIST == toscaPropertyType1) {
+ Collection<Object> list = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() {
+ });
+ propertyConstraint.validate(list);
+ } else if (ToscaType.MAP == toscaPropertyType1) {
+ final Map<String, Object> map = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() {
+ });
+ propertyConstraint.validate(map);
+ }
+ } catch (ConstraintValueDoNotMatchPropertyTypeException | ConstraintViolationException exception) {
+ errorMessages.add("\n" + propertyConstraint.getErrorMessage(toscaPropertyType1, exception,
+ getCompletePropertyName(propertyDefinition)));
+ }
+ });
+ }
+
+ private boolean isACollectionConstraint(PropertyConstraint constraint) {
+ if (constraint instanceof MaxLengthConstraint) {
+ return true;
+ }
+ if (constraint instanceof MinLengthConstraint) {
+ return true;
+ }
+ return constraint instanceof LengthConstraint;
+ }
+
private void evaluateListType(PropertyDefinition propertyDefinition) {
try {
if (propertyDefinition.getSchemaType() == null) {
propertyDefinition.setSchema(createStringSchema());
}
- List<Object> list = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() {});
- evaluateCollectionType(propertyDefinition, list);
+ Collection<?> list = ConstraintUtil.parseToCollection(null != propertyDefinition.getValue() ?
+ propertyDefinition.getValue() : propertyDefinition.getDefaultValue(), new TypeReference<List<?>>() {});
+ final Map<String, Object> map = new HashMap<>();
+ int index = 0;
+ for (Object obj : list) {
+ map.put(String.valueOf(index),obj);
+ index++;
+ }
+ evaluateCollectionType(propertyDefinition, map);
} catch (ConstraintValueDoNotMatchPropertyTypeException e) {
logger.debug(e.getMessage(), e);
errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, getCompletePropertyName(propertyDefinition)));
if (propertyDefinition.getSchemaType() == null) {
propertyDefinition.setSchema(createStringSchema());
}
- final Map<String, Object> map = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() {});
- evaluateCollectionType(propertyDefinition, map.values());
+ final Map<String, Object> map = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() {
+ });
+ evaluateCollectionType(propertyDefinition, map);
} catch (ConstraintValueDoNotMatchPropertyTypeException e) {
logger.debug(e.getMessage(), e);
errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, getCompletePropertyName(propertyDefinition)));
}
}
- private void evaluateCollectionType(final PropertyDefinition propertyDefinition, final Collection<Object> valueList) {
+ private void evaluateCollectionType(final PropertyDefinition propertyDefinition, final Map<String, Object> valueMap) {
final String schemaType = propertyDefinition.getSchemaType();
- for (final Object value : valueList) {
+ for (String mapKey : valueMap.keySet()) {
+ final Object value = valueMap.get(mapKey);
try {
- final PropertyDefinition propertyCopyWithNewValue = copyPropertyWithNewValue(propertyDefinition, objectMapper.writeValueAsString(value));
- if (ToscaType.isPrimitiveType(schemaType)) {
- evaluateCollectionPrimitiveSchemaType(propertyCopyWithNewValue, schemaType);
- } else if (ToscaType.isCollectionType(schemaType)) {
- propertyCopyWithNewValue.setType(schemaType);
- propertyCopyWithNewValue.setSchemaType(propertyDefinition.getSchemaProperty().getSchemaType());
- evaluateCollectionTypeProperties(propertyCopyWithNewValue);
- } else {
- propertyCopyWithNewValue.setType(schemaType);
- completePropertyName.append(UNDERSCORE);
- completePropertyName.append(propertyCopyWithNewValue.getName());
- evaluateComplexTypeProperties(propertyCopyWithNewValue);
+ final PropertyDefinition propertyCopyWithNewValue = copyPropertyWithNewValue(propertyDefinition,
+ objectMapper.writeValueAsString(value),mapKey);
+ propertyCopyWithNewValue.setToscaSubPath(mapKey);
+ if (!isValueAToscaFunction(propertyCopyWithNewValue)) {
+ if (ToscaType.isPrimitiveType(schemaType)) {
+ evaluateCollectionPrimitiveSchemaType(propertyCopyWithNewValue, schemaType);
+ } else if (ToscaType.isCollectionType(schemaType)) {
+ propertyCopyWithNewValue.setType(schemaType);
+ propertyCopyWithNewValue.setSchemaType(propertyDefinition.getSchemaProperty().getSchemaType());
+ evaluateCollectionTypeProperties(propertyCopyWithNewValue);
+ } else {
+ propertyCopyWithNewValue.setType(schemaType);
+ completePropertyName.append(UNDERSCORE);
+ completePropertyName.append(propertyCopyWithNewValue.getName());
+ evaluateComplexTypeProperties(propertyCopyWithNewValue);
+ }
}
} catch (final Exception e) {
logger.debug(e.getMessage(), e);
return propertyName;
}
- private PropertyDefinition copyPropertyWithNewValue(final PropertyDefinition propertyToCopy, final String value) {
+ private PropertyDefinition copyPropertyWithNewValue(final PropertyDefinition propertyToCopy, final String value, final String key) {
final var propertyDefinition = new PropertyDefinition(propertyToCopy);
+ if (key != null && propertyToCopy.getSubPropertyToscaFunctions() != null) {
+ propertyToCopy.getSubPropertyToscaFunctions().forEach(subPropertyToscaFunction -> {
+ final List<String> subPropertyPath = subPropertyToscaFunction.getSubPropertyPath();
+ if (subPropertyPath.get((subPropertyPath.size() - 1)).equals(key)) {
+ propertyDefinition.setToscaFunction(subPropertyToscaFunction.getToscaFunction());
+ }
+ });
+ }
propertyDefinition.setValue(value);
return propertyDefinition;
}
- private boolean isValidValueConstraintPresent(List<PropertyConstraint> propertyConstraints) {
- return propertyConstraints != null && propertyConstraints.stream().anyMatch(ValidValuesConstraint.class::isInstance);
- }
-
private PropertyDefinition getPropertyDefinitionObjectFromInputs(PropertyDefinition property) {
InputDefinition inputDefinition = (InputDefinition) property;
PropertyDefinition propertyDefinition = null;
propertyDefinition.setType(inputDefinition.getType());
propertyDefinition.setValue(inputDefinition.getDefaultValue());
propertyDefinition.setName(inputDefinition.getName());
+ propertyDefinition.setConstraints(inputDefinition.getConstraints());
} else if (Objects.nonNull(inputDefinition.getInputPath())) {
propertyDefinition = evaluateComplexTypeInputs(inputDefinition);
+ propertyDefinition.setConstraints(inputDefinition.getConstraints());
}
return propertyDefinition;
}