From 681864fee3c95dd281493f881db276b7b7abe87d Mon Sep 17 00:00:00 2001 From: Jarno Rantala Date: Wed, 11 Dec 2013 15:31:30 +0200 Subject: [PATCH] Backported null value support for NestedMethodProperty to 7.1 (#12884) Support for null values in NestedMethodProperty was already implemented in master branch (#11435) This changeset includes changesets made for that. Change-Id: I10696467f792e234326075bbcdd5aad487905a7e Merge: no --- .../data/util/AbstractBeanContainer.java | 10 +++-- server/src/com/vaadin/data/util/BeanItem.java | 9 +++-- .../data/util/NestedMethodProperty.java | 10 ++++- .../vaadin/data/util/BeanContainerTest.java | 13 ++++++ .../data/util/BeanItemContainerTest.java | 12 ++++++ .../data/util/NestedMethodPropertyTest.java | 40 ++++++++++--------- .../data/util/PropertyDescriptorTest.java | 18 ++++++++- 7 files changed, 82 insertions(+), 30 deletions(-) diff --git a/server/src/com/vaadin/data/util/AbstractBeanContainer.java b/server/src/com/vaadin/data/util/AbstractBeanContainer.java index 35403d6419..b19cdd980c 100644 --- a/server/src/com/vaadin/data/util/AbstractBeanContainer.java +++ b/server/src/com/vaadin/data/util/AbstractBeanContainer.java @@ -836,8 +836,9 @@ public abstract class AbstractBeanContainer extends * Adds a nested container property for the container, e.g. * "manager.address.street". * - * All intermediate getters must exist and must return non-null values when - * the property value is accessed. + * All intermediate getters must exist and should return non-null values + * when the property value is accessed. If an intermediate getter returns + * null, a null value will be returned. * * @see NestedMethodProperty * @@ -854,8 +855,9 @@ public abstract class AbstractBeanContainer extends * property to the container. The named property itself is removed from the * model as its subproperties are added. * - * All intermediate getters must exist and must return non-null values when - * the property value is accessed. + * All intermediate getters must exist and should return non-null values + * when the property value is accessed. If an intermediate getter returns + * null, a null value will be returned. * * @see NestedMethodProperty * @see #addNestedContainerProperty(String) diff --git a/server/src/com/vaadin/data/util/BeanItem.java b/server/src/com/vaadin/data/util/BeanItem.java index fc51be8f36..49f5f95898 100644 --- a/server/src/com/vaadin/data/util/BeanItem.java +++ b/server/src/com/vaadin/data/util/BeanItem.java @@ -255,12 +255,13 @@ public class BeanItem extends PropertysetItem { } /** - * Adds a nested property to the item. + * Adds a nested property to the item. The property must not exist in the + * item already and must of form "field1.field2" where field2 is a field in + * the object referenced to by field1. If an intermediate property returns + * null, the property will return a null value * * @param nestedPropertyId - * property id to add. This property must not exist in the item - * already and must of of form "field1.field2" where field2 is a - * field in the object referenced to by field1 + * property id to add. */ public void addNestedProperty(String nestedPropertyId) { addItemProperty(nestedPropertyId, new NestedMethodProperty( diff --git a/server/src/com/vaadin/data/util/NestedMethodProperty.java b/server/src/com/vaadin/data/util/NestedMethodProperty.java index b62ecfbfc3..8fe3b9d4c5 100644 --- a/server/src/com/vaadin/data/util/NestedMethodProperty.java +++ b/server/src/com/vaadin/data/util/NestedMethodProperty.java @@ -31,8 +31,9 @@ import com.vaadin.data.util.MethodProperty.MethodException; * The property is specified in the dotted notation, e.g. "address.street", and * can contain multiple levels of nesting. * - * When accessing the property value, all intermediate getters must return - * non-null values. + * When accessing the property value, all intermediate getters must exist and + * should return non-null values when the property value is accessed. If an + * intermediate getter returns null, a null value will be returned. * * @see MethodProperty * @@ -76,6 +77,8 @@ public class NestedMethodProperty extends AbstractProperty { * Constructs a nested method property for a given object instance. The * property name is a dot separated string pointing to a nested property, * e.g. "manager.address.street". + *

+ * Calling getValue will return null if any intermediate getter returns null * * @param instance * top-level bean to which the property applies @@ -199,6 +202,9 @@ public class NestedMethodProperty extends AbstractProperty { Object object = instance; for (Method m : getMethods) { object = m.invoke(object); + if (object == null) { + return null; + } } return (T) object; } catch (final Throwable e) { diff --git a/server/tests/src/com/vaadin/data/util/BeanContainerTest.java b/server/tests/src/com/vaadin/data/util/BeanContainerTest.java index 9037e303a8..684ab5d6bc 100644 --- a/server/tests/src/com/vaadin/data/util/BeanContainerTest.java +++ b/server/tests/src/com/vaadin/data/util/BeanContainerTest.java @@ -457,4 +457,17 @@ public class BeanContainerTest extends AbstractBeanContainerTest { .getValue()); } + public void testNestedContainerPropertyWithNullBean() { + BeanContainer container = new BeanContainer( + NestedMethodPropertyTest.Person.class); + container.setBeanIdProperty("name"); + + container.addBean(new NestedMethodPropertyTest.Person("John", null)); + assertTrue(container + .addNestedContainerProperty("address.postalCodeObject")); + assertTrue(container.addNestedContainerProperty("address.street")); + assertNull(container.getContainerProperty("John", "address.street") + .getValue()); + } + } diff --git a/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java b/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java index 6b88eb336d..767a9e2e4d 100644 --- a/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java +++ b/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java @@ -714,4 +714,16 @@ public class BeanItemContainerTest extends AbstractBeanContainerTest { .getValue()); } + public void testNestedContainerPropertyWithNullBean() { + BeanItemContainer container = new BeanItemContainer( + NestedMethodPropertyTest.Person.class); + NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person( + "John", null); + assertNotNull(container.addBean(john)); + assertTrue(container + .addNestedContainerProperty("address.postalCodeObject")); + assertTrue(container.addNestedContainerProperty("address.street")); + assertNull(container.getContainerProperty(john, "address.street") + .getValue()); + } } diff --git a/server/tests/src/com/vaadin/data/util/NestedMethodPropertyTest.java b/server/tests/src/com/vaadin/data/util/NestedMethodPropertyTest.java index 640ede8743..1133626df9 100644 --- a/server/tests/src/com/vaadin/data/util/NestedMethodPropertyTest.java +++ b/server/tests/src/com/vaadin/data/util/NestedMethodPropertyTest.java @@ -7,9 +7,10 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import junit.framework.Assert; import junit.framework.TestCase; +import org.junit.Assert; + public class NestedMethodPropertyTest extends TestCase { public static class Address implements Serializable { @@ -248,29 +249,16 @@ public class NestedMethodPropertyTest extends TestCase { vaadin, "manager.address.street"); joonas.setAddress(null); - try { - streetProperty.getValue(); - fail(); - } catch (Exception e) { - // should get exception - } + assertNull(streetProperty.getValue()); vaadin.setManager(null); - try { - managerNameProperty.getValue(); - fail(); - } catch (Exception e) { - // should get exception - } - try { - streetProperty.getValue(); - fail(); - } catch (Exception e) { - // should get exception - } + assertNull(managerNameProperty.getValue()); + assertNull(streetProperty.getValue()); vaadin.setManager(joonas); Assert.assertEquals("Joonas", managerNameProperty.getValue()); + Assert.assertNull(streetProperty.getValue()); + } public void testMultiLevelNestedPropertySetValue() { @@ -314,6 +302,20 @@ public class NestedMethodPropertyTest extends TestCase { Assert.assertEquals("Ruukinkatu 2-4", property2.getValue()); } + public void testSerializationWithIntermediateNull() throws IOException, + ClassNotFoundException { + vaadin.setManager(null); + NestedMethodProperty streetProperty = new NestedMethodProperty( + vaadin, "manager.address.street"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(streetProperty); + @SuppressWarnings("unchecked") + NestedMethodProperty property2 = (NestedMethodProperty) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Assert.assertNull(property2.getValue()); + } + public void testIsReadOnly() { NestedMethodProperty streetProperty = new NestedMethodProperty( vaadin, "manager.address.street"); diff --git a/server/tests/src/com/vaadin/data/util/PropertyDescriptorTest.java b/server/tests/src/com/vaadin/data/util/PropertyDescriptorTest.java index 14e70d76d4..12ded84fe2 100644 --- a/server/tests/src/com/vaadin/data/util/PropertyDescriptorTest.java +++ b/server/tests/src/com/vaadin/data/util/PropertyDescriptorTest.java @@ -39,7 +39,8 @@ public class PropertyDescriptorTest extends TestCase { Assert.assertEquals("John", property.getValue()); } - public void testNestedPropertyDescriptorSerialization() throws Exception { + public void testSimpleNestedPropertyDescriptorSerialization() + throws Exception { NestedPropertyDescriptor pd = new NestedPropertyDescriptor( "name", Person.class); @@ -52,4 +53,19 @@ public class PropertyDescriptorTest extends TestCase { Property property = pd2.createProperty(new Person("John", null)); Assert.assertEquals("John", property.getValue()); } + + public void testNestedPropertyDescriptorSerialization() throws Exception { + NestedPropertyDescriptor pd = new NestedPropertyDescriptor( + "address.street", Person.class); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(pd); + @SuppressWarnings("unchecked") + VaadinPropertyDescriptor pd2 = (VaadinPropertyDescriptor) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Property property = pd2.createProperty(new Person("John", null)); + Assert.assertNull(property.getValue()); + } + } -- 2.39.5