11 changed files with 6 additions and 509 deletions
@ -1,7 +0,0 @@
@@ -1,7 +0,0 @@
|
||||
package org.springframework.ui.lifecycle; |
||||
|
||||
public interface BindAndValidateLifecycle { |
||||
|
||||
public void execute(); |
||||
|
||||
} |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
package org.springframework.ui.lifecycle; |
||||
|
||||
public interface BindAndValidateLifecycleFactory { |
||||
BindAndValidateLifecycle getLifecycle(Object model); |
||||
} |
@ -1,88 +0,0 @@
@@ -1,88 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2009 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.ui.lifecycle; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.springframework.ui.alert.AlertContext; |
||||
import org.springframework.ui.binding.binder.Binder; |
||||
import org.springframework.ui.binding.binder.BindingResult; |
||||
import org.springframework.ui.binding.binder.BindingResults; |
||||
import org.springframework.ui.validation.ValidationFailure; |
||||
import org.springframework.ui.validation.Validator; |
||||
|
||||
/** |
||||
* Implementation of the model bind and validate lifecycle. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
*/ |
||||
public final class BindAndValidateLifecycleImpl { |
||||
|
||||
private Binder binder; |
||||
|
||||
private Validator validator; |
||||
|
||||
private ValidationDecider validationDecider = ValidationDecider.ALWAYS_VALIDATE; |
||||
|
||||
private final AlertContext alertContext; |
||||
|
||||
/** |
||||
* Create a new bind and validate lifecycle. |
||||
* @param binder the binder to use for model binding |
||||
* @param validator the validator to use for model validation |
||||
* @param alertContext a context for adding binding and validation-related alerts |
||||
*/ |
||||
public BindAndValidateLifecycleImpl(Binder binder, Validator validator, AlertContext alertContext) { |
||||
this.binder = binder; |
||||
this.validator = validator; |
||||
this.alertContext = alertContext; |
||||
} |
||||
|
||||
/** |
||||
* Configures the strategy that determines if validation should execute after binding. |
||||
* @param validationDecider the validation decider |
||||
*/ |
||||
public void setValidationDecider(ValidationDecider validationDecider) { |
||||
this.validationDecider = validationDecider; |
||||
} |
||||
|
||||
/** |
||||
* Execute the bind and validate lifecycle. |
||||
* Any bind or validation errors are recorded as alerts against the {@link AlertContext}. |
||||
* @param sourceValues the source values to bind and validate |
||||
*/ |
||||
public void execute(Map<String, ? extends Object> sourceValues) { |
||||
BindingResults bindingResults = binder.bind(sourceValues); |
||||
List<ValidationFailure> validationFailures = validate(bindingResults); |
||||
for (BindingResult result : bindingResults.failures()) { |
||||
alertContext.add(result.getProperty(), result.getAlert()); |
||||
} |
||||
for (ValidationFailure failure : validationFailures) { |
||||
alertContext.add(failure.getProperty(), failure.getAlert()); |
||||
} |
||||
} |
||||
|
||||
private List<ValidationFailure> validate(BindingResults bindingResults) { |
||||
if (validator != null && validationDecider.shouldValidateAfter(bindingResults)) { |
||||
return validator.validate(binder.getModel(), bindingResults.successes().properties()); |
||||
} else { |
||||
return Collections.emptyList(); |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,43 +0,0 @@
@@ -1,43 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2009 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.ui.lifecycle; |
||||
|
||||
import org.springframework.ui.binding.binder.BindingResults; |
||||
|
||||
/** |
||||
* Decides if validation should run for an execution of the bind and validate lifecycle. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
* @see BindAndValidateLifecycleImpl#execute(java.util.Map) |
||||
*/ |
||||
interface ValidationDecider { |
||||
|
||||
/** |
||||
* Should validation execute after model binding? |
||||
* @param results the results of model binding |
||||
* @return yes or no |
||||
*/ |
||||
boolean shouldValidateAfter(BindingResults results); |
||||
|
||||
/** |
||||
* Singleton reference to a ValidationDecider that always returns true. |
||||
*/ |
||||
static final ValidationDecider ALWAYS_VALIDATE = new ValidationDecider() { |
||||
public boolean shouldValidateAfter(BindingResults results) { |
||||
return true; |
||||
} |
||||
}; |
||||
} |
@ -1,21 +0,0 @@
@@ -1,21 +0,0 @@
|
||||
package org.springframework.ui.validation; |
||||
|
||||
import org.springframework.ui.alert.Alert; |
||||
|
||||
/** |
||||
* A single validation failure generated by a Validator. |
||||
* @author Keith Donald |
||||
* @see Validator#validate(Object, java.util.List) |
||||
*/ |
||||
public interface ValidationFailure { |
||||
|
||||
/** |
||||
* The name of the model property associated with this validation result. |
||||
*/ |
||||
String getProperty(); |
||||
|
||||
/** |
||||
* Gets the alert for this validation failure, appropriate for rendering the failure to the user. |
||||
*/ |
||||
Alert getAlert(); |
||||
} |
@ -1,34 +0,0 @@
@@ -1,34 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2009 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.ui.validation; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Validates a model object. |
||||
* @author Keith Donald |
||||
* @param <M> the type of model object this validator supports |
||||
*/ |
||||
public interface Validator { |
||||
|
||||
/** |
||||
* Validate the properties of the model object. |
||||
* @param model the model object |
||||
* @param properties the properties to validate |
||||
* @return a list of validation failures, empty if there were no failures |
||||
*/ |
||||
List<ValidationFailure> validate(Object model, List<String> properties); |
||||
} |
@ -1,308 +0,0 @@
@@ -1,308 +0,0 @@
|
||||
package org.springframework.ui.lifecycle; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Ignore; |
||||
import org.junit.Test; |
||||
import org.springframework.ui.alert.Alert; |
||||
import org.springframework.ui.alert.Alerts; |
||||
import org.springframework.ui.alert.Severity; |
||||
import org.springframework.ui.alert.support.DefaultAlertContext; |
||||
import org.springframework.ui.binding.binder.WebBinder; |
||||
import org.springframework.ui.binding.support.GenericBindingFactory; |
||||
import org.springframework.ui.format.number.CurrencyFormat; |
||||
import org.springframework.ui.validation.ValidationFailure; |
||||
import org.springframework.ui.validation.Validator; |
||||
import org.springframework.ui.validation.constraint.Impact; |
||||
import org.springframework.ui.validation.constraint.Message; |
||||
import org.springframework.ui.validation.constraint.ValidationConstraint; |
||||
|
||||
import edu.emory.mathcs.backport.java.util.Collections; |
||||
|
||||
public class BindAndValidateLifecycleTests { |
||||
|
||||
private BindAndValidateLifecycleImpl lifecycle; |
||||
|
||||
private TestBean model; |
||||
|
||||
private DefaultAlertContext alertContext; |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
model = new TestBean(); |
||||
alertContext = new DefaultAlertContext(); |
||||
WebBinder binder = new WebBinder(new GenericBindingFactory(model)); |
||||
Validator validator = new TestBeanValidator(); |
||||
lifecycle = new BindAndValidateLifecycleImpl(binder, validator, alertContext); |
||||
} |
||||
|
||||
static class TestBeanValidator implements Validator { |
||||
public List<ValidationFailure> validate(Object model, List<String> properties) { |
||||
TestBean bean = (TestBean) model; |
||||
RequiredConstraint required = new RequiredConstraint(); |
||||
boolean valid = required.validate(bean); |
||||
if (!valid) { |
||||
|
||||
} |
||||
return Collections.emptyList(); |
||||
} |
||||
} |
||||
|
||||
@Message({"en=#{label} is required", "es=#{label} es necesario"}) |
||||
static class RequiredConstraint implements ValidationConstraint<Object> { |
||||
public boolean validate(Object value) { |
||||
if (value != null) { |
||||
return value instanceof String ? ((String) value).length() > 0 : true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Message("#{label} is a weak password") |
||||
@Impact(Severity.WARNING) |
||||
static class StrongPasswordConstraint implements ValidationConstraint<String> { |
||||
public boolean validate(String password) { |
||||
if (password.length() > 6) { |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Message("#{label} could not be confirmed; #{value} must match #{model.confirmPassword}") |
||||
static class ConfirmedPasswordConstraint implements ValidationConstraint<SignupForm> { |
||||
public boolean validate(SignupForm form) { |
||||
if (form.password.equals(form.confirmPassword)) { |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Message("#{label} must be between #{this.min} and #{this.max}") |
||||
static class RangeConstraint implements ValidationConstraint<Number> { |
||||
private Long min; |
||||
|
||||
private Long max; |
||||
|
||||
public RangeConstraint(Long min, Long max) { |
||||
this.min = min; |
||||
this.max = max; |
||||
} |
||||
|
||||
public boolean validate(Number value) { |
||||
Long longValue = value.longValue(); |
||||
if (longValue >= min && longValue <= max) { |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
static class TestValidationFailure implements ValidationFailure { |
||||
|
||||
private String property; |
||||
|
||||
private String message; |
||||
|
||||
public TestValidationFailure(String property, String message) { |
||||
this.property = property; |
||||
} |
||||
|
||||
public String getProperty() { |
||||
return property; |
||||
} |
||||
|
||||
public Alert getAlert() { |
||||
return Alerts.error(message); |
||||
} |
||||
|
||||
} |
||||
|
||||
@Test |
||||
@Ignore |
||||
public void testExecuteLifecycleNoErrors() { |
||||
Map<String, Object> userMap = new HashMap<String, Object>(); |
||||
userMap.put("string", "test"); |
||||
userMap.put("integer", "3"); |
||||
userMap.put("foo", "BAR"); |
||||
lifecycle.execute(userMap); |
||||
assertEquals(0, alertContext.getAlerts().size()); |
||||
} |
||||
|
||||
@Test |
||||
@Ignore |
||||
public void testExecuteLifecycleBindingErrors() { |
||||
Map<String, Object> userMap = new HashMap<String, Object>(); |
||||
userMap.put("string", "test"); |
||||
userMap.put("integer", "bogus"); |
||||
userMap.put("foo", "BAR"); |
||||
lifecycle.execute(userMap); |
||||
assertEquals(1, alertContext.getAlerts().size()); |
||||
assertEquals(Severity.FATAL, alertContext.getAlerts("integer").get(0).getSeverity()); |
||||
assertEquals("Failed to bind to property 'integer'; user value 'bogus' could not be converted to property type [java.lang.Integer]", alertContext.getAlerts("integer").get(0).getMessage()); |
||||
} |
||||
|
||||
public static enum FooEnum { |
||||
BAR, BAZ, BOOP; |
||||
} |
||||
|
||||
public static class TestBean { |
||||
private String string; |
||||
private int integer; |
||||
private Date date; |
||||
private FooEnum foo; |
||||
private BigDecimal currency; |
||||
private List<FooEnum> foos; |
||||
private List<Address> addresses; |
||||
|
||||
public String getString() { |
||||
return string; |
||||
} |
||||
|
||||
public void setString(String string) { |
||||
this.string = string; |
||||
} |
||||
|
||||
public int getInteger() { |
||||
return integer; |
||||
} |
||||
|
||||
public void setInteger(int integer) { |
||||
this.integer = integer; |
||||
} |
||||
|
||||
public Date getDate() { |
||||
return date; |
||||
} |
||||
|
||||
public void setDate(Date date) { |
||||
this.date = date; |
||||
} |
||||
|
||||
public FooEnum getFoo() { |
||||
return foo; |
||||
} |
||||
|
||||
public void setFoo(FooEnum foo) { |
||||
this.foo = foo; |
||||
} |
||||
|
||||
@CurrencyFormat |
||||
public BigDecimal getCurrency() { |
||||
return currency; |
||||
} |
||||
|
||||
public void setCurrency(BigDecimal currency) { |
||||
this.currency = currency; |
||||
} |
||||
|
||||
public List<FooEnum> getFoos() { |
||||
return foos; |
||||
} |
||||
|
||||
public void setFoos(List<FooEnum> foos) { |
||||
this.foos = foos; |
||||
} |
||||
|
||||
public List<Address> getAddresses() { |
||||
return addresses; |
||||
} |
||||
|
||||
public void setAddresses(List<Address> addresses) { |
||||
this.addresses = addresses; |
||||
} |
||||
|
||||
} |
||||
|
||||
public static class Address { |
||||
private String street; |
||||
private String city; |
||||
private String state; |
||||
private String zip; |
||||
private String country; |
||||
|
||||
public String getStreet() { |
||||
return street; |
||||
} |
||||
|
||||
public void setStreet(String street) { |
||||
this.street = street; |
||||
} |
||||
|
||||
public String getCity() { |
||||
return city; |
||||
} |
||||
|
||||
public void setCity(String city) { |
||||
this.city = city; |
||||
} |
||||
|
||||
public String getState() { |
||||
return state; |
||||
} |
||||
|
||||
public void setState(String state) { |
||||
this.state = state; |
||||
} |
||||
|
||||
public String getZip() { |
||||
return zip; |
||||
} |
||||
|
||||
public void setZip(String zip) { |
||||
this.zip = zip; |
||||
} |
||||
|
||||
public String getCountry() { |
||||
return country; |
||||
} |
||||
|
||||
public void setCountry(String country) { |
||||
this.country = country; |
||||
} |
||||
|
||||
} |
||||
|
||||
public class TestAnnotatedBean { |
||||
|
||||
private String editable; |
||||
|
||||
private String notEditable; |
||||
|
||||
public String getEditable() { |
||||
return editable; |
||||
} |
||||
|
||||
public void setEditable(String editable) { |
||||
this.editable = editable; |
||||
} |
||||
|
||||
public String getNotEditable() { |
||||
return notEditable; |
||||
} |
||||
|
||||
public void setNotEditable(String notEditable) { |
||||
this.notEditable = notEditable; |
||||
} |
||||
|
||||
} |
||||
|
||||
public static class SignupForm { |
||||
private String username; |
||||
private String password; |
||||
private String confirmPassword; |
||||
} |
||||
} |
Loading…
Reference in new issue