]> source.dussan.org Git - vaadin-framework.git/commitdiff
#6074 bean property based item id resolver for BeanContainer
authorHenri Sara <henri.sara@itmill.com>
Wed, 1 Dec 2010 15:14:18 +0000 (15:14 +0000)
committerHenri Sara <henri.sara@itmill.com>
Wed, 1 Dec 2010 15:14:18 +0000 (15:14 +0000)
svn changeset:16256/svn branch:6.5

src/com/vaadin/data/util/AbstractBeanContainer.java
src/com/vaadin/data/util/BeanContainer.java
tests/src/com/vaadin/tests/server/container/BeanContainerTest.java

index 4708af2a08a2c9f555ea4dee6fd489ec1b8e6a05..499f8593fa9f4d3231a1f23a25fa592764ce331c 100644 (file)
@@ -6,6 +6,8 @@ package com.vaadin.data.util;
 import java.beans.PropertyDescriptor;
 import java.io.IOException;
 import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -84,6 +86,62 @@ public abstract class AbstractBeanContainer<IDTYPE, BT> implements Indexed,
         public IDTYPE getIdForBean(BT bean);
     }
 
+    /**
+     * A item identifier resolver that returns the value of a bean property.
+     * 
+     * The bean must have a getter for the property, and the getter must return
+     * an object of type IDTYPE.
+     */
+    protected class PropertyBasedBeanIdResolver implements
+            BeanIdResolver<IDTYPE, BT> {
+
+        private final Object propertyId;
+        private transient Method getMethod;
+
+        public PropertyBasedBeanIdResolver(Object propertyId) {
+            if (propertyId == null) {
+                throw new IllegalArgumentException(
+                        "Property identifier must not be null");
+            }
+            this.propertyId = propertyId;
+            if (getGetter() == null) {
+                throw new IllegalArgumentException(
+                        "Missing accessor for property " + propertyId);
+            }
+        }
+
+        private Method getGetter() {
+            if (getMethod == null) {
+                try {
+                    String propertyName = propertyId.toString();
+                    if (Character.isLowerCase(propertyName.charAt(0))) {
+                        final char[] buf = propertyName.toCharArray();
+                        buf[0] = Character.toUpperCase(buf[0]);
+                        propertyName = new String(buf);
+                    }
+
+                    getMethod = getBeanType().getMethod("get" + propertyName,
+                            new Class[] {});
+                } catch (NoSuchMethodException ignored) {
+                    throw new IllegalArgumentException();
+                }
+            }
+            return getMethod;
+        }
+
+        @SuppressWarnings("unchecked")
+        public IDTYPE getIdForBean(BT bean) throws IllegalArgumentException {
+            try {
+                return (IDTYPE) getGetter().invoke(bean);
+            } catch (IllegalAccessException e) {
+                throw new IllegalArgumentException(e);
+            } catch (InvocationTargetException e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+
+    }
+
     /**
      * The resolver that finds the item ID for a bean, or null not to use
      * automatic resolving.
@@ -1020,4 +1078,16 @@ public abstract class AbstractBeanContainer<IDTYPE, BT> implements Indexed,
         return beanIdResolver;
     }
 
+    /**
+     * Create an item identifier resolver using a named bean property.
+     * 
+     * @param propertyId
+     *            property identifier, which must map to a getter in BT
+     * @return created resolver
+     */
+    protected BeanIdResolver<IDTYPE, BT> createBeanPropertyResolver(
+            Object propertyId) {
+        return new PropertyBasedBeanIdResolver(propertyId);
+    }
+
 }
index 911e696229918f06b4a40f30008405777277d8e8..dbfc197674e4cb2d75d4d87e2d6b5e1630ced132 100644 (file)
@@ -117,9 +117,19 @@ public class BeanContainer<IDTYPE, BT> extends
 
     // automatic item id resolution
 
+    /**
+     * Sets the bean id resolver to use a property of the beans as the
+     * identifier.
+     * 
+     * @param propertyId
+     *            the identifier of the property to use to find item identifiers
+     */
+    public void setBeanIdProperty(Object propertyId) {
+        setIdResolver(createBeanPropertyResolver(propertyId));
+    }
+
     @Override
-    public void setIdResolver(
-            com.vaadin.data.util.AbstractBeanContainer.BeanIdResolver<IDTYPE, BT> beanIdResolver) {
+    public void setIdResolver(BeanIdResolver<IDTYPE, BT> beanIdResolver) {
         super.setIdResolver(beanIdResolver);
     }
 
index c683e4f5984ecdc29bc1edda8ee1bfbe8ab8d335..c8ca3cae2acb8a9c11287782e780ad7e2ff9b375 100644 (file)
@@ -377,4 +377,26 @@ public class BeanContainerTest extends AbstractBeanContainerTest {
         assertEquals(0, container.size());
     }
 
+    public void testAddBeanWithPropertyResolver() {
+        BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+                Person.class);
+        container.setBeanIdProperty("name");
+
+        assertNotNull(container.addBean(new Person("John")));
+        assertNotNull(container.addBeanAfter(null, new Person("Jane")));
+        assertNotNull(container.addBeanAt(0, new Person("Jack")));
+
+        container.addAll(Arrays.asList(new Person[] { new Person("Jill"),
+                new Person("Joe") }));
+
+        assertTrue(container.containsId("John"));
+        assertTrue(container.containsId("Jane"));
+        assertTrue(container.containsId("Jack"));
+        assertTrue(container.containsId("Jill"));
+        assertTrue(container.containsId("Joe"));
+        assertEquals(3, container.indexOfId("Jill"));
+        assertEquals(4, container.indexOfId("Joe"));
+        assertEquals(5, container.size());
+    }
+
 }