bind and validate lifecycle initial commit

This commit is contained in:
Keith Donald 2009-06-11 20:29:01 +00:00
parent 8998228fac
commit 1d6a3e5360
7 changed files with 183 additions and 12 deletions

View File

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

View File

@ -15,7 +15,6 @@
*/
package org.springframework.ui.binding;
import java.util.List;
import java.util.Map;
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.
* TODO consider returning BindingResults object that makes it easier to query/introspect results
* @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.

View File

@ -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();
}

View File

@ -23,6 +23,7 @@ import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
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.BindingConfiguration;
import org.springframework.ui.binding.BindingResult;
import org.springframework.ui.binding.BindingResults;
import org.springframework.ui.binding.FormatterRegistry;
import org.springframework.ui.binding.UserValue;
import org.springframework.ui.binding.UserValues;
@ -128,8 +130,8 @@ public class GenericBinder implements Binder {
}
}
public List<BindingResult> bind(UserValues values) {
List<BindingResult> results = new ArrayList<BindingResult>(values.size());
public BindingResults bind(UserValues values) {
ArrayListBindingResults results = new ArrayListBindingResults(values.size());
for (UserValue value : values) {
BindingImpl binding = (BindingImpl) getBinding(value.getProperty());
results.add(binding.setValue(value.getValue()));
@ -147,6 +149,54 @@ public class GenericBinder implements Binder {
// 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 {
private Expression property;

View File

@ -24,6 +24,7 @@ import org.springframework.ui.binding.Binder;
import org.springframework.ui.binding.Binding;
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.format.AnnotationFormatterFactory;
import org.springframework.ui.format.Formatter;
@ -55,7 +56,7 @@ public class GenericBinderTests {
values.add("string", "test");
values.add("integer", "3");
values.add("foo", "BAR");
List<BindingResult> results = binder.bind(values);
BindingResults results = binder.bind(values);
assertEquals(3, results.size());
assertEquals("string", results.get(0).getProperty());
@ -85,7 +86,7 @@ public class GenericBinderTests {
// bad value
values.add("integer", "bogus");
values.add("foo", "BAR");
List<BindingResult> results = binder.bind(values);
BindingResults results = binder.bind(values);
assertEquals(3, results.size());
assertTrue(results.get(1).isError());
assertEquals("typeConversionFailure", results.get(1).getErrorCode());
@ -127,7 +128,7 @@ public class GenericBinderTests {
@Test
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());
assertTrue(results.get(0).isError());
assertEquals("propertyNotFound", results.get(0).getErrorCode());
@ -139,7 +140,7 @@ public class GenericBinderTests {
userMap.put("string", "test");
userMap.put("integer", "3");
UserValues values = binder.createUserValues(userMap);
List<BindingResult> results = binder.bind(values);
BindingResults results = binder.bind(values);
assertEquals(2, results.size());
assertEquals("test", results.get(0).getUserValue());
assertEquals("3", results.get(1).getUserValue());
@ -245,7 +246,7 @@ public class GenericBinderTests {
values.add("addresses[5].state", "FL");
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("Palm Bay", bean.addresses.get(1).city);
Assert.assertNotNull(bean.addresses.get(2));

View File

@ -16,7 +16,7 @@ import org.junit.Test;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.ui.binding.Binder;
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.format.date.DateFormatter;
import org.springframework.ui.format.number.CurrencyFormat;
@ -50,7 +50,7 @@ public class WebBinderTests {
userMap.put("_currency", "doesn't matter");
userMap.put("_addresses", "doesn't matter");
UserValues values = binder.createUserValues(userMap);
List<BindingResult> results = binder.bind(values);
BindingResults results = binder.bind(values);
assertEquals(6, results.size());
assertEquals("test", results.get(0).getUserValue());
assertEquals(null, results.get(1).getUserValue());

View File

@ -0,0 +1,9 @@
package org.springframework.ui.validation;
import java.util.List;
public interface Validator {
void validate(Object model, List<String> properties);
}