]> source.dussan.org Git - vaadin-framework.git/commitdiff
#6063 BeanItemContainer broken when working with an interface that extends another...
authorHenri Sara <henri.sara@itmill.com>
Tue, 30 Nov 2010 10:47:58 +0000 (10:47 +0000)
committerHenri Sara <henri.sara@itmill.com>
Tue, 30 Nov 2010 10:47:58 +0000 (10:47 +0000)
svn changeset:16225/svn branch:6.5

src/com/vaadin/data/util/BeanItem.java
tests/src/com/vaadin/tests/server/container/BeanItemTest.java

index 534969ba4f205f2569653a39233612649c69e122..eb0d2f44c3525b9ea650d7da64043f9bc441ff8e 100644 (file)
@@ -5,12 +5,15 @@
 package com.vaadin.data.util;
 
 import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
 import java.beans.Introspector;
 import java.beans.PropertyDescriptor;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.LinkedHashMap;
+import java.util.List;
 
 import com.vaadin.data.Property;
 
@@ -165,15 +168,15 @@ public class BeanItem<BT> extends PropertysetItem {
 
         // Try to introspect, if it fails, we just have an empty Item
         try {
-            final BeanInfo info = Introspector.getBeanInfo(beanClass);
-            final PropertyDescriptor[] pds = info.getPropertyDescriptors();
+            List<PropertyDescriptor> propertyDescriptors = getBeanPropertyDescriptor(beanClass);
 
             // Add all the bean properties as MethodProperties to this Item
-            for (int i = 0; i < pds.length; i++) {
-                final Method getMethod = pds[i].getReadMethod();
+            // later entries on the list overwrite earlier ones
+            for (PropertyDescriptor pd : propertyDescriptors) {
+                final Method getMethod = pd.getReadMethod();
                 if ((getMethod != null)
                         && getMethod.getDeclaringClass() != Object.class) {
-                    pdMap.put(pds[i].getName(), pds[i]);
+                    pdMap.put(pd.getName(), pd);
                 }
             }
         } catch (final java.beans.IntrospectionException ignored) {
@@ -182,6 +185,44 @@ public class BeanItem<BT> extends PropertysetItem {
         return pdMap;
     }
 
+    /**
+     * Returns the property descriptors of a class or an interface.
+     * 
+     * For an interface, superinterfaces are also iterated as Introspector does
+     * not take them into account (Oracle Java bug 4275879), but in that case,
+     * both the setter and the getter for a property must be in the same
+     * interface and should not be overridden in subinterfaces for the discovery
+     * to work correctly.
+     * 
+     * For interfaces, the iteration is depth first and the properties of
+     * superinterfaces are returned before those of their subinterfaces.
+     * 
+     * @param beanClass
+     * @return
+     * @throws IntrospectionException
+     */
+    private static List<PropertyDescriptor> getBeanPropertyDescriptor(
+            final Class<?> beanClass) throws IntrospectionException {
+        // Oracle bug 4275879: Introspector does not consider superinterfaces of
+        // an interface
+        if (beanClass.isInterface()) {
+            List<PropertyDescriptor> propertyDescriptors = new ArrayList<PropertyDescriptor>();
+
+            for (Class<?> cls : beanClass.getInterfaces()) {
+                propertyDescriptors.addAll(getBeanPropertyDescriptor(cls));
+            }
+
+            BeanInfo info = Introspector.getBeanInfo(beanClass);
+            propertyDescriptors.addAll(Arrays.asList(info
+                    .getPropertyDescriptors()));
+
+            return propertyDescriptors;
+        } else {
+            BeanInfo info = Introspector.getBeanInfo(beanClass);
+            return Arrays.asList(info.getPropertyDescriptors());
+        }
+    }
+
     /**
      * Gets the underlying JavaBean object.
      * 
index a9897f0ae4b538b75ac9a4d9d7d9b113342404f0..f1472991c74fcb457299aeeb46d3174009dde75e 100644 (file)
@@ -1,8 +1,12 @@
 package com.vaadin.tests.server.container;
 
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 
 import junit.framework.Assert;
 import junit.framework.TestCase;
@@ -105,6 +109,29 @@ public class BeanItemTest extends TestCase {
         }
     }
 
+    protected static interface MySuperInterface {
+        public int getSuper1();
+
+        public void setSuper1(int i);
+
+        public int getOverride();
+    }
+
+    protected static interface MySuperInterface2 {
+        public int getSuper2();
+    }
+
+    protected static interface MySubInterface extends MySuperInterface,
+            MySuperInterface2 {
+        public int getSub();
+
+        public void setSub(int i);
+
+        public int getOverride();
+
+        public void setOverride(int i);
+    }
+
     public void testGetProperties() {
         BeanItem<MySuperClass> item = new BeanItem<MySuperClass>(
                 new MySuperClass());
@@ -141,6 +168,41 @@ public class BeanItemTest extends TestCase {
         Assert.assertFalse(item.getItemProperty("name2").isReadOnly());
     }
 
+    public void testGetInterfaceProperties() throws SecurityException,
+            NoSuchMethodException, IllegalArgumentException,
+            IllegalAccessException, InvocationTargetException {
+        Method method = BeanItem.class.getDeclaredMethod(
+                "getPropertyDescriptors", Class.class);
+        method.setAccessible(true);
+        LinkedHashMap<String, PropertyDescriptor> propertyDescriptors = (LinkedHashMap<String, PropertyDescriptor>) method
+                .invoke(null, MySuperInterface.class);
+
+        Assert.assertEquals(2, propertyDescriptors.size());
+        Assert.assertTrue(propertyDescriptors.containsKey("super1"));
+        Assert.assertTrue(propertyDescriptors.containsKey("override"));
+
+        Assert.assertNull(propertyDescriptors.get("override").getWriteMethod());
+    }
+
+    public void testGetSuperInterfaceProperties() throws SecurityException,
+            NoSuchMethodException, IllegalArgumentException,
+            IllegalAccessException, InvocationTargetException {
+        Method method = BeanItem.class.getDeclaredMethod(
+                "getPropertyDescriptors", Class.class);
+        method.setAccessible(true);
+        LinkedHashMap<String, PropertyDescriptor> propertyDescriptors = (LinkedHashMap<String, PropertyDescriptor>) method
+                .invoke(null, MySubInterface.class);
+
+        Assert.assertEquals(4, propertyDescriptors.size());
+        Assert.assertTrue(propertyDescriptors.containsKey("sub"));
+        Assert.assertTrue(propertyDescriptors.containsKey("super1"));
+        Assert.assertTrue(propertyDescriptors.containsKey("super2"));
+        Assert.assertTrue(propertyDescriptors.containsKey("override"));
+
+        Assert.assertNotNull(propertyDescriptors.get("override")
+                .getWriteMethod());
+    }
+
     public void testPropertyExplicitOrder() {
         Collection<String> ids = new ArrayList<String>();
         ids.add("name");