From 54c873b4c430a6c13698080fcde99835ca2a541b Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 11 Jan 2013 16:25:47 -0500 Subject: [PATCH] Support multiple Validators in DataBinder DataBinder now allows registering additional Validator instances. This may be useful when adding a Spring Validator to a globally registered JSR-303 LocalValidatorFactoryBean. Issue: SPR-9436 --- .../validation/DataBinder.java | 74 +++++++++++++++---- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/validation/DataBinder.java b/spring-context/src/main/java/org/springframework/validation/DataBinder.java index a9d5d835873..35e0ea4a568 100644 --- a/spring-context/src/main/java/org/springframework/validation/DataBinder.java +++ b/spring-context/src/main/java/org/springframework/validation/DataBinder.java @@ -18,7 +18,11 @@ package org.springframework.validation; import java.beans.PropertyEditor; import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; @@ -141,7 +145,7 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter { private BindingErrorProcessor bindingErrorProcessor = new DefaultBindingErrorProcessor(); - private Validator validator; + private final List validators = new ArrayList(); private ConversionService conversionService; @@ -493,21 +497,58 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter { /** * Set the Validator to apply after each binding step. + * @see #addValidators(Validator...) + * @see #replaceValidators(Validator...) */ public void setValidator(Validator validator) { - if (validator != null && (getTarget() != null && !validator.supports(getTarget().getClass()))) { - throw new IllegalStateException("Invalid target for Validator [" + validator + "]: " + getTarget()); + assertValidators(validator); + this.validators.clear(); + this.validators.add(validator); + } + + private void assertValidators(Validator... validators) { + Assert.notNull(validators, "Validators required"); + for (Validator validator : validators) { + if (validator != null && (getTarget() != null && !validator.supports(getTarget().getClass()))) { + throw new IllegalStateException("Invalid target for Validator [" + validator + "]: " + getTarget()); + } } - this.validator = validator; } /** - * Return the Validator to apply after each binding step, if any. + * Add Validators to apply after each binding step. + * @see #setValidator(Validator) + * @see #replaceValidators(Validator...) + */ + public void addValidators(Validator... validators) { + assertValidators(validators); + this.validators.addAll(Arrays.asList(validators)); + } + + /** + * Replace the Validators to apply after each binding step. + * @see #setValidator(Validator) + * @see #addValidators(Validator...) + */ + public void replaceValidators(Validator... validators) { + assertValidators(validators); + this.validators.clear(); + this.validators.addAll(Arrays.asList(validators)); + } + + /** + * Return the primary Validator to apply after each binding step, if any. */ public Validator getValidator() { - return this.validator; + return this.validators.size() > 0 ? this.validators.get(0) : null; } + /** + * Return the Validators to apply after data binding. + */ + public List getValidators() { + return Collections.unmodifiableList(this.validators); + } //--------------------------------------------------------------------- // Implementation of PropertyEditorRegistry/TypeConverter interface @@ -708,28 +749,31 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter { /** - * Invoke the specified Validator, if any. + * Invoke the specified Validators, if any. * @see #setValidator(Validator) * @see #getBindingResult() */ public void validate() { - this.validator.validate(getTarget(), getBindingResult()); + for (Validator validator : this.validators) { + validator.validate(getTarget(), getBindingResult()); + } } /** - * Invoke the specified Validator, if any, with the given validation hints. + * Invoke the specified Validators, if any, with the given validation hints. *

Note: Validation hints may get ignored by the actual target Validator. * @param validationHints one or more hint objects to be passed to a {@link SmartValidator} * @see #setValidator(Validator) * @see SmartValidator#validate(Object, Errors, Object...) */ public void validate(Object... validationHints) { - Validator validator = getValidator(); - if (!ObjectUtils.isEmpty(validationHints) && validator instanceof SmartValidator) { - ((SmartValidator) validator).validate(getTarget(), getBindingResult(), validationHints); - } - else if (validator != null) { - validator.validate(getTarget(), getBindingResult()); + for (Validator validator : getValidators()) { + if (!ObjectUtils.isEmpty(validationHints) && validator instanceof SmartValidator) { + ((SmartValidator) validator).validate(getTarget(), getBindingResult(), validationHints); + } + else if (validator != null) { + validator.validate(getTarget(), getBindingResult()); + } } }