bind and validate lifecycle initial commit
This commit is contained in:
parent
8998228fac
commit
1d6a3e5360
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2004-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;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.ui.binding.BindingResults;
|
||||||
|
import org.springframework.ui.binding.UserValues;
|
||||||
|
import org.springframework.ui.binding.support.WebBinder;
|
||||||
|
import org.springframework.ui.message.MessageContext;
|
||||||
|
import org.springframework.ui.validation.Validator;
|
||||||
|
|
||||||
|
public class WebBindAndValidateLifecycle {
|
||||||
|
|
||||||
|
private WebBinder binder;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private MessageContext messages;
|
||||||
|
|
||||||
|
private ValidationDecider validationDecider = ValidationDecider.ALWAYS_VALIDATE;
|
||||||
|
|
||||||
|
private Validator validator;
|
||||||
|
|
||||||
|
public WebBindAndValidateLifecycle(Object model, MessageContext messages) {
|
||||||
|
this.binder = new WebBinder(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void execute(Map<String, ? extends Object> userMap) {
|
||||||
|
UserValues values = binder.createUserValues(userMap);
|
||||||
|
BindingResults results = binder.bind(values);
|
||||||
|
if (validationDecider.shouldValidateAfter(results)) {
|
||||||
|
validator.validate(binder.getModel(), results.successes().properties());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ValidationDecider {
|
||||||
|
|
||||||
|
boolean shouldValidateAfter(BindingResults results);
|
||||||
|
|
||||||
|
public static ValidationDecider ALWAYS_VALIDATE = new ValidationDecider() {
|
||||||
|
public boolean shouldValidateAfter(BindingResults results) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.ui.binding;
|
package org.springframework.ui.binding;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.ui.format.AnnotationFormatterFactory;
|
import org.springframework.ui.format.AnnotationFormatterFactory;
|
||||||
|
|
@ -74,10 +73,10 @@ public interface Binder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind values in the map to the properties of the model object.
|
* Bind values in the map to the properties of the model object.
|
||||||
* TODO consider returning BindingResults object that makes it easier to query/introspect results
|
|
||||||
* @param values user-entered values to bind
|
* @param values user-entered values to bind
|
||||||
|
* @return the results of the binding operation
|
||||||
*/
|
*/
|
||||||
List<BindingResult> bind(UserValues values);
|
BindingResults bind(UserValues values);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link UserValue} list from a Map of user-submitted fields.
|
* Creates a {@link UserValue} list from a Map of user-submitted fields.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2004-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.binding;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The results of a bind operation.
|
||||||
|
* @author Keith Donald
|
||||||
|
* @see Binder#bind(UserValues)
|
||||||
|
*/
|
||||||
|
public interface BindingResults extends Iterable<BindingResult> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The subset of BindingResults that were successful.
|
||||||
|
*/
|
||||||
|
BindingResults successes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The subset of BindingResults that failed.
|
||||||
|
*/
|
||||||
|
BindingResults failures();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of results.
|
||||||
|
*/
|
||||||
|
int size();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The BindingResult at the specified index.
|
||||||
|
* @throws IndexOutOfBoundsException if the index is out of bounds
|
||||||
|
*/
|
||||||
|
BindingResult get(int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of properties for which binding was attempted.
|
||||||
|
*/
|
||||||
|
List<String> properties();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -23,6 +23,7 @@ import java.text.ParseException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -48,6 +49,7 @@ import org.springframework.ui.binding.Binder;
|
||||||
import org.springframework.ui.binding.Binding;
|
import org.springframework.ui.binding.Binding;
|
||||||
import org.springframework.ui.binding.BindingConfiguration;
|
import org.springframework.ui.binding.BindingConfiguration;
|
||||||
import org.springframework.ui.binding.BindingResult;
|
import org.springframework.ui.binding.BindingResult;
|
||||||
|
import org.springframework.ui.binding.BindingResults;
|
||||||
import org.springframework.ui.binding.FormatterRegistry;
|
import org.springframework.ui.binding.FormatterRegistry;
|
||||||
import org.springframework.ui.binding.UserValue;
|
import org.springframework.ui.binding.UserValue;
|
||||||
import org.springframework.ui.binding.UserValues;
|
import org.springframework.ui.binding.UserValues;
|
||||||
|
|
@ -128,8 +130,8 @@ public class GenericBinder implements Binder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BindingResult> bind(UserValues values) {
|
public BindingResults bind(UserValues values) {
|
||||||
List<BindingResult> results = new ArrayList<BindingResult>(values.size());
|
ArrayListBindingResults results = new ArrayListBindingResults(values.size());
|
||||||
for (UserValue value : values) {
|
for (UserValue value : values) {
|
||||||
BindingImpl binding = (BindingImpl) getBinding(value.getProperty());
|
BindingImpl binding = (BindingImpl) getBinding(value.getProperty());
|
||||||
results.add(binding.setValue(value.getValue()));
|
results.add(binding.setValue(value.getValue()));
|
||||||
|
|
@ -147,6 +149,54 @@ public class GenericBinder implements Binder {
|
||||||
|
|
||||||
// internal helpers
|
// internal helpers
|
||||||
|
|
||||||
|
static class ArrayListBindingResults implements BindingResults {
|
||||||
|
|
||||||
|
private List<BindingResult> results;
|
||||||
|
|
||||||
|
public ArrayListBindingResults(int size) {
|
||||||
|
results = new ArrayList<BindingResult>(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(BindingResult result) {
|
||||||
|
results.add(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementing Iterable
|
||||||
|
|
||||||
|
public Iterator<BindingResult> iterator() {
|
||||||
|
return results.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementing BindingResults
|
||||||
|
|
||||||
|
public BindingResults successes() {
|
||||||
|
// TODO
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindingResults failures() {
|
||||||
|
// TODO
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindingResult get(int index) {
|
||||||
|
return results.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> properties() {
|
||||||
|
List<String> properties = new ArrayList<String>(results.size());
|
||||||
|
for (BindingResult result : this) {
|
||||||
|
properties.add(result.getProperty());
|
||||||
|
}
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return results.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class BindingImpl implements Binding {
|
class BindingImpl implements Binding {
|
||||||
|
|
||||||
private Expression property;
|
private Expression property;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import org.springframework.ui.binding.Binder;
|
||||||
import org.springframework.ui.binding.Binding;
|
import org.springframework.ui.binding.Binding;
|
||||||
import org.springframework.ui.binding.BindingConfiguration;
|
import org.springframework.ui.binding.BindingConfiguration;
|
||||||
import org.springframework.ui.binding.BindingResult;
|
import org.springframework.ui.binding.BindingResult;
|
||||||
|
import org.springframework.ui.binding.BindingResults;
|
||||||
import org.springframework.ui.binding.UserValues;
|
import org.springframework.ui.binding.UserValues;
|
||||||
import org.springframework.ui.format.AnnotationFormatterFactory;
|
import org.springframework.ui.format.AnnotationFormatterFactory;
|
||||||
import org.springframework.ui.format.Formatter;
|
import org.springframework.ui.format.Formatter;
|
||||||
|
|
@ -55,7 +56,7 @@ public class GenericBinderTests {
|
||||||
values.add("string", "test");
|
values.add("string", "test");
|
||||||
values.add("integer", "3");
|
values.add("integer", "3");
|
||||||
values.add("foo", "BAR");
|
values.add("foo", "BAR");
|
||||||
List<BindingResult> results = binder.bind(values);
|
BindingResults results = binder.bind(values);
|
||||||
assertEquals(3, results.size());
|
assertEquals(3, results.size());
|
||||||
|
|
||||||
assertEquals("string", results.get(0).getProperty());
|
assertEquals("string", results.get(0).getProperty());
|
||||||
|
|
@ -85,7 +86,7 @@ public class GenericBinderTests {
|
||||||
// bad value
|
// bad value
|
||||||
values.add("integer", "bogus");
|
values.add("integer", "bogus");
|
||||||
values.add("foo", "BAR");
|
values.add("foo", "BAR");
|
||||||
List<BindingResult> results = binder.bind(values);
|
BindingResults results = binder.bind(values);
|
||||||
assertEquals(3, results.size());
|
assertEquals(3, results.size());
|
||||||
assertTrue(results.get(1).isError());
|
assertTrue(results.get(1).isError());
|
||||||
assertEquals("typeConversionFailure", results.get(1).getErrorCode());
|
assertEquals("typeConversionFailure", results.get(1).getErrorCode());
|
||||||
|
|
@ -127,7 +128,7 @@ public class GenericBinderTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindSingleValuePropertyNotFound() throws ParseException {
|
public void bindSingleValuePropertyNotFound() throws ParseException {
|
||||||
List<BindingResult> results = binder.bind(UserValues.single("bogus", "2009-06-01"));
|
BindingResults results = binder.bind(UserValues.single("bogus", "2009-06-01"));
|
||||||
assertEquals(1, results.size());
|
assertEquals(1, results.size());
|
||||||
assertTrue(results.get(0).isError());
|
assertTrue(results.get(0).isError());
|
||||||
assertEquals("propertyNotFound", results.get(0).getErrorCode());
|
assertEquals("propertyNotFound", results.get(0).getErrorCode());
|
||||||
|
|
@ -139,7 +140,7 @@ public class GenericBinderTests {
|
||||||
userMap.put("string", "test");
|
userMap.put("string", "test");
|
||||||
userMap.put("integer", "3");
|
userMap.put("integer", "3");
|
||||||
UserValues values = binder.createUserValues(userMap);
|
UserValues values = binder.createUserValues(userMap);
|
||||||
List<BindingResult> results = binder.bind(values);
|
BindingResults results = binder.bind(values);
|
||||||
assertEquals(2, results.size());
|
assertEquals(2, results.size());
|
||||||
assertEquals("test", results.get(0).getUserValue());
|
assertEquals("test", results.get(0).getUserValue());
|
||||||
assertEquals("3", results.get(1).getUserValue());
|
assertEquals("3", results.get(1).getUserValue());
|
||||||
|
|
@ -245,7 +246,7 @@ public class GenericBinderTests {
|
||||||
values.add("addresses[5].state", "FL");
|
values.add("addresses[5].state", "FL");
|
||||||
values.add("addresses[5].zip", "32901");
|
values.add("addresses[5].zip", "32901");
|
||||||
|
|
||||||
List<BindingResult> results = binder.bind(values);
|
BindingResults results = binder.bind(values);
|
||||||
Assert.assertEquals(6, bean.addresses.size());
|
Assert.assertEquals(6, bean.addresses.size());
|
||||||
Assert.assertEquals("Palm Bay", bean.addresses.get(1).city);
|
Assert.assertEquals("Palm Bay", bean.addresses.get(1).city);
|
||||||
Assert.assertNotNull(bean.addresses.get(2));
|
Assert.assertNotNull(bean.addresses.get(2));
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import org.junit.Test;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
import org.springframework.ui.binding.Binder;
|
import org.springframework.ui.binding.Binder;
|
||||||
import org.springframework.ui.binding.BindingConfiguration;
|
import org.springframework.ui.binding.BindingConfiguration;
|
||||||
import org.springframework.ui.binding.BindingResult;
|
import org.springframework.ui.binding.BindingResults;
|
||||||
import org.springframework.ui.binding.UserValues;
|
import org.springframework.ui.binding.UserValues;
|
||||||
import org.springframework.ui.format.date.DateFormatter;
|
import org.springframework.ui.format.date.DateFormatter;
|
||||||
import org.springframework.ui.format.number.CurrencyFormat;
|
import org.springframework.ui.format.number.CurrencyFormat;
|
||||||
|
|
@ -50,7 +50,7 @@ public class WebBinderTests {
|
||||||
userMap.put("_currency", "doesn't matter");
|
userMap.put("_currency", "doesn't matter");
|
||||||
userMap.put("_addresses", "doesn't matter");
|
userMap.put("_addresses", "doesn't matter");
|
||||||
UserValues values = binder.createUserValues(userMap);
|
UserValues values = binder.createUserValues(userMap);
|
||||||
List<BindingResult> results = binder.bind(values);
|
BindingResults results = binder.bind(values);
|
||||||
assertEquals(6, results.size());
|
assertEquals(6, results.size());
|
||||||
assertEquals("test", results.get(0).getUserValue());
|
assertEquals("test", results.get(0).getUserValue());
|
||||||
assertEquals(null, results.get(1).getUserValue());
|
assertEquals(null, results.get(1).getUserValue());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package org.springframework.ui.validation;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface Validator {
|
||||||
|
|
||||||
|
void validate(Object model, List<String> properties);
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue