From bb26e8b100ba94cac295e459dd08aa5ce9e614df Mon Sep 17 00:00:00 2001 From: Henri Sara Date: Tue, 30 Nov 2010 10:47:58 +0000 Subject: [PATCH] #6063 BeanItemContainer broken when working with an interface that extends another interface svn changeset:16225/svn branch:6.5 --- src/com/vaadin/data/util/BeanItem.java | 51 +++++++++++++-- .../tests/server/container/BeanItemTest.java | 62 +++++++++++++++++++ 2 files changed, 108 insertions(+), 5 deletions(-) diff --git a/src/com/vaadin/data/util/BeanItem.java b/src/com/vaadin/data/util/BeanItem.java index 534969ba4f..eb0d2f44c3 100644 --- a/src/com/vaadin/data/util/BeanItem.java +++ b/src/com/vaadin/data/util/BeanItem.java @@ -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 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 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 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 getBeanPropertyDescriptor( + final Class beanClass) throws IntrospectionException { + // Oracle bug 4275879: Introspector does not consider superinterfaces of + // an interface + if (beanClass.isInterface()) { + List propertyDescriptors = new ArrayList(); + + 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. * diff --git a/tests/src/com/vaadin/tests/server/container/BeanItemTest.java b/tests/src/com/vaadin/tests/server/container/BeanItemTest.java index a9897f0ae4..f1472991c7 100644 --- a/tests/src/com/vaadin/tests/server/container/BeanItemTest.java +++ b/tests/src/com/vaadin/tests/server/container/BeanItemTest.java @@ -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 item = new BeanItem( 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 propertyDescriptors = (LinkedHashMap) 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 propertyDescriptors = (LinkedHashMap) 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 ids = new ArrayList(); ids.add("name"); -- 2.39.5