diff options
Diffstat (limited to 'server/src/com/vaadin/data/fieldgroup')
-rw-r--r-- | server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java | 65 | ||||
-rw-r--r-- | server/src/com/vaadin/data/fieldgroup/FieldGroup.java | 89 |
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); } - } /** |