master
Keith Donald 15 years ago
parent 726d3464c1
commit 990d446c84
  1. 69
      org.springframework.context/src/main/java/org/springframework/model/binder/support/AbstractBinder.java
  2. 20
      org.springframework.context/src/main/java/org/springframework/model/binder/support/AlertBindingResult.java
  3. 2
      org.springframework.context/src/main/java/org/springframework/model/binder/support/ArrayListBindingResults.java
  4. 16
      org.springframework.context/src/main/java/org/springframework/model/binder/support/FieldNotEditableResult.java
  5. 16
      org.springframework.context/src/main/java/org/springframework/model/binder/support/FieldNotFoundResult.java
  6. 1
      org.springframework.context/src/main/java/org/springframework/model/ui/FieldNotFoundException.java
  7. 1
      org.springframework.context/src/main/java/org/springframework/model/ui/PresentationModel.java
  8. 5
      org.springframework.context/src/main/java/org/springframework/model/ui/binder/package-info.java
  9. 3
      org.springframework.context/src/main/java/org/springframework/model/ui/config/BinderExecutor.java
  10. 81
      org.springframework.context/src/main/java/org/springframework/model/ui/support/PresentationModelBinder.java
  11. 2
      org.springframework.context/src/main/java/org/springframework/model/ui/support/WebBinder.java
  12. 2
      org.springframework.context/src/test/java/org/springframework/model/ui/binder/GenericBinderTests.java
  13. 2
      org.springframework.context/src/test/java/org/springframework/model/ui/binder/WebBinderTests.java

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.model.ui.binder;
package org.springframework.model.binder.support;
import java.util.ArrayList;
import java.util.List;
@ -24,32 +24,21 @@ import org.springframework.model.binder.Binder;
import org.springframework.model.binder.BindingResult;
import org.springframework.model.binder.BindingResults;
import org.springframework.model.binder.MissingFieldException;
import org.springframework.model.ui.BindingStatus;
import org.springframework.model.ui.FieldModel;
import org.springframework.model.ui.FieldNotFoundException;
import org.springframework.model.ui.PresentationModel;
import org.springframework.util.Assert;
/**
* A generic {@link Binder binder} suitable for use in most environments.
* A base {@link Binder binder} implementation designed for subclassing.
* @author Keith Donald
* @since 3.0
* @see #setMessageSource(MessageSource)
* @see #setRequiredFields(String[])
* @see #bind(Map)
*/
public class PresentationModelBinder implements Binder {
public abstract class AbstractBinder implements Binder {
private PresentationModel presentationModel;
private String[] requiredFields;
private MessageSource messageSource;
public PresentationModelBinder(PresentationModel presentationModel) {
Assert.notNull(presentationModel, "The PresentationModel is required");
this.presentationModel = presentationModel;
}
private MessageSource messageSource;
/**
* Configure the MessageSource that resolves localized {@link BindingResult} alert messages.
@ -59,7 +48,7 @@ public class PresentationModelBinder implements Binder {
Assert.notNull(messageSource, "The MessageSource is required");
this.messageSource = messageSource;
}
/**
* Configure the fields for which values must be present in each bind attempt.
* @param fieldNames the field names
@ -68,18 +57,6 @@ public class PresentationModelBinder implements Binder {
public void setRequiredFields(String[] fieldNames) {
this.requiredFields = fieldNames;
}
// subclassing hooks
/**
* Get the model for the field.
* @param fieldName
* @return the field model
* @throws NoSuchFieldException if no such field exists
*/
protected FieldModel getFieldModel(String fieldName) {
return presentationModel.getFieldModel(fieldName);
}
// implementing Binder
@ -88,18 +65,14 @@ public class PresentationModelBinder implements Binder {
checkRequired(fieldValues);
ArrayListBindingResults results = new ArrayListBindingResults(fieldValues.size());
for (Map.Entry<String, ? extends Object> fieldValue : fieldValues.entrySet()) {
try {
FieldModel field = getFieldModel(fieldValue.getKey());
results.add(bind(fieldValue, field));
} catch (FieldNotFoundException e) {
results.add(new FieldNotFoundResult(fieldValue.getKey(), fieldValue.getValue(), messageSource));
}
results.add(bind(fieldValue));
}
return results;
}
// subclassing hooks
/**
* Hook subclasses may use to filter the source values to bind.
* This hook allows the binder to pre-process the field values before binding occurs.
@ -112,6 +85,20 @@ public class PresentationModelBinder implements Binder {
return fieldValues;
}
/**
* The configured MessageSource that resolves binding result alert messages.
*/
protected MessageSource getMessageSource() {
return messageSource;
}
/**
* Hook method subclasses should override to perform a single binding.
* @param fieldValue the field value to bind
* @return the binding result
*/
protected abstract BindingResult bind(Map.Entry<String, ? extends Object> fieldValue);
// internal helpers
private void checkRequired(Map<String, ? extends Object> fieldValues) {
@ -135,18 +122,4 @@ public class PresentationModelBinder implements Binder {
}
}
private BindingResult bind(Map.Entry<String, ? extends Object> fieldValue, FieldModel field) {
String fieldName = fieldValue.getKey();
Object value = fieldValue.getValue();
if (!field.isEditable()) {
return new FieldNotEditableResult(fieldName, value, messageSource);
} else {
field.applySubmittedValue(value);
if (field.getBindingStatus() == BindingStatus.DIRTY) {
field.commit();
}
return new BindingStatusResult(fieldName, value, field.getStatusAlert());
}
}
}

@ -13,24 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.model.ui.binder;
package org.springframework.model.binder.support;
import org.springframework.model.alert.Alert;
import org.springframework.model.alert.Severity;
import org.springframework.model.binder.BindingResult;
class BindingStatusResult implements BindingResult {
public class AlertBindingResult implements BindingResult {
private String fieldName;
private Object sourceValue;
private Object submittedValue;
private Alert bindingStatusAlert;
private Alert alert;
public BindingStatusResult(String fieldName, Object sourceValue, Alert alert) {
public AlertBindingResult(String fieldName, Object sourceValue, Alert alert) {
this.fieldName = fieldName;
this.sourceValue = sourceValue;
this.bindingStatusAlert = alert;
this.submittedValue = sourceValue;
this.alert = alert;
}
public String getFieldName() {
@ -38,15 +38,15 @@ class BindingStatusResult implements BindingResult {
}
public Object getSubmittedValue() {
return sourceValue;
return submittedValue;
}
public boolean isFailure() {
return bindingStatusAlert.getSeverity().compareTo(Severity.INFO) > 1;
return alert.getSeverity().compareTo(Severity.INFO) > 1;
}
public Alert getAlert() {
return bindingStatusAlert;
return alert;
}
public String toString() {

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.model.ui.binder;
package org.springframework.model.binder.support;
import java.util.ArrayList;
import java.util.Iterator;

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.model.ui.binder;
package org.springframework.model.binder.support;
import org.springframework.context.MessageSource;
import org.springframework.core.style.StylerUtils;
@ -23,17 +23,17 @@ import org.springframework.model.binder.BindingResult;
import org.springframework.model.message.MessageBuilder;
import org.springframework.model.message.ResolvableArgument;
class FieldNotEditableResult implements BindingResult {
public class FieldNotEditableResult implements BindingResult {
private String property;
private Object sourceValue;
private Object submittedValue;
private MessageSource messageSource;
public FieldNotEditableResult(String property, Object sourceValue, MessageSource messageSource) {
public FieldNotEditableResult(String property, Object submittedValue, MessageSource messageSource) {
this.property = property;
this.sourceValue = sourceValue;
this.submittedValue = submittedValue;
this.messageSource = messageSource;
}
@ -42,7 +42,7 @@ class FieldNotEditableResult implements BindingResult {
}
public Object getSubmittedValue() {
return sourceValue;
return submittedValue;
}
public boolean isFailure() {
@ -63,9 +63,9 @@ class FieldNotEditableResult implements BindingResult {
MessageBuilder builder = new MessageBuilder(messageSource);
builder.code("bindSuccess");
builder.arg("label", new ResolvableArgument(property));
builder.arg("value", sourceValue);
builder.arg("value", submittedValue);
// TODO lazily create default message
builder.defaultMessage("Successfully bound user value " + StylerUtils.style(sourceValue)
builder.defaultMessage("Successfully bound user value " + StylerUtils.style(submittedValue)
+ " to property '" + property + "'");
return builder.build();
}

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.model.ui.binder;
package org.springframework.model.binder.support;
import org.springframework.context.MessageSource;
import org.springframework.core.style.StylerUtils;
@ -23,17 +23,17 @@ import org.springframework.model.binder.BindingResult;
import org.springframework.model.message.MessageBuilder;
import org.springframework.model.message.ResolvableArgument;
class FieldNotFoundResult implements BindingResult {
public class FieldNotFoundResult implements BindingResult {
private String property;
private Object sourceValue;
private Object submittedValue;
private MessageSource messageSource;
public FieldNotFoundResult(String property, Object sourceValue, MessageSource messageSource) {
public FieldNotFoundResult(String property, Object submittedValue, MessageSource messageSource) {
this.property = property;
this.sourceValue = sourceValue;
this.submittedValue = submittedValue;
this.messageSource = messageSource;
}
@ -42,7 +42,7 @@ class FieldNotFoundResult implements BindingResult {
}
public Object getSubmittedValue() {
return sourceValue;
return submittedValue;
}
public boolean isFailure() {
@ -63,9 +63,9 @@ class FieldNotFoundResult implements BindingResult {
MessageBuilder builder = new MessageBuilder(messageSource);
builder.code("bindSuccess");
builder.arg("label", new ResolvableArgument(property));
builder.arg("value", sourceValue);
builder.arg("value", submittedValue);
// TODO lazily create default message
builder.defaultMessage("Successfully bound user value " + StylerUtils.style(sourceValue)
builder.defaultMessage("Successfully bound user value " + StylerUtils.style(submittedValue)
+ " to property '" + property + "'");
return builder.build();
}

@ -15,6 +15,7 @@
*/
package org.springframework.model.ui;
/**
* Thrown when a PresentationModel field cannot be found.
* @author Keith Donald

@ -15,6 +15,7 @@
*/
package org.springframework.model.ui;
/**
* Represents the state and behavior of a presentation independently of the GUI controls used in the interface.
* Pulls the state and behavior of a view out into a model class that is part of the presentation.

@ -1,5 +0,0 @@
/**
* Binder implementation that binds to PresentationModels.
*/
package org.springframework.model.ui.binder;

@ -13,11 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.model.ui.binder;
package org.springframework.model.ui.config;
import org.springframework.model.binder.Binder;
import org.springframework.model.binder.BindingResults;
import org.springframework.model.ui.config.FieldModelConfiguration;
/**
* A SPI interface that lets you configure a {@link Binder}, then execute it.

@ -0,0 +1,81 @@
/*
* 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.model.ui.support;
import java.util.Map;
import org.springframework.context.MessageSource;
import org.springframework.model.binder.Binder;
import org.springframework.model.binder.BindingResult;
import org.springframework.model.binder.support.AbstractBinder;
import org.springframework.model.binder.support.AlertBindingResult;
import org.springframework.model.binder.support.FieldNotEditableResult;
import org.springframework.model.binder.support.FieldNotFoundResult;
import org.springframework.model.ui.BindingStatus;
import org.springframework.model.ui.FieldModel;
import org.springframework.model.ui.FieldNotFoundException;
import org.springframework.model.ui.PresentationModel;
import org.springframework.util.Assert;
/**
* A generic {@link Binder binder} suitable for use in most environments.
* @author Keith Donald
* @since 3.0
* @see #setMessageSource(MessageSource)
* @see #setRequiredFields(String[])
* @see #bind(Map)
*/
public class PresentationModelBinder extends AbstractBinder {
private PresentationModel presentationModel;
public PresentationModelBinder(PresentationModel presentationModel) {
Assert.notNull(presentationModel, "The PresentationModel is required");
this.presentationModel = presentationModel;
}
// subclassing hooks
/**
* Get the model for the field.
* @param fieldName
* @return the field model
* @throws NoSuchFieldException if no such field exists
*/
protected FieldModel getFieldModel(String fieldName) {
return presentationModel.getFieldModel(fieldName);
}
protected BindingResult bind(Map.Entry<String, ? extends Object> fieldValue) {
String fieldName = fieldValue.getKey();
Object value = fieldValue.getValue();
FieldModel field;
try {
field = getFieldModel(fieldName);
} catch (FieldNotFoundException e) {
return new FieldNotFoundResult(fieldName, value, getMessageSource());
}
if (!field.isEditable()) {
return new FieldNotEditableResult(fieldName, value, getMessageSource());
} else {
field.applySubmittedValue(value);
if (field.getBindingStatus() == BindingStatus.DIRTY) {
field.commit();
}
return new AlertBindingResult(fieldName, value, field.getStatusAlert());
}
}
}

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.model.ui.binder;
package org.springframework.model.ui.support;
import java.util.LinkedHashMap;
import java.util.Map;

@ -27,7 +27,6 @@ import org.springframework.model.binder.MissingFieldException;
import org.springframework.model.message.MockMessageSource;
import org.springframework.model.ui.BindingStatus;
import org.springframework.model.ui.FieldModel;
import org.springframework.model.ui.binder.PresentationModelBinder;
import org.springframework.model.ui.format.AnnotationFormatterFactory;
import org.springframework.model.ui.format.Formatted;
import org.springframework.model.ui.format.Formatter;
@ -38,6 +37,7 @@ import org.springframework.model.ui.format.number.IntegerFormatter;
import org.springframework.model.ui.support.CollectionTypeDescriptor;
import org.springframework.model.ui.support.DefaultPresentationModel;
import org.springframework.model.ui.support.GenericFormatterRegistry;
import org.springframework.model.ui.support.PresentationModelBinder;
public class GenericBinderTests {

@ -15,12 +15,12 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.model.binder.BindingResults;
import org.springframework.model.ui.binder.WebBinder;
import org.springframework.model.ui.format.date.DateFormatter;
import org.springframework.model.ui.format.number.CurrencyFormat;
import org.springframework.model.ui.format.number.CurrencyFormatter;
import org.springframework.model.ui.support.DefaultPresentationModel;
import org.springframework.model.ui.support.GenericFormatterRegistry;
import org.springframework.model.ui.support.WebBinder;
public class WebBinderTests {

Loading…
Cancel
Save