]> source.dussan.org Git - vaadin-framework.git/commitdiff
#8095 Use Bean Validation automatically in BeanFieldBinder
authorArtur Signell <artur@vaadin.com>
Mon, 19 Dec 2011 12:53:45 +0000 (14:53 +0200)
committerArtur Signell <artur@vaadin.com>
Mon, 19 Dec 2011 12:53:45 +0000 (14:53 +0200)
src/com/vaadin/data/fieldbinder/BeanFieldBinder.java
src/com/vaadin/data/fieldbinder/FieldBinder.java
tests/server-side/com/vaadin/tests/data/bean/PersonWithBeanValidationAnnotations.java [new file with mode: 0644]
tests/testbench/com/vaadin/tests/fieldbinder/FieldBinderWithBeanValidation.java [new file with mode: 0644]

index 1b049383bf2d77d6ca5c4e877e324b61231a6bc8..8ec78bb7e85661d96f95d86649b9624e5265f82e 100644 (file)
@@ -7,6 +7,7 @@ import com.vaadin.data.Item;
 import com.vaadin.data.Property;\r
 import com.vaadin.data.util.BeanItem;\r
 import com.vaadin.data.util.NestedMethodProperty;\r
+import com.vaadin.data.validator.BeanValidationValidator;\r
 import com.vaadin.ui.Field;\r
 \r
 public class BeanFieldBinder<T> extends FieldBinder {\r
@@ -105,68 +106,15 @@ public class BeanFieldBinder<T> extends FieldBinder {
 \r
     }\r
 \r
-    // private static void addFieldsFromType(List<Object> fields, Class<?> type,\r
-    // String prefix) {\r
-    // for (java.lang.reflect.Field f : getAllFields(type)) {\r
-    // if (isSimpleType(f)) {\r
-    // fields.add(prefix + f.getName());\r
-    // } else {\r
-    // String subPrefix = f.getName() + ".";\r
-    // if (!prefix.equals("")) {\r
-    // subPrefix = prefix + subPrefix;\r
-    // }\r
-    //\r
-    // addFieldsFromType(fields, f.getType(), subPrefix);\r
-    // }\r
-    //\r
-    // }\r
-    //\r
-    // }\r
-\r
-    // /**\r
-    // * Return a list of all fields in the given class. Includes private fields\r
-    // * and also fields from super classes.\r
-    // *\r
-    // * @param type\r
-    // * @return\r
-    // */\r
-    // private static List<java.lang.reflect.Field> getAllFields(Class<?> type)\r
-    // {\r
-    // System.out.println("getAllFields for " + type.getName());\r
-    // List<java.lang.reflect.Field> fields = new\r
-    // ArrayList<java.lang.reflect.Field>();\r
-    //\r
-    // Class<?> superClass = type.getSuperclass();\r
-    // if (superClass != Object.class) {\r
-    // fields.addAll(getAllFields(superClass));\r
-    // }\r
-    //\r
-    // for (java.lang.reflect.Field f : type.getDeclaredFields()) {\r
-    // fields.add(f);\r
-    // }\r
-    //\r
-    // return fields;\r
-    // }\r
-\r
-    // private static boolean isSimpleType(java.lang.reflect.Field f) {\r
-    // // FIXME: What other classes? Boolean, Integer etc. How do we know what\r
-    // // is a mapped class that should be expanded? Or should we make the user\r
-    // // provide them?\r
-    // Class<?> type = f.getType();\r
-    // if (type.isPrimitive()) {\r
-    // return true;\r
-    // }\r
-    // if (Enum.class.isAssignableFrom(type)) {\r
-    // return true;\r
-    // }\r
-    // if (Number.class.isAssignableFrom(type)) {\r
-    // return true;\r
-    // }\r
-    // if (CharSequence.class.isAssignableFrom(type)) {\r
-    // return true;\r
-    // }\r
-    //\r
-    // return false;\r
-    // }\r
+    @Override\r
+    protected void configureField(Field<?> field) {\r
+        super.configureField(field);\r
+        // Add Bean validators if there are annotations\r
+        BeanValidationValidator validator = BeanValidationValidator\r
+                .addValidator(field, getPropertyIdForField(field), beanType);\r
+        if (field.getLocale() != null) {\r
+            validator.setLocale(field.getLocale());\r
+        }\r
+    }\r
 \r
 }
\ No newline at end of file
index a30ef2f671d0072b7d0aaac9eaa8a02aa34eb255..78c2b6c8fbff82a0e062c97d79c90e5c852b95ac 100644 (file)
@@ -198,6 +198,9 @@ public class FieldBinder implements Serializable {
      * Binds the field with the given propertyId from the current item. If an\r
      * item has not been set then the binding is postponed until the item is set\r
      * using {@link #setItemDataSource(Item)}.\r
+     * <p>\r
+     * This method also adds validators when applicable.\r
+     * </p>\r
      * \r
      * @param field\r
      *            The field to bind\r
@@ -291,15 +294,13 @@ public class FieldBinder implements Serializable {
      * Configures a field with the settings set for this FieldBinder.\r
      * <p>\r
      * By default this updates the buffered, read only and enabled state of the\r
-     * field.\r
+     * field. Also adds validators when applicable.\r
      * \r
      * @param field\r
      *            The field to update\r
      */\r
     protected void configureField(Field<?> field) {\r
-        // FIXME: Could use setBuffered if that was in Field\r
-        field.setReadThrough(!isFieldsBuffered());\r
-        field.setWriteThrough(!isFieldsBuffered());\r
+        field.setBuffered(isFieldsBuffered());\r
 \r
         field.setEnabled(isFieldsEnabled());\r
         field.setReadOnly(isFieldsReadOnly());\r
@@ -479,6 +480,18 @@ public class FieldBinder implements Serializable {
         return propertyIdToField.get(propertyId);\r
     }\r
 \r
+    /**\r
+     * Returns the property id that is bound to the given field\r
+     * \r
+     * @param field\r
+     *            The field to use to lookup the property id\r
+     * @return The property id that is bound to the field or null if the field\r
+     *         is not bound to any property id by this FieldBinder\r
+     */\r
+    public Object getPropertyIdForField(Field field) {\r
+        return fieldToPropertyId.get(field);\r
+    }\r
+\r
     /**\r
      * Adds a commit handler.\r
      * <p>\r
diff --git a/tests/server-side/com/vaadin/tests/data/bean/PersonWithBeanValidationAnnotations.java b/tests/server-side/com/vaadin/tests/data/bean/PersonWithBeanValidationAnnotations.java
new file mode 100644 (file)
index 0000000..4a7d5a5
--- /dev/null
@@ -0,0 +1,156 @@
+package com.vaadin.tests.data.bean;\r
+\r
+import java.math.BigDecimal;\r
+import java.util.Date;\r
+\r
+import javax.validation.constraints.Digits;\r
+import javax.validation.constraints.Max;\r
+import javax.validation.constraints.Min;\r
+import javax.validation.constraints.NotNull;\r
+import javax.validation.constraints.Past;\r
+import javax.validation.constraints.Size;\r
+\r
+public class PersonWithBeanValidationAnnotations {\r
+    @NotNull\r
+    @Size(min = 5, max = 20)\r
+    private String firstName;\r
+    @NotNull\r
+    private String lastName;\r
+\r
+    private String email;\r
+\r
+    @Min(0)\r
+    @Max(100)\r
+    private int age;\r
+\r
+    @NotNull\r
+    private Sex sex;\r
+\r
+    private Address address;\r
+    private boolean deceased;\r
+\r
+    @NotNull\r
+    @Past\r
+    private Date birthDate;\r
+\r
+    @Min(0)\r
+    private Integer salary; // null if unknown\r
+\r
+    @Digits(integer = 6, fraction = 2)\r
+    private Double salaryDouble; // null if unknown\r
+\r
+    private BigDecimal rent;\r
+\r
+    public PersonWithBeanValidationAnnotations() {\r
+\r
+    }\r
+\r
+    @Override\r
+    public String toString() {\r
+        return "Person [firstName=" + firstName + ", lastName=" + lastName\r
+                + ", email=" + email + ", age=" + age + ", sex=" + sex\r
+                + ", address=" + address + ", deceased=" + deceased\r
+                + ", salary=" + salary + ", salaryDouble=" + salaryDouble\r
+                + ", rent=" + rent + "]";\r
+    }\r
+\r
+    public PersonWithBeanValidationAnnotations(String firstName,\r
+            String lastName, String email, int age, Sex sex, Address address) {\r
+        super();\r
+        this.firstName = firstName;\r
+        this.lastName = lastName;\r
+        this.email = email;\r
+        this.age = age;\r
+        this.sex = sex;\r
+        this.address = address;\r
+    }\r
+\r
+    public String getFirstName() {\r
+        return firstName;\r
+    }\r
+\r
+    public void setFirstName(String firstName) {\r
+        this.firstName = firstName;\r
+    }\r
+\r
+    public String getLastName() {\r
+        return lastName;\r
+    }\r
+\r
+    public void setLastName(String lastName) {\r
+        this.lastName = lastName;\r
+    }\r
+\r
+    public int getAge() {\r
+        return age;\r
+    }\r
+\r
+    public void setAge(int age) {\r
+        this.age = age;\r
+    }\r
+\r
+    public Address getAddress() {\r
+        return address;\r
+    }\r
+\r
+    public void setAddress(Address address) {\r
+        this.address = address;\r
+    }\r
+\r
+    public Sex getSex() {\r
+        return sex;\r
+    }\r
+\r
+    public void setSex(Sex sex) {\r
+        this.sex = sex;\r
+    }\r
+\r
+    public String getEmail() {\r
+        return email;\r
+    }\r
+\r
+    public void setEmail(String email) {\r
+        this.email = email;\r
+    }\r
+\r
+    public boolean getDeceased() {\r
+        return deceased;\r
+    }\r
+\r
+    public void setDeceased(boolean deceased) {\r
+        this.deceased = deceased;\r
+    }\r
+\r
+    public Integer getSalary() {\r
+        return salary;\r
+    }\r
+\r
+    public void setSalary(Integer salary) {\r
+        this.salary = salary;\r
+    }\r
+\r
+    public BigDecimal getRent() {\r
+        return rent;\r
+    }\r
+\r
+    public void setRent(BigDecimal rent) {\r
+        this.rent = rent;\r
+    }\r
+\r
+    public Double getSalaryDouble() {\r
+        return salaryDouble;\r
+    }\r
+\r
+    public void setSalaryDouble(Double salaryDouble) {\r
+        this.salaryDouble = salaryDouble;\r
+    }\r
+\r
+    public Date getBirthDate() {\r
+        return birthDate;\r
+    }\r
+\r
+    public void setBirthDate(Date birthDate) {\r
+        this.birthDate = birthDate;\r
+    }\r
+\r
+}\r
diff --git a/tests/testbench/com/vaadin/tests/fieldbinder/FieldBinderWithBeanValidation.java b/tests/testbench/com/vaadin/tests/fieldbinder/FieldBinderWithBeanValidation.java
new file mode 100644 (file)
index 0000000..43ed23e
--- /dev/null
@@ -0,0 +1,107 @@
+package com.vaadin.tests.fieldbinder;\r
+\r
+import com.vaadin.data.fieldbinder.BeanFieldBinder;\r
+import com.vaadin.data.fieldbinder.FieldBinder;\r
+import com.vaadin.data.fieldbinder.FieldBinder.CommitException;\r
+import com.vaadin.data.fieldbinder.FormBuilder;\r
+import com.vaadin.data.util.BeanItem;\r
+import com.vaadin.tests.components.TestBase;\r
+import com.vaadin.tests.data.bean.Address;\r
+import com.vaadin.tests.data.bean.Country;\r
+import com.vaadin.tests.data.bean.Person;\r
+import com.vaadin.tests.data.bean.PersonWithBeanValidationAnnotations;\r
+import com.vaadin.tests.data.bean.Sex;\r
+import com.vaadin.tests.util.Log;\r
+import com.vaadin.ui.Button;\r
+import com.vaadin.ui.Button.ClickEvent;\r
+import com.vaadin.ui.Root;\r
+import com.vaadin.ui.Table;\r
+import com.vaadin.ui.TextArea;\r
+import com.vaadin.ui.TextField;\r
+\r
+public class FieldBinderWithBeanValidation extends TestBase {\r
+\r
+    private Log log = new Log(5);\r
+    private TextField firstName;\r
+    private TextArea lastName;\r
+    private TextField email;\r
+    private TextField age;\r
+    private Table sex;\r
+    private TextField deceased;\r
+\r
+    @Override\r
+    protected void setup() {\r
+        addComponent(log);\r
+\r
+        final BeanFieldBinder<PersonWithBeanValidationAnnotations> binder = new BeanFieldBinder<PersonWithBeanValidationAnnotations>(\r
+                PersonWithBeanValidationAnnotations.class);\r
+\r
+        FormBuilder builder = new FormBuilder(binder);\r
+        builder.buildAndBindFields(this);\r
+        addComponent(firstName);\r
+        addComponent(lastName);\r
+        addComponent(email);\r
+        addComponent(age);\r
+        addComponent(sex);\r
+        addComponent(deceased);\r
+\r
+        Button commitButton = new Button("Commit", new Button.ClickListener() {\r
+\r
+            public void buttonClick(ClickEvent event) {\r
+                String msg = "Commit succesful";\r
+                try {\r
+                    binder.commit();\r
+                } catch (CommitException e) {\r
+                    msg = "Commit failed: " + e.getMessage();\r
+                }\r
+                Root.getCurrentRoot().showNotification(msg);\r
+                log.log(msg);\r
+\r
+            }\r
+        });\r
+        Button discardButton = new Button("Discard",\r
+                new Button.ClickListener() {\r
+\r
+                    public void buttonClick(ClickEvent event) {\r
+                        binder.discard();\r
+                        log.log("Discarded changes");\r
+\r
+                    }\r
+                });\r
+        Button showBean = new Button("Show bean values",\r
+                new Button.ClickListener() {\r
+\r
+                    public void buttonClick(ClickEvent event) {\r
+                        log.log(getPerson(binder).toString());\r
+\r
+                    }\r
+                });\r
+        addComponent(commitButton);\r
+        addComponent(discardButton);\r
+        addComponent(showBean);\r
+        sex.setPageLength(0);\r
+\r
+        PersonWithBeanValidationAnnotations p = new PersonWithBeanValidationAnnotations(\r
+                "John", "Doe", "john@doe.com", 64, Sex.MALE, new Address(\r
+                        "John street", 11223, "John's town", Country.USA));\r
+        binder.setItemDataSource(new BeanItem<PersonWithBeanValidationAnnotations>(\r
+                p));\r
+    }\r
+\r
+    public static Person getPerson(FieldBinder binder) {\r
+        return ((BeanItem<Person>) binder.getItemDataSource()).getBean();\r
+    }\r
+\r
+    @Override\r
+    protected String getDescription() {\r
+        // TODO Auto-generated method stub\r
+        return null;\r
+    }\r
+\r
+    @Override\r
+    protected Integer getTicketNumber() {\r
+        // TODO Auto-generated method stub\r
+        return null;\r
+    }\r
+\r
+}\r