property not found / required

This commit is contained in:
Keith Donald
2009-07-20 16:10:06 +00:00
parent 3cd3cddbe0
commit f39f91701d
4 changed files with 159 additions and 24 deletions

View File

@@ -19,18 +19,20 @@ import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.context.MessageSource;
import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.convert.TypeConverter;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.DefaultTypeConverter;
import org.springframework.ui.binding.Binder;
import org.springframework.ui.binding.Binding;
import org.springframework.ui.binding.BindingResult;
import org.springframework.ui.binding.BindingResults;
import org.springframework.ui.binding.MissingSourceValuesException;
import org.springframework.ui.binding.Binding.BindingStatus;
import org.springframework.ui.binding.config.BindingRuleConfiguration;
import org.springframework.ui.binding.config.Condition;
@@ -57,6 +59,8 @@ public class GenericBinder implements Binder {
private MessageSource messageSource;
private String[] requiredProperties = new String[0];
/**
* Creates a new binder for the model object.
* @param model the model object containing properties this binder will bind to
@@ -140,10 +144,15 @@ public class GenericBinder implements Binder {
public BindingResults bind(Map<String, ? extends Object> sourceValues) {
sourceValues = filter(sourceValues);
checkRequired(sourceValues);
ArrayListBindingResults results = new ArrayListBindingResults(sourceValues.size());
for (Map.Entry<String, ? extends Object> sourceValue : sourceValues.entrySet()) {
Binding binding = getBinding(sourceValue.getKey());
results.add(bind(sourceValue, binding));
try {
Binding binding = getBinding(sourceValue.getKey());
results.add(bind(sourceValue, binding));
} catch (PropertyNotFoundException e) {
results.add(new PropertyNotFoundResult(sourceValue.getKey(), sourceValue.getValue(), messageSource));
}
}
return results;
}
@@ -163,6 +172,24 @@ public class GenericBinder implements Binder {
}
// internal helpers
private void checkRequired(Map<String, ? extends Object> sourceValues) {
List<String> missingRequired = new ArrayList<String>();
for (String required : requiredProperties) {
boolean found = false;
for (String property : sourceValues.keySet()) {
if (property.equals(required)) {
found = true;
}
}
if (!found) {
missingRequired.add(required);
}
}
if (!missingRequired.isEmpty()) {
throw new MissingSourceValuesException(missingRequired, sourceValues);
}
}
private GenericBindingRule getBindingRule(String property) {
GenericBindingRule rule = bindingRules.get(property);
@@ -217,6 +244,10 @@ public class GenericBinder implements Binder {
// implementing BindingContext
public MessageSource getMessageSource() {
return messageSource;
}
public TypeConverter getTypeConverter() {
return typeConverter;
}
@@ -326,8 +357,7 @@ public class GenericBinder implements Binder {
return propDesc;
}
}
throw new IllegalArgumentException("No property '" + property + "' found on model ["
+ modelClass.getName() + "]");
throw new PropertyNotFoundException(property, modelClass);
}
private BeanInfo getBeanInfo(Class<?> clazz) {
@@ -341,6 +371,8 @@ public class GenericBinder implements Binder {
public interface BindingContext {
MessageSource getMessageSource();
TypeConverter getTypeConverter();
Condition getEditableCondition();
@@ -362,4 +394,8 @@ public class GenericBinder implements Binder {
}
public void setRequired(String[] propertyPaths) {
this.requiredProperties = propertyPaths;
}
}

View File

@@ -0,0 +1,23 @@
package org.springframework.ui.binding.support;
public class PropertyNotFoundException extends RuntimeException {
private String property;
private Class<?> modelClass;
public PropertyNotFoundException(String property, Class<?> modelClass) {
super("No property '" + property + "' found on model [" + modelClass.getName() + "]");
this.property = property;
this.modelClass = modelClass;
}
public String getProperty() {
return property;
}
public Class<?> getModelClass() {
return modelClass;
}
}

View File

@@ -0,0 +1,64 @@
package org.springframework.ui.binding.support;
import org.springframework.context.MessageSource;
import org.springframework.core.style.StylerUtils;
import org.springframework.ui.alert.Alert;
import org.springframework.ui.alert.Severity;
import org.springframework.ui.binding.BindingResult;
import org.springframework.ui.message.MessageBuilder;
import org.springframework.ui.message.ResolvableArgument;
class PropertyNotFoundResult implements BindingResult {
private String property;
private Object sourceValue;
private MessageSource messageSource;
public PropertyNotFoundResult(String property, Object sourceValue, MessageSource messageSource) {
this.property = property;
this.sourceValue = sourceValue;
this.messageSource = messageSource;
}
public String getProperty() {
return property;
}
public Object getSourceValue() {
return sourceValue;
}
public boolean isFailure() {
return true;
}
public Alert getAlert() {
return new Alert() {
public String getCode() {
return "propertyNotFound";
}
public Severity getSeverity() {
return Severity.WARNING;
}
public String getMessage() {
MessageBuilder builder = new MessageBuilder(messageSource);
builder.code("bindSuccess");
builder.arg("label", new ResolvableArgument(property));
builder.arg("value", sourceValue);
// TODO lazily create default message
builder.defaultMessage("Successfully bound user value " + StylerUtils.style(sourceValue)
+ " to property '" + property + "'");
return builder.build();
}
};
}
public String toString() {
return getAlert().toString();
}
}