]> source.dussan.org Git - vaadin-framework.git/commitdiff
Simplified support for null intermediate properties (#11435)
authorArtur Signell <artur@vaadin.com>
Fri, 29 Nov 2013 09:53:20 +0000 (11:53 +0200)
committerVaadin Code Review <review@vaadin.com>
Sat, 30 Nov 2013 07:32:25 +0000 (07:32 +0000)
Removed support for explicitly throwing NPE for intermediate properties as no use
case could be identified where this would be the expected or wanted behavior.

Change-Id: I10696467f792e234326075bbcdd5aad487905a7e

server/src/com/vaadin/data/util/AbstractBeanContainer.java
server/src/com/vaadin/data/util/BeanItem.java
server/src/com/vaadin/data/util/NestedMethodProperty.java
server/src/com/vaadin/data/util/NestedPropertyDescriptor.java
server/tests/src/com/vaadin/data/util/BeanContainerTest.java
server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java
server/tests/src/com/vaadin/data/util/NestedMethodPropertyTest.java
server/tests/src/com/vaadin/data/util/PropertyDescriptorTest.java

index 67239996a23d8f4450ae25f4fa41709960fb3bda..d94588bdc9e187fc7851cc7913be25fd2a8052d3 100644 (file)
@@ -848,8 +848,9 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> 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
      * 
@@ -857,32 +858,8 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends
      * @return true if the property was added
      */
     public boolean addNestedContainerProperty(String propertyId) {
-        return addNestedContainerProperty(propertyId, false);
-    }
-
-    /**
-     * 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 or the <code>nullBeansAllowed</code> must
-     * be set to true. If the <code>nullBeansAllowed</code> flag is set to true,
-     * calling getValue of the added property will return null if the property
-     * or any of its intermediate getters returns null. If set to false, null
-     * values returned by intermediate getters will cause NullPointerException.
-     * The default value is false to ensure backwards compatibility.
-     * 
-     * @see NestedMethodProperty
-     * 
-     * @param propertyId
-     * @param nullBeansAllowed
-     *            set true to allow null values from intermediate getters
-     * @return true if the property was added
-     */
-    public boolean addNestedContainerProperty(String propertyId,
-            boolean nullBeansAllowed) {
         return addContainerProperty(propertyId, new NestedPropertyDescriptor(
-                propertyId, type, nullBeansAllowed));
+                propertyId, type));
     }
 
     /**
@@ -890,8 +867,9 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> 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)
@@ -900,42 +878,13 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends
      */
     @SuppressWarnings("unchecked")
     public void addNestedContainerBean(String propertyId) {
-        addNestedContainerBean(propertyId, false);
-    }
-
-    /**
-     * Adds a nested container properties for all sub-properties of a named
-     * property to the container. The named property itself is removed from the
-     * model as its subproperties are added.
-     * 
-     * Unless
-     * <code>nullBeansAllowed<code>  is set to true, all intermediate getters must
-     * exist and must return non-null values when the property values are
-     * accessed. If the <code>nullBeansAllowed</code> flag is set to true,
-     * calling getValue of the added subproperties will return null if the
-     * property or any of their intermediate getters returns null. If set to
-     * false, null values returned by intermediate getters will cause
-     * NullPointerException. The default value is false to ensure backwards
-     * compatibility.
-     * 
-     * @see NestedMethodProperty
-     * @see #addNestedContainerProperty(String)
-     * 
-     * @param propertyId
-     * @param nullBeansAllowed
-     *            set true to allow null values from intermediate getters
-     */
-    @SuppressWarnings("unchecked")
-    public void addNestedContainerBean(String propertyId,
-            boolean nullBeansAllowed) {
         Class<?> propertyType = getType(propertyId);
         LinkedHashMap<String, VaadinPropertyDescriptor<Object>> pds = BeanItem
                 .getPropertyDescriptors((Class<Object>) propertyType);
         for (String subPropertyId : pds.keySet()) {
             String qualifiedPropertyId = propertyId + "." + subPropertyId;
             NestedPropertyDescriptor<BEANTYPE> pd = new NestedPropertyDescriptor<BEANTYPE>(
-                    qualifiedPropertyId, (Class<BEANTYPE>) type,
-                    nullBeansAllowed);
+                    qualifiedPropertyId, (Class<BEANTYPE>) type);
             model.put(qualifiedPropertyId, pd);
             model.remove(propertyId);
             for (BeanItem<BEANTYPE> item : itemIdToItem.values()) {
index 4834fe4f8971735fbd2cbb95bcd052c14e782654..49f5f958988fae4e7d93e97e86aa02229f7b2cbd 100644 (file)
@@ -255,39 +255,19 @@ public class BeanItem<BT> 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<Object>(
                 getBean(), nestedPropertyId));
     }
 
-    /**
-     * Adds a nested property to the item. If the <code>nullBeansAllowed</code>
-     * flag is set to true, calling getValue of the added property will return
-     * null if the property or any of its intermediate getters returns null. If
-     * set to false, null values returned by intermediate getters will cause
-     * NullPointerException. The default value is false to ensure backwards
-     * compatibility.
-     * 
-     * @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
-     * @param nullBeansAllowed
-     *            set true to allow null values from intermediate getters
-     */
-    public void addNestedProperty(String nestedPropertyId,
-            boolean nullBeansAllowed) {
-        addItemProperty(nestedPropertyId, new NestedMethodProperty<Object>(
-                getBean(), nestedPropertyId, nullBeansAllowed));
-    }
-
     /**
      * Gets the underlying JavaBean object.
      * 
index 7a3963c17e874e0945a1c6e63db8704cf2fcea92..8fe3b9d4c53a4d75570de609c2c5c9a2b93cb7d5 100644 (file)
@@ -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 or the <code>nullBeansAllowed</code> must be set to true.
+ * 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
  * 
@@ -55,15 +56,6 @@ public class NestedMethodProperty<T> extends AbstractProperty<T> {
      */
     private Object instance;
 
-    /**
-     * a boolean flag indicating whether intermediate getters may return null
-     * values. If the flag is set to true, calling getValue will return null if
-     * the property or any of its intermediate getters returns null. If set to
-     * false, intermediate getters returning null value will throw Exception.
-     * The default value is false to ensure backwards compatibility.
-     */
-    private boolean nullBeansAllowed = false;
-
     private Class<? extends T> type;
 
     /* Special serialization to handle method references */
@@ -85,6 +77,8 @@ public class NestedMethodProperty<T> extends AbstractProperty<T> {
      * 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".
+     * <p>
+     * Calling getValue will return null if any intermediate getter returns null
      * 
      * @param instance
      *            top-level bean to which the property applies
@@ -94,33 +88,7 @@ public class NestedMethodProperty<T> extends AbstractProperty<T> {
      *             if the property name is invalid
      */
     public NestedMethodProperty(Object instance, String propertyName) {
-        this(instance, propertyName, false);
-    }
-
-    /**
-     * 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". The <code>nullBeansAllowed</code> controls
-     * the behavior in cases where the intermediate getters may return null
-     * values. If the flag is set to true, calling getValue will return null if
-     * the property or any of its intermediate getters returns null. If set to
-     * false, null values returned by intermediate getters will cause
-     * NullPointerException. The default value is false to ensure backwards
-     * compatibility.
-     * 
-     * @param instance
-     *            top-level bean to which the property applies
-     * @param propertyName
-     *            dot separated nested property name
-     * @param nullBeansAllowed
-     *            set true to allow null values from intermediate getters
-     * @throws IllegalArgumentException
-     *             if the property name is invalid
-     */
-    public NestedMethodProperty(Object instance, String propertyName,
-            boolean nullBeansAllowed) {
         this.instance = instance;
-        this.nullBeansAllowed = nullBeansAllowed;
         initialize(instance.getClass(), propertyName);
     }
 
@@ -138,25 +106,6 @@ public class NestedMethodProperty<T> extends AbstractProperty<T> {
         initialize(instanceClass, propertyName);
     }
 
-    /**
-     * For internal use to deduce property type etc. without a bean instance.
-     * Calling {@link #setValue(Object)} or {@link #getValue()} on properties
-     * constructed this way is not supported.
-     * 
-     * @param instanceClass
-     *            class of the top-level bean
-     * @param propertyName
-     *            dot separated nested property name
-     * @param nullBeansAllowed
-     *            set true to allow null values from intermediate getters
-     */
-    NestedMethodProperty(Class<?> instanceClass, String propertyName,
-            boolean nullBeansAllowed) {
-        instance = null;
-        this.nullBeansAllowed = nullBeansAllowed;
-        initialize(instanceClass, propertyName);
-    }
-
     /**
      * Initializes most of the internal fields based on the top-level bean
      * instance and property name (dot-separated string).
@@ -253,7 +202,7 @@ public class NestedMethodProperty<T> extends AbstractProperty<T> {
             Object object = instance;
             for (Method m : getMethods) {
                 object = m.invoke(object);
-                if (object == null && nullBeansAllowed) {
+                if (object == null) {
                     return null;
                 }
             }
index 67eb30fae5272d70ea1fc551729c80aa4be29eb9..b2055fe776b98e408a0b53e911ae26eadd2d9aec 100644 (file)
@@ -34,7 +34,6 @@ public class NestedPropertyDescriptor<BT> implements
 
     private final String name;
     private final Class<?> propertyType;
-    private final boolean nullBeansAllowed;
 
     /**
      * Creates a property descriptor that can create MethodProperty instances to
@@ -49,29 +48,10 @@ public class NestedPropertyDescriptor<BT> implements
      */
     public NestedPropertyDescriptor(String name, Class<BT> beanType)
             throws IllegalArgumentException {
-        this(name, beanType, false);
-    }
-
-    /**
-     * Creates a property descriptor that can create MethodProperty instances to
-     * access the underlying bean property.
-     * 
-     * @param name
-     *            of the property in a dotted path format, e.g. "address.street"
-     * @param beanType
-     *            type (class) of the top-level bean
-     * @param nullBeansAllowed
-     *            set true to allow null values from intermediate getters
-     * @throws IllegalArgumentException
-     *             if the property name is invalid
-     */
-    public NestedPropertyDescriptor(String name, Class<BT> beanType,
-            boolean nullBeansAllowed) throws IllegalArgumentException {
         this.name = name;
         NestedMethodProperty<?> property = new NestedMethodProperty<Object>(
-                beanType, name, nullBeansAllowed);
+                beanType, name);
         this.propertyType = property.getType();
-        this.nullBeansAllowed = nullBeansAllowed;
     }
 
     @Override
@@ -86,7 +66,7 @@ public class NestedPropertyDescriptor<BT> implements
 
     @Override
     public Property<?> createProperty(BT bean) {
-        return new NestedMethodProperty<Object>(bean, name, nullBeansAllowed);
+        return new NestedMethodProperty<Object>(bean, name);
     }
 
 }
index 2dcbb4aed8370cd04f226f0a0f48119150caa355..a6c3bb0b8bd3406adaf1a3da30a81c008916c3c4 100644 (file)
@@ -465,20 +465,11 @@ public class BeanContainerTest extends AbstractBeanContainerTest {
         container.addBean(new NestedMethodPropertyTest.Person("John", null));
         assertTrue(container
                 .addNestedContainerProperty("address.postalCodeObject"));
-        assertTrue(container.addNestedContainerProperty("address.street", true));
+        assertTrue(container.addNestedContainerProperty("address.street"));
         // the nested properties added with allowNullBean setting should return
         // null
         assertNull(container.getContainerProperty("John", "address.street")
                 .getValue());
-        // nested properties added without allowNullBean setting should throw
-        // exception
-        try {
-            container.getContainerProperty("John", "address.postalCodeObject")
-                    .getValue();
-            fail();
-        } catch (Exception e) {
-            // should throw exception
-        }
     }
 
 }
index 35f09fc8f3033d2146cea4cd659a166c03b362f9..b9633753b460b9c787da1cd410262e4545b724b3 100644 (file)
@@ -729,20 +729,10 @@ public class BeanItemContainerTest extends AbstractBeanContainerTest {
         assertNotNull(container.addBean(john));
         assertTrue(container
                 .addNestedContainerProperty("address.postalCodeObject"));
-        assertTrue(container.addNestedContainerProperty("address.street", true));
-        // the nested properties added with allowNullBean setting should return
-        // null
+        assertTrue(container.addNestedContainerProperty("address.street"));
+        // the nested properties should return null
         assertNull(container.getContainerProperty(john, "address.street")
                 .getValue());
-        // nested properties added without allowNullBean setting should throw
-        // exception
-        try {
-            container.getContainerProperty(john, "address.postalCodeObject")
-                    .getValue();
-            fail();
-        } catch (Exception e) {
-            // should throw exception
-        }
     }
 
     public void testItemAddedEvent() {
index d51732201089822366d14e8704ef6fe287d86788..1133626df9aea5d17d0cd12f1c4bff1e81fc2b60 100644 (file)
@@ -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,46 +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());
-    }
-
-    public void testNullNestedPropertyWithAllowNullBeans() {
-        NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>(
-                vaadin, "manager.name", true);
-        NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>(
-                vaadin, "manager.address.street", true);
-
-        joonas.setAddress(null);
-        // should return null
         Assert.assertNull(streetProperty.getValue());
 
-        vaadin.setManager(null);
-        Assert.assertNull(managerNameProperty.getValue());
-        vaadin.setManager(joonas);
-        Assert.assertEquals("Joonas", managerNameProperty.getValue());
-        Assert.assertNull(streetProperty.getValue());
     }
 
     public void testMultiLevelNestedPropertySetValue() {
@@ -331,11 +302,11 @@ public class NestedMethodPropertyTest extends TestCase {
         Assert.assertEquals("Ruukinkatu 2-4", property2.getValue());
     }
 
-    public void testSerializationWithNullBeansAllowed() throws IOException,
+    public void testSerializationWithIntermediateNull() throws IOException,
             ClassNotFoundException {
         vaadin.setManager(null);
         NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>(
-                vaadin, "manager.address.street", true);
+                vaadin, "manager.address.street");
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         new ObjectOutputStream(baos).writeObject(streetProperty);
         @SuppressWarnings("unchecked")
index 0ae76430f68b84fbeca7991923269e18d6d20c35..12ded84fe229e8aebe0e4f333d8bffa4be799ca8 100644 (file)
@@ -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<Person> pd = new NestedPropertyDescriptor<Person>(
                 "name", Person.class);
 
@@ -53,10 +54,9 @@ public class PropertyDescriptorTest extends TestCase {
         Assert.assertEquals("John", property.getValue());
     }
 
-    public void testNestedPropertyDescriptorWithNullBeansAllowedSerialization()
-            throws Exception {
+    public void testNestedPropertyDescriptorSerialization() throws Exception {
         NestedPropertyDescriptor<Person> pd = new NestedPropertyDescriptor<Person>(
-                "address.street", Person.class, true);
+                "address.street", Person.class);
 
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         new ObjectOutputStream(baos).writeObject(pd);