From: Artur Signell Date: Mon, 19 Dec 2011 12:53:45 +0000 (+0200) Subject: #8095 Use Bean Validation automatically in BeanFieldBinder X-Git-Tag: 7.0.0.alpha1~106 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=c1d9b76384c9783f5662057c190b6adf69f6285e;p=vaadin-framework.git #8095 Use Bean Validation automatically in BeanFieldBinder --- diff --git a/src/com/vaadin/data/fieldbinder/BeanFieldBinder.java b/src/com/vaadin/data/fieldbinder/BeanFieldBinder.java index 1b049383bf..8ec78bb7e8 100644 --- a/src/com/vaadin/data/fieldbinder/BeanFieldBinder.java +++ b/src/com/vaadin/data/fieldbinder/BeanFieldBinder.java @@ -7,6 +7,7 @@ import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.util.BeanItem; import com.vaadin.data.util.NestedMethodProperty; +import com.vaadin.data.validator.BeanValidationValidator; import com.vaadin.ui.Field; public class BeanFieldBinder extends FieldBinder { @@ -105,68 +106,15 @@ public class BeanFieldBinder extends FieldBinder { } - // private static void addFieldsFromType(List fields, Class type, - // String prefix) { - // for (java.lang.reflect.Field f : getAllFields(type)) { - // if (isSimpleType(f)) { - // fields.add(prefix + f.getName()); - // } else { - // String subPrefix = f.getName() + "."; - // if (!prefix.equals("")) { - // subPrefix = prefix + subPrefix; - // } - // - // addFieldsFromType(fields, f.getType(), subPrefix); - // } - // - // } - // - // } - - // /** - // * Return a list of all fields in the given class. Includes private fields - // * and also fields from super classes. - // * - // * @param type - // * @return - // */ - // private static List getAllFields(Class type) - // { - // System.out.println("getAllFields for " + type.getName()); - // List fields = new - // ArrayList(); - // - // Class superClass = type.getSuperclass(); - // if (superClass != Object.class) { - // fields.addAll(getAllFields(superClass)); - // } - // - // for (java.lang.reflect.Field f : type.getDeclaredFields()) { - // fields.add(f); - // } - // - // return fields; - // } - - // private static boolean isSimpleType(java.lang.reflect.Field f) { - // // FIXME: What other classes? Boolean, Integer etc. How do we know what - // // is a mapped class that should be expanded? Or should we make the user - // // provide them? - // Class type = f.getType(); - // if (type.isPrimitive()) { - // return true; - // } - // if (Enum.class.isAssignableFrom(type)) { - // return true; - // } - // if (Number.class.isAssignableFrom(type)) { - // return true; - // } - // if (CharSequence.class.isAssignableFrom(type)) { - // return true; - // } - // - // return false; - // } + @Override + protected void configureField(Field field) { + super.configureField(field); + // Add Bean validators if there are annotations + BeanValidationValidator validator = BeanValidationValidator + .addValidator(field, getPropertyIdForField(field), beanType); + if (field.getLocale() != null) { + validator.setLocale(field.getLocale()); + } + } } \ No newline at end of file diff --git a/src/com/vaadin/data/fieldbinder/FieldBinder.java b/src/com/vaadin/data/fieldbinder/FieldBinder.java index a30ef2f671..78c2b6c8fb 100644 --- a/src/com/vaadin/data/fieldbinder/FieldBinder.java +++ b/src/com/vaadin/data/fieldbinder/FieldBinder.java @@ -198,6 +198,9 @@ public class FieldBinder implements Serializable { * Binds the field with the given propertyId from the current item. If an * item has not been set then the binding is postponed until the item is set * using {@link #setItemDataSource(Item)}. + *

+ * This method also adds validators when applicable. + *

* * @param field * The field to bind @@ -291,15 +294,13 @@ public class FieldBinder implements Serializable { * Configures a field with the settings set for this FieldBinder. *

* By default this updates the buffered, read only and enabled state of the - * field. + * field. Also adds validators when applicable. * * @param field * The field to update */ protected void configureField(Field field) { - // FIXME: Could use setBuffered if that was in Field - field.setReadThrough(!isFieldsBuffered()); - field.setWriteThrough(!isFieldsBuffered()); + field.setBuffered(isFieldsBuffered()); field.setEnabled(isFieldsEnabled()); field.setReadOnly(isFieldsReadOnly()); @@ -479,6 +480,18 @@ public class FieldBinder implements Serializable { return propertyIdToField.get(propertyId); } + /** + * Returns the property id that is bound to the given field + * + * @param field + * The field to use to lookup the property id + * @return The property id that is bound to the field or null if the field + * is not bound to any property id by this FieldBinder + */ + public Object getPropertyIdForField(Field field) { + return fieldToPropertyId.get(field); + } + /** * Adds a commit handler. *

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 index 0000000000..4a7d5a5c2e --- /dev/null +++ b/tests/server-side/com/vaadin/tests/data/bean/PersonWithBeanValidationAnnotations.java @@ -0,0 +1,156 @@ +package com.vaadin.tests.data.bean; + +import java.math.BigDecimal; +import java.util.Date; + +import javax.validation.constraints.Digits; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Past; +import javax.validation.constraints.Size; + +public class PersonWithBeanValidationAnnotations { + @NotNull + @Size(min = 5, max = 20) + private String firstName; + @NotNull + private String lastName; + + private String email; + + @Min(0) + @Max(100) + private int age; + + @NotNull + private Sex sex; + + private Address address; + private boolean deceased; + + @NotNull + @Past + private Date birthDate; + + @Min(0) + private Integer salary; // null if unknown + + @Digits(integer = 6, fraction = 2) + private Double salaryDouble; // null if unknown + + private BigDecimal rent; + + public PersonWithBeanValidationAnnotations() { + + } + + @Override + public String toString() { + return "Person [firstName=" + firstName + ", lastName=" + lastName + + ", email=" + email + ", age=" + age + ", sex=" + sex + + ", address=" + address + ", deceased=" + deceased + + ", salary=" + salary + ", salaryDouble=" + salaryDouble + + ", rent=" + rent + "]"; + } + + public PersonWithBeanValidationAnnotations(String firstName, + String lastName, String email, int age, Sex sex, Address address) { + super(); + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.age = age; + this.sex = sex; + this.address = address; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public Sex getSex() { + return sex; + } + + public void setSex(Sex sex) { + this.sex = sex; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public boolean getDeceased() { + return deceased; + } + + public void setDeceased(boolean deceased) { + this.deceased = deceased; + } + + public Integer getSalary() { + return salary; + } + + public void setSalary(Integer salary) { + this.salary = salary; + } + + public BigDecimal getRent() { + return rent; + } + + public void setRent(BigDecimal rent) { + this.rent = rent; + } + + public Double getSalaryDouble() { + return salaryDouble; + } + + public void setSalaryDouble(Double salaryDouble) { + this.salaryDouble = salaryDouble; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + +} diff --git a/tests/testbench/com/vaadin/tests/fieldbinder/FieldBinderWithBeanValidation.java b/tests/testbench/com/vaadin/tests/fieldbinder/FieldBinderWithBeanValidation.java new file mode 100644 index 0000000000..43ed23e5ad --- /dev/null +++ b/tests/testbench/com/vaadin/tests/fieldbinder/FieldBinderWithBeanValidation.java @@ -0,0 +1,107 @@ +package com.vaadin.tests.fieldbinder; + +import com.vaadin.data.fieldbinder.BeanFieldBinder; +import com.vaadin.data.fieldbinder.FieldBinder; +import com.vaadin.data.fieldbinder.FieldBinder.CommitException; +import com.vaadin.data.fieldbinder.FormBuilder; +import com.vaadin.data.util.BeanItem; +import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.data.bean.Address; +import com.vaadin.tests.data.bean.Country; +import com.vaadin.tests.data.bean.Person; +import com.vaadin.tests.data.bean.PersonWithBeanValidationAnnotations; +import com.vaadin.tests.data.bean.Sex; +import com.vaadin.tests.util.Log; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Root; +import com.vaadin.ui.Table; +import com.vaadin.ui.TextArea; +import com.vaadin.ui.TextField; + +public class FieldBinderWithBeanValidation extends TestBase { + + private Log log = new Log(5); + private TextField firstName; + private TextArea lastName; + private TextField email; + private TextField age; + private Table sex; + private TextField deceased; + + @Override + protected void setup() { + addComponent(log); + + final BeanFieldBinder binder = new BeanFieldBinder( + PersonWithBeanValidationAnnotations.class); + + FormBuilder builder = new FormBuilder(binder); + builder.buildAndBindFields(this); + addComponent(firstName); + addComponent(lastName); + addComponent(email); + addComponent(age); + addComponent(sex); + addComponent(deceased); + + Button commitButton = new Button("Commit", new Button.ClickListener() { + + public void buttonClick(ClickEvent event) { + String msg = "Commit succesful"; + try { + binder.commit(); + } catch (CommitException e) { + msg = "Commit failed: " + e.getMessage(); + } + Root.getCurrentRoot().showNotification(msg); + log.log(msg); + + } + }); + Button discardButton = new Button("Discard", + new Button.ClickListener() { + + public void buttonClick(ClickEvent event) { + binder.discard(); + log.log("Discarded changes"); + + } + }); + Button showBean = new Button("Show bean values", + new Button.ClickListener() { + + public void buttonClick(ClickEvent event) { + log.log(getPerson(binder).toString()); + + } + }); + addComponent(commitButton); + addComponent(discardButton); + addComponent(showBean); + sex.setPageLength(0); + + PersonWithBeanValidationAnnotations p = new PersonWithBeanValidationAnnotations( + "John", "Doe", "john@doe.com", 64, Sex.MALE, new Address( + "John street", 11223, "John's town", Country.USA)); + binder.setItemDataSource(new BeanItem( + p)); + } + + public static Person getPerson(FieldBinder binder) { + return ((BeanItem) binder.getItemDataSource()).getBean(); + } + + @Override + protected String getDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + protected Integer getTicketNumber() { + // TODO Auto-generated method stub + return null; + } + +}