diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/BindingStatus.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/BindingStatus.java
index 1cb6600353d..d85b499baf6 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/BindingStatus.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/BindingStatus.java
@@ -16,9 +16,10 @@
package org.springframework.ui.binding;
/**
- * Binding states.
+ * FieldModel binding states.
* @author Keith Donald
* @since 3.0
+ * @see FieldModel#getBindingStatus()
*/
public enum BindingStatus {
@@ -28,9 +29,9 @@ public enum BindingStatus {
CLEAN,
/**
- * An invalid source value is applied.
+ * An invalid submitted value is applied.
*/
- INVALID_SOURCE_VALUE,
+ INVALID_SUBMITTED_VALUE,
/**
* The binding buffer contains a valid value that has not been committed.
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/Binding.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/FieldModel.java
similarity index 63%
rename from org.springframework.context/src/main/java/org/springframework/ui/binding/Binding.java
rename to org.springframework.context/src/main/java/org/springframework/ui/binding/FieldModel.java
index 620434f68f6..ccfba7519e7 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/Binding.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/FieldModel.java
@@ -19,11 +19,11 @@ import org.springframework.ui.alert.Alert;
import org.springframework.ui.alert.Severity;
/**
- * A binding between one or more UI components and a model property.
+ * A model for a single data field containing dynamic information to display in the view.
* @author Keith Donald
* @since 3.0
*/
-public interface Binding {
+public interface FieldModel {
/**
* The model value formatted for display in a single field in the UI.
@@ -33,47 +33,47 @@ public interface Binding {
String getRenderValue();
/**
- * The bound model value.
+ * The field model value.
*/
Object getValue();
/**
- * The bound model value type.
+ * The field model value type.
*/
Class> getValueType();
/**
- * If this Binding is editable.
+ * If editable.
* Used to determine if the user can edit the field value.
- * A Binding that is not editable cannot have source values applied and cannot be committed.
+ * A Binding that is not editable cannot have submitted values applied and cannot be committed.
*/
boolean isEditable();
/**
- * If this Binding is enabled.
+ * If enabled.
* Used to determine if the user can interact with the field at all.
- * A Binding that is not enabled cannot have source values applied and cannot be committed.
+ * A Binding that is not enabled cannot have submitted values applied and cannot be committed.
*/
boolean isEnabled();
/**
- * If this Binding is visible.
+ * If visible.
* Used to determine if the user can see the field.
*/
boolean isVisible();
/**
- * The current binding status.
+ * The current field binding status.
* Initially {@link BindingStatus#CLEAN clean}.
- * Is {@link BindingStatus#DIRTY} after applying a source value to the value buffer.
+ * Is {@link BindingStatus#DIRTY} after applying a submitted value to the value buffer.
* Is {@link BindingStatus#COMMITTED} after successfully committing the buffered value.
- * Is {@link BindingStatus#INVALID_SOURCE_VALUE} if a source value could not be applied.
+ * Is {@link BindingStatus#INVALID_SUBMITTED_VALUE} if a submitted value could not be applied.
* Is {@link BindingStatus#COMMIT_FAILURE} if a buffered value could not be committed.
*/
BindingStatus getBindingStatus();
/**
- * The current validation status.
+ * The current field validation status.
* Initially {@link ValidationStatus#NOT_VALIDATED}.
* Is {@link ValidationStatus#VALID} after value is successfully validated.
* Is {@link ValidationStatus#INVALID} after value fails validation.
@@ -82,31 +82,31 @@ public interface Binding {
ValidationStatus getValidationStatus();
/**
- * An alert that communicates current status to the user.
+ * An alert that communicates current FieldModel status to the user.
* Returns null if {@link BindingStatus#CLEAN} and {@link ValidationStatus#NOT_VALIDATED}.
* Returns a {@link Severity#INFO} Alert with code bindSuccess when {@link BindingStatus#COMMITTED}.
- * Returns a {@link Severity#ERROR} Alert with code typeMismatch when {@link BindingStatus#INVALID_SOURCE_VALUE} or {@link BindingStatus#COMMIT_FAILURE} due to a value parse / type conversion error.
+ * Returns a {@link Severity#ERROR} Alert with code typeMismatch when {@link BindingStatus#INVALID_SUBMITTED_VALUE} or {@link BindingStatus#COMMIT_FAILURE} due to a value parse / type conversion error.
* Returns a {@link Severity#FATAL} Alert with code internalError when {@link BindingStatus#COMMIT_FAILURE} due to a unexpected runtime exception.
* Returns a {@link Severity#INFO} Alert describing results of validation if {@link ValidationStatus#VALID} or {@link ValidationStatus#INVALID}.
*/
Alert getStatusAlert();
/**
- * Apply the source value to this binding.
- * The source value is parsed and stored in the binding's value buffer.
+ * Apply a submitted value to this FieldModel.
+ * The submitted value is parsed and stored in the value buffer.
* Sets to {@link BindingStatus#DIRTY} if succeeds.
- * Sets to {@link BindingStatus#INVALID_SOURCE_VALUE} if fails.
- * @param sourceValue
+ * Sets to {@link BindingStatus#INVALID_SUBMITTED_VALUE} if fails.
+ * @param submittedValue
* @throws IllegalStateException if not editable or not enabled
*/
- void applySourceValue(Object sourceValue);
+ void applySubmittedValue(Object submittedValue);
/**
- * If {@link BindingStatus#INVALID_SOURCE_VALUE}, returns the invalid source value.
+ * If {@link BindingStatus#INVALID_SUBMITTED_VALUE}, returns the invalid submitted value.
* Returns null otherwise.
- * @return the invalid source value
+ * @return the invalid submitted value
*/
- Object getInvalidSourceValue();
+ Object getInvalidSubmittedValue();
/**
* Validate the model value.
@@ -130,45 +130,46 @@ public interface Binding {
void revert();
/**
- * Get a Binding to a nested property value.
- * @param property the nested property name, such as "foo"; should not be a property path like "foo.bar"
- * @return the binding to the nested property
- * @throws IllegalStateException if not a bean
+ * Get a model for a nested field.
+ * @param fieldName the nested field name, such as "foo"; should not be a property path like "foo.bar"
+ * @return the nested field model
+ * @throws IllegalStateException if {@link #isList()}
+ * @throws FieldNotFoundException if no such nested field exists
*/
- Binding getNestedBinding(String property);
+ FieldModel getNested(String fieldName);
/**
- * If bound to an indexable collection, either a {@link java.util.List} or an array.
+ * If an indexable {@link java.util.List} or array.
*/
boolean isList();
/**
- * If a list, get a Binding to a element in the list..
+ * If {@link #isList()}, get a FieldModel for a element in the list..
* @param index the element index
* @return the indexed binding
* @throws IllegalStateException if not a list
*/
- Binding getListElementBinding(int index);
+ FieldModel getListElement(int index);
/**
- * If bound to a Map.
+ * If a Map.
*/
boolean isMap();
/**
- * If a Map, get a Binding to a value in the Map.
+ * If {@link #isMap()}, get FieldModel for a value in the Map.
* @param key the map key
* @return the keyed binding
* @throws IllegalStateException if not a map
*/
- Binding getMapValueBinding(Object key);
+ FieldModel getMapValue(Object key);
/**
* Format a potential model value for display.
- * If a list binding, expects the model value to be a potential list element & uses the configured element formatter.
- * If a map binding, expects the model value to be a potential map value & uses the configured map value formatter.
+ * If {@link #isList()}, expects the value to be a potential list element & uses the configured element formatter.
+ * If {@link #isMap()}, expects the value to be a potential map value & uses the configured map value formatter.
* @param potentialValue the potential value
* @return the formatted string
*/
- String formatValue(Object potentialModelValue);
+ String formatValue(Object potentialValue);
}
\ No newline at end of file
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/BindingFactory.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/FieldNotFoundException.java
similarity index 58%
rename from org.springframework.context/src/main/java/org/springframework/ui/binding/BindingFactory.java
rename to org.springframework.context/src/main/java/org/springframework/ui/binding/FieldNotFoundException.java
index 8aceee3750b..998b4a86399 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/BindingFactory.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/FieldNotFoundException.java
@@ -16,22 +16,27 @@
package org.springframework.ui.binding;
/**
- * A factory for model property bindings.
+ * Thrown when a PresentationModel field cannot be found.
* @author Keith Donald
* @since 3.0
+ * @see PresentationModel#getFieldModel(String)
+ * @see FieldModel#getNested(String)
*/
-public interface BindingFactory {
+@SuppressWarnings("serial")
+public class FieldNotFoundException extends RuntimeException {
+
+ private String field;
/**
- * The model object upon which bindings may be accessed.
+ * Creates a new FieldNotFoundException.
+ * @param fieldName the field not found exception
*/
- Object getModel();
+ public FieldNotFoundException(String fieldName) {
+ super("No field '" + fieldName + "' found");
+ }
- /**
- * Get a binding to a model property.
- * @param property the property path
- * @throws NoSuchBindingException if no binding to the property exists
- */
- Binding getBinding(String property);
-
-}
\ No newline at end of file
+ public String getField() {
+ return field;
+ }
+
+}
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/PresentationModel.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/PresentationModel.java
new file mode 100644
index 00000000000..c9c87097a0d
--- /dev/null
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/PresentationModel.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * 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.
+ * Coordinates with the domain layer and provides an interface to the view that minimizes decision making in the view.
+ * @author Keith Donald
+ * @since 3.0
+ */
+public interface PresentationModel {
+
+ /**
+ * Get the model for the field.
+ * @param fieldName the field name.
+ * @throws FieldNotFoundException if no such field exists
+ */
+ FieldModel getFieldModel(String fieldName);
+
+}
\ No newline at end of file
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/BindingFactoryLocator.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/PresentationModelFactory.java
similarity index 63%
rename from org.springframework.context/src/main/java/org/springframework/ui/binding/BindingFactoryLocator.java
rename to org.springframework.context/src/main/java/org/springframework/ui/binding/PresentationModelFactory.java
index b671c60e2e8..4ce62b77e8e 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/BindingFactoryLocator.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/PresentationModelFactory.java
@@ -16,19 +16,19 @@
package org.springframework.ui.binding;
/**
- * A locator for BindingFactories indexed by their models.
- * Makes it easy for clients to lookup BindingFactories for models the need to bind to.
+ * A factory for domain object PresentationModels.
+ * Makes it easy for clients to lookup PresentationModels for domain objects they need to bind to.
* @author Keith Donald
* @since 3.0
*/
-public interface BindingFactoryLocator {
+public interface PresentationModelFactory {
/**
- * Get the BindingFactory for the model object.
- * If no such BindingFactory exists, one is created and cached.
+ * Get the PresentationModel for the domain object.
+ * If none exists, one is created and cached.
* Never returns null.
- * @param model the model object
- * @return the binding Factory
+ * @param domainObject the model object
+ * @return the presentation model
*/
- public BindingFactory getBindingFactory(Object model);
+ public PresentationModel getPresentationModel(Object domainObject);
}
\ No newline at end of file
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/ValidationStatus.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/ValidationStatus.java
index ac60413c0b3..3e5c31c01f4 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/ValidationStatus.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/ValidationStatus.java
@@ -16,9 +16,10 @@
package org.springframework.ui.binding;
/**
- * Validation states.
+ * FieldModel Validation states.
* @author Keith Donald
* @since 3.0
+ * @see FieldModel#getValidationStatus()
*/
public enum ValidationStatus {
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/ArrayListBindingResults.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/ArrayListBindingResults.java
index a6a215f4841..8ea45639354 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/ArrayListBindingResults.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/ArrayListBindingResults.java
@@ -70,7 +70,7 @@ class ArrayListBindingResults implements BindingResults {
public List properties() {
List properties = new ArrayList(results.size());
for (BindingResult result : this) {
- properties.add(result.getProperty());
+ properties.add(result.getFieldName());
}
return properties;
}
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/Binder.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/Binder.java
index a42158f515d..2284abb9b01 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/Binder.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/Binder.java
@@ -17,7 +17,7 @@ package org.springframework.ui.binding.binder;
import java.util.Map;
-import org.springframework.ui.binding.Binding;
+import org.springframework.ui.binding.FieldModel;
/**
* Binds user-entered values to properties of a model object.
@@ -28,18 +28,13 @@ import org.springframework.ui.binding.Binding;
*/
public interface Binder {
- /**
- * The model this binder binds to.
- */
- public Object getModel();
-
/**
* Bind the source values to the properties of the model.
- * A result is returned for each registered {@link Binding}.
- * @param sourceValues the source values to bind
+ * A result is returned for each registered {@link FieldModel}.
+ * @param fieldValues the field values to bind
* @return the results of the binding operation
- * @throws MissingSourceValuesException when the sourceValues Map is missing entries for required bindings
+ * @throws MissingFieldException when the fieldValues Map is missing entries for required bindings
*/
- BindingResults bind(Map sourceValues);
+ BindingResults bind(Map fieldValues);
}
\ No newline at end of file
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BinderExecutor.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BinderExecutor.java
index c8adb150a43..4fb16ad9b7e 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BinderExecutor.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BinderExecutor.java
@@ -15,7 +15,7 @@
*/
package org.springframework.ui.binding.binder;
-import org.springframework.ui.binding.config.BindingRuleConfiguration;
+import org.springframework.ui.binding.config.FieldModelConfiguration;
/**
* A SPI interface that lets you configure a model binder, then execute it.
@@ -37,7 +37,7 @@ public interface BinderExecutor {
* @param property the model property
* @return a builder API for configuring the rule
*/
- BindingRuleConfiguration bindingRule(String property);
+ FieldModelConfiguration bindingRule(String property);
// TODO allow injection of pre-created BindingRules
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BindingResult.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BindingResult.java
index ae64628bc52..74f85838388 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BindingResult.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BindingResult.java
@@ -26,17 +26,17 @@ import org.springframework.ui.alert.Alert;
public interface BindingResult {
/**
- * The model property this binding result is for.
- * @see Binder#getNestedBinding(String)
+ * The name of the field this binding result is for.
+ * @see Binder#getNested(String)
*/
- String getProperty();
+ String getFieldName();
/**
- * The raw source value for which binding was attempted.
+ * The raw submitted value for which binding was attempted.
* If not a failure, this value was successfully bound to the model.
* @see #isFailure()
*/
- Object getSourceValue();
+ Object getSubmittedValue();
/**
* Indicates if the binding failed.
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BindingStatusResult.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BindingStatusResult.java
index f22810e52a0..465d5b24ced 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BindingStatusResult.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/BindingStatusResult.java
@@ -20,23 +20,23 @@ import org.springframework.ui.alert.Severity;
class BindingStatusResult implements BindingResult {
- private String property;
+ private String fieldName;
private Object sourceValue;
private Alert bindingStatusAlert;
- public BindingStatusResult(String property, Object sourceValue, Alert alert) {
- this.property = property;
+ public BindingStatusResult(String fieldName, Object sourceValue, Alert alert) {
+ this.fieldName = fieldName;
this.sourceValue = sourceValue;
this.bindingStatusAlert = alert;
}
- public String getProperty() {
- return property;
+ public String getFieldName() {
+ return fieldName;
}
- public Object getSourceValue() {
+ public Object getSubmittedValue() {
return sourceValue;
}
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/PropertyNotEditableResult.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/FieldNotEditableResult.java
similarity index 89%
rename from org.springframework.context/src/main/java/org/springframework/ui/binding/binder/PropertyNotEditableResult.java
rename to org.springframework.context/src/main/java/org/springframework/ui/binding/binder/FieldNotEditableResult.java
index 201411f5b9b..2a0dffc66fc 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/PropertyNotEditableResult.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/FieldNotEditableResult.java
@@ -22,7 +22,7 @@ import org.springframework.ui.alert.Severity;
import org.springframework.ui.message.MessageBuilder;
import org.springframework.ui.message.ResolvableArgument;
-class PropertyNotEditableResult implements BindingResult {
+class FieldNotEditableResult implements BindingResult {
private String property;
@@ -30,17 +30,17 @@ class PropertyNotEditableResult implements BindingResult {
private MessageSource messageSource;
- public PropertyNotEditableResult(String property, Object sourceValue, MessageSource messageSource) {
+ public FieldNotEditableResult(String property, Object sourceValue, MessageSource messageSource) {
this.property = property;
this.sourceValue = sourceValue;
this.messageSource = messageSource;
}
- public String getProperty() {
+ public String getFieldName() {
return property;
}
- public Object getSourceValue() {
+ public Object getSubmittedValue() {
return sourceValue;
}
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/PropertyNotFoundResult.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/FieldNotFoundResult.java
similarity index 89%
rename from org.springframework.context/src/main/java/org/springframework/ui/binding/binder/PropertyNotFoundResult.java
rename to org.springframework.context/src/main/java/org/springframework/ui/binding/binder/FieldNotFoundResult.java
index 7115e04eed8..2c3dcb0b442 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/PropertyNotFoundResult.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/FieldNotFoundResult.java
@@ -22,7 +22,7 @@ import org.springframework.ui.alert.Severity;
import org.springframework.ui.message.MessageBuilder;
import org.springframework.ui.message.ResolvableArgument;
-class PropertyNotFoundResult implements BindingResult {
+class FieldNotFoundResult implements BindingResult {
private String property;
@@ -30,17 +30,17 @@ class PropertyNotFoundResult implements BindingResult {
private MessageSource messageSource;
- public PropertyNotFoundResult(String property, Object sourceValue, MessageSource messageSource) {
+ public FieldNotFoundResult(String property, Object sourceValue, MessageSource messageSource) {
this.property = property;
this.sourceValue = sourceValue;
this.messageSource = messageSource;
}
- public String getProperty() {
+ public String getFieldName() {
return property;
}
- public Object getSourceValue() {
+ public Object getSubmittedValue() {
return sourceValue;
}
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/GenericBinder.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/GenericBinder.java
index 044059df7cb..dc8ed2e9169 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/GenericBinder.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/GenericBinder.java
@@ -21,10 +21,10 @@ import java.util.Map;
import org.springframework.context.MessageSource;
import org.springframework.core.convert.TypeConverter;
-import org.springframework.ui.binding.Binding;
-import org.springframework.ui.binding.BindingFactory;
+import org.springframework.ui.binding.FieldModel;
+import org.springframework.ui.binding.FieldNotFoundException;
+import org.springframework.ui.binding.PresentationModel;
import org.springframework.ui.binding.BindingStatus;
-import org.springframework.ui.binding.support.PropertyNotFoundException;
import org.springframework.util.Assert;
/**
@@ -37,15 +37,15 @@ import org.springframework.util.Assert;
*/
public class GenericBinder implements Binder {
- private BindingFactory bindingFactory;
+ private PresentationModel presentationModel;
- private String[] requiredProperties;
+ private String[] requiredFields;
private MessageSource messageSource;
- public GenericBinder(BindingFactory bindingFactory) {
- Assert.notNull(bindingFactory, "The BindingFactory is required");
- this.bindingFactory = bindingFactory;
+ public GenericBinder(PresentationModel presentationModel) {
+ Assert.notNull(presentationModel, "The PresentationModel is required");
+ this.presentationModel = presentationModel;
}
/**
@@ -58,34 +58,38 @@ public class GenericBinder implements Binder {
}
/**
- * Configure the properties for which source values must be present in each bind attempt.
- * @param propertyPaths the property path expressions
- * @see MissingSourceValuesException
+ * Configure the fields for which values must be present in each bind attempt.
+ * @param fieldNames the field names
+ * @see MissingFieldException
*/
- public void setRequired(String[] propertyPaths) {
- this.requiredProperties = propertyPaths;
+ public void setRequiredFields(String[] fieldNames) {
+ this.requiredFields = fieldNames;
}
- public Object getModel() {
- return bindingFactory.getModel();
- }
+ // subclassing hooks
- protected Binding getBinding(String property) {
- return bindingFactory.getBinding(property);
+ /**
+ * 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
- public BindingResults bind(Map sourceValues) {
- sourceValues = filter(sourceValues);
- checkRequired(sourceValues);
- ArrayListBindingResults results = new ArrayListBindingResults(sourceValues.size());
- for (Map.Entry sourceValue : sourceValues.entrySet()) {
+ public BindingResults bind(Map fieldValues) {
+ fieldValues = filter(fieldValues);
+ checkRequired(fieldValues);
+ ArrayListBindingResults results = new ArrayListBindingResults(fieldValues.size());
+ for (Map.Entry fieldValue : fieldValues.entrySet()) {
try {
- Binding binding = getBinding(sourceValue.getKey());
- results.add(bind(sourceValue, binding));
- } catch (PropertyNotFoundException e) {
- results.add(new PropertyNotFoundResult(sourceValue.getKey(), sourceValue.getValue(), messageSource));
+ FieldModel field = getFieldModel(fieldValue.getKey());
+ results.add(bind(fieldValue, field));
+ } catch (FieldNotFoundException e) {
+ results.add(new FieldNotFoundResult(fieldValue.getKey(), fieldValue.getValue(), messageSource));
}
}
return results;
@@ -95,26 +99,26 @@ public class GenericBinder implements Binder {
/**
* Hook subclasses may use to filter the source values to bind.
- * This hook allows the binder to pre-process the source values before binding occurs.
+ * This hook allows the binder to pre-process the field values before binding occurs.
* For example, a Binder might insert empty or default values for fields that are not present.
* As another example, a Binder might collapse multiple source values into a single source value.
- * @param sourceValues the original source values map provided by the caller
- * @return the filtered source values map that will be used to bind
+ * @param fieldValues the original fieldValues map provided by the caller
+ * @return the filtered fieldValues map that will be used to bind
*/
- protected Map filter(Map sourceValues) {
- return sourceValues;
+ protected Map filter(Map fieldValues) {
+ return fieldValues;
}
// internal helpers
- private void checkRequired(Map sourceValues) {
- if (requiredProperties == null) {
+ private void checkRequired(Map fieldValues) {
+ if (requiredFields == null) {
return;
}
List missingRequired = new ArrayList();
- for (String required : requiredProperties) {
+ for (String required : requiredFields) {
boolean found = false;
- for (String property : sourceValues.keySet()) {
+ for (String property : fieldValues.keySet()) {
if (property.equals(required)) {
found = true;
}
@@ -124,21 +128,21 @@ public class GenericBinder implements Binder {
}
}
if (!missingRequired.isEmpty()) {
- throw new MissingSourceValuesException(missingRequired, sourceValues);
+ throw new MissingFieldException(missingRequired, fieldValues);
}
}
- private BindingResult bind(Map.Entry sourceValue, Binding binding) {
- String property = sourceValue.getKey();
- Object value = sourceValue.getValue();
- if (!binding.isEditable()) {
- return new PropertyNotEditableResult(property, value, messageSource);
+ private BindingResult bind(Map.Entry fieldValue, FieldModel field) {
+ String fieldName = fieldValue.getKey();
+ Object value = fieldValue.getValue();
+ if (!field.isEditable()) {
+ return new FieldNotEditableResult(fieldName, value, messageSource);
} else {
- binding.applySourceValue(value);
- if (binding.getBindingStatus() == BindingStatus.DIRTY) {
- binding.commit();
+ field.applySubmittedValue(value);
+ if (field.getBindingStatus() == BindingStatus.DIRTY) {
+ field.commit();
}
- return new BindingStatusResult(property, value, binding.getStatusAlert());
+ return new BindingStatusResult(fieldName, value, field.getStatusAlert());
}
}
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/MissingSourceValuesException.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/MissingFieldException.java
similarity index 76%
rename from org.springframework.context/src/main/java/org/springframework/ui/binding/binder/MissingSourceValuesException.java
rename to org.springframework.context/src/main/java/org/springframework/ui/binding/binder/MissingFieldException.java
index 6f528fa03be..ac948fdeb44 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/MissingSourceValuesException.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/MissingFieldException.java
@@ -26,7 +26,7 @@ import java.util.Map;
* @see Binder#bind(java.util.Map)
*/
@SuppressWarnings("serial")
-public class MissingSourceValuesException extends RuntimeException {
+public class MissingFieldException extends RuntimeException {
private List missing;
@@ -35,7 +35,7 @@ public class MissingSourceValuesException extends RuntimeException {
* @param missing
* @param sourceValues
*/
- public MissingSourceValuesException(List missing, Map sourceValues) {
+ public MissingFieldException(List missing, Map sourceValues) {
super(getMessage(missing, sourceValues));
this.missing = missing;
}
@@ -49,9 +49,9 @@ public class MissingSourceValuesException extends RuntimeException {
private static String getMessage(List missingRequired, Map sourceValues) {
if (missingRequired.size() == 1) {
- return "Missing a source value for required propertyPath [" + missingRequired.get(0) + "]; sourceValues map contained " + sourceValues.keySet();
+ return "Missing a field [" + missingRequired.get(0) + "]; fieldValues map contained " + sourceValues.keySet();
} else {
- return "Missing source values to required propertyPaths " + missingRequired + "; sourceValues map contained " + sourceValues.keySet();
+ return "Missing fields " + missingRequired + "; fieldValues map contained " + sourceValues.keySet();
}
}
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/WebBinder.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/WebBinder.java
index a8a9dc121a0..55feb27faa2 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/WebBinder.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/binder/WebBinder.java
@@ -18,8 +18,8 @@ package org.springframework.ui.binding.binder;
import java.util.LinkedHashMap;
import java.util.Map;
-import org.springframework.ui.binding.Binding;
-import org.springframework.ui.binding.BindingFactory;
+import org.springframework.ui.binding.FieldModel;
+import org.springframework.ui.binding.PresentationModel;
/**
* A binder designed for use in HTTP (web) environments.
@@ -39,13 +39,12 @@ public class WebBinder extends GenericBinder {
* Creates a new web binder for the model object.
* @param model the model object containing properties this binder will bind to
*/
- public WebBinder(BindingFactory bindingFactory) {
+ public WebBinder(PresentationModel bindingFactory) {
super(bindingFactory);
}
/**
- * Configure the prefix to detect the default user value for a property when no value was submitted.
- * This is used to configure a default {@link UserValue} for binding when no value is submitted by the client.
+ * Configure the prefix used to detect the default value for a field when no value is submitted.
* Default is '!'.
*/
public void setDefaultPrefix(String defaultPrefix) {
@@ -53,8 +52,8 @@ public class WebBinder extends GenericBinder {
}
/**
- * Configure the prefix to detect the presence of a property on the web UI when no user value for the property was actually submitted.
- * This is used to configure a empty {@link UserValue} for binding when no other {@link #setDefaultPrefix(String) default value} is specified by the client.
+ * Configure the prefix used to detect the presence of a field on the web UI when no value was actually submitted.
+ * This is used to configure a empty field when no other {@link #setDefaultPrefix(String) default value} is specified by the client.
* Default is '_'.
*/
public void setPresentPrefix(String presentPrefix) {
@@ -62,20 +61,20 @@ public class WebBinder extends GenericBinder {
}
@Override
- protected Map filter(Map sourceValues) {
+ protected Map filter(Map fieldValues) {
LinkedHashMap filteredValues = new LinkedHashMap();
- for (Map.Entry entry : sourceValues.entrySet()) {
+ for (Map.Entry entry : fieldValues.entrySet()) {
String field = entry.getKey();
Object value = entry.getValue();
if (field.startsWith(defaultPrefix)) {
field = field.substring(defaultPrefix.length());
- if (!sourceValues.containsKey(field)) {
+ if (!fieldValues.containsKey(field)) {
filteredValues.put(field, value);
}
} else if (field.startsWith(presentPrefix)) {
field = field.substring(presentPrefix.length());
- if (!sourceValues.containsKey(field) && !sourceValues.containsKey(defaultPrefix + field)) {
- value = getEmptyValue(getBinding(field));
+ if (!fieldValues.containsKey(field) && !fieldValues.containsKey(defaultPrefix + field)) {
+ value = getEmptyValue(getFieldModel(field));
filteredValues.put(field, value);
}
} else {
@@ -85,7 +84,7 @@ public class WebBinder extends GenericBinder {
return filteredValues;
}
- protected Object getEmptyValue(Binding binding) {
+ protected Object getEmptyValue(FieldModel binding) {
Class> type = binding.getValueType();
if (boolean.class.equals(type) || Boolean.class.equals(type)) {
return Boolean.FALSE;
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/config/BindingRuleConfiguration.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/config/FieldModelConfiguration.java
similarity index 74%
rename from org.springframework.context/src/main/java/org/springframework/ui/binding/config/BindingRuleConfiguration.java
rename to org.springframework.context/src/main/java/org/springframework/ui/binding/config/FieldModelConfiguration.java
index a2cfe6b948b..bd10e73c5b8 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/config/BindingRuleConfiguration.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/config/FieldModelConfiguration.java
@@ -21,35 +21,35 @@ import org.springframework.ui.format.Formatter;
* A fluent interface for configuring a newly added binding rule.
* @author Keith Donald
*/
-public interface BindingRuleConfiguration {
+public interface FieldModelConfiguration {
/**
* Set the Formatter to use to format bound property values.
*/
- BindingRuleConfiguration formatWith(Formatter> formatter);
+ FieldModelConfiguration formatWith(Formatter> formatter);
/**
* If a map property, set the Formatter to use to format map keys.
*/
- BindingRuleConfiguration formatKeysWith(Formatter> formatter);
+ FieldModelConfiguration formatKeysWith(Formatter> formatter);
/**
* If an list or map property, set the Formatter to use to format indexed elements.
*/
- BindingRuleConfiguration formatElementsWith(Formatter> formatter);
+ FieldModelConfiguration formatElementsWith(Formatter> formatter);
/**
* Set when the binding is editable.
*/
- BindingRuleConfiguration editableWhen(Condition condition);
+ FieldModelConfiguration editableWhen(Condition condition);
/**
* Set when the binding is enabled.
*/
- BindingRuleConfiguration enabledWhen(Condition condition);
+ FieldModelConfiguration enabledWhen(Condition condition);
/**
* Set when the binding is visible.
*/
- BindingRuleConfiguration visibleWhen(Condition condition);
+ FieldModelConfiguration visibleWhen(Condition condition);
}
\ No newline at end of file
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/support/CollectionTypeDescriptor.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/support/CollectionTypeDescriptor.java
index ebb4555b5c3..a9ba2bb25cc 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/support/CollectionTypeDescriptor.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/support/CollectionTypeDescriptor.java
@@ -15,29 +15,26 @@
*/
package org.springframework.ui.binding.support;
+import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
public class CollectionTypeDescriptor {
- private Class> collectionType;
+ private Class> type;
private Class> elementType;
- /**
- * Creates a new generic collection property type
- * @param collectionType the collection type
- * @param elementType the element type
- */
- public CollectionTypeDescriptor(Class> collectionType, Class> elementType) {
- this.collectionType = collectionType;
+ public CollectionTypeDescriptor(Class> type, Class> elementType) {
+ Assert.notNull(type, "The collection type is required");
+ this.type = type;
this.elementType = elementType;
}
/**
* The collection type.
*/
- public Class> getCollectionType() {
- return collectionType;
+ public Class> getType() {
+ return type;
}
/**
@@ -52,11 +49,11 @@ public class CollectionTypeDescriptor {
return false;
}
CollectionTypeDescriptor type = (CollectionTypeDescriptor) o;
- return collectionType.equals(type.collectionType)
+ return type.equals(type.type)
&& ObjectUtils.nullSafeEquals(elementType, type.elementType);
}
public int hashCode() {
- return collectionType.hashCode() + elementType.hashCode();
+ return type.hashCode() + elementType.hashCode();
}
}
\ No newline at end of file
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericBinding.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/support/DefaultFieldModel.java
similarity index 65%
rename from org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericBinding.java
rename to org.springframework.context/src/main/java/org/springframework/ui/binding/support/DefaultFieldModel.java
index 80ba735029b..e79e85ebcc4 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericBinding.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/support/DefaultFieldModel.java
@@ -34,38 +34,38 @@ import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.style.StylerUtils;
import org.springframework.ui.alert.Alert;
import org.springframework.ui.alert.Severity;
-import org.springframework.ui.binding.Binding;
import org.springframework.ui.binding.BindingStatus;
+import org.springframework.ui.binding.FieldModel;
import org.springframework.ui.binding.ValidationStatus;
import org.springframework.ui.format.Formatter;
import org.springframework.ui.message.MessageBuilder;
import org.springframework.ui.message.ResolvableArgument;
-public class GenericBinding implements Binding {
+public class DefaultFieldModel implements FieldModel {
private ValueModel valueModel;
- private BindingContext bindingContext;
+ private FieldModelContext context;
private ValueBuffer buffer;
private BindingStatus bindingStatus;
- private Object sourceValue;
+ private Object submittedValue;
- private Exception invalidSourceValueCause;
+ private Exception invalidSubmittedValueCause;
- public GenericBinding(ValueModel valueModel, BindingContext bindingContext) {
+ public DefaultFieldModel(ValueModel valueModel, FieldModelContext context) {
this.valueModel = valueModel;
- this.bindingContext = bindingContext;
+ this.context = context;
buffer = new ValueBuffer(valueModel);
bindingStatus = BindingStatus.CLEAN;
}
- // implementing Binding
+ // implementing FieldModel
public String getRenderValue() {
- return format(getValue(), bindingContext.getFormatter());
+ return format(getValue(), context.getFormatter());
}
public Object getValue() {
@@ -81,42 +81,42 @@ public class GenericBinding implements Binding {
}
public boolean isEditable() {
- return valueModel.isWriteable() && bindingContext.getEditableCondition().isTrue();
+ return valueModel.isWriteable() && context.getEditableCondition().isTrue();
}
public boolean isEnabled() {
- return bindingContext.getEnabledCondition().isTrue();
+ return context.getEnabledCondition().isTrue();
}
public boolean isVisible() {
- return bindingContext.getVisibleCondition().isTrue();
+ return context.getVisibleCondition().isTrue();
}
@SuppressWarnings("unchecked")
- public void applySourceValue(Object sourceValue) {
+ public void applySubmittedValue(Object submittedValue) {
assertEditable();
assertEnabled();
- if (sourceValue instanceof String) {
+ if (submittedValue instanceof String) {
try {
- Object parsed = bindingContext.getFormatter().parse((String) sourceValue, getLocale());
+ Object parsed = context.getFormatter().parse((String) submittedValue, getLocale());
buffer.setValue(coerseToValueType(parsed));
- sourceValue = null;
+ submittedValue = null;
bindingStatus = BindingStatus.DIRTY;
} catch (ParseException e) {
- this.sourceValue = sourceValue;
- invalidSourceValueCause = e;
- bindingStatus = BindingStatus.INVALID_SOURCE_VALUE;
+ this.submittedValue = submittedValue;
+ invalidSubmittedValueCause = e;
+ bindingStatus = BindingStatus.INVALID_SUBMITTED_VALUE;
} catch (ConversionFailedException e) {
- this.sourceValue = sourceValue;
- invalidSourceValueCause = e;
- bindingStatus = BindingStatus.INVALID_SOURCE_VALUE;
+ this.submittedValue = submittedValue;
+ invalidSubmittedValueCause = e;
+ bindingStatus = BindingStatus.INVALID_SUBMITTED_VALUE;
}
- } else if (sourceValue instanceof String[]) {
+ } else if (submittedValue instanceof String[]) {
Object parsed;
if (isMap()) {
- String[] sourceValues = (String[]) sourceValue;
- Formatter keyFormatter = bindingContext.getKeyFormatter();
- Formatter valueFormatter = bindingContext.getElementFormatter();
+ String[] sourceValues = (String[]) submittedValue;
+ Formatter keyFormatter = context.getKeyFormatter();
+ Formatter valueFormatter = context.getElementFormatter();
Map map = new LinkedHashMap(sourceValues.length);
for (int i = 0; i < sourceValues.length; i++) {
String entryString = sourceValues[i];
@@ -126,59 +126,59 @@ public class GenericBinding implements Binding {
Object parsedMapValue = valueFormatter.parse(keyValue[1], getLocale());
map.put(parsedMapKey, parsedMapValue);
} catch (ParseException e) {
- this.sourceValue = sourceValue;
- invalidSourceValueCause = e;
- bindingStatus = BindingStatus.INVALID_SOURCE_VALUE;
+ this.submittedValue = submittedValue;
+ invalidSubmittedValueCause = e;
+ bindingStatus = BindingStatus.INVALID_SUBMITTED_VALUE;
break;
}
}
parsed = map;
} else {
- String[] sourceValues = (String[]) sourceValue;
+ String[] sourceValues = (String[]) submittedValue;
List list = new ArrayList(sourceValues.length);
for (int i = 0; i < sourceValues.length; i++) {
Object parsedValue;
try {
- parsedValue = bindingContext.getElementFormatter().parse(sourceValues[i], getLocale());
+ parsedValue = context.getElementFormatter().parse(sourceValues[i], getLocale());
list.add(parsedValue);
} catch (ParseException e) {
- this.sourceValue = sourceValue;
- invalidSourceValueCause = e;
- bindingStatus = BindingStatus.INVALID_SOURCE_VALUE;
+ this.submittedValue = submittedValue;
+ invalidSubmittedValueCause = e;
+ bindingStatus = BindingStatus.INVALID_SUBMITTED_VALUE;
break;
}
}
parsed = list;
}
- if (bindingStatus != BindingStatus.INVALID_SOURCE_VALUE) {
+ if (bindingStatus != BindingStatus.INVALID_SUBMITTED_VALUE) {
try {
buffer.setValue(coerseToValueType(parsed));
- sourceValue = null;
+ submittedValue = null;
bindingStatus = BindingStatus.DIRTY;
} catch (ConversionFailedException e) {
- this.sourceValue = sourceValue;
- invalidSourceValueCause = e;
- bindingStatus = BindingStatus.INVALID_SOURCE_VALUE;
+ this.submittedValue = submittedValue;
+ invalidSubmittedValueCause = e;
+ bindingStatus = BindingStatus.INVALID_SUBMITTED_VALUE;
}
}
} else {
try {
- buffer.setValue(coerseToValueType(sourceValue));
- sourceValue = null;
+ buffer.setValue(coerseToValueType(submittedValue));
+ submittedValue = null;
bindingStatus = BindingStatus.DIRTY;
} catch (ConversionFailedException e) {
- this.sourceValue = sourceValue;
- invalidSourceValueCause = e;
- bindingStatus = BindingStatus.INVALID_SOURCE_VALUE;
+ this.submittedValue = submittedValue;
+ invalidSubmittedValueCause = e;
+ bindingStatus = BindingStatus.INVALID_SUBMITTED_VALUE;
}
}
}
- public Object getInvalidSourceValue() {
- if (bindingStatus != BindingStatus.INVALID_SOURCE_VALUE) {
- throw new IllegalStateException("No invalid source value");
+ public Object getInvalidSubmittedValue() {
+ if (bindingStatus != BindingStatus.INVALID_SUBMITTED_VALUE) {
+ throw new IllegalStateException("No invalid submitted value applied to this field");
}
- return sourceValue;
+ return submittedValue;
}
public BindingStatus getBindingStatus() {
@@ -186,32 +186,33 @@ public class GenericBinding implements Binding {
}
public ValidationStatus getValidationStatus() {
+ // TODO implementation
return ValidationStatus.NOT_VALIDATED;
}
public Alert getStatusAlert() {
- if (bindingStatus == BindingStatus.INVALID_SOURCE_VALUE) {
+ if (bindingStatus == BindingStatus.INVALID_SUBMITTED_VALUE) {
return new AbstractAlert() {
public String getCode() {
return "typeMismatch";
}
public String getMessage() {
- MessageBuilder builder = new MessageBuilder(bindingContext.getMessageSource());
+ MessageBuilder builder = new MessageBuilder(context.getMessageSource());
builder.code(getCode());
- if (invalidSourceValueCause instanceof ParseException) {
- ParseException e = (ParseException) invalidSourceValueCause;
- builder.arg("label", bindingContext.getLabel());
- builder.arg("value", sourceValue);
+ if (invalidSubmittedValueCause instanceof ParseException) {
+ ParseException e = (ParseException) invalidSubmittedValueCause;
+ builder.arg("label", context.getLabel());
+ builder.arg("value", submittedValue);
builder.arg("errorOffset", e.getErrorOffset());
- builder.defaultMessage("Failed to bind '" + bindingContext.getLabel() + "'; the source value "
- + StylerUtils.style(sourceValue) + " has an invalid format and could no be parsed");
+ builder.defaultMessage("Failed to bind '" + context.getLabel() + "'; the submitted value "
+ + StylerUtils.style(submittedValue) + " has an invalid format and could no be parsed");
} else {
- ConversionFailedException e = (ConversionFailedException) invalidSourceValueCause;
- builder.arg("label", new ResolvableArgument(bindingContext.getLabel()));
- builder.arg("value", sourceValue);
- builder.defaultMessage("Failed to bind '" + bindingContext.getLabel() + "'; the source value "
- + StylerUtils.style(sourceValue) + " has could not be converted to "
+ ConversionFailedException e = (ConversionFailedException) invalidSubmittedValueCause;
+ builder.arg("label", new ResolvableArgument(context.getLabel()));
+ builder.arg("value", submittedValue);
+ builder.defaultMessage("Failed to bind '" + context.getLabel() + "'; the submitted value "
+ + StylerUtils.style(submittedValue) + " has could not be converted to "
+ e.getTargetType().getName());
}
@@ -257,6 +258,7 @@ public class GenericBinding implements Binding {
}
public void validate() {
+ // TODO implementation
}
public void commit() {
@@ -270,57 +272,57 @@ public class GenericBinding implements Binding {
bindingStatus = BindingStatus.COMMITTED;
}
} else {
- throw new IllegalStateException("Binding is not dirty; nothing to commit");
+ throw new IllegalStateException("Field is not dirty; nothing to commit");
}
}
public void revert() {
- if (bindingStatus == BindingStatus.INVALID_SOURCE_VALUE) {
- sourceValue = null;
- invalidSourceValueCause = null;
+ if (bindingStatus == BindingStatus.INVALID_SUBMITTED_VALUE) {
+ submittedValue = null;
+ invalidSubmittedValueCause = null;
bindingStatus = BindingStatus.CLEAN;
} else if (bindingStatus == BindingStatus.DIRTY || bindingStatus == BindingStatus.COMMIT_FAILURE) {
buffer.clear();
bindingStatus = BindingStatus.CLEAN;
} else {
- throw new IllegalStateException("Nothing to revert");
+ throw new IllegalStateException("Field is clean or committed; nothing to revert");
}
}
- public Binding getNestedBinding(String property) {
- return bindingContext.getNestedBinding(property);
+ public FieldModel getNested(String fieldName) {
+ return context.getNested(fieldName);
}
public boolean isList() {
- return List.class.isAssignableFrom(getValueType());
+ return getValueType().isArray() || List.class.isAssignableFrom(getValueType());
}
- public Binding getListElementBinding(int index) {
- return bindingContext.getListElementBinding(index);
+ public FieldModel getListElement(int index) {
+ return context.getListElement(index);
}
public boolean isMap() {
return Map.class.isAssignableFrom(getValueType());
}
- public Binding getMapValueBinding(Object key) {
+ public FieldModel getMapValue(Object key) {
if (key instanceof String) {
try {
- key = bindingContext.getKeyFormatter().parse((String) key, getLocale());
+ key = context.getKeyFormatter().parse((String) key, getLocale());
} catch (ParseException e) {
throw new IllegalArgumentException("Unable to parse map key '" + key + "'", e);
}
}
- return bindingContext.getMapValueBinding(key);
+ return context.getMapValue(key);
}
@SuppressWarnings("unchecked")
public String formatValue(Object value) {
Formatter formatter;
if (Collection.class.isAssignableFrom(getValueType()) || getValueType().isArray() || isMap()) {
- formatter = bindingContext.getElementFormatter();
+ formatter = context.getElementFormatter();
} else {
- formatter = bindingContext.getFormatter();
+ formatter = context.getFormatter();
}
return format(value, formatter);
}
@@ -330,7 +332,7 @@ public class GenericBinding implements Binding {
@SuppressWarnings("unchecked")
private String format(Object value, Formatter formatter) {
Class> formattedType = getFormattedObjectType(formatter.getClass());
- value = bindingContext.getTypeConverter().convert(value, formattedType);
+ value = context.getTypeConverter().convert(value, formattedType);
return formatter.format(value, getLocale());
}
@@ -370,7 +372,7 @@ public class GenericBinding implements Binding {
@SuppressWarnings("unchecked")
private Object coerseToValueType(Object parsed) {
TypeDescriptor targetType = valueModel.getValueTypeDescriptor();
- TypeConverter converter = bindingContext.getTypeConverter();
+ TypeConverter converter = context.getTypeConverter();
if (parsed != null && converter.canConvert(parsed.getClass(), targetType)) {
return converter.convert(parsed, targetType);
} else {
@@ -380,13 +382,13 @@ public class GenericBinding implements Binding {
private void assertEditable() {
if (!isEditable()) {
- throw new IllegalStateException("Binding is not editable");
+ throw new IllegalStateException("Field is not editable");
}
}
private void assertEnabled() {
if (!isEditable()) {
- throw new IllegalStateException("Binding is not enabled");
+ throw new IllegalStateException("Field is not enabled");
}
}
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericBindingFactory.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/support/DefaultPresentationModel.java
similarity index 53%
rename from org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericBindingFactory.java
rename to org.springframework.context/src/main/java/org/springframework/ui/binding/support/DefaultPresentationModel.java
index 4ea4add0796..998f0c254c0 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericBindingFactory.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/support/DefaultPresentationModel.java
@@ -29,11 +29,11 @@ import org.springframework.context.MessageSource;
import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.convert.TypeConverter;
import org.springframework.core.convert.support.DefaultTypeConverter;
-import org.springframework.ui.binding.Binding;
-import org.springframework.ui.binding.BindingFactory;
+import org.springframework.ui.binding.FieldModel;
+import org.springframework.ui.binding.FieldNotFoundException;
+import org.springframework.ui.binding.PresentationModel;
import org.springframework.ui.binding.binder.Binder;
-import org.springframework.ui.binding.binder.BindingResult;
-import org.springframework.ui.binding.config.BindingRuleConfiguration;
+import org.springframework.ui.binding.config.FieldModelConfiguration;
import org.springframework.ui.binding.config.Condition;
import org.springframework.ui.format.Formatter;
import org.springframework.util.Assert;
@@ -42,15 +42,16 @@ import org.springframework.util.Assert;
* A generic {@link Binder binder} suitable for use in most environments.
* @author Keith Donald
* @since 3.0
+ * @see #setFormatterRegistry(FormatterRegistry)
* @see #setMessageSource(MessageSource)
* @see #setTypeConverter(TypeConverter)
* @see #bind(Map)
*/
-public class GenericBindingFactory implements BindingFactory {
+public class DefaultPresentationModel implements PresentationModel {
- private Object model;
+ private Object domainModel;
- private Map bindingRules;
+ private Map fieldModelRules;
private FormatterRegistry formatterRegistry;
@@ -59,19 +60,19 @@ public class GenericBindingFactory implements BindingFactory {
private MessageSource messageSource;
/**
- * Creates a new binder for the model object.
- * @param model the model object containing properties this binder will bind to
+ * Creates a new presentation model for the domain model.
+ * @param domainModel the domain model object
*/
- public GenericBindingFactory(Object model) {
- Assert.notNull(model, "The model to bind to is required");
- this.model = model;
- bindingRules = new HashMap();
+ public DefaultPresentationModel(Object domainModel) {
+ Assert.notNull(domainModel, "The domain model to bind to is required");
+ this.domainModel = domainModel;
+ fieldModelRules = new HashMap();
formatterRegistry = new GenericFormatterRegistry();
typeConverter = new DefaultTypeConverter();
}
/**
- * Configures the registry of Formatters to query when no explicit Formatter has been registered for a Binding.
+ * Configures the registry of Formatters to query when no explicit Formatter has been registered for a field.
* Allows Formatters to be applied by property type and by property annotation.
* @param registry the formatter registry
*/
@@ -81,7 +82,7 @@ public class GenericBindingFactory implements BindingFactory {
}
/**
- * Configure the MessageSource that resolves localized {@link BindingResult} alert messages.
+ * Configure the MessageSource that resolves localized UI alert messages.
* @param messageSource the message source
*/
public void setMessageSource(MessageSource messageSource) {
@@ -90,10 +91,11 @@ public class GenericBindingFactory implements BindingFactory {
}
/**
- * Configure the TypeConverter that converts values as required by Binding setValue and getValue attempts.
- * For a setValue attempt, the TypeConverter will be asked to perform a conversion if the value parsed by the Binding's Formatter is not assignable to the target property type.
- * For a getValue attempt, the TypeConverter will be asked to perform a conversion if the property type does not match the type T required by the Binding's Formatter.
- * @param typeConverter the type converter used by the binding system, which is based on Spring EL
+ * Configure the TypeConverter that converts values as required by the binding system.
+ * For a {@link FieldModel#applySubmittedValue(Object) applySubmittedValue call}, this TypeConverter will be asked to perform a conversion if the value parsed by the field's Formatter is not assignable to the target value type.
+ * For a {@link FieldModel#getRenderValue() getRenderValue call}, this TypeConverter will be asked to perform a conversion if the value type does not match the type T required by the field's Formatter.
+ * For a {@link FieldModel#getMapValue(Object) getMapValue call} this TypeConverter will be asked to convert the Map key to the type required if there is no keyFormatter registered for the field.
+ * @param typeConverter the type converter used by the binding system
*/
public void setTypeConverter(TypeConverter typeConverter) {
Assert.notNull(typeConverter, "The TypeConverter is required");
@@ -101,57 +103,57 @@ public class GenericBindingFactory implements BindingFactory {
}
/**
- * Add a new binding rule for the property at the path specified.
+ * Add a a new FieldModelRule for the property at the path specified.
* @param propertyPath binding rule property path in format prop.nestedProp
* @return a builder for the binding rule
*/
- public BindingRuleConfiguration bindingRule(String propertyPath) {
- PropertyPath path = new PropertyPath(propertyPath);
- GenericBindingRule rule = getBindingRule(path.getFirstElement().getValue());
- for (PropertyPathElement element : path.getNestedElements()) {
- rule = rule.getBindingRule(element.getValue());
+ public FieldModelConfiguration field(String propertyPath) {
+ FieldPath path = new FieldPath(propertyPath);
+ PropertyFieldModelRule rule = getRule(path.getFirstElement().getValue());
+ for (FieldPathElement element : path.getNestedElements()) {
+ rule = rule.getNestedRule(element.getValue());
}
return rule;
}
- // implementing Binder
-
- public Object getModel() {
- return model;
+ public Object getDomainModel() {
+ return domainModel;
}
- public Binding getBinding(String property) {
- PropertyPath path = new PropertyPath(property);
- Binding binding = getBindingRule(path.getFirstElement().getValue()).getBinding(model);
- for (PropertyPathElement element : path.getNestedElements()) {
+ // implementing PresentationModel
+
+ public FieldModel getFieldModel(String fieldName) {
+ FieldPath path = new FieldPath(fieldName);
+ FieldModel field = getRule(path.getFirstElement().getValue()).getFieldModel(domainModel);
+ for (FieldPathElement element : path.getNestedElements()) {
if (element.isIndex()) {
- if (binding.isMap()) {
- binding = binding.getMapValueBinding(element.getValue());
- } else if (binding.isList()) {
- binding = binding.getListElementBinding(element.getIntValue());
+ if (field.isMap()) {
+ field = field.getMapValue(element.getValue());
+ } else if (field.isList()) {
+ field = field.getListElement(element.getIntValue());
} else {
- throw new IllegalArgumentException("Attempted to index a property that is not a List or Map");
+ throw new IllegalArgumentException("Attempted to index a field that is not a List, Array, or a Map");
}
} else {
- binding = binding.getNestedBinding(element.getValue());
+ field = field.getNested(element.getValue());
}
}
- return binding;
+ return field;
}
- private GenericBindingRule getBindingRule(String property) {
- GenericBindingRule rule = bindingRules.get(property);
+ private PropertyFieldModelRule getRule(String fieldName) {
+ PropertyFieldModelRule rule = fieldModelRules.get(fieldName);
if (rule == null) {
- rule = new GenericBindingRule(property, model.getClass());
- bindingRules.put(property, rule);
+ rule = new PropertyFieldModelRule(fieldName, domainModel.getClass());
+ fieldModelRules.put(fieldName, rule);
}
return rule;
}
@SuppressWarnings("unchecked")
- class GenericBindingRule implements BindingRuleConfiguration, BindingContext {
+ class PropertyFieldModelRule implements FieldModelConfiguration, FieldModelContext {
- private Class> modelClass;
+ private Class> domainModelClass;
private PropertyDescriptor property;
@@ -167,20 +169,20 @@ public class GenericBindingFactory implements BindingFactory {
private Condition visibleCondition = Condition.ALWAYS_TRUE;
- private Map nestedBindingRules;
+ private Map nestedFieldModelRules;
- private Binding binding;
+ private FieldModel fieldModel;
- private Map listElementBindings;
+ private Map listElements;
- private Map