d-baranowski / Devtales-Blog

Source code for my blog.
1 stars 0 forks source link

Validation in Spring boot #29

Open d-baranowski opened 6 years ago

d-baranowski commented 6 years ago

Multiple validation errors from Spring boot. You can inject them with autovired beans. You can call addConstraintViolation in a loop

public class ConfiguredQueryParametersValidator implements ConstraintValidator<ConfiguredQueryParametersConstraint, QueryParameters> {

private final QueryParamConfigResolver configResolver;
private final List<IQueryParamValidator> availableValidators;
private List<ReportQueryParam> reportQueryParams;
private List<IQueryParamValidator> applicableQueryParamValidators;
private Set<String> applicableQueryParameterNames;

ConfiguredQueryParametersValidator(final QueryParamConfigResolver configResolver,
                                   final List<IQueryParamValidator> availableValidators) {
    super();
    this.configResolver = configResolver;
    this.availableValidators = availableValidators;
}

@Override
public void initialize(ConfiguredQueryParametersConstraint constraintAnnotation) {
    this.reportQueryParams = this.configResolver.getForDomain(constraintAnnotation.domainName());
    this.applicableQueryParameterNames = reportQueryParams.stream()
            .map(ReportQueryParam::getName).collect(Collectors.toSet());

    this.applicableQueryParamValidators = this.availableValidators.stream().filter(
            validator -> containsAny(applicableQueryParameterNames, validator.getQueryParamNames()))
            .collect(Collectors.toList());

    final List<IQueryParamValidator> validatorsThatShouldAlwaysBeIncluded = this.availableValidators.stream()
            .filter(
                    validator -> validator.getQueryParamNames().equals(VALIDATES_ALL_PARAMS)
            ).collect(Collectors.toList());

    this.applicableQueryParamValidators.addAll(validatorsThatShouldAlwaysBeIncluded);
}

private static boolean containsAny(Set<String> first, Set<String> second) {
    return !Sets.intersection(first, second).isEmpty();
}

@Override
public boolean isValid(final QueryParameters queryParameters,
                       final ConstraintValidatorContext constraintValidatorContext) {
    constraintValidatorContext.disableDefaultConstraintViolation();

    if (!checkForUnexpectedQueryParameters(queryParameters, constraintValidatorContext)) {
        return false;
    }

    boolean isAnyInvalid = false;
    for (final IQueryParamValidator validator : this.applicableQueryParamValidators) {
        final String validationMessage = validator.validate(queryParameters.getQueryParameters());
        if (!validationMessage.equals(IS_VALID)) {
            constraintValidatorContext
                    .buildConstraintViolationWithTemplate(validationMessage)
                    .addConstraintViolation();
            isAnyInvalid = true;
        }
    }

    return !isAnyInvalid;
}

private boolean checkForUnexpectedQueryParameters(final QueryParameters queryParameters,
                                                  final ConstraintValidatorContext constraintValidatorContext) {
    final Set<String> requestParameterNames =
            queryParameters.getQueryParameters().stream()
                    .map(CompileQueryParam::getName).collect(Collectors.toSet());

    final Set<String> unexpected = Sets.difference(requestParameterNames, this.applicableQueryParameterNames);

    if (!unexpected.isEmpty()) {
        constraintValidatorContext
                .buildConstraintViolationWithTemplate(produceErrorMessageForUnexpectedQueryParameters(unexpected))
                .addConstraintViolation();

        return false;
    }

    return true;
}

private static String produceErrorMessageForUnexpectedQueryParameters(final Set<String> unexpected) {
    return String.format("There have been unexpected queryParameters %s.", unexpected.toString());
}

}