From b4a00526a4b7827c8bbb1c626d5f38debfacefec Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Mon, 2 Mar 2009 20:09:47 +0000 Subject: [PATCH] polish --- .../ValidationFailureMessageCodesFactory.java | 7 +++ .../ValidationFailureModelContext.java | 57 ++----------------- ...dationFailureMessageCodesFactoryTests.java | 6 +- ...ionFailureMessageResolverFactoryTests.java | 28 ++++----- ...dationFailureMessageCodesFactoryTests.java | 6 +- .../validation/DefaultValidationContext.java | 54 ++++++++++++++---- 6 files changed, 76 insertions(+), 82 deletions(-) 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 index a60943ef..2d68bed9 100644 --- a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactory.java +++ b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactory.java @@ -34,6 +34,13 @@ public class ValidationFailureMessageCodesFactory { this.failureMessageCodePrefix = failureMessageCodePrefix; } + /** + * Create the message codes for the validation failure in the provided model context. Subclasses may override to + * customize the failure message code mapping algorithm. + * @param failure the validation failure + * @param modelContext the failure model context + * @return the failure message codes + */ public String[] createMessageCodes(ValidationFailure failure, ValidationFailureModelContext modelContext) { String constraintMessageCode = appendFailureMessageCodePrefix().append(codeSeparator()).append( failure.getConstraint()).toString(); diff --git a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureModelContext.java b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureModelContext.java index a44a2bdd..bd0bfe75 100644 --- a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureModelContext.java +++ b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureModelContext.java @@ -1,74 +1,29 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package org.springframework.binding.validation; /** * Provides additional model context regarding a validation failure. Used by a * {@link ValidationFailureMessageResolverFactory} to resolve failure messages. */ -public class ValidationFailureModelContext { - - private String model; - - private Object invalidValue; - - private Class propertyType; - - private String propertyConverter; - - /** - * Creates a new validation model context. - * @param model the name of the model object that was validated - * @param invalidValue the invalid value the user entered (may be null) - * @param propertyType the type of the property that failed to validate (may be null) - * @param propertyConverter the id of the custom converter configured to format the property value (may be null) - */ - public ValidationFailureModelContext(String model, Object invalidValue, Class propertyType, String propertyConverter) { - this.model = model; - this.invalidValue = invalidValue; - this.propertyType = propertyType; - this.propertyConverter = propertyConverter; - } +public interface ValidationFailureModelContext { /** * The name of the model object that was validated. */ - public String getModel() { - return model; - } + public String getModel(); /** * When reporting a property validation failure, the invalid user entered value. */ - public Object getInvalidValue() { - return invalidValue; - } + public Object getInvalidValue(); /** * When reporting a property validation failure, the type of the property that failed to validate. */ - public Class getPropertyType() { - return propertyType; - } + public Class getPropertyType(); /** * When reporting a property validation failure, the id of the custom converter used to format the UI display value. */ - public String getPropertyConverter() { - return propertyConverter; - } + public String getPropertyConverter(); -} +} \ No newline at end of file diff --git a/spring-binding/src/test/java/org/springframework/binding/validation/DefaultSpringMvcValidationFailureMessageCodesFactoryTests.java b/spring-binding/src/test/java/org/springframework/binding/validation/DefaultSpringMvcValidationFailureMessageCodesFactoryTests.java index ed5a9dd9..524a4bef 100644 --- a/spring-binding/src/test/java/org/springframework/binding/validation/DefaultSpringMvcValidationFailureMessageCodesFactoryTests.java +++ b/spring-binding/src/test/java/org/springframework/binding/validation/DefaultSpringMvcValidationFailureMessageCodesFactoryTests.java @@ -7,15 +7,15 @@ public class DefaultSpringMvcValidationFailureMessageCodesFactoryTests extends T public void testCreateGeneralModelFailureMessageCodes() { ValidationFailure failure = new ValidationFailureBuilder().constraint("invalid").build(); - String[] codes = factory.createMessageCodes(failure, new ValidationFailureModelContext("testBean", null, null, - null)); + String[] codes = factory.createMessageCodes(failure, new TestValidationFailureModelContext("testBean", null, + null, null)); assertEquals("validation.invalid.testBean", codes[0]); assertEquals("validation.invalid", codes[1]); } public void testCreatePropertyFailureMessageCodes() { ValidationFailure failure = new ValidationFailureBuilder().forProperty("foo").constraint("required").build(); - String[] codes = factory.createMessageCodes(failure, new ValidationFailureModelContext("testBean", null, + String[] codes = factory.createMessageCodes(failure, new TestValidationFailureModelContext("testBean", null, String.class, null)); assertEquals("validation.required.testBean.foo", codes[0]); assertEquals("validation.required.java.lang.String", codes[1]); diff --git a/spring-binding/src/test/java/org/springframework/binding/validation/DefaultValidationFailureMessageResolverFactoryTests.java b/spring-binding/src/test/java/org/springframework/binding/validation/DefaultValidationFailureMessageResolverFactoryTests.java index 394d21b5..4a08a0ce 100644 --- a/spring-binding/src/test/java/org/springframework/binding/validation/DefaultValidationFailureMessageResolverFactoryTests.java +++ b/spring-binding/src/test/java/org/springframework/binding/validation/DefaultValidationFailureMessageResolverFactoryTests.java @@ -32,16 +32,16 @@ public class DefaultValidationFailureMessageResolverFactoryTests extends TestCas public void testResolveMessage() { ValidationFailure failure = builder.forProperty("foo").constraint("required").build(); - MessageResolver resolver = factory.createMessageResolver(failure, new ValidationFailureModelContext("testBean", - "", String.class, null)); + MessageResolver resolver = factory.createMessageResolver(failure, new TestValidationFailureModelContext( + "testBean", "", String.class, null)); Message message = resolver.resolveMessage(messageSource, Locale.getDefault()); assertEquals("Foo is required", message.getText()); } public void testResolveMessageNoPropertyLabel() { ValidationFailure failure = builder.forProperty("bogus").constraint("required").build(); - MessageResolver resolver = factory.createMessageResolver(failure, new ValidationFailureModelContext("testBean", - "", String.class, null)); + MessageResolver resolver = factory.createMessageResolver(failure, new TestValidationFailureModelContext( + "testBean", "", String.class, null)); Message message = resolver.resolveMessage(messageSource, Locale.getDefault()); assertEquals("bogus is required", message.getText()); } @@ -50,8 +50,8 @@ public class DefaultValidationFailureMessageResolverFactoryTests extends TestCas ValidationFailureBuilder builder = new ValidationFailureBuilder(); ValidationFailure failure = builder.forProperty("checkinDate").constraint("invalidFormat").arg("format", "yyyy-MM-dd").build(); - MessageResolver resolver = factory.createMessageResolver(failure, new ValidationFailureModelContext("testBean", - "bogus", Date.class, null)); + MessageResolver resolver = factory.createMessageResolver(failure, new TestValidationFailureModelContext( + "testBean", "bogus", Date.class, null)); Message message = resolver.resolveMessage(messageSource, Locale.getDefault()); assertEquals("Check In Date must be in format yyyy-MM-dd", message.getText()); } @@ -59,8 +59,8 @@ public class DefaultValidationFailureMessageResolverFactoryTests extends TestCas public void testResolveMessageWithCustomResolvableArg() { ValidationFailure failure = builder.forProperty("checkinDate").constraint("invalidFormat").resolvableArg( "format", "formats.dateFormat").build(); - MessageResolver resolver = factory.createMessageResolver(failure, new ValidationFailureModelContext("testBean", - "bogus", Date.class, null)); + MessageResolver resolver = factory.createMessageResolver(failure, new TestValidationFailureModelContext( + "testBean", "bogus", Date.class, null)); Message message = resolver.resolveMessage(messageSource, Locale.getDefault()); assertEquals("Check In Date must be in format yyyy-MM-dd", message.getText()); } @@ -68,8 +68,8 @@ public class DefaultValidationFailureMessageResolverFactoryTests extends TestCas public void testResolveMessageWithValue() { ValidationFailure failure = builder.forProperty("checkinDate").constraint("invalidFormat2").resolvableArg( "format", "formats.dateFormat").build(); - MessageResolver resolver = factory.createMessageResolver(failure, new ValidationFailureModelContext("testBean", - "bogus", Date.class, null)); + MessageResolver resolver = factory.createMessageResolver(failure, new TestValidationFailureModelContext( + "testBean", "bogus", Date.class, null)); Message message = resolver.resolveMessage(messageSource, Locale.getDefault()); assertEquals("Check In Date must be in format yyyy-MM-dd but it was 'bogus'", message.getText()); } @@ -77,8 +77,8 @@ public class DefaultValidationFailureMessageResolverFactoryTests extends TestCas public void testResolveMessageWithArgDefaultConversion() { ValidationFailure failure = builder.forProperty("amount").constraint("range").arg("min", new Integer(1)).arg( "max", new Integer(100)).build(); - MessageResolver resolver = factory.createMessageResolver(failure, new ValidationFailureModelContext("testBean", - "bogus", Integer.class, null)); + MessageResolver resolver = factory.createMessageResolver(failure, new TestValidationFailureModelContext( + "testBean", "bogus", Integer.class, null)); Message message = resolver.resolveMessage(messageSource, Locale.getDefault()); assertEquals("Amount must be between 1 and 100", message.getText()); } @@ -87,8 +87,8 @@ public class DefaultValidationFailureMessageResolverFactoryTests extends TestCas conversionService.addConverter("stringToMoney", new StringToMoney()); ValidationFailure failure = builder.forProperty("amount").constraint("range").arg("min", new Money(1)).arg( "max", new Money(100)).build(); - MessageResolver resolver = factory.createMessageResolver(failure, new ValidationFailureModelContext("testBean", - "bogus", Money.class, "stringToMoney")); + MessageResolver resolver = factory.createMessageResolver(failure, new TestValidationFailureModelContext( + "testBean", "bogus", Money.class, "stringToMoney")); Message message = resolver.resolveMessage(messageSource, Locale.getDefault()); assertEquals("Amount must be between $1 and $100", message.getText()); } diff --git a/spring-binding/src/test/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactoryTests.java b/spring-binding/src/test/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactoryTests.java index d0450aab..4cb77acb 100644 --- a/spring-binding/src/test/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactoryTests.java +++ b/spring-binding/src/test/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactoryTests.java @@ -7,15 +7,15 @@ public class ValidationFailureMessageCodesFactoryTests extends TestCase { public void testCreateGeneralModelFailureMessageCodes() { ValidationFailure failure = new ValidationFailureBuilder().constraint("invalid").build(); - String[] codes = factory.createMessageCodes(failure, new ValidationFailureModelContext("testBean", null, null, - null)); + String[] codes = factory.createMessageCodes(failure, new TestValidationFailureModelContext("testBean", null, + null, null)); assertEquals("validation.testBean.invalid", codes[0]); assertEquals("validation.invalid", codes[1]); } public void testCreatePropertyFailureMessageCodes() { ValidationFailure failure = new ValidationFailureBuilder().forProperty("foo").constraint("required").build(); - String[] codes = factory.createMessageCodes(failure, new ValidationFailureModelContext("testBean", null, + String[] codes = factory.createMessageCodes(failure, new TestValidationFailureModelContext("testBean", null, String.class, null)); assertEquals("validation.testBean.foo.required", codes[0]); assertEquals("validation.java.lang.String.required", codes[1]); diff --git a/spring-webflow/src/main/java/org/springframework/webflow/validation/DefaultValidationContext.java b/spring-webflow/src/main/java/org/springframework/webflow/validation/DefaultValidationContext.java index 95dc89ae..168d223b 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/validation/DefaultValidationContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/validation/DefaultValidationContext.java @@ -9,16 +9,26 @@ import org.springframework.binding.mapping.MappingResultsCriteria; import org.springframework.binding.message.MessageContext; import org.springframework.binding.validation.ValidationContext; import org.springframework.binding.validation.ValidationFailure; +import org.springframework.binding.validation.ValidationFailureMessageResolverFactory; +import org.springframework.binding.validation.ValidationFailureModelContext; import org.springframework.webflow.execution.RequestContext; public class DefaultValidationContext implements ValidationContext { + private String modelName; + + private Object model; + + private String converterId; + private RequestContext requestContext; private String eventId; private MappingResults mappingResults; + private ValidationFailureMessageResolverFactory failureMessageResolverFactory; + public DefaultValidationContext(RequestContext requestContext, String eventId, MappingResults mappingResults) { this.requestContext = requestContext; this.eventId = eventId; @@ -34,24 +44,46 @@ public class DefaultValidationContext implements ValidationContext { } public Object getUserValue(String property) { - if (mappingResults != null) { - List results = mappingResults.getResults(new PropertyMappingResult(property)); - if (!results.isEmpty()) { - MappingResult result = (MappingResult) results.get(0); - return result.getOriginalValue(); - } - } - return null; + MappingResult result = getMappingResult(property); + return result != null ? result.getOriginalValue() : null; } - public void addFailure(ValidationFailure failure) { - // TODO + public void addFailure(final ValidationFailure failure) { + ValidationFailureModelContext modelContext = new ValidationFailureModelContext() { + public String getModel() { + return modelName; + } + + public Object getInvalidValue() { + return getUserValue(failure.getProperty()); + } + + public Class getPropertyType() { + MappingResult result = getMappingResult(failure.getProperty()); + return result != null ? result.getMapping().getTargetExpression().getValueType(model) : null; + } + + public String getPropertyConverter() { + return converterId; + } + }; + getMessageContext().addMessage(failureMessageResolverFactory.createMessageResolver(failure, modelContext)); } public MessageContext getMessageContext() { return requestContext.getMessageContext(); } + private MappingResult getMappingResult(String property) { + if (mappingResults != null) { + List results = mappingResults.getResults(new PropertyMappingResult(property)); + if (!results.isEmpty()) { + return (MappingResult) results.get(0); + } + } + return null; + } + private static class PropertyMappingResult implements MappingResultsCriteria { private String property; @@ -69,4 +101,4 @@ public class DefaultValidationContext implements ValidationContext { } } -} +} \ No newline at end of file