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
\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
* 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
* 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
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
--- /dev/null
+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
--- /dev/null
+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