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;
*
*/
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) {
}
}
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) {
}
}
this(bean, Arrays.asList(propertyIds));
}
+ /**
+ * <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.
*
package com.itmill.toolkit.data.util;
+import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
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;
* 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>
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;
public BeanItemContainer(Class<BT> type) throws InstantiationException,
IllegalAccessException {
this.type = type;
- BT pojomodel = type.newInstance();
- model = new BeanItem(pojomodel);
+ model = BeanItem.getPropertyDescriptors(type);
}
/**
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);
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) {
@SuppressWarnings("unchecked")
public Collection getContainerPropertyIds() {
- return model.getItemPropertyIds();
+ return model.keySet();
}
public Item getItem(Object itemId) {
}
public Class<?> getType(Object propertyId) {
- return model.getItemProperty(propertyId).getType();
+ return model.get(propertyId).getPropertyType();
}
public boolean removeAllItems() throws UnsupportedOperationException {