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 deleted file mode 100644 index c2db4ccd..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/validation/DefaultSpringMvcValidationFailureMessageCodesFactory.java +++ /dev/null @@ -1,50 +0,0 @@ -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}
- * 
- * - * Notice how the constraint comes after model/property qualifiers in the default algorithm, while the original Spring - * MVC algorithm has the constraint come before. The default algorithm is believed to be more object oriented and - * generally preferred for new applications. The Spring MVC algorithm is supported for backwards compatibility and - * consistency with existing Spring MVC web applications. - * - * @author Keith Donald - */ -public class DefaultSpringMvcValidationFailureMessageCodesFactory extends ValidationFailureMessageCodesFactory { - - 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( - failure.getConstraint()).append(codeSeparator()).append(modelContext.getModel()).append( - codeSeparator()).append(failure.getProperty()).toString(); - String typeConstraintMessageCode = appendFailureMessageCodePrefix().append(codeSeparator()).append( - failure.getConstraint()).append(codeSeparator()).append(modelContext.getPropertyType().getName()) - .toString(); - return new String[] { propertyConstraintMessageCode, typeConstraintMessageCode, constraintMessageCode }; - } else { - String objectConstraintMessageCode = appendFailureMessageCodePrefix().append(codeSeparator()).append( - failure.getConstraint()).append(codeSeparator()).append(modelContext.getModel()).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 deleted file mode 100644 index f03c19a4..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/validation/DefaultValidationFailureMessageResolverFactory.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * 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; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; - -import org.springframework.binding.collection.StringKeyedMapAdapter; -import org.springframework.binding.convert.ConversionService; -import org.springframework.binding.expression.Expression; -import org.springframework.binding.expression.ExpressionParser; -import org.springframework.binding.expression.support.FluentParserContext; -import org.springframework.binding.message.Message; -import org.springframework.binding.message.MessageResolver; -import org.springframework.context.MessageSource; -import org.springframework.context.MessageSourceResolvable; -import org.springframework.context.support.DefaultMessageSourceResolvable; -import org.springframework.util.Assert; - -/** - * Maps validation failures to messages resolvable in a {@link MessageSource}. Configurable with an - * {@link ExpressionParser} to allow messages containing #{expressions} to be parameterized with failure arguments. - * Configurable with a {@link ConversionService} to support String-encoding failure arguments. - * - * Employs the following algorithm to map property validation failure to a message: - *
    - *
  1. Try the ${failureMessageCodePrefix}.${model}.${property}.${constraint} code; if matches, resolve message and - * return. - *
  2. Try the ${failureMessageCodePrefix}.${propertyType}.${constraint} code; if matches, resolve message and return. - *
  3. Try the ${failureMessageCodePrefix}.${constraint} code; if matches, resolve message and return. - *
- * - * Named message arguments may be denoted by using ${} or #{} expressions. For property validation failures, the value - * of the "label" argument is automatically mapped to the message with code - * ${labelMessageCodePrefix}.${objectName}.${propertyName}, allowing localization of the property label. Also, the - * "value" argument holds a reference to the invalid user-entered value that triggered the failure. - * - * messages.properties example: - * - *
- * validation.booking.checkinDate.required=The Checkin Date is required
- * validation.java.util.Date.required=Dates are required
- * validation.required=#{label} is required
- * validation.range=#{label} must be between #{min} and #{max} but it was #{value}
- * 
- * label.booking.checkoutDate=Check Out Date
- * label.booking.amount=Amount
- * 
- * @author Keith Donald - */ -public class DefaultValidationFailureMessageResolverFactory implements ValidationFailureMessageResolverFactory { - - protected static final char CODE_SEPARATOR = '.'; - - private ExpressionParser expressionParser; - - private ConversionService conversionService; - - private String labelMessageCodePrefix = "label"; - - private ValidationFailureMessageCodesFactory failureMessageCodesFactory = new ValidationFailureMessageCodesFactory(); - - /** - * Creates a new message resolver factory. - * @param expressionParser the expression parser - * @param conversionService the conversion service - */ - public DefaultValidationFailureMessageResolverFactory(ExpressionParser expressionParser, - ConversionService conversionService) { - Assert.notNull(expressionParser, "The expressionParser is required"); - this.expressionParser = expressionParser; - this.conversionService = conversionService; - } - - /** - * A prefix to prepend to all validation failure message codes; default is "validation". - * @param failureMessageCodePrefix the failure message code prefix - */ - public void setFailureMessageCodePrefix(String failureMessageCodePrefix) { - failureMessageCodesFactory.setFailureMessageCodePrefix(failureMessageCodePrefix); - } - - /** - * The prefix to prepend to all property label message codes; default is "label". - * @param labelMessageCodePrefix the label message code prefix - */ - public void setLabelMessageCodePrefix(String labelMessageCodePrefix) { - this.labelMessageCodePrefix = labelMessageCodePrefix; - } - - public MessageResolver createMessageResolver(ValidationFailure failure, ValidationFailureModelContext modelContext) { - return new DefaultValidationMessageResolver(failure, modelContext); - } - - private class DefaultValidationMessageResolver implements MessageResolver { - - private static final String LABEL_ARGUMENT = "label"; - - private static final String VALUE_ARGUMENT = "value"; - - private ValidationFailure failure; - - private ValidationFailureModelContext modelContext; - - public DefaultValidationMessageResolver(ValidationFailure failure, ValidationFailureModelContext modelContext) { - this.modelContext = modelContext; - this.failure = failure; - } - - public Message resolveMessage(MessageSource messageSource, Locale locale) { - DefaultMessageSourceResolvable resolvable = new DefaultMessageSourceResolvable(failureMessageCodesFactory - .createMessageCodes(failure, modelContext), failure.getMessage()); - String text = messageSource.getMessage(resolvable, locale); - Expression expression = expressionParser.parseExpression(text, new FluentParserContext() - .evaluate(Map.class).template()); - Map stringArgs = new HashMap(); - if (!stringArgs.containsKey(LABEL_ARGUMENT)) { - String label; - if (failure.getProperty() != null) { - label = appendLabelPrefix().append(CODE_SEPARATOR).append(modelContext.getModel()).append( - CODE_SEPARATOR).append(failure.getProperty()).toString(); - } else { - label = appendLabelPrefix().append(CODE_SEPARATOR).append(modelContext.getModel()).toString(); - } - stringArgs.put(LABEL_ARGUMENT, new DefaultMessageSourceResolvable(new String[] { label }, failure - .getProperty())); - } - if (!stringArgs.containsKey(VALUE_ARGUMENT) && failure.getProperty() != null) { - stringArgs.put(VALUE_ARGUMENT, modelContext.getInvalidValue()); - } - if (failure.getArguments() != null) { - Iterator it = failure.getArguments().entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - Object arg = entry.getValue(); - if (!(arg instanceof String) && !(arg instanceof MessageSourceResolvable)) { - if (modelContext.getPropertyConverter() != null - && arg.getClass().equals(modelContext.getPropertyType())) { - arg = conversionService.executeConversion(modelContext.getPropertyConverter(), arg, - String.class); - } else { - arg = conversionService.executeConversion(arg, String.class); - } - } - stringArgs.put(entry.getKey(), arg); - } - } - text = (String) expression.getValue(new LazyMessageResolvingMap(messageSource, locale, stringArgs)); - return new Message(failure.getProperty(), text, failure.getSeverity()); - } - - private StringBuilder appendLabelPrefix() { - return new StringBuilder().append(labelMessageCodePrefix); - } - } - - private static class LazyMessageResolvingMap extends StringKeyedMapAdapter { - - private MessageSource messageSource; - - private Locale locale; - - private Map args; - - public LazyMessageResolvingMap(MessageSource messageSource, Locale locale, Map args) { - this.messageSource = messageSource; - this.locale = locale; - this.args = args; - } - - protected Object getAttribute(String key) { - Object arg = args.get(key); - if (arg instanceof MessageSourceResolvable) { - arg = messageSource.getMessage(((MessageSourceResolvable) arg), locale); - args.put(key, arg); - } - return arg; - } - - protected Iterator getAttributeNames() { - return args.keySet().iterator(); - } - - protected void removeAttribute(String key) { - throw new UnsupportedOperationException("Should not be called"); - } - - protected void setAttribute(String key, Object value) { - throw new UnsupportedOperationException("Should not be called"); - } - - } -} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationContext.java b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationContext.java index b4dacb40..1f0254cc 100644 --- a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationContext.java +++ b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationContext.java @@ -28,6 +28,11 @@ import org.springframework.binding.message.MessageContext; */ public interface ValidationContext { + /** + * A context for adding failure messages to display to the user directly. + */ + public MessageContext getMessageContext(); + /** * The current user. */ @@ -45,53 +50,4 @@ public interface ValidationContext { */ public Object getUserValue(String property); - /** - * Set the property of the model that is about to be validated. This property becomes the "current property" - * associated with this context. - * @param property the name of the property that will be validated - */ - public void setProperty(String property); - - /** - * Validate the current property using the constraint provided. The value of the current property will be passed - * directly to the constraint for validation. Internally, the constraint may use {@link #addDefaultFailure()} to - * report a default failure, or {@link #addFailure(ValidationFailure)} to report a custom failure. - * @param constraint the validation constraint to invoek - */ - public void validate(Object constraint); - - /** - * Validate the current property context using the constraint provided. Call this method when additional context - * besides just the property value is required for constraint validation. Internally, the constraint may use - * {@link #addDefaultFailure()} to report a default failure, or {@link #addFailure(ValidationFailure)} to report a - * custom failure. - * @param constraint the validation constraint to invoke - * @param propertyContext the property context object to validate - */ - public void validate(Object constraint, Object propertyContext); - - /** - * Add the default validation failure for the current context. Called by a validation constraint to report failures - * against the current object being validated. - */ - public void addDefaultFailure(); - - /** - * Add a validation failure to this context. Called by a validation constraint to report failures against the - * current object being validated. Use to report a general failure against the object, or a specific failure against - * a property on the object. The failure code provided is typically mapped to one or message codes that result in a - * Message being added to the {@link MessageContext}. - * @param failure the validation failure - * @see #getMessageContext() - * @see ValidationFailureMessageResolverFactory - */ - public void addFailure(ValidationFailure failure); - - /** - * A context for adding messages to display to the user directly. The {@link #addFailure(ValidationFailure)} - * operation provides a higher level of abstraction for reporting validation failures. This method provides more - * control over the actual message added. - */ - public MessageContext getMessageContext(); - } diff --git a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailure.java b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailure.java deleted file mode 100644 index edd14594..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailure.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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; - -import java.util.Collections; -import java.util.Map; - -import org.springframework.binding.message.Severity; -import org.springframework.util.Assert; - -/** - * An indication of a validation failure. A failure is generated when a validation constraint is violated; for example - * "required", "length", "invalidFormat". A failure has a severity describing the intensity of the violation. A failure - * may have an explicit message summarizing what went wrong, and may also provide additional details, such as a cause or - * suggested recovery action. A failure may also have additional arguments that can be used as named parameters in any - * UI display messages. - */ -public class ValidationFailure { - - private String property; - - private String constraint; - - private Severity severity; - - private String message; - - private Map details; - - private Map arguments; - - /** - * Creates a new validation failure - * @param severity the severity of the failure (required) - * @param property the property that failed to validate (may be null) - * @param constraint the name of the validation constraint that failed (may be null) - * @param message an explicit failure message (may be null) - * @param details additional failure details (may be null) - * @param arguments named failure arguments (may be null) - */ - public ValidationFailure(Severity severity, String property, String constraint, String message, Map details, - Map arguments) { - Assert.notNull(severity, "The severity is required"); - this.property = property; - this.constraint = constraint; - this.message = message; - this.details = details != null ? Collections.unmodifiableMap(details) : Collections.EMPTY_MAP; - this.arguments = arguments != null ? Collections.unmodifiableMap(arguments) : Collections.EMPTY_MAP; - } - - /** - * The name of the property that failed to validate. May be null to indicate a failure against the currently - * validating object. - */ - public String getProperty() { - return property; - } - - /** - * The name of the validation constraint that caused this failure to be reported. This constraint name can be used - * to resolve the failure message if no explicit {@link #getMessage()} is configured. May be null to indicate a - * failure against the currently validating constraint. - */ - public String getConstraint() { - return constraint; - } - - /** - * The severity of the failure, which measures the impact of the constraint violation. - */ - public Severity getSeverity() { - return severity; - } - - /** - * The message summarizing this failure. May be a literal string or a resolvable message code. Can be null. If null, - * the failure message will be resolved using the constraint that was being validated when this failure was - * reported. - */ - public String getMessage() { - return message; - } - - /** - * A map of details providing additional information about this failure. Each entry in this map is a failure detail - * item that has a name and value. The name uniquely identifies the failure detail and describes its purpose; for - * example, a "cause" or "recommendedAction". The value is the failure detail message, either a literal string or - * resolvable code. If resolvable, the detail code is relative to the constraint associated with this failure. - * Returns an empty map if no details are present. - */ - public Map getDetails() { - return details; - } - - /** - * An map of arguments that can be used as named parameters in resolvable messages associated with this validation - * failure. Each constraint that can fail defines a set of arguments that are specific to it. For example, a length - * constraint might define arguments of "min" and "max" of Integer values. In the message bundle, you then might see - * "length=The ${label} field value must be between ${min} and ${max}". Returns an empty map if no arguments are - * present. - */ - public Map getArguments() { - return arguments; - } - -} diff --git a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureBuilder.java b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureBuilder.java deleted file mode 100644 index 21d3418e..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureBuilder.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2004-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; - -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - -import org.springframework.binding.message.Severity; -import org.springframework.context.MessageSourceResolvable; -import org.springframework.context.support.DefaultMessageSourceResolvable; - -/** - * A builder that provides a fluent interface for configuring a Validation failure. Example: - * - *
- * new ValidationFailureBuilder().forProperty("foo").constraint("required").build();
- * 
- * @author Keith Donald - * - */ -public class ValidationFailureBuilder { - - private String property; - - private String constraint; - - private Severity severity; - - private Map args; - - private String message; - - private Map details; - - /** - * Sets the failure to be of warning severity. - * @return this, for fluent call chaining - */ - public ValidationFailureBuilder warning() { - severity = Severity.WARNING; - return this; - } - - /** - * Sets the failure to be of error severity. This is the default Severity. - * @return this, for fluent call chaining - */ - public ValidationFailureBuilder error() { - severity = Severity.ERROR; - return this; - } - - /** - * Sets the property the failure occurred against. - * @param property the property name - * @return this, for fluent call chaining - */ - public ValidationFailureBuilder forProperty(String property) { - this.property = property; - return this; - } - - /** - * Sets the name of the constraint that failed. - * @param constraint the name of the validation constraint - * @return this, for fluent call chaining - */ - public ValidationFailureBuilder constraint(String constraint) { - this.constraint = constraint; - return this; - } - - /** - * Sets an explicit failure message. The value may be a literal string or a resolvable message code. - * @param message the failure message - * @return this, for fluent call chaining - */ - public ValidationFailureBuilder message(String message) { - this.message = message; - return this; - } - - /** - * Add a detail to associate with the failure. The value provided serves as both the logical name of the detail and - * the code used to resolve the detail message text. - * @param nameAndValue the value to use as both the logical name of the message and the constraint-relative message - * code; for example, "cause" or "recommendedAction". - * @return this, for fluent call chaining - */ - public ValidationFailureBuilder detail(String nameAndValue) { - return detail(nameAndValue, nameAndValue); - } - - /** - * Add a detail to associate with the failure. - * @param name the logical name of the message; for example, "cause" or "recommendedAction" - * @param value the detail value, either a hard coded message string or a constraint-relative message code used to - * resolve the detail message text - * @return this, for fluent call chaining - */ - public ValidationFailureBuilder detail(String name, String value) { - if (details == null) { - details = new HashMap(); - } - details.put(name, value); - return this; - } - - /** - * Adds a failure message argument. - * @param name the argument name - * @param value the argument value - * @return this, for fluent call chaining - */ - public ValidationFailureBuilder arg(String name, Object value) { - if (args == null) { - args = new TreeMap(); - } - args.put(name, value); - return this; - } - - /** - * Adds a failure message argument whose value is also message source resolvable. Use this when the argument value - * itself needs to be localized. - * @param name the argument name - * @param code the code that will be used to resolve the argument - * @see MessageSourceResolvable - * @return this, for fluent call chaining - */ - public ValidationFailureBuilder resolvableArg(String name, String code) { - return arg(name, new DefaultMessageSourceResolvable(code)); - } - - /** - * Build the ValidationFailure. Call after setting builder properties. - * @see #forProperty(String) - * @see #constraint(String) - * @see #message(String) - * @see #detail(String) - * @see #arg(String, Object) - * @see #resolvableArg(String, String) - * @return this, for fluent call chaining - */ - public ValidationFailure build() { - if (severity == null) { - severity = Severity.ERROR; - } - return new ValidationFailure(severity, property, constraint, message, details, args); - } - -} \ No newline at end of file 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 deleted file mode 100644 index 2d68bed9..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactory.java +++ /dev/null @@ -1,69 +0,0 @@ -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; - } - - /** - * 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(); - 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 deleted file mode 100644 index 0c577fce..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureMessageResolverFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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; - -import org.springframework.binding.message.Message; -import org.springframework.binding.message.MessageContext; -import org.springframework.binding.message.MessageResolver; - -/** - * Translates a ValidationFailure into a MessageResolver that can be used to add a localized failure {@link Message} to - * a {@link MessageContext} . - * - * @author Keith Donald - */ -public interface ValidationFailureMessageResolverFactory { - - /** - * Creates a new MessageResolver that can resolve the failure {@link Message} for the reported ValidationFailure. - * @param failure a validation failure reported by a validator - * @param modelContext additional information about the model that failed to validate - * @return the failure message resolver - */ - public MessageResolver createMessageResolver(ValidationFailure failure, ValidationFailureModelContext modelContext); - -} 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 deleted file mode 100644 index bd0bfe75..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationFailureModelContext.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.springframework.binding.validation; - -/** - * Provides additional model context regarding a validation failure. Used by a - * {@link ValidationFailureMessageResolverFactory} to resolve failure messages. - */ -public interface ValidationFailureModelContext { - - /** - * The name of the model object that was validated. - */ - public String getModel(); - - /** - * When reporting a property validation failure, the invalid user entered value. - */ - public Object getInvalidValue(); - - /** - * When reporting a property validation failure, the type of the property that failed to validate. - */ - 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(); - -} \ No newline at end of file diff --git a/spring-binding/src/test/java/org/springframework/binding/validation/AccountRegistrationForm.java b/spring-binding/src/test/java/org/springframework/binding/validation/AccountRegistrationForm.java deleted file mode 100644 index 4c3cec51..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/validation/AccountRegistrationForm.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.springframework.binding.validation; - -import org.springframework.binding.validation.ConfirmationConstraint.ConfirmationForm; - -public class AccountRegistrationForm { - private String username; - private String password; - private String confirmedPassword; - - public void validate(ValidationContext context) { - context.setProperty("username"); - context.validate(new RequiredConstraint()); - context.validate(new LengthConstraint(3, 10)); - - context.setProperty("password"); - context.validate(new RequiredConstraint()); - context.validate(new LengthConstraint(6, 10)); - context.validate(new PasswordStrengthConstraint()); - - context.setProperty("confirmedPassword"); - context.validate(new ConfirmationConstraint(), new ConfirmationForm(password, confirmedPassword)); - } -} diff --git a/spring-binding/src/test/java/org/springframework/binding/validation/ConfirmationConstraint.java b/spring-binding/src/test/java/org/springframework/binding/validation/ConfirmationConstraint.java deleted file mode 100644 index 4a3a911b..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/validation/ConfirmationConstraint.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.springframework.binding.validation; - -import org.springframework.util.ObjectUtils; - -public class ConfirmationConstraint { - - public void validate(ConfirmationForm form, ValidationContext context) { - if (form.getValue() == null) { - return; - } - if (!ObjectUtils.nullSafeEquals(form.getValue(), form.getConfirmedValue())) { - context.addDefaultFailure(); - } - } - - public static class ConfirmationForm { - - private Object value; - - private Object confirmedValue; - - public ConfirmationForm(String value, String confirmedValue) { - this.value = value; - this.confirmedValue = confirmedValue; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } - - public Object getConfirmedValue() { - return confirmedValue; - } - - public void setConfirmedValue(Object confirmedValue) { - this.confirmedValue = confirmedValue; - } - - } - -} \ 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 deleted file mode 100644 index 524a4bef..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/validation/DefaultSpringMvcValidationFailureMessageCodesFactoryTests.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.springframework.binding.validation; - -import junit.framework.TestCase; - -public class DefaultSpringMvcValidationFailureMessageCodesFactoryTests extends TestCase { - private DefaultSpringMvcValidationFailureMessageCodesFactory factory = new DefaultSpringMvcValidationFailureMessageCodesFactory(); - - public void testCreateGeneralModelFailureMessageCodes() { - ValidationFailure failure = new ValidationFailureBuilder().constraint("invalid").build(); - 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 TestValidationFailureModelContext("testBean", null, - String.class, null)); - assertEquals("validation.required.testBean.foo", codes[0]); - assertEquals("validation.required.java.lang.String", codes[1]); - assertEquals("validation.required", codes[2]); - } -} 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 deleted file mode 100644 index 4a08a0ce..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/validation/DefaultValidationFailureMessageResolverFactoryTests.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.springframework.binding.validation; - -import java.util.Date; -import java.util.Locale; - -import junit.framework.TestCase; - -import org.jboss.el.ExpressionFactoryImpl; -import org.springframework.binding.convert.converters.StringToObject; -import org.springframework.binding.convert.service.DefaultConversionService; -import org.springframework.binding.expression.el.ELExpressionParser; -import org.springframework.binding.message.Message; -import org.springframework.binding.message.MessageResolver; -import org.springframework.context.support.ResourceBundleMessageSource; - -public class DefaultValidationFailureMessageResolverFactoryTests extends TestCase { - - private ELExpressionParser parser = new ELExpressionParser(new ExpressionFactoryImpl()); - - private DefaultConversionService conversionService = new DefaultConversionService(); - - private ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); - - private DefaultValidationFailureMessageResolverFactory factory; - - private ValidationFailureBuilder builder = new ValidationFailureBuilder(); - - public void setUp() { - factory = new DefaultValidationFailureMessageResolverFactory(parser, conversionService); - messageSource.setBasename("org.springframework.binding.validation.messages"); - } - - public void testResolveMessage() { - ValidationFailure failure = builder.forProperty("foo").constraint("required").build(); - 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 TestValidationFailureModelContext( - "testBean", "", String.class, null)); - Message message = resolver.resolveMessage(messageSource, Locale.getDefault()); - assertEquals("bogus is required", message.getText()); - } - - public void testResolveMessageWithCustomArg() { - ValidationFailureBuilder builder = new ValidationFailureBuilder(); - ValidationFailure failure = builder.forProperty("checkinDate").constraint("invalidFormat").arg("format", - "yyyy-MM-dd").build(); - 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()); - } - - public void testResolveMessageWithCustomResolvableArg() { - ValidationFailure failure = builder.forProperty("checkinDate").constraint("invalidFormat").resolvableArg( - "format", "formats.dateFormat").build(); - 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()); - } - - public void testResolveMessageWithValue() { - ValidationFailure failure = builder.forProperty("checkinDate").constraint("invalidFormat2").resolvableArg( - "format", "formats.dateFormat").build(); - 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()); - } - - 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 TestValidationFailureModelContext( - "testBean", "bogus", Integer.class, null)); - Message message = resolver.resolveMessage(messageSource, Locale.getDefault()); - assertEquals("Amount must be between 1 and 100", message.getText()); - } - - public void testResolveMessageWithArgCustomConversion() { - 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 TestValidationFailureModelContext( - "testBean", "bogus", Money.class, "stringToMoney")); - Message message = resolver.resolveMessage(messageSource, Locale.getDefault()); - assertEquals("Amount must be between $1 and $100", message.getText()); - } - - public static class Money { - private int amount; - - public Money(int amount) { - this.amount = amount; - } - - public int getAmount() { - return amount; - } - } - - public static class StringToMoney extends StringToObject { - - public StringToMoney() { - super(Money.class); - } - - protected Object toObject(String string, Class targetClass) throws Exception { - throw new UnsupportedOperationException("Not supported"); - } - - protected String toString(Object object) throws Exception { - return "$" + String.valueOf(((Money) object).amount); - } - - } -} diff --git a/spring-binding/src/test/java/org/springframework/binding/validation/LengthConstraint.java b/spring-binding/src/test/java/org/springframework/binding/validation/LengthConstraint.java deleted file mode 100644 index f83be355..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/validation/LengthConstraint.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.springframework.binding.validation; - -public class LengthConstraint { - - private Integer min; - - private Integer max; - - public LengthConstraint(int min, int max) { - this.min = new Integer(min); - this.max = new Integer(max); - } - - public Integer getMin() { - return min; - } - - public Integer getMax() { - return max; - } - - public void validate(String value, ValidationContext context) { - if (value == null || value.length() < min.intValue() || value.length() > max.intValue()) { - context.addFailure(createFailure()); - } - } - - protected ValidationFailure createFailure() { - return new ValidationFailureBuilder().arg("min", getMin()).arg("max", getMax()).build(); - } - -} diff --git a/spring-binding/src/test/java/org/springframework/binding/validation/PasswordStrengthConstraint.java b/spring-binding/src/test/java/org/springframework/binding/validation/PasswordStrengthConstraint.java deleted file mode 100644 index ced40700..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/validation/PasswordStrengthConstraint.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.springframework.binding.validation; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class PasswordStrengthConstraint { - - private Pattern pattern = Pattern.compile("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]$"); - - public void validate(String password, ValidationContext context) { - Matcher matcher = pattern.matcher(password); - if (!matcher.find()) { - context.addFailure(createFailure()); - } - } - - protected ValidationFailure createFailure() { - return new ValidationFailureBuilder().warning().detail("cause").detail("recommendedAction") - .build(); - } - -} \ No newline at end of file diff --git a/spring-binding/src/test/java/org/springframework/binding/validation/RequiredConstraint.java b/spring-binding/src/test/java/org/springframework/binding/validation/RequiredConstraint.java deleted file mode 100644 index 1f80538b..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/validation/RequiredConstraint.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.springframework.binding.validation; - -public class RequiredConstraint { - - public void validate(Object value, ValidationContext context) { - if (value == null) { - context.addDefaultFailure(); - } - } - -} \ No newline at end of file diff --git a/spring-binding/src/test/java/org/springframework/binding/validation/TestValidationFailureModelContext.java b/spring-binding/src/test/java/org/springframework/binding/validation/TestValidationFailureModelContext.java deleted file mode 100644 index 0d228297..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/validation/TestValidationFailureModelContext.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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; - -import org.springframework.binding.validation.ValidationFailureMessageResolverFactory; -import org.springframework.binding.validation.ValidationFailureModelContext; - -/** - * Provides additional model context regarding a validation failure. Used by a - * {@link ValidationFailureMessageResolverFactory} to resolve failure messages. - */ -public class TestValidationFailureModelContext implements 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 TestValidationFailureModelContext(String model, Object invalidValue, Class propertyType, - String propertyConverter) { - this.model = model; - this.invalidValue = invalidValue; - this.propertyType = propertyType; - this.propertyConverter = propertyConverter; - } - - public String getModel() { - return model; - } - - public Object getInvalidValue() { - return invalidValue; - } - - public Class getPropertyType() { - return propertyType; - } - - public String getPropertyConverter() { - return propertyConverter; - } - -} 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 deleted file mode 100644 index 4cb77acb..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/validation/ValidationFailureMessageCodesFactoryTests.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.springframework.binding.validation; - -import junit.framework.TestCase; - -public class ValidationFailureMessageCodesFactoryTests extends TestCase { - private ValidationFailureMessageCodesFactory factory = new ValidationFailureMessageCodesFactory(); - - public void testCreateGeneralModelFailureMessageCodes() { - ValidationFailure failure = new ValidationFailureBuilder().constraint("invalid").build(); - 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 TestValidationFailureModelContext("testBean", null, - String.class, null)); - assertEquals("validation.testBean.foo.required", codes[0]); - assertEquals("validation.java.lang.String.required", codes[1]); - assertEquals("validation.required", codes[2]); - } -} diff --git a/spring-binding/src/test/java/org/springframework/binding/validation/messages.properties b/spring-binding/src/test/java/org/springframework/binding/validation/messages.properties deleted file mode 100644 index 7c27dc16..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/validation/messages.properties +++ /dev/null @@ -1,10 +0,0 @@ -validation.required=#{label} is required -validation.invalidFormat=#{label} must be in format #{format} -validation.invalidFormat2=#{label} must be in format #{format} but it was '#{value}' -validation.range=#{label} must be between #{min} and #{max} - -label.testBean.foo=Foo -label.testBean.checkinDate=Check In Date -label.testBean.amount=Amount - -formats.dateFormat=yyyy-MM-dd \ No newline at end of file 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 aa6da78e..c1b57b1c 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 @@ -8,33 +8,26 @@ import org.springframework.binding.mapping.MappingResults; 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; this.mappingResults = mappingResults; } + public MessageContext getMessageContext() { + return requestContext.getMessageContext(); + } + public String getUserEvent() { return eventId; } @@ -48,48 +41,6 @@ public class DefaultValidationContext implements ValidationContext { return result != null ? result.getOriginalValue() : null; } - public void setProperty(String property) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void validate(Object constraint, Object propertyContext) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void validate(Object constraint) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void addDefaultFailure() { - throw new UnsupportedOperationException("Not yet implemented"); - } - - 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));