mvc compat

This commit is contained in:
Keith Donald
2009-03-02 14:54:27 +00:00
parent 65111d1f1b
commit 77b49c7cc0
4 changed files with 116 additions and 30 deletions

View File

@@ -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:
*
* <pre>
* ${failureMessageCodePrefix}.${model}.${property}.${constraint}
* ${failureMessageCodePrefix}.${propertyType}.${constraint}
* ${failureMessageCodePrefix}.${constraint}
* </pre>
*
* while this original Spring MVC algorithm results in these codes:
*
* <pre>
* ${failureMessageCodePrefix}.${constraint}.${model}.${property}
* ${failureMessageCodePrefix}.${constraint}.${propertyType}
* ${failureMessageCodePrefix}.${constraint}
* </pre>
*
* @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 };
}
}
}

View File

@@ -39,8 +39,8 @@ import org.springframework.util.Assert;
*
* Employs the following algorithm to map property validation failure to a message:
* <ol>
* <li>Try the ${failureMessageCodePrefix}.${objectName}.${propertyName}.${constraint} code; if matches, resolve message
* and return.
* <li>Try the ${failureMessageCodePrefix}.${model}.${property}.${constraint} code; if matches, resolve message and
* return.
* <li>Try the ${failureMessageCodePrefix}.${propertyType}.${constraint} code; if matches, resolve message and return.
* <li>Try the ${failureMessageCodePrefix}.${constraint} code; if matches, resolve message and return.
* </ol>
@@ -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);
}

View File

@@ -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:
*
* <pre>
* ${failureMessageCodePrefix}.${model}.${property}.${constraint}
* ${failureMessageCodePrefix}.${propertyType}.${constraint}
* ${failureMessageCodePrefix}.${constraint}
* </pre>
*
* @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;
}
}

View File

@@ -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