aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/com/vaadin/data/fieldgroup
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/com/vaadin/data/fieldgroup')
-rw-r--r--server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java65
-rw-r--r--server/src/com/vaadin/data/fieldgroup/FieldGroup.java89
2 files changed, 92 insertions, 62 deletions
diff --git a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java
index e5d53b759d..23a72ee1e5 100644
--- a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java
+++ b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java
@@ -15,18 +15,20 @@
*/
package com.vaadin.data.fieldgroup;
+import java.beans.IntrospectionException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import com.vaadin.data.Item;
import com.vaadin.data.util.BeanItem;
+import com.vaadin.data.util.BeanUtil;
import com.vaadin.data.validator.BeanValidator;
import com.vaadin.ui.Field;
public class BeanFieldGroup<T> extends FieldGroup {
- private Class<T> beanType;
+ private final Class<T> beanType;
private static Boolean beanValidationImplementationAvailable = null;
private final Map<Field<?>, BeanValidator> defaultValidators;
@@ -47,17 +49,20 @@ public class BeanFieldGroup<T> extends FieldGroup {
* form "fieldName" or "fieldName.subField[.subField2]" but the
* method declaration comes from parent.
*/
- java.lang.reflect.Field f;
try {
- f = getField(beanType, propertyId.toString());
- return f.getType();
- } catch (SecurityException e) {
- throw new BindException("Cannot determine type of propertyId '"
- + propertyId + "'.", e);
- } catch (NoSuchFieldException e) {
+ Class<?> type = BeanUtil.getPropertyType(beanType,
+ propertyId.toString());
+ if (type == null) {
+ throw new BindException(
+ "Cannot determine type of propertyId '"
+ + propertyId
+ + "'. The propertyId was not found in "
+ + beanType.getName());
+ }
+ return type;
+ } catch (IntrospectionException e) {
throw new BindException("Cannot determine type of propertyId '"
- + propertyId + "'. The propertyId was not found in "
- + beanType.getName(), e);
+ + propertyId + "'. Unable to introspect " + beanType, e);
}
}
}
@@ -79,32 +84,6 @@ public class BeanFieldGroup<T> extends FieldGroup {
return null;
}
- private static java.lang.reflect.Field getField(Class<?> cls,
- String propertyId) throws SecurityException, NoSuchFieldException {
- if (propertyId.contains(".")) {
- String[] parts = propertyId.split("\\.", 2);
- // Get the type of the field in the "cls" class
- java.lang.reflect.Field field1 = getField(cls, parts[0]);
- // Find the rest from the sub type
- return getField(field1.getType(), parts[1]);
- } else {
- try {
- // Try to find the field directly in the given class
- java.lang.reflect.Field field1 = cls
- .getDeclaredField(propertyId);
- return field1;
- } catch (NoSuchFieldException e) {
- // Try super classes until we reach Object
- Class<?> superClass = cls.getSuperclass();
- if (superClass != null && superClass != Object.class) {
- return getField(superClass, propertyId);
- } else {
- throw e;
- }
- }
- }
- }
-
private static String getFieldName(Class<?> cls, String propertyId)
throws SecurityException, NoSuchFieldException {
for (java.lang.reflect.Field field1 : cls.getDeclaredFields()) {
@@ -125,21 +104,29 @@ public class BeanFieldGroup<T> extends FieldGroup {
* Helper method for setting the data source directly using a bean. This
* method wraps the bean in a {@link BeanItem} and calls
* {@link #setItemDataSource(Item)}.
+ * <p>
+ * For null values, a null item is passed to
+ * {@link #setItemDataSource(Item)} to be properly clear fields.
*
* @param bean
* The bean to use as data source.
*/
public void setItemDataSource(T bean) {
- setItemDataSource(new BeanItem(bean));
+ if (bean == null) {
+ setItemDataSource((Item) null);
+ } else {
+ setItemDataSource(new BeanItem<T>(bean, beanType));
+ }
}
@Override
public void setItemDataSource(Item item) {
- if (!(item instanceof BeanItem)) {
+ if (item == null || (item instanceof BeanItem)) {
+ super.setItemDataSource(item);
+ } else {
throw new RuntimeException(getClass().getSimpleName()
+ " only supports BeanItems as item data source");
}
- super.setItemDataSource(item);
}
@Override
diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
index 5a4e877554..c89b94ace9 100644
--- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
+++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
@@ -255,6 +255,9 @@ public class FieldGroup implements Serializable {
fieldToPropertyId.put(field, propertyId);
propertyIdToField.put(propertyId, field);
if (itemDataSource == null) {
+ // Clear any possible existing binding to clear the field
+ field.setPropertyDataSource(null);
+ field.clear();
// Will be bound when data source is set
return;
}
@@ -452,6 +455,56 @@ public class FieldGroup implements Serializable {
// Not using buffered mode, nothing to do
return;
}
+
+ startTransactions();
+
+ try {
+ firePreCommitEvent();
+
+ List<InvalidValueException> invalidValueExceptions = commitFields();
+
+ if (invalidValueExceptions.isEmpty()) {
+ firePostCommitEvent();
+ commitTransactions();
+ } else {
+ throwInvalidValueException(invalidValueExceptions);
+ }
+ } catch (Exception e) {
+ rollbackTransactions();
+
+ throw new CommitException("Commit failed", e);
+ }
+
+ }
+
+ private List<InvalidValueException> commitFields() {
+ List<InvalidValueException> invalidValueExceptions = new ArrayList<InvalidValueException>();
+
+ for (Field<?> f : fieldToPropertyId.keySet()) {
+ try {
+ f.commit();
+ } catch (InvalidValueException e) {
+ invalidValueExceptions.add(e);
+ }
+ }
+
+ return invalidValueExceptions;
+ }
+
+ private void throwInvalidValueException(
+ List<InvalidValueException> invalidValueExceptions) {
+ if (invalidValueExceptions.size() == 1) {
+ throw invalidValueExceptions.get(0);
+ } else {
+ InvalidValueException[] causes = invalidValueExceptions
+ .toArray(new InvalidValueException[invalidValueExceptions
+ .size()]);
+
+ throw new InvalidValueException(null, causes);
+ }
+ }
+
+ private void startTransactions() throws CommitException {
for (Field<?> f : fieldToPropertyId.keySet()) {
Property.Transactional<?> property = (Property.Transactional<?>) f
.getPropertyDataSource();
@@ -462,33 +515,23 @@ public class FieldGroup implements Serializable {
}
property.startTransaction();
}
- try {
- firePreCommitEvent();
- // Commit the field values to the properties
- for (Field<?> f : fieldToPropertyId.keySet()) {
- f.commit();
- }
- firePostCommitEvent();
+ }
- // Commit the properties
- for (Field<?> f : fieldToPropertyId.keySet()) {
- ((Property.Transactional<?>) f.getPropertyDataSource())
- .commit();
- }
+ private void commitTransactions() {
+ for (Field<?> f : fieldToPropertyId.keySet()) {
+ ((Property.Transactional<?>) f.getPropertyDataSource()).commit();
+ }
+ }
- } catch (Exception e) {
- for (Field<?> f : fieldToPropertyId.keySet()) {
- try {
- ((Property.Transactional<?>) f.getPropertyDataSource())
- .rollback();
- } catch (Exception rollbackException) {
- // FIXME: What to do ?
- }
+ private void rollbackTransactions() {
+ for (Field<?> f : fieldToPropertyId.keySet()) {
+ try {
+ ((Property.Transactional<?>) f.getPropertyDataSource())
+ .rollback();
+ } catch (Exception rollbackException) {
+ // FIXME: What to do ?
}
-
- throw new CommitException("Commit failed", e);
}
-
}
/**