From b0398e876695be532d9d0edc8764f622ed56c837 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Fri, 16 Dec 2011 09:27:56 +0200 Subject: [PATCH] #8095 Added field type to field factory to be able to validate that a field of correct type is created and to be able to create different fields (e.g. selects) based on what the user wants. --- .../DefaultFieldBinderFieldFactory.java | 111 +++++++++++++++--- .../fieldbinder/FieldBinderFieldFactory.java | 8 +- .../vaadin/data/fieldbinder/FormBuilder.java | 53 ++++++--- 3 files changed, 138 insertions(+), 34 deletions(-) diff --git a/src/com/vaadin/data/fieldbinder/DefaultFieldBinderFieldFactory.java b/src/com/vaadin/data/fieldbinder/DefaultFieldBinderFieldFactory.java index c2dac85164..18a979cf65 100644 --- a/src/com/vaadin/data/fieldbinder/DefaultFieldBinderFieldFactory.java +++ b/src/com/vaadin/data/fieldbinder/DefaultFieldBinderFieldFactory.java @@ -6,41 +6,118 @@ package com.vaadin.data.fieldbinder; import java.util.EnumSet; import com.vaadin.data.Item; +import com.vaadin.ui.AbstractSelect; +import com.vaadin.ui.AbstractTextField; import com.vaadin.ui.CheckBox; import com.vaadin.ui.ComboBox; import com.vaadin.ui.Field; +import com.vaadin.ui.ListSelect; +import com.vaadin.ui.NativeSelect; +import com.vaadin.ui.OptionGroup; +import com.vaadin.ui.PasswordField; +import com.vaadin.ui.Table; +import com.vaadin.ui.TextArea; import com.vaadin.ui.TextField; public class DefaultFieldBinderFieldFactory implements FieldBinderFieldFactory { public static final Object CAPTION_PROPERTY_ID = "Caption"; - @SuppressWarnings("unchecked") - public Field createField(Class type) { + public Field createField(Class type, Class fieldType) { if (Enum.class.isAssignableFrom(type)) { - return createEnumField((Class>) type); - } - if (Boolean.class.isAssignableFrom(type) + return createEnumField(type, fieldType); + } else if (Boolean.class.isAssignableFrom(type) || boolean.class.isAssignableFrom(type)) { - return createBooleanField(); + return createBooleanField(fieldType); } - return createDefaultField(type); + return createDefaultField(type, fieldType); } - private Field createBooleanField() { - CheckBox cb = new CheckBox(null); - cb.setImmediate(true); - return cb; - } + private Field createEnumField(Class type, + Class fieldType) { + if (AbstractSelect.class.isAssignableFrom(fieldType)) { + AbstractSelect s = createCompatibleSelect((Class) fieldType); + populateWithEnumData(s, (Class) type); + return s; + } - private Field createDefaultField(Class type) { - return new TextField(); + return null; } - public Field createEnumField(Class enumClass) { - ComboBox select = new ComboBox(null); + protected AbstractSelect createCompatibleSelect( + Class fieldType) { + AbstractSelect select; + if (fieldType.isAssignableFrom(ListSelect.class)) { + select = new ListSelect(); + select.setMultiSelect(false); + } else if (fieldType.isAssignableFrom(NativeSelect.class)) { + select = new NativeSelect(); + } else if (fieldType.isAssignableFrom(OptionGroup.class)) { + select = new OptionGroup(); + select.setMultiSelect(false); + } else if (fieldType.isAssignableFrom(Table.class)) { + Table t = new Table(); + t.setSelectable(true); + select = t; + } else { + select = new ComboBox(null); + } select.setImmediate(true); select.setNullSelectionAllowed(false); + + return select; + } + + protected Field createBooleanField(Class fieldType) { + if (fieldType.isAssignableFrom(CheckBox.class)) { + CheckBox cb = new CheckBox(null); + cb.setImmediate(true); + return cb; + } else if (AbstractTextField.class.isAssignableFrom(fieldType)) { + return createAbstractTextField((Class) fieldType); + } + + return null; + } + + protected AbstractTextField createAbstractTextField( + Class fieldType) { + if (fieldType.isAssignableFrom(PasswordField.class)) { + PasswordField pf = new PasswordField(); + pf.setImmediate(true); + return pf; + } else if (fieldType.isAssignableFrom(TextField.class)) { + TextField tf = new TextField(); + tf.setImmediate(true); + return tf; + } else if (fieldType.isAssignableFrom(TextArea.class)) { + TextArea ta = new TextArea(); + ta.setImmediate(true); + return ta; + } + + return null; + } + + protected Field createDefaultField(Class type, + Class fieldType) { + if (AbstractTextField.class.isAssignableFrom(fieldType)) { + return createAbstractTextField((Class) fieldType); + } + return null; + } + + /** + * @param select + * @param enumClass + */ + protected void populateWithEnumData(AbstractSelect select, + Class enumClass) { + // TODO EnumContainer? + select.removeAllItems(); + for (Object p : select.getContainerPropertyIds()) { + select.removeContainerProperty(p); + } select.addContainerProperty(CAPTION_PROPERTY_ID, String.class, ""); select.setItemCaptionPropertyId(CAPTION_PROPERTY_ID); @SuppressWarnings("unchecked") @@ -49,7 +126,5 @@ public class DefaultFieldBinderFieldFactory implements FieldBinderFieldFactory { Item newItem = select.addItem(r); newItem.getItemProperty(CAPTION_PROPERTY_ID).setValue(r.toString()); } - return select; } - } diff --git a/src/com/vaadin/data/fieldbinder/FieldBinderFieldFactory.java b/src/com/vaadin/data/fieldbinder/FieldBinderFieldFactory.java index 0d445364d3..3d4b0b49a3 100644 --- a/src/com/vaadin/data/fieldbinder/FieldBinderFieldFactory.java +++ b/src/com/vaadin/data/fieldbinder/FieldBinderFieldFactory.java @@ -21,7 +21,11 @@ public interface FieldBinderFieldFactory extends Serializable { * * @param dataType * The type that we want to edit using the field - * @return A field capable of editing the given type of data + * @param fieldType + * The type of field we want to create. If set to {@link Field} + * then any type of field is accepted + * @return A field that can be assigned to the given fieldType and that is + * capable of editing the given type of data */ - Field createField(Class dataType); + Field createField(Class dataType, Class fieldType); } diff --git a/src/com/vaadin/data/fieldbinder/FormBuilder.java b/src/com/vaadin/data/fieldbinder/FormBuilder.java index a623cb1e24..2dc567570e 100644 --- a/src/com/vaadin/data/fieldbinder/FormBuilder.java +++ b/src/com/vaadin/data/fieldbinder/FormBuilder.java @@ -5,21 +5,29 @@ package com.vaadin.data.fieldbinder; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; +import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.logging.Logger; + +import org.apache.tools.ant.BuildException; import com.vaadin.data.fieldbinder.FieldBinder.BindException; import com.vaadin.ui.DefaultFieldFactory; import com.vaadin.ui.Field; /** - * FIXME Javadoc + * Class for constructing form fields based on a data type. + *

* + * FIXME Javadoc */ -public class FormBuilder { +public class FormBuilder implements Serializable { private FieldBinderFieldFactory fieldFactory = new com.vaadin.data.fieldbinder.DefaultFieldBinderFieldFactory(); private FieldBinder fieldBinder; + private static final Logger logger = Logger.getLogger(FormBuilder.class + .getName()); /** * Constructs a FormBuilder that can be used to build forms automatically. @@ -77,11 +85,11 @@ public class FormBuilder { * @param propertyId * The property id to bind to. Must be present in the field * finder. - * @return The created and bound field + * @return The created and bound field. Can be any type of {@link Field}. */ public Field buildAndBind(String caption, Object propertyId) { Class type = getFieldBinder().getPropertyType(propertyId); - return buildAndBind(caption, propertyId, type); + return buildAndBind(caption, propertyId, type, Field.class); } @@ -96,29 +104,44 @@ public class FormBuilder { * binder. * @param type * The data model type we want to edit using the field + * @param fieldType + * The type of field we want to create * @return The created and bound field */ protected Field buildAndBind(String caption, Object propertyId, - Class type) { - Field field = build(caption, type); + Class type, Class fieldType) { + Field field = build(caption, type, fieldType); fieldBinder.bind(field, propertyId); return field; } /** - * Creates a field based on the given type. The type should be the data - * model type and not a Vaadin Field type. + * Creates a field based on the given data type. + *

+ * The data type is the type that we want to edit using the field. The field + * type is the type of field we want to create, can be {@link Field} if any + * Field is good. + *

* * @param caption * The caption for the new field - * @param type + * @param dataType * The data model type that we want to edit using the field + * @param fieldType + * The type of field that we want to create * @return A Field capable of editing the given type */ - protected Field build(String caption, Class type) { - System.err.println("Building a field with caption " + caption - + " of type " + type.getName()); - Field field = getFieldFactory().createField(type); + protected Field build(String caption, Class dataType, + Class fieldType) { + logger.finest("Building a field with caption " + caption + " of type " + + dataType.getName()); + Field field = getFieldFactory().createField(dataType, fieldType); + if (field == null) { + throw new BuildException("Unable to build a field of type " + + fieldType.getName() + " for editing " + + dataType.getName()); + } + field.setCaption(caption); return field; } @@ -171,6 +194,8 @@ public class FormBuilder { // Process next field continue; } + Class fieldType = (Class) f + .getType(); Object propertyId = null; if (propertyIdAnnotation != null) { @@ -210,7 +235,7 @@ public class FormBuilder { .createCaptionByPropertyId(propertyId); } // Create the component (Field) - builtField = build(caption, propertyType); + builtField = build(caption, propertyType, fieldType); // Store it in the field setJavaFieldValue(object, f, builtField); } -- 2.39.5