content: package alien4cloud.utils;
  
  import org.alien4cloud.tosca.exceptions.ConstraintFunctionalException;
  import org.alien4cloud.tosca.exceptions.ConstraintValueDoNotMatchPropertyTypeException;
  import org.alien4cloud.tosca.exceptions.ConstraintViolationException;
  import org.alien4cloud.tosca.model.definitions.PropertyDefinition;
  import org.springframework.stereotype.Component;
  
  import alien4cloud.rest.model.RestErrorBuilder;
  import alien4cloud.rest.model.RestErrorCode;
  import alien4cloud.rest.model.RestResponse;
  import alien4cloud.rest.model.RestResponseBuilder;
  import alien4cloud.tosca.properties.constraints.ConstraintUtil;
  import alien4cloud.utils.services.ConstraintPropertyService;
  import lombok.extern.slf4j.Slf4j;
  
  /**
   * Rest service that creates a proper REST error from constraint validation.
   */
  @Slf4j
  @Component
  public class RestConstraintValidator {
      /**
       * Performs validation of a property value against it's definition and eventually build a valid rest error in case of violations.
       *
       * @param propertyName The name of the property to check.
       * @param propertyValue The value of the property to check.
       * @param propertyDefinition The definition of the property.
       * @return Null if no constraints are violated, a RestResponse with validation results in case some constraints are violated.
       */
      public RestResponse<ConstraintUtil.ConstraintInformation> validate(final String propertyName, final Object propertyValue,
              final PropertyDefinition propertyDefinition) {
          if (propertyValue == null || !(propertyValue instanceof String)) {
              // by convention updateproperty with null value => reset to default if exists
              return null;
          }
          try {
              ConstraintPropertyService.checkPropertyConstraint(propertyName, (String) propertyValue, propertyDefinition);
          } catch (ConstraintFunctionalException e) {
              return fromException(e, propertyName, propertyValue);
          }
          return null;
      }
  
      public static RestResponse<ConstraintUtil.ConstraintInformation> fromException(ConstraintFunctionalException ex, String propertyName, Object propertyValue) {
          if (ex instanceof ConstraintViolationException) {
              ConstraintViolationException e = (ConstraintViolationException) ex;
              log.debug("Constraint violation error for property <" + propertyName + "> with value <" + propertyValue + ">", e);
              return RestResponseBuilder.<ConstraintUtil.ConstraintInformation> builder().data(e.getConstraintInformation())
                      .error(RestErrorBuilder.builder(RestErrorCode.PROPERTY_CONSTRAINT_VIOLATION_ERROR).message(e.getMessage()).build()).build();
          } else if (ex instanceof ConstraintValueDoNotMatchPropertyTypeException) {
              ConstraintValueDoNotMatchPropertyTypeException e = (ConstraintValueDoNotMatchPropertyTypeException) ex;
              log.debug("Constraint value violation error for property <" + e.getConstraintInformation().getName() + "> with value <"
                      + e.getConstraintInformation().getValue() + "> and type <" + e.getConstraintInformation().getType() + ">", e);
              return RestResponseBuilder.<ConstraintUtil.ConstraintInformation> builder().data(e.getConstraintInformation())
                      .error(RestErrorBuilder.builder(RestErrorCode.PROPERTY_TYPE_VIOLATION_ERROR).message(e.getMessage()).build()).build();
          } else {
              throw new IllegalArgumentException("Unexpected ConstraintFunctionalException type", ex);
          }
      }
  }