Class FieldBuilder<T>
- java.lang.Object
-
- org.dellroad.stuff.vaadin8.FieldBuilder<T>
-
- Type Parameters:
T- backing object type
- All Implemented Interfaces:
Serializable
public class FieldBuilder<T> extends Object implements Serializable
Automatically builds aBinderand configures and binds fields based on method annotations.FieldBuilderannotations allow for the automatic construction of forms for editing the annotated bean type. Annotations specify how bean properties should be edited in a form. As a result, all information about how to edit a Java type, including field customization such as captions, widths, etc., can be specified declaratively.@ProvidesFieldvs.@FieldBuilder.FooFieldBuildersupports two types of annotations that can tell it how to construct fields: the@ProvidesFieldannotates a method that knows how to build aHasValuewidget suitable for editing the named bean property. This is the most general approach, but it requires adding code.The
@FieldBuilder.Fooannotations are the purely declarative way to specify how to construct a field. These annotations annotate Java bean property getter methods, and specify how to configure aHasValuewidget that will edit the annotated property. The annotations@FieldBuilder.AbstractComponent,@FieldBuilder.AbstractField,@FieldBuilder.ComboBox, etc. mirror to the Vaadin widget class hierarchy and configure the corresponding widget properties (separate annotations were used for each class in the hierarchy because Java doesn't allow annotation inheritance).Configuring the Binding
In addition to configuring the fields associated with each bean property in the
Binder, you may also want to configure the bindings themselves, for example, to specify aConverterorValidator. The@FieldBuilder.Bindingannotation allows you to configure the binding, using properties relevant toBinder.BindingBuilder.@FieldBuilder.Bindingalso allows you to specify the order in which the fields should appear in the form.Example
A simple example shows how these annotations are used:
// Use a 10 row TextArea to edit the "description" property @FieldBuilder.AbstractComponent(caption = "Description:") @FieldBuilder.TextArea(rows = 10) @FieldBuilder.Binding(required = "Description is mandatory", validator = MyValidator.class) public String getDescription() { return this.description; } // Use an enum combo box to edit the gender property @FieldBuilder.EnumComboBox(caption = "Gender:") @FieldBuilder.Binding(required = "Gender is mandatory", order = 3.0) public Gender getGender() { return this.gender; } // Use my own custom field to edit the "foobar" property public Foobar getFoobar() { ... } public void setFoobar(Foobar foobar) { ... } @FieldBuilder.ProvidesField("foobar") private static MyCustomField createFoobarField() { ... }Building the Form
Use
FieldBuilder.buildAndBind()to setup theBinder, and then add the bound fields to your form:// Create fields based on FieldBuilder.* annotations Binder<Person> binder = new FieldBuilder(Person.class).buildAndBind().getBinder(); // Layout the fields in a form FormLayout layout = new FormLayout(); layout.add((Component)binder.getBinding("description").get().getField()); layout.add((Component)binder.getBinding("gender").get().getField()); layout.add((Component)binder.getBinding("foobar").get().getField()); // Bind a value Person person = new Person("Joe Smith", 100); binder.setBean(person);To use the generated fields as editor bindings for a
Grid, seesetEditorBindings(com.vaadin.ui.Grid<T>). For declarative configuration ofGridcolumns, see@GridColumn.- See Also:
FieldBuilder.AbstractDateField,FieldBuilder.AbstractTextField,FieldBuilder.CheckBox,FieldBuilder.CheckBoxGroup,FieldBuilder.ComboBox,FieldBuilder.DateField,FieldBuilder.DateTimeField,FieldBuilder.EnumComboBox,FieldBuilder.InlineDateField,FieldBuilder.ListSelect,FieldBuilder.PasswordField,FieldBuilder.RadioButtonGroup,FieldBuilder.RichTextArea,FieldBuilder.Slider,FieldBuilder.TextArea,FieldBuilder.TextField,GridColumn, Serialized Form
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static interfaceFieldBuilder.AbstractComponentSpecifies how a Java property should be edited using anAbstractComponent.static interfaceFieldBuilder.AbstractDateFieldSpecifies how a Java property should be edited using anAbstractDateField.static interfaceFieldBuilder.AbstractFieldSpecifies how a Java property should be edited using anAbstractField.static interfaceFieldBuilder.AbstractListingSpecifies how a Java property should be edited using anAbstractListing.static interfaceFieldBuilder.AbstractMultiSelectSpecifies how a Java property should be edited using anAbstractMultiSelect.static interfaceFieldBuilder.AbstractSingleSelectSpecifies how a Java property should be edited using anAbstractSingleSelect.static interfaceFieldBuilder.AbstractTextFieldSpecifies how a Java property should be edited using aAbstractTextField.static interfaceFieldBuilder.BindingSpecifies properties of theBinderbinding itself.static interfaceFieldBuilder.CheckBoxSpecifies how a Java property should be edited using anCheckBox.static interfaceFieldBuilder.CheckBoxGroupSpecifies how a Java property should be edited using anCheckBoxGroup.static interfaceFieldBuilder.ComboBoxSpecifies how a Java property should be edited using anComboBox.static interfaceFieldBuilder.DateFieldSpecifies how a Java property should be edited using aDateField.static interfaceFieldBuilder.DateTimeFieldSpecifies how a Java property should be edited using anDateTimeField.static interfaceFieldBuilder.EnumComboBoxSpecifies how a Java property should be edited using anEnumComboBox.static interfaceFieldBuilder.InlineDateFieldSpecifies how a Java property should be edited using anInlineDateField.static interfaceFieldBuilder.ListSelectSpecifies how a Java property should be edited using anListSelect.static interfaceFieldBuilder.PasswordFieldSpecifies how a Java property should be edited using aPasswordField.static interfaceFieldBuilder.ProvidesFieldSpecifies that the annotated method will return aHasValuesuitable for editing the specified property.static interfaceFieldBuilder.RadioButtonGroupSpecifies how a Java property should be edited using anRadioButtonGroup.static interfaceFieldBuilder.RichTextAreaSpecifies how a Java property should be edited using aRichTextArea.static interfaceFieldBuilder.SliderSpecifies how a Java property should be edited using aSlider.static interfaceFieldBuilder.TextAreaSpecifies how a Java property should be edited using aTextArea.static interfaceFieldBuilder.TextFieldSpecifies how a Java property should be edited using aTextField.
-
Constructor Summary
Constructors Constructor Description FieldBuilder(Class<T> type)Constructor.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description FieldBuilder<T>buildAndBind()Introspect forFieldBuilderannotations on getter methods of the configured class, and create and bind the corresponding fields.FieldBuilder<T>buildAndBind(T bean)Introspect forFieldBuilderannotations on getter methods of the configured class, create and bind the corresponding fields, and set the given bean in theBinder.protected List<org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<?>>buildApplierList(Method method)Find all relevant annotations on the given method as well as on any supertype methods it overrides.protected List<org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<?>>buildDirectApplierList(Method method)Find all relevant annotations declared directly on the givenMethod.protected HasValue<?>buildField(Collection<? extends org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<?>> appliers, String description)Instantiate and configure anHasValueaccording to the given scanned annotations.protected voiddoBuildAndBind(T bean)protected <A extends Annotation>
org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<A>getAnnotationApplier(Method method, A annotation)Get theFieldBuilder.AnnotationApplierthat applies the given annotation.Binder<T>getBinder()Get the binder associated with this instance.Set<String>getPropertyNames()Get the names of all properties discovered and bound by the most recent invocation ofbuildAndBind().Class<T>getType()Get the type associated with this instance.FieldBuilder<T>setEditorBindings(Grid<T> grid)Set this instance's field bindings as the editor bindings for the corresponding columns in the givenGrid.
-
-
-
Method Detail
-
getType
public Class<T> getType()
Get the type associated with this instance.- Returns:
- configured type
-
getBinder
public Binder<T> getBinder()
Get the binder associated with this instance.- Returns:
- binder
- Throws:
IllegalStateException- ifbuildAndBind()has not yet been invoked
-
getPropertyNames
public Set<String> getPropertyNames()
Get the names of all properties discovered and bound by the most recent invocation ofbuildAndBind().This will be the subset of all of the
Binder's properties containing those for which the getter method had@FieldBuilderannotations.The returned
Setwill iterate fields in order by@FieldBuilder.Binding.order()values, then by name.- Returns:
- field names
- Throws:
IllegalStateException- ifbuildAndBind()has not yet been invoked
-
buildAndBind
public FieldBuilder<T> buildAndBind()
Introspect forFieldBuilderannotations on getter methods of the configured class, and create and bind the corresponding fields.Note that non-static
@ProvidesFieldannotations on instance methods are ignored, because there is no bean instance provided; usebuildAndBind(Object)instead of this method to include them.- Returns:
- this instance
-
buildAndBind
public FieldBuilder<T> buildAndBind(T bean)
Introspect forFieldBuilderannotations on getter methods of the configured class, create and bind the corresponding fields, and set the given bean in theBinder.- Parameters:
bean- bean to introspect and bind- Returns:
- this instance
- Throws:
IllegalArgumentException- ifbeanis null
-
setEditorBindings
public FieldBuilder<T> setEditorBindings(Grid<T> grid)
Set this instance's field bindings as the editor bindings for the corresponding columns in the givenGrid.This method invokes
Grid.Column.setEditorBinding(Binder.Binding)for each binding for which theGridhas a column whose column ID matches the binding property name.- Parameters:
grid-Gridfor editor bindings- Returns:
- this instance
- Throws:
IllegalStateException- ifbuildAndBind()has not yet been invokedIllegalArgumentException- ifgridis null- See Also:
Grid.Column.setEditorBinding(Binder.Binding)
-
doBuildAndBind
protected void doBuildAndBind(T bean)
-
buildField
protected HasValue<?> buildField(Collection<? extends org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<?>> appliers, String description)
Instantiate and configure anHasValueaccording to the given scanned annotations.- Parameters:
appliers- annotation appliersdescription- description of the field (used for exception messages)- Returns:
- new field
-
buildApplierList
protected List<org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<?>> buildApplierList(Method method)
Find all relevant annotations on the given method as well as on any supertype methods it overrides. The method must be a getter method taking no arguments. Annotations are ordered so that annotations on a method in type X appear before annotations on an overridden method in type Y, a supertype of X.- Parameters:
method- annotated getter method- Returns:
- appliers for annotations found
- Throws:
IllegalArgumentException- ifmethodis nullIllegalArgumentException- ifmethodhas parameters
-
buildDirectApplierList
protected List<org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<?>> buildDirectApplierList(Method method)
Find all relevant annotations declared directly on the givenMethod.- Parameters:
method- method to inspect- Returns:
- annotations found
- Throws:
IllegalArgumentException- ifmethodis null
-
getAnnotationApplier
protected <A extends Annotation> org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<A> getAnnotationApplier(Method method, A annotation)
Get theFieldBuilder.AnnotationApplierthat applies the given annotation. Subclasses can add support for additional annotation types by overriding this method.- Type Parameters:
A- annotation type- Parameters:
method- method to inspectannotation- method annotation to inspect- Returns:
- corresponding
FieldBuilder.AnnotationApplier, or null if annotation is unknown
-
-