From 77b49c7cc00ef8f78ca4873856cfe18fdbd6368d Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Mon, 2 Mar 2009 14:54:27 +0000 Subject: [PATCH] mvc compat --- ...cValidationFailureMessageCodesFactory.java | 44 +++++++++++++ ...lidationFailureMessageResolverFactory.java | 38 +++--------- .../ValidationFailureMessageCodesFactory.java | 62 +++++++++++++++++++ ...lidationFailureMessageResolverFactory.java | 2 + 4 files changed, 116 insertions(+), 30 deletions(-) create mode 100644 spring-binding/src/main/java/org/springframework/binding/validation/DefaultSpringMvcValidationFailureMessageCodesFactory.java create mode 100644 spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactory.java diff --git a/spring-binding/src/main/java/org/springframework/binding/validation/DefaultSpringMvcValidationFailureMessageCodesFactory.java b/spring-binding/src/main/java/org/springframework/binding/validation/DefaultSpringMvcValidationFailureMessageCodesFactory.java new file mode 100644 index 00000000..59b86cb4 --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/validation/DefaultSpringMvcValidationFailureMessageCodesFactory.java @@ -0,0 +1,44 @@ +package org.springframework.binding.validation; + +/** + * Failure message codes factory specialization that applies default Spring MVC errorCode-to-messageCodes mapping rules. + * The difference between this subclass and the default {@link ValidationFailureMessageCodesFactory} is where the + * constraint code falls in the message code. Specifically, for a property validation failure the default algorithm + * results in these codes: + * + *
+ * ${failureMessageCodePrefix}.${model}.${property}.${constraint}
+ * ${failureMessageCodePrefix}.${propertyType}.${constraint}
+ * ${failureMessageCodePrefix}.${constraint}
+ * 
+ * + * while this original Spring MVC algorithm results in these codes: + * + *
+ * ${failureMessageCodePrefix}.${constraint}.${model}.${property}
+ * ${failureMessageCodePrefix}.${constraint}.${propertyType}
+ * ${failureMessageCodePrefix}.${constraint}
+ * 
+ * + * @author Keith Donald + */ +public class DefaultSpringMvcValidationFailureMessageCodesFactory extends ValidationFailureMessageCodesFactory { + + public String[] createMessageCodes(ValidationFailure failure, ValidationFailureModelContext modelContext) { + String constraintMessageCode = appendFailureMessageCodePrefix().append(failure.getConstraint()).append( + codeSeparator()).toString(); + if (failure.getProperty() != null) { + String propertyConstraintMessageCode = appendFailureMessageCodePrefix().append(codeSeparator()).append( + failure.getConstraint()).append(modelContext.getModel()).append(codeSeparator()).append( + failure.getProperty()).append(codeSeparator()).toString(); + String typeConstraintMessageCode = appendFailureMessageCodePrefix().append(codeSeparator()).append( + failure.getConstraint()).append(modelContext.getPropertyType().getName()).toString(); + return new String[] { propertyConstraintMessageCode, typeConstraintMessageCode, constraintMessageCode }; + } else { + String objectConstraintMessageCode = appendFailureMessageCodePrefix().append(codeSeparator()).append( + failure.getConstraint()).append(modelContext.getModel()).append(codeSeparator()).toString(); + return new String[] { objectConstraintMessageCode, constraintMessageCode }; + } + } + +} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/validation/DefaultValidationFailureMessageResolverFactory.java b/spring-binding/src/main/java/org/springframework/binding/validation/DefaultValidationFailureMessageResolverFactory.java index a8e46cdf..ae740576 100644 --- a/spring-binding/src/main/java/org/springframework/binding/validation/DefaultValidationFailureMessageResolverFactory.java +++ b/spring-binding/src/main/java/org/springframework/binding/validation/DefaultValidationFailureMessageResolverFactory.java @@ -39,8 +39,8 @@ import org.springframework.util.Assert; * * Employs the following algorithm to map property validation failure to a message: *
    - *
  1. Try the ${failureMessageCodePrefix}.${objectName}.${propertyName}.${constraint} code; if matches, resolve message - * and return. + *
  2. Try the ${failureMessageCodePrefix}.${model}.${property}.${constraint} code; if matches, resolve message and + * return. *
  3. Try the ${failureMessageCodePrefix}.${propertyType}.${constraint} code; if matches, resolve message and return. *
  4. Try the ${failureMessageCodePrefix}.${constraint} code; if matches, resolve message and return. *
@@ -65,16 +65,16 @@ import org.springframework.util.Assert; */ public class DefaultValidationFailureMessageResolverFactory implements ValidationFailureMessageResolverFactory { - private static final char CODE_SEPARATOR = '.'; + protected static final char CODE_SEPARATOR = '.'; private ExpressionParser expressionParser; private ConversionService conversionService; - private String failureMessageCodePrefix = "validation"; - private String labelMessageCodePrefix = "label"; + private ValidationFailureMessageCodesFactory failureMessageCodesFactory = new ValidationFailureMessageCodesFactory(); + /** * Creates a new message resolver factory. * @param expressionParser the expression parser @@ -92,7 +92,7 @@ public class DefaultValidationFailureMessageResolverFactory implements Validatio * @param failureMessageCodePrefix the failure message code prefix */ public void setFailureMessageCodePrefix(String failureMessageCodePrefix) { - this.failureMessageCodePrefix = failureMessageCodePrefix; + failureMessageCodesFactory.setFailureMessageCodePrefix(failureMessageCodePrefix); } /** @@ -123,8 +123,8 @@ public class DefaultValidationFailureMessageResolverFactory implements Validatio } public Message resolveMessage(MessageSource messageSource, Locale locale) { - DefaultMessageSourceResolvable resolvable = new DefaultMessageSourceResolvable(buildCodes(), failure - .getDefaultMessage()); + DefaultMessageSourceResolvable resolvable = new DefaultMessageSourceResolvable(failureMessageCodesFactory + .createMessageCodes(failure, modelContext), failure.getDefaultMessage()); String text = messageSource.getMessage(resolvable, locale); Expression expression = expressionParser.parseExpression(text, new FluentParserContext() .evaluate(Map.class).template()); @@ -164,28 +164,6 @@ public class DefaultValidationFailureMessageResolverFactory implements Validatio return new Message(failure.getProperty(), text, failure.getSeverity()); } - private String[] buildCodes() { - String constraintMessageCode = appendMessageCodePrefix().append(CODE_SEPARATOR).append( - failure.getConstraint()).toString(); - if (failure.getProperty() != null) { - String propertyConstraintMessageCode = appendMessageCodePrefix().append(CODE_SEPARATOR).append( - modelContext.getModel()).append(CODE_SEPARATOR).append(failure.getProperty()).append( - CODE_SEPARATOR).append(failure.getConstraint()).toString(); - String typeConstraintMessageCode = appendMessageCodePrefix().append(CODE_SEPARATOR).append( - modelContext.getPropertyType().getName()).append(CODE_SEPARATOR) - .append(failure.getConstraint()).toString(); - return new String[] { propertyConstraintMessageCode, typeConstraintMessageCode, constraintMessageCode }; - } else { - String objectConstraintMessageCode = appendMessageCodePrefix().append(CODE_SEPARATOR).append( - modelContext.getModel()).append(CODE_SEPARATOR).append(failure.getConstraint()).toString(); - return new String[] { objectConstraintMessageCode, failure.getConstraint() }; - } - } - - private StringBuilder appendMessageCodePrefix() { - return new StringBuilder().append(failureMessageCodePrefix); - } - private StringBuilder appendLabelPrefix() { return new StringBuilder().append(labelMessageCodePrefix); } diff --git a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactory.java b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactory.java new file mode 100644 index 00000000..a60943ef --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactory.java @@ -0,0 +1,62 @@ +package org.springframework.binding.validation; + +/** + * A helper factory for validation failure message codes. Subclasses may override + * {@link #createMessageCodes(ValidationFailure, ValidationFailureModelContext)} to customize how failure message codes + * are translated. + * + * For a property validation failure, the default algorithm in this class returns these message codes: + * + *
+ * ${failureMessageCodePrefix}.${model}.${property}.${constraint}
+ * ${failureMessageCodePrefix}.${propertyType}.${constraint}
+ * ${failureMessageCodePrefix}.${constraint}
+ * 
+ * + * @author Keith Donald + */ +public class ValidationFailureMessageCodesFactory { + + private String failureMessageCodePrefix = "validation"; + + /** + * The prefix to prepend to all validation failure message codes. + */ + public String getFailureMessageCodePrefix() { + return failureMessageCodePrefix; + } + + /** + * A prefix to prepend to all validation failure message codes; default if not set explicitly is "validation". + * @param failureMessageCodePrefix the failure message code prefix + */ + public void setFailureMessageCodePrefix(String failureMessageCodePrefix) { + this.failureMessageCodePrefix = failureMessageCodePrefix; + } + + public String[] createMessageCodes(ValidationFailure failure, ValidationFailureModelContext modelContext) { + String constraintMessageCode = appendFailureMessageCodePrefix().append(codeSeparator()).append( + failure.getConstraint()).toString(); + if (failure.getProperty() != null) { + String propertyConstraintMessageCode = appendFailureMessageCodePrefix().append(codeSeparator()).append( + modelContext.getModel()).append(codeSeparator()).append(failure.getProperty()).append( + codeSeparator()).append(failure.getConstraint()).toString(); + String typeConstraintMessageCode = appendFailureMessageCodePrefix().append(codeSeparator()).append( + modelContext.getPropertyType().getName()).append(codeSeparator()).append(failure.getConstraint()) + .toString(); + return new String[] { propertyConstraintMessageCode, typeConstraintMessageCode, constraintMessageCode }; + } else { + String objectConstraintMessageCode = appendFailureMessageCodePrefix().append(codeSeparator()).append( + modelContext.getModel()).append(codeSeparator()).append(failure.getConstraint()).toString(); + return new String[] { objectConstraintMessageCode, constraintMessageCode }; + } + } + + protected StringBuilder appendFailureMessageCodePrefix() { + return new StringBuilder().append(failureMessageCodePrefix); + } + + protected char codeSeparator() { + return DefaultValidationFailureMessageResolverFactory.CODE_SEPARATOR; + } +} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageResolverFactory.java b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageResolverFactory.java index 0c577fce..e3b9c9f1 100644 --- a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageResolverFactory.java +++ b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageResolverFactory.java @@ -27,6 +27,8 @@ import org.springframework.binding.message.MessageResolver; */ public interface ValidationFailureMessageResolverFactory { + public static final char CODE_SEPARATOR = '.'; + /** * Creates a new MessageResolver that can resolve the failure {@link Message} for the reported ValidationFailure. * @param failure a validation failure reported by a validator