]> source.dussan.org Git - vaadin-framework.git/commitdiff
#8095 Allow binding all fields in a class using FieldBinder instead of
authorArtur Signell <artur@vaadin.com>
Mon, 19 Dec 2011 13:41:10 +0000 (15:41 +0200)
committerArtur Signell <artur@vaadin.com>
Mon, 19 Dec 2011 14:41:02 +0000 (16:41 +0200)
FormBuilder

src/com/vaadin/data/fieldbinder/FieldBinder.java
src/com/vaadin/data/fieldbinder/FormBuilder.java
src/com/vaadin/tools/ReflectTools.java

index 78c2b6c8fbff82a0e062c97d79c90e5c852b95ac..39045df96fd3c04e0b7ca6603c5c7ef0399743db 100644 (file)
@@ -16,7 +16,9 @@ import com.vaadin.data.Item;
 import com.vaadin.data.Property;\r
 import com.vaadin.data.TransactionalProperty;\r
 import com.vaadin.data.Validator.InvalidValueException;\r
+import com.vaadin.data.fieldbinder.FormBuilder.FormBuilderException;\r
 import com.vaadin.data.util.TransactionalPropertyWrapper;\r
+import com.vaadin.tools.ReflectTools;\r
 import com.vaadin.ui.Field;\r
 \r
 /**\r
@@ -620,6 +622,68 @@ public class FieldBinder implements Serializable {
         return false;\r
     }\r
 \r
+    /**\r
+     * Binds fields for the given class.\r
+     * <p>\r
+     * This method processes all fields whose type extends {@link Field} and\r
+     * that can be mapped to a property id. Property id mapping is done based on\r
+     * the field name or on a {@link PropertyId} annotation on the field. All\r
+     * non-null fields for which a property id can be determined are bound to\r
+     * the property id.\r
+     * \r
+     * @param object\r
+     *            The object to process\r
+     * @throws FormBuilderException\r
+     *             If there is a problem building or binding a field\r
+     */\r
+    public void bindFields(Object object) throws BindException {\r
+        Class<?> objectClass = object.getClass();\r
+\r
+        for (java.lang.reflect.Field f : objectClass.getDeclaredFields()) {\r
+\r
+            if (!Field.class.isAssignableFrom(f.getType())) {\r
+                // Process next field\r
+                continue;\r
+            }\r
+\r
+            PropertyId propertyIdAnnotation = f.getAnnotation(PropertyId.class);\r
+\r
+            Class<? extends Field> fieldType = (Class<? extends Field>) f\r
+                    .getType();\r
+\r
+            Object propertyId = null;\r
+            if (propertyIdAnnotation != null) {\r
+                // @PropertyId(propertyId) always overrides property id\r
+                propertyId = propertyIdAnnotation.value();\r
+            } else {\r
+                propertyId = f.getName();\r
+            }\r
+\r
+            // Ensure that the property id exists\r
+            Class<?> propertyType;\r
+\r
+            try {\r
+                propertyType = getPropertyType(propertyId);\r
+            } catch (BindException e) {\r
+                // Property id was not found, skip this field\r
+                continue;\r
+            }\r
+\r
+            try {\r
+                // Get the field from the object\r
+                Field<?> field = (Field<?>) ReflectTools.getJavaFieldValue(\r
+                        object, f);\r
+                // Bind it to the property id\r
+                bind(field, propertyId);\r
+            } catch (Exception e) {\r
+                // If we cannot determine the value, just skip the field and try\r
+                // the next one\r
+                continue;\r
+            }\r
+\r
+        }\r
+    }\r
+\r
     public static class CommitException extends Exception {\r
 \r
         public CommitException() {\r
index 2dc567570e31ac661e2781cc3c44797cb09d861e..c5f88185b192ff6a813bfe2cfef40e4a29506bdd 100644 (file)
@@ -3,16 +3,13 @@
  */\r
 package com.vaadin.data.fieldbinder;\r
 \r
-import java.beans.IntrospectionException;\r
-import java.beans.PropertyDescriptor;\r
 import java.io.Serializable;\r
-import java.lang.reflect.InvocationTargetException;\r
-import java.lang.reflect.Method;\r
 import java.util.logging.Logger;\r
 \r
 import org.apache.tools.ant.BuildException;\r
 \r
 import com.vaadin.data.fieldbinder.FieldBinder.BindException;\r
+import com.vaadin.tools.ReflectTools;\r
 import com.vaadin.ui.DefaultFieldFactory;\r
 import com.vaadin.ui.Field;\r
 \r
@@ -162,29 +159,6 @@ public class FormBuilder implements Serializable {
      *             If there is a problem building or binding a field\r
      */\r
     public void buildAndBindFields(Object object) throws FormBuilderException {\r
-        buildAndBindFields(object, false);\r
-    }\r
-\r
-    /**\r
-     * Builds and binds fields for the given class.\r
-     * <p>\r
-     * This method processes all fields whose type extends {@link Field} and\r
-     * that can be mapped to a property id. Property id mapping is done based on\r
-     * the field name or on a {@link PropertyId} annotation on the field. All\r
-     * fields for which a property id can be determined are built if they are\r
-     * null and then bound to the property id. Also existing fields are bound to\r
-     * the corresponding property id.\r
-     * \r
-     * @param object\r
-     *            The object to process\r
-     * @param onlyBind\r
-     *            true if only binding should be done, false if also building\r
-     *            should be done when necessary\r
-     * @throws FormBuilderException\r
-     *             If there is a problem building or binding a field\r
-     */\r
-    public void buildAndBindFields(Object object, boolean onlyBind)\r
-            throws FormBuilderException {\r
         Class<?> objectClass = object.getClass();\r
 \r
         for (java.lang.reflect.Field f : objectClass.getDeclaredFields()) {\r
@@ -217,14 +191,15 @@ public class FormBuilder implements Serializable {
 \r
             Field<?> builtField;\r
             try {\r
-                builtField = (Field<?>) getJavaFieldValue(object, f);\r
+                builtField = (Field<?>) ReflectTools.getJavaFieldValue(object,\r
+                        f);\r
             } catch (Exception e) {\r
                 // If we cannot determine the value, just skip the field and try\r
                 // the next one\r
                 continue;\r
             }\r
 \r
-            if (builtField == null && !onlyBind) {\r
+            if (builtField == null) {\r
                 // Field is null -> build the field\r
                 Caption captionAnnotation = f.getAnnotation(Caption.class);\r
                 String caption;\r
@@ -234,10 +209,12 @@ public class FormBuilder implements Serializable {
                     caption = DefaultFieldFactory\r
                             .createCaptionByPropertyId(propertyId);\r
                 }\r
+\r
                 // Create the component (Field)\r
                 builtField = build(caption, propertyType, fieldType);\r
+\r
                 // Store it in the field\r
-                setJavaFieldValue(object, f, builtField);\r
+                ReflectTools.setJavaFieldValue(object, f, builtField);\r
             }\r
 \r
             // Bind it to the property id\r
@@ -248,132 +225,6 @@ public class FormBuilder implements Serializable {
         }\r
     }\r
 \r
-    /**\r
-     * Returns the value of the java field.\r
-     * <p>\r
-     * Uses getter if present, otherwise tries to access even private fields.\r
-     * \r
-     * @param object\r
-     *            The object containing the field\r
-     * @param field\r
-     *            The field we want to get the value for\r
-     * @return The value of the field in the object\r
-     * @throws FormBuilderException\r
-     *             If the field value cannot be determined\r
-     */\r
-    protected Object getJavaFieldValue(Object object,\r
-            java.lang.reflect.Field field) throws FormBuilderException {\r
-        PropertyDescriptor pd;\r
-        try {\r
-            pd = new PropertyDescriptor(field.getName(), object.getClass());\r
-            Method getter = pd.getReadMethod();\r
-            if (getter != null) {\r
-                return getter.invoke(object, (Object[]) null);\r
-            }\r
-        } catch (Exception e) {\r
-            // Ignore all problems with getter and try to get the value directly\r
-            // from the field\r
-        }\r
-\r
-        try {\r
-            if (!field.isAccessible()) {\r
-                // Try to gain access even if field is private\r
-                field.setAccessible(true);\r
-            }\r
-            return field.get(object);\r
-        } catch (IllegalArgumentException e) {\r
-            throw new FormBuilderException("Could not get value for field '"\r
-                    + field.getName() + "'", e.getCause());\r
-        } catch (IllegalAccessException e) {\r
-            throw new FormBuilderException(\r
-                    "Access denied while assigning built component to field '"\r
-                            + field.getName() + "' in "\r
-                            + object.getClass().getName(), e);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sets the value of a java field.\r
-     * <p>\r
-     * Uses setter if present, otherwise tries to access even private fields\r
-     * directly.\r
-     * \r
-     * @param object\r
-     *            The object containing the field\r
-     * @param field\r
-     *            The field we want to set the value for\r
-     * @param value\r
-     *            The value to set\r
-     * @throws FormBuilderException\r
-     *             If the value could not be assigned to the field\r
-     */\r
-    protected void setJavaFieldValue(Object object,\r
-            java.lang.reflect.Field field, Object value)\r
-            throws FormBuilderException {\r
-        PropertyDescriptor pd;\r
-        try {\r
-            pd = new PropertyDescriptor(field.getName(), object.getClass());\r
-            Method setter = pd.getWriteMethod();\r
-            if (setter != null) {\r
-                try {\r
-                    setter.invoke(object, value);\r
-                } catch (IllegalArgumentException e) {\r
-                    throw new FormBuilderException(\r
-                            "Could not assign built component to field '"\r
-                                    + field.getName() + "'", e);\r
-                } catch (IllegalAccessException e) {\r
-                    throw new FormBuilderException(\r
-                            "Access denied while assigning built component to field using "\r
-                                    + setter.getName() + " in "\r
-                                    + object.getClass().getName(), e);\r
-                } catch (InvocationTargetException e) {\r
-                    throw new FormBuilderException(\r
-                            "Could not assign built component to field '"\r
-                                    + field.getName() + "'", e.getCause());\r
-                }\r
-            }\r
-        } catch (IntrospectionException e1) {\r
-            // Ignore this and try to set directly using the field\r
-        }\r
-\r
-        try {\r
-            if (!field.isAccessible()) {\r
-                // Try to gain access even if field is private\r
-                field.setAccessible(true);\r
-            }\r
-            field.set(object, value);\r
-        } catch (IllegalArgumentException e) {\r
-            throw new FormBuilderException(\r
-                    "Could not assign built component to field '"\r
-                            + field.getName() + "'", e.getCause());\r
-        } catch (IllegalAccessException e) {\r
-            throw new FormBuilderException(\r
-                    "Access denied while assigning built component to field '"\r
-                            + field.getName() + "' in "\r
-                            + object.getClass().getName(), e);\r
-        }\r
-    }\r
-\r
-    // /**\r
-    // * Constructs fields for all properties in the data source and adds them\r
-    // to\r
-    // * the given component container. The order of the fields is determined by\r
-    // * the order in which the item returns its property ids.\r
-    // *\r
-    // * This is pretty much what the old Form class used to do.\r
-    // *\r
-    // * @param cc\r
-    // * The ComponentContainer where fields should be added.\r
-    // */\r
-    // public void buildAndBindEverything(ComponentContainer cc) {\r
-    // Item ds = getFieldBinder().getItemDataSource();\r
-    // for (Object propertyId : ds.getItemPropertyIds()) {\r
-    // Field<?> f = buildAndBind(propertyId);\r
-    // cc.addComponent(f);\r
-    // }\r
-    //\r
-    // }\r
-\r
     public static class FormBuilderException extends RuntimeException {\r
 \r
         public FormBuilderException() {\r
index 9f0667f90e3fc8c529f764bf78b6a7d85eaa352f..03c5b8be92a7b0e6d867072f92380bb796c67830 100644 (file)
@@ -3,8 +3,13 @@
  */
 package com.vaadin.tools;
 
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
+import com.vaadin.data.fieldbinder.FormBuilder.FormBuilderException;
+
 /**
  * An util class with helpers for reflection operations. Used internally by
  * Vaadin and should not be used by application developers. Subject to change at
@@ -37,4 +42,110 @@ public class ReflectTools {
             throw new ExceptionInInitializerError(e);
         }
     }
+
+    /**
+     * Returns the value of the java field.
+     * <p>
+     * Uses getter if present, otherwise tries to access even private fields
+     * directly.
+     * 
+     * @param object
+     *            The object containing the field
+     * @param field
+     *            The field we want to get the value for
+     * @return The value of the field in the object
+     * @throws FormBuilderException
+     *             If the field value cannot be determined
+     */
+    public static Object getJavaFieldValue(Object object,
+            java.lang.reflect.Field field) throws FormBuilderException {
+        PropertyDescriptor pd;
+        try {
+            pd = new PropertyDescriptor(field.getName(), object.getClass());
+            Method getter = pd.getReadMethod();
+            if (getter != null) {
+                return getter.invoke(object, (Object[]) null);
+            }
+        } catch (Exception e) {
+            // Ignore all problems with getter and try to get the value directly
+            // from the field
+        }
+
+        try {
+            if (!field.isAccessible()) {
+                // Try to gain access even if field is private
+                field.setAccessible(true);
+            }
+            return field.get(object);
+        } catch (IllegalArgumentException e) {
+            throw new FormBuilderException("Could not get value for field '"
+                    + field.getName() + "'", e.getCause());
+        } catch (IllegalAccessException e) {
+            throw new FormBuilderException(
+                    "Access denied while assigning built component to field '"
+                            + field.getName() + "' in "
+                            + object.getClass().getName(), e);
+        }
+    }
+
+    /**
+     * Sets the value of a java field.
+     * <p>
+     * Uses setter if present, otherwise tries to access even private fields
+     * directly.
+     * 
+     * @param object
+     *            The object containing the field
+     * @param field
+     *            The field we want to set the value for
+     * @param value
+     *            The value to set
+     * @throws FormBuilderException
+     *             If the value could not be assigned to the field
+     */
+    public static void setJavaFieldValue(Object object,
+            java.lang.reflect.Field field, Object value)
+            throws FormBuilderException {
+        PropertyDescriptor pd;
+        try {
+            pd = new PropertyDescriptor(field.getName(), object.getClass());
+            Method setter = pd.getWriteMethod();
+            if (setter != null) {
+                try {
+                    setter.invoke(object, value);
+                } catch (IllegalArgumentException e) {
+                    throw new FormBuilderException(
+                            "Could not assign value to field '"
+                                    + field.getName() + "'", e);
+                } catch (IllegalAccessException e) {
+                    throw new FormBuilderException(
+                            "Access denied while assigning value to field using "
+                                    + setter.getName() + " in "
+                                    + object.getClass().getName(), e);
+                } catch (InvocationTargetException e) {
+                    throw new FormBuilderException(
+                            "Could not assign value to field '"
+                                    + field.getName() + "'", e.getCause());
+                }
+            }
+        } catch (IntrospectionException e1) {
+            // Ignore this and try to set directly using the field
+        }
+
+        try {
+            if (!field.isAccessible()) {
+                // Try to gain access even if field is private
+                field.setAccessible(true);
+            }
+            field.set(object, value);
+        } catch (IllegalArgumentException e) {
+            throw new FormBuilderException("Could not assign value to field '"
+                    + field.getName() + "'", e.getCause());
+        } catch (IllegalAccessException e) {
+            throw new FormBuilderException(
+                    "Access denied while assigning value to field '"
+                            + field.getName() + "' in "
+                            + object.getClass().getName(), e);
+        }
+    }
 }