summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenri Sara <henri.sara@itmill.com>2009-04-02 07:50:52 +0000
committerHenri Sara <henri.sara@itmill.com>2009-04-02 07:50:52 +0000
commit4a765948a65dab18869ee6425dba3ba909fdf274 (patch)
tree5eb2ec949b6dd3a8460272b66f1d84029b934dee
parent5218e96b2838388e2c9b77cf3aad7aecbb43a3c1 (diff)
downloadvaadin-framework-4a765948a65dab18869ee6425dba3ba909fdf274.tar.gz
vaadin-framework-4a765948a65dab18869ee6425dba3ba909fdf274.zip
#1061: merged [7281] from 5.4: BeanItemContainer no longer requires a public default constructor in the bean and supports bean subclasses (with parent properties only)
svn changeset:7282/svn branch:6.0
-rw-r--r--src/com/itmill/toolkit/data/util/BeanItem.java125
-rw-r--r--src/com/itmill/toolkit/data/util/BeanItemContainer.java21
-rw-r--r--src/com/itmill/toolkit/tests/containers/BeanItemContainerTest.java17
3 files changed, 106 insertions, 57 deletions
diff --git a/src/com/itmill/toolkit/data/util/BeanItem.java b/src/com/itmill/toolkit/data/util/BeanItem.java
index b867491cdb..65bc57a1b3 100644
--- a/src/com/itmill/toolkit/data/util/BeanItem.java
+++ b/src/com/itmill/toolkit/data/util/BeanItem.java
@@ -10,7 +10,7 @@ import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Iterator;
+import java.util.LinkedHashMap;
import com.itmill.toolkit.data.Property;
@@ -47,30 +47,35 @@ public class BeanItem extends PropertysetItem {
*
*/
public BeanItem(Object bean) {
+ this(bean, getPropertyDescriptors(bean.getClass()));
+ }
- this.bean = bean;
+ /**
+ * <p>
+ * Creates a new instance of <code>BeanItem</code> using a pre-computed set
+ * of properties. The properties are identified by their respective bean
+ * names.
+ * </p>
+ *
+ * @param bean
+ * the Java Bean to copy properties from.
+ * @param propertyDescriptors
+ * pre-computed property descriptors
+ */
+ BeanItem(Object bean,
+ LinkedHashMap<String, PropertyDescriptor> propertyDescriptors) {
- // Try to introspect, if it fails, we just have an empty Item
- try {
- // Create bean information
- final BeanInfo info = Introspector.getBeanInfo(bean.getClass());
- final PropertyDescriptor[] pd = info.getPropertyDescriptors();
+ this.bean = bean;
- // Add all the bean properties as MethodProperties to this Item
- for (int i = 0; i < pd.length; i++) {
- final Method getMethod = pd[i].getReadMethod();
- final Method setMethod = pd[i].getWriteMethod();
- final Class<?> type = pd[i].getPropertyType();
- final String name = pd[i].getName();
+ for (PropertyDescriptor pd : propertyDescriptors.values()) {
+ final Method getMethod = pd.getReadMethod();
+ final Method setMethod = pd.getWriteMethod();
+ final Class<?> type = pd.getPropertyType();
+ final String name = pd.getName();
+ final Property p = new MethodProperty(type, bean, getMethod,
+ setMethod);
+ addItemProperty(name, p);
- if ((getMethod != null)
- && getMethod.getDeclaringClass() != Object.class) {
- final Property p = new MethodProperty(type, bean,
- getMethod, setMethod);
- addItemProperty(name, p);
- }
- }
- } catch (final java.beans.IntrospectionException ignored) {
}
}
@@ -96,32 +101,22 @@ public class BeanItem extends PropertysetItem {
this.bean = bean;
- // Try to introspect, if it fails, we just have an empty Item
- try {
- // Create bean information
- final BeanInfo info = Introspector.getBeanInfo(bean.getClass());
- final PropertyDescriptor[] pd = info.getPropertyDescriptors();
-
- // Add all the bean properties as MethodProperties to this Item
- final Iterator iter = propertyIds.iterator();
- while (iter.hasNext()) {
- final Object id = iter.next();
- for (int i = 0; i < pd.length; i++) {
- final String name = pd[i].getName();
- if (name.equals(id)) {
- final Method getMethod = pd[i].getReadMethod();
- final Method setMethod = pd[i].getWriteMethod();
- final Class<?> type = pd[i].getPropertyType();
- if ((getMethod != null)) {
- final Property p = new MethodProperty(type, bean,
- getMethod, setMethod);
- addItemProperty(name, p);
- }
- }
- }
+ // Create bean information
+ LinkedHashMap<String, PropertyDescriptor> pds = getPropertyDescriptors(bean
+ .getClass());
+
+ // Add all the bean properties as MethodProperties to this Item
+ for (Object id : propertyIds) {
+ PropertyDescriptor pd = pds.get(id);
+ if (pd != null) {
+ final String name = pd.getName();
+ final Method getMethod = pd.getReadMethod();
+ final Method setMethod = pd.getWriteMethod();
+ final Class<?> type = pd.getPropertyType();
+ final Property p = new MethodProperty(type, bean, getMethod,
+ setMethod);
+ addItemProperty(name, p);
}
-
- } catch (final java.beans.IntrospectionException ignored) {
}
}
@@ -149,6 +144,44 @@ public class BeanItem extends PropertysetItem {
}
/**
+ * <p>
+ * Perform introspection on a Java Bean class to find its properties.
+ * </p>
+ *
+ * <p>
+ * Note : This version only supports introspectable bean properties and
+ * their getter and setter methods. Stand-alone <code>is</code> and
+ * <code>are</code> methods are not supported.
+ * </p>
+ *
+ * @param beanClass
+ * the Java Bean class to get properties for.
+ * @return an ordered map from property names to property descriptors
+ */
+ static LinkedHashMap<String, PropertyDescriptor> getPropertyDescriptors(
+ final Class<?> beanClass) {
+ final LinkedHashMap<String, PropertyDescriptor> pdMap = new LinkedHashMap<String, PropertyDescriptor>();
+
+ // Try to introspect, if it fails, we just have an empty Item
+ try {
+ final BeanInfo info = Introspector.getBeanInfo(beanClass);
+ final PropertyDescriptor[] pds = info.getPropertyDescriptors();
+
+ // Add all the bean properties as MethodProperties to this Item
+ for (int i = 0; i < pds.length; i++) {
+ final Method getMethod = pds[i].getReadMethod();
+ if ((getMethod != null)
+ && getMethod.getDeclaringClass() != Object.class) {
+ pdMap.put(pds[i].getName(), pds[i]);
+ }
+ }
+ } catch (final java.beans.IntrospectionException ignored) {
+ }
+
+ return pdMap;
+ }
+
+ /**
* Gets the underlying JavaBean object.
*
* @return the bean object.
diff --git a/src/com/itmill/toolkit/data/util/BeanItemContainer.java b/src/com/itmill/toolkit/data/util/BeanItemContainer.java
index 457526efc4..5ba44568ad 100644
--- a/src/com/itmill/toolkit/data/util/BeanItemContainer.java
+++ b/src/com/itmill/toolkit/data/util/BeanItemContainer.java
@@ -1,5 +1,6 @@
package com.itmill.toolkit.data.util;
+import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -7,6 +8,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -27,7 +29,7 @@ import com.itmill.toolkit.data.Property.ValueChangeNotifier;
* An {@link ArrayList} backed container for {@link BeanItem}s.
* <p>
* Bean objects act as identifiers. For this reason, they should implement
- * Object.equals(Object) and Object.hashCode() .
+ * Object.equals(Object) and Object.hashCode().
* </p>
*
* @param <BT>
@@ -41,8 +43,9 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
private ArrayList<BT> allItems = new ArrayList<BT>();
private final Map<BT, BeanItem> beanToItem = new HashMap<BT, BeanItem>();
+ // internal data model to obtain property IDs etc.
private final Class<BT> type;
- private final BeanItem model;
+ private final LinkedHashMap<String, PropertyDescriptor> model;
private List<ItemSetChangeListener> itemSetChangeListeners;
@@ -51,8 +54,7 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
public BeanItemContainer(Class<BT> type) throws InstantiationException,
IllegalAccessException {
this.type = type;
- BT pojomodel = type.newInstance();
- model = new BeanItem(pojomodel);
+ model = BeanItem.getPropertyDescriptors(type);
}
/**
@@ -67,8 +69,7 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
public BeanItemContainer(Collection<BT> list)
throws InstantiationException, IllegalAccessException {
type = (Class<BT>) list.iterator().next().getClass();
- BT pojomodel = type.newInstance();
- model = new BeanItem(pojomodel);
+ model = BeanItem.getPropertyDescriptors(type);
int i = 0;
for (BT bt : list) {
addItemAt(i++, bt);
@@ -111,11 +112,11 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
if (allItems.contains(newItemId)) {
return null;
}
- if (newItemId.getClass().isAssignableFrom(type)) {
+ if (type.isAssignableFrom(newItemId.getClass())) {
BT pojo = (BT) newItemId;
// "list" will be updated in filterAll()
allItems.add(index, pojo);
- BeanItem beanItem = new BeanItem(pojo);
+ BeanItem beanItem = new BeanItem(pojo, model);
beanToItem.put(pojo, beanItem);
// add listeners to be able to update filtering on property changes
for (Filter filter : filters) {
@@ -230,7 +231,7 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
@SuppressWarnings("unchecked")
public Collection getContainerPropertyIds() {
- return model.getItemPropertyIds();
+ return model.keySet();
}
public Item getItem(Object itemId) {
@@ -243,7 +244,7 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
}
public Class<?> getType(Object propertyId) {
- return model.getItemProperty(propertyId).getType();
+ return model.get(propertyId).getPropertyType();
}
public boolean removeAllItems() throws UnsupportedOperationException {
diff --git a/src/com/itmill/toolkit/tests/containers/BeanItemContainerTest.java b/src/com/itmill/toolkit/tests/containers/BeanItemContainerTest.java
index cc5b04a699..bbfc72fb02 100644
--- a/src/com/itmill/toolkit/tests/containers/BeanItemContainerTest.java
+++ b/src/com/itmill/toolkit/tests/containers/BeanItemContainerTest.java
@@ -22,10 +22,17 @@ public class BeanItemContainerTest {
for (int i = 0; i < 100; i++) {
col.add(new Hello());
}
+ col.add(new Hello2());
c = new BeanItemContainer<Hello>(col);
- System.out.print(c + " contains " + c.size() + " objects");
+ System.out.println(c + " contains " + c.size() + " objects");
+
+ // test that subclass properties are handled correctly
+ System.out.println(c + " item 0 second = "
+ + c.getContainerProperty(c.getIdByIndex(0), "second"));
+ System.out.println(c + " item 100 second = "
+ + c.getContainerProperty(c.getIdByIndex(100), "second"));
}
@@ -57,4 +64,12 @@ public class BeanItemContainerTest {
}
+ public static class Hello2 extends Hello {
+
+ @Override
+ public String getSecond() {
+ return "second";
+ }
+
+ }
}