diff options
author | Henri Sara <hesara@vaadin.com> | 2013-02-14 14:31:58 +0200 |
---|---|---|
committer | Henri Sara <hesara@vaadin.com> | 2013-02-14 14:31:58 +0200 |
commit | 50e53f0734042b2daebe99d6f1476fca0fa72151 (patch) | |
tree | 9e4e90876028f5820a23e6fde8b8570685fb25e6 | |
parent | 9185ce0a26db5574079e6a196dd121af9c3286ae (diff) | |
parent | b72934473733b543498ba3a3c1082a332f539961 (diff) | |
download | vaadin-framework-50e53f0734042b2daebe99d6f1476fca0fa72151.tar.gz vaadin-framework-50e53f0734042b2daebe99d6f1476fca0fa72151.zip |
Merge remote-tracking branch 'origin/7.0'
Change-Id: I7428e1c57836f055a39b39425a3bcb6bada38d1e
10 files changed, 223 insertions, 60 deletions
diff --git a/client/src/com/vaadin/client/ui/VLabel.java b/client/src/com/vaadin/client/ui/VLabel.java index 83fc8e207e..8acd653778 100644 --- a/client/src/com/vaadin/client/ui/VLabel.java +++ b/client/src/com/vaadin/client/ui/VLabel.java @@ -16,7 +16,6 @@ package com.vaadin.client.ui; -import com.google.gwt.dom.client.Style.Display; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.HTML; import com.vaadin.client.ApplicationConnection; @@ -57,10 +56,8 @@ public class VLabel extends HTML { super.setWidth(width); if (width == null || width.equals("")) { setStyleName(getElement(), CLASSNAME_UNDEFINED_WIDTH, true); - getElement().getStyle().setDisplay(Display.INLINE_BLOCK); } else { setStyleName(getElement(), CLASSNAME_UNDEFINED_WIDTH, false); - getElement().getStyle().clearDisplay(); } } diff --git a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java index 7e44c26c9e..55bd3a4641 100644 --- a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java @@ -58,6 +58,23 @@ public class BeanFieldGroup<T> extends FieldGroup { } } + @Override + protected Object findPropertyId(java.lang.reflect.Field memberField) { + String fieldName = memberField.getName(); + Item dataSource = getItemDataSource(); + if (dataSource != null && dataSource.getItemProperty(fieldName) != null) { + return fieldName; + } else { + String minifiedFieldName = minifyFieldName(fieldName); + try { + return getFieldName(beanType, minifiedFieldName); + } catch (SecurityException e) { + } catch (NoSuchFieldException e) { + } + } + return null; + } + private static java.lang.reflect.Field getField(Class<?> cls, String propertyId) throws SecurityException, NoSuchFieldException { if (propertyId.contains(".")) { @@ -75,7 +92,7 @@ public class BeanFieldGroup<T> extends FieldGroup { } catch (NoSuchFieldError e) { // Try super classes until we reach Object Class<?> superClass = cls.getSuperclass(); - if (superClass != Object.class) { + if (superClass != null && superClass != Object.class) { return getField(superClass, propertyId); } else { throw e; @@ -84,6 +101,22 @@ public class BeanFieldGroup<T> extends FieldGroup { } } + private static String getFieldName(Class<?> cls, String propertyId) + throws SecurityException, NoSuchFieldException { + for (java.lang.reflect.Field field1 : cls.getDeclaredFields()) { + if (propertyId.equals(minifyFieldName(field1.getName()))) { + return field1.getName(); + } + } + // Try super classes until we reach Object + Class<?> superClass = cls.getSuperclass(); + if (superClass != null && superClass != Object.class) { + return getFieldName(superClass, propertyId); + } else { + throw new NoSuchFieldException(); + } + } + /** * Helper method for setting the data source directly using a bean. This * method wraps the bean in a {@link BeanItem} and calls @@ -166,4 +199,4 @@ public class BeanFieldGroup<T> extends FieldGroup { } return beanValidationImplementationAvailable; } -}
\ No newline at end of file +} diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java index dc1fdbb78d..6c515dbdee 100644 --- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java @@ -733,11 +733,12 @@ public class FieldGroup implements Serializable { * that have not been initialized. * <p> * This method processes all (Java) member fields whose type extends - * {@link Field} and that can be mapped to a property id. Property id - * mapping is done based on the field name or on a @{@link PropertyId} - * annotation on the field. Fields that are not initialized (null) are built - * using the field factory. All non-null fields for which a property id can - * be determined are bound to the property id. + * {@link Field} and that can be mapped to a property id. Property ids are + * searched in the following order: @{@link PropertyId} annotations, exact + * field name matches and the case-insensitive matching that ignores + * underscores. Fields that are not initialized (null) are built using the + * field factory. All non-null fields for which a property id can be + * determined are bound to the property id. * </p> * <p> * For example: @@ -777,11 +778,12 @@ public class FieldGroup implements Serializable { * member fields that have not been initialized. * <p> * This method processes all (Java) member fields whose type extends - * {@link Field} and that can be mapped to a property id. Property id - * mapping is done based on the field name or on a @{@link PropertyId} - * annotation on the field. Fields that are not initialized (null) are built - * using the field factory is buildFields is true. All non-null fields for - * which a property id can be determined are bound to the property id. + * {@link Field} and that can be mapped to a property id. Property ids are + * searched in the following order: @{@link PropertyId} annotations, exact + * field name matches and the case-insensitive matching that ignores + * underscores. Fields that are not initialized (null) are built using the + * field factory is buildFields is true. All non-null fields for which a + * property id can be determined are bound to the property id. * </p> * * @param objectWithMemberFields @@ -812,7 +814,16 @@ public class FieldGroup implements Serializable { // @PropertyId(propertyId) always overrides property id propertyId = propertyIdAnnotation.value(); } else { - propertyId = memberField.getName(); + try { + propertyId = findPropertyId(memberField); + } catch (SearchException e) { + // Property id was not found, skip this field + continue; + } + if (propertyId == null) { + // Property id was not found, skip this field + continue; + } } // Ensure that the property id exists @@ -873,6 +884,54 @@ public class FieldGroup implements Serializable { } } + /** + * Searches for a property id from the current itemDataSource that matches + * the given memberField. + * <p> + * If perfect match is not found, uses a case insensitive search that also + * ignores underscores. Returns null if no match is found. Throws a + * SearchException if no item data source has been set. + * </p> + * <p> + * The propertyId search logic used by + * {@link #buildAndBindMemberFields(Object, boolean) + * buildAndBindMemberFields} can easily be customized by overriding this + * method. No other changes are needed. + * </p> + * + * @param memberField + * The field an object id is searched for + * @return + */ + protected Object findPropertyId(java.lang.reflect.Field memberField) { + String fieldName = memberField.getName(); + if (getItemDataSource() == null) { + throw new SearchException( + "Property id type for field '" + + fieldName + + "' could not be determined. No item data source has been set."); + } + Item dataSource = getItemDataSource(); + if (dataSource.getItemProperty(fieldName) != null) { + return fieldName; + } else { + String minifiedFieldName = minifyFieldName(fieldName); + for (Object itemPropertyId : dataSource.getItemPropertyIds()) { + if (itemPropertyId instanceof String) { + String itemPropertyName = (String) itemPropertyId; + if (minifiedFieldName.equals(minifyFieldName(itemPropertyName))) { + return itemPropertyName; + } + } + } + } + return null; + } + + protected static String minifyFieldName(String fieldName) { + return fieldName.toLowerCase().replace("_", ""); + } + public static class CommitException extends Exception { public CommitException() { @@ -909,6 +968,18 @@ public class FieldGroup implements Serializable { } + public static class SearchException extends RuntimeException { + + public SearchException(String message) { + super(message); + } + + public SearchException(String message, Throwable t) { + super(message, t); + } + + } + /** * Builds a field and binds it to the given property id using the field * binder. diff --git a/server/src/com/vaadin/data/util/IndexedContainer.java b/server/src/com/vaadin/data/util/IndexedContainer.java index 1705365f60..306f9cf23b 100644 --- a/server/src/com/vaadin/data/util/IndexedContainer.java +++ b/server/src/com/vaadin/data/util/IndexedContainer.java @@ -166,7 +166,8 @@ public class IndexedContainer extends public Property getContainerProperty(Object itemId, Object propertyId) { // map lookup more efficient than propertyIds if there are many // properties - if (!containsId(itemId) || !types.containsKey(propertyId)) { + if (!containsId(itemId) || propertyId == null + || !types.containsKey(propertyId)) { return null; } diff --git a/server/src/com/vaadin/server/VaadinPortletService.java b/server/src/com/vaadin/server/VaadinPortletService.java index e59ea7fd5e..8c1e7af0fa 100644 --- a/server/src/com/vaadin/server/VaadinPortletService.java +++ b/server/src/com/vaadin/server/VaadinPortletService.java @@ -46,7 +46,12 @@ public class VaadinPortletService extends VaadinService { } } - protected VaadinPortlet getPortlet() { + /** + * Retrieves a reference to the portlet associated with this service. + * + * @return A reference to the VaadinPortlet this service is using + */ + public VaadinPortlet getPortlet() { return portlet; } diff --git a/server/src/com/vaadin/server/VaadinServletService.java b/server/src/com/vaadin/server/VaadinServletService.java index 71f47ea217..7120e3a5c5 100644 --- a/server/src/com/vaadin/server/VaadinServletService.java +++ b/server/src/com/vaadin/server/VaadinServletService.java @@ -44,7 +44,12 @@ public class VaadinServletService extends VaadinService { } } - protected VaadinServlet getServlet() { + /** + * Retrieves a reference to the servlet associated with this service. + * + * @return A reference to the VaadinServlet this service is using + */ + public VaadinServlet getServlet() { return servlet; } diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java index 422e0a1796..619d717d97 100644 --- a/server/src/com/vaadin/ui/AbstractField.java +++ b/server/src/com/vaadin/ui/AbstractField.java @@ -373,30 +373,6 @@ public abstract class AbstractField<T> extends AbstractComponent implements /* Property interface implementation */ /** - * Returns the (field) value converted to a String using toString(). - * - * @see java.lang.Object#toString() - * @deprecated As of 7.0, use {@link #getValue()} to get the value of the - * field, {@link #getConvertedValue()} to get the field value - * converted to the data model type or - * {@link #getPropertyDataSource()} .getValue() to get the value - * of the data source. - */ - @Deprecated - @Override - public String toString() { - logger.warning("You are using AbstractField.toString() to get the value for a " - + getClass().getSimpleName() - + ". This will not be supported starting from Vaadin 7.1 " - + "(your debugger might call toString() and cause this message to appear)."); - final Object value = getFieldValue(); - if (value == null) { - return null; - } - return value.toString(); - } - - /** * Gets the current value of the field. * * <p> diff --git a/server/src/com/vaadin/ui/Label.java b/server/src/com/vaadin/ui/Label.java index f49a1403cf..f413ea47f2 100644 --- a/server/src/com/vaadin/ui/Label.java +++ b/server/src/com/vaadin/ui/Label.java @@ -203,23 +203,6 @@ public class Label extends AbstractComponent implements Property<String>, } /** - * Returns the value displayed by this label. - * - * @see java.lang.Object#toString() - * @deprecated As of 7.0, use {@link #getValue()} to get the value of the - * label or {@link #getPropertyDataSource()} .getValue() to get - * the value of the data source. - */ - @Deprecated - @Override - public String toString() { - logger.warning("You are using Label.toString() to get the value for a " - + getClass().getSimpleName() - + ". This will not be supported starting from Vaadin 7.1 (your debugger might call toString() and cause this message to appear)."); - return getValue(); - } - - /** * Gets the type of the Property. * * @see com.vaadin.data.Property#getType() diff --git a/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java b/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java index 971cdb5f62..09e5a26c15 100644 --- a/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java +++ b/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java @@ -384,4 +384,12 @@ public class TestIndexedContainer extends AbstractInMemoryContainerTest { assertNull(ic.getContainerProperty(object1, "xyz")); } + // test getting null property id (#10445) + public void testNullPropertyId() { + IndexedContainer ic = new IndexedContainer(); + String object1 = new String("Obj1"); + ic.addItem(object1); + assertNull(ic.getContainerProperty(object1, null)); + } + } diff --git a/server/tests/src/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBinding.java b/server/tests/src/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBinding.java new file mode 100644 index 0000000000..3f4368c295 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBinding.java @@ -0,0 +1,84 @@ +package com.vaadin.tests.server.component.fieldgroup; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.TextField; + +public class CaseInsensitiveBinding { + + @Test + public void caseInsensitivityAndUnderscoreRemoval() { + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("LastName", new ObjectProperty<String>("Sparrow")); + + class MyForm extends FormLayout { + TextField lastName = new TextField("Last name"); + + public MyForm() { + + // Should bind to the LastName property + addComponent(lastName); + } + } + + MyForm form = new MyForm(); + + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue("Sparrow".equals(form.lastName.getValue())); + } + + @Test + public void UnderscoreRemoval() { + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("first_name", new ObjectProperty<String>("Jack")); + + class MyForm extends FormLayout { + TextField firstName = new TextField("First name"); + + public MyForm() { + // Should bind to the first_name property + addComponent(firstName); + } + } + + MyForm form = new MyForm(); + + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue("Jack".equals(form.firstName.getValue())); + } + + @Test + public void perfectMatchPriority() { + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("first_name", new ObjectProperty<String>( + "Not this")); + item.addItemProperty("firstName", new ObjectProperty<String>("This")); + + class MyForm extends FormLayout { + TextField firstName = new TextField("First name"); + + public MyForm() { + // should bind to the firstName property, not first_name property + addComponent(firstName); + } + } + + MyForm form = new MyForm(); + + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue("This".equals(form.firstName.getValue())); + } + +}
\ No newline at end of file |