]> source.dussan.org Git - vaadin-framework.git/commitdiff
#1061: merge to 6.0 of initial import of BeanItemContainer to the toolkit
authorHenri Sara <henri.sara@itmill.com>
Wed, 1 Apr 2009 11:49:17 +0000 (11:49 +0000)
committerHenri Sara <henri.sara@itmill.com>
Wed, 1 Apr 2009 11:49:17 +0000 (11:49 +0000)
svn changeset:7268/svn branch:6.0

build/build.xml
build/package/eclipse-classpath
src/com/itmill/toolkit/data/util/BeanItemContainer.java [new file with mode: 0644]
src/com/itmill/toolkit/tests/containers/BeanItemContainerTest.java [new file with mode: 0644]

index 38f305c830b20f85196a5e9083202495d6584f2c..04b96fe430366b359c72e6564d43a84ad9f901c5 100644 (file)
                                <exclude name="ITMILL/themes/sampler/**" if="build.sampler.disabled" />
                                <include name="demo/**/*" />
                                <include name="WEB-INF/lib/hsqldb.jar" />
-                               <include name="WEB-INF/lib/beanitemcontainer-20090216.jar" />
                                <include name="ITMILL/themes/**/*" />
                                <include name="META-INF/**/*" />
                        </fileset>
                <mkdir dir="${result-path}/classes" />
                <javac source="1.5" target="1.5" classpathref="compile.classpath.server-side" destdir="${result-path}/classes" debug="true" encoding="UTF-8">
              <src path="${result-path}/src"/>
-                       <classpath>
-                               <pathelement location="WebContent/WEB-INF/lib/beanitemcontainer-20090216.jar" />
-                       </classpath>
              <!-- This seems to be included by default: include name="${toolkit-package}/**"/ -->
              <exclude name="${toolkit-package}/demo/sampler/**" if="build.sampler.disabled" />
              <exclude name="${toolkit-package}/tests/**"/>
index 9cd2ee212bdb143002d16edf9a9dbccbc9cfa314..d5a181374dcfe44b55df7f2672212d242789d2f6 100644 (file)
@@ -3,7 +3,6 @@
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
        <classpathentry kind="src" path="WebContent/WEB-INF/src"/>
        <classpathentry kind="lib" path="WebContent/WEB-INF/lib/itmill-toolkit-<version></version>.jar"/>
-       <classpathentry kind="lib" path="WebContent/WEB-INF/lib/beanitemcontainer-20090216.jar"/>
        <classpathentry kind="lib" path="gwt/gwt-user.jar" />
        <classpathentry kind="lib" path="gwt/gwt-servlet.jar" />
        <classpathentry kind="lib" path="WebContent/demo/lib/reservr/gwt-maps.jar" />
diff --git a/src/com/itmill/toolkit/data/util/BeanItemContainer.java b/src/com/itmill/toolkit/data/util/BeanItemContainer.java
new file mode 100644 (file)
index 0000000..24b1657
--- /dev/null
@@ -0,0 +1,354 @@
+package com.itmill.toolkit.data.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import com.itmill.toolkit.data.Container;
+import com.itmill.toolkit.data.Item;
+import com.itmill.toolkit.data.Property;
+import com.itmill.toolkit.data.Container.Filterable;
+import com.itmill.toolkit.data.Container.Indexed;
+import com.itmill.toolkit.data.Container.ItemSetChangeNotifier;
+import com.itmill.toolkit.data.Container.Sortable;
+
+/**
+ * An {@link ArrayList} backed container for {@link BeanItem}s.
+ * <p>
+ * Bean objects act as identifiers.
+ * 
+ * @param <BT>
+ */
+public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
+        ItemSetChangeNotifier {
+    private ArrayList<BT> list = new ArrayList<BT>();
+    private final HashMap<BT, BeanItem> beanToItem = new HashMap<BT, BeanItem>();
+    private final Class<BT> type;
+    private final BeanItem model;
+    private LinkedList<ItemSetChangeListener> itemSetChangeListeners;
+    private ArrayList<BT> allItems;
+    private HashSet<Filter> filters;
+
+    public BeanItemContainer(Class<BT> type) throws InstantiationException,
+            IllegalAccessException {
+        this.type = type;
+        BT pojomodel = type.newInstance();
+        model = new BeanItem(pojomodel);
+    }
+
+    /**
+     * Constructs BeanItemContainer with given collection of beans in it.
+     * 
+     * @param list
+     *            non empty {@link Collection} of beans.
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     */
+    @SuppressWarnings("unchecked")
+    public BeanItemContainer(Collection<BT> list)
+            throws InstantiationException, IllegalAccessException {
+        type = (Class<BT>) list.iterator().next().getClass();
+        BT pojomodel = type.newInstance();
+        model = new BeanItem(pojomodel);
+        int i = 0;
+        for (BT bt : list) {
+            addItemAt(i++, bt);
+        }
+    }
+
+    public Object addItemAt(int index) throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    @SuppressWarnings("unchecked")
+    public Item addItemAt(int index, Object newItemId)
+            throws UnsupportedOperationException {
+        if (newItemId.getClass().isAssignableFrom(type)) {
+            BT pojo = (BT) newItemId;
+            list.add(index, pojo);
+            BeanItem beanItem = new BeanItem(pojo);
+            beanToItem.put(pojo, beanItem);
+            fireItemSetChange();
+            return beanItem;
+        } else {
+            return null;
+        }
+    }
+
+    public Object getIdByIndex(int index) {
+        return list.get(index);
+    }
+
+    public int indexOfId(Object itemId) {
+        return list.indexOf(itemId);
+    }
+
+    public Object addItemAfter(Object previousItemId)
+            throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    public Item addItemAfter(Object previousItemId, Object newItemId)
+            throws UnsupportedOperationException {
+        int index = indexOfId(previousItemId) + 1;
+        if (index > 0) {
+            addItemAt(index, newItemId);
+        }
+        return null;
+    }
+
+    public Object firstItemId() {
+        return list.iterator().next();
+    }
+
+    public boolean isFirstId(Object itemId) {
+        return firstItemId() == itemId;
+    }
+
+    public boolean isLastId(Object itemId) {
+        return lastItemId() == itemId;
+    }
+
+    public Object lastItemId() {
+        try {
+            return list.get(list.size() - 1);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            return null;
+        }
+    }
+
+    public Object nextItemId(Object itemId) {
+        try {
+            return list.get(list.indexOf(itemId) + 1);
+        } catch (Exception e) {
+            // out of bounds
+            return null;
+        }
+    }
+
+    public Object prevItemId(Object itemId) {
+        try {
+            return list.get(list.indexOf(itemId) - 1);
+        } catch (Exception e) {
+            // out of bounds
+            return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public boolean addContainerProperty(Object propertyId, Class type,
+            Object defaultValue) throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    public Object addItem() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    public Item addItem(Object itemId) throws UnsupportedOperationException {
+        if (list.isEmpty()) {
+            return addItemAt(0, itemId);
+        } else {
+            return addItemAt(indexOfId(lastItemId()) + 1, itemId);
+        }
+    }
+
+    public boolean containsId(Object itemId) {
+        return list.contains(itemId);
+    }
+
+    public Property getContainerProperty(Object itemId, Object propertyId) {
+        return beanToItem.get(itemId).getItemProperty(propertyId);
+    }
+
+    @SuppressWarnings("unchecked")
+    public Collection getContainerPropertyIds() {
+        return model.getItemPropertyIds();
+    }
+
+    public Item getItem(Object itemId) {
+        return beanToItem.get(itemId);
+    }
+
+    @SuppressWarnings("unchecked")
+    public Collection getItemIds() {
+        return (Collection) list.clone();
+    }
+
+    public Class<?> getType(Object propertyId) {
+        return model.getItemProperty(propertyId).getType();
+    }
+
+    public boolean removeAllItems() throws UnsupportedOperationException {
+        list.clear();
+        beanToItem.clear();
+        fireItemSetChange();
+        return true;
+    }
+
+    public boolean removeContainerProperty(Object propertyId)
+            throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    public boolean removeItem(Object itemId)
+            throws UnsupportedOperationException {
+        if (list.contains(itemId)) {
+            beanToItem.remove(itemId);
+            list.remove(itemId);
+            fireItemSetChange();
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public int size() {
+        return list.size();
+    }
+
+    public Collection<Object> getSortableContainerPropertyIds() {
+        LinkedList<Object> sortables = new LinkedList<Object>();
+        for (Object propertyId : getContainerPropertyIds()) {
+            Class<?> propertyType = getType(propertyId);
+            if (Comparable.class.isAssignableFrom(propertyType)) {
+                sortables.add(propertyId);
+            }
+        }
+        return sortables;
+    }
+
+    public void sort(Object[] propertyId, boolean[] ascending) {
+        for (int i = 0; i < ascending.length; i++) {
+            final boolean asc = ascending[i];
+            final Object property = propertyId[i];
+            Collections.sort(list, new Comparator<BT>() {
+                @SuppressWarnings("unchecked")
+                public int compare(BT a, BT b) {
+                    Comparable va = (Comparable) beanToItem.get(a)
+                            .getItemProperty(property).getValue();
+                    Comparable vb = (Comparable) beanToItem.get(b)
+                            .getItemProperty(property).getValue();
+
+                    return asc ? va.compareTo(vb) : vb.compareTo(va);
+                }
+            });
+        }
+    }
+
+    public void addListener(ItemSetChangeListener listener) {
+        if (itemSetChangeListeners == null) {
+            itemSetChangeListeners = new LinkedList<ItemSetChangeListener>();
+        }
+        itemSetChangeListeners.add(listener);
+    }
+
+    public void removeListener(ItemSetChangeListener listener) {
+        if (itemSetChangeListeners != null) {
+            itemSetChangeListeners.remove(listener);
+        }
+    }
+
+    private void fireItemSetChange() {
+        if (itemSetChangeListeners != null) {
+            final Object[] l = itemSetChangeListeners.toArray();
+            final Container.ItemSetChangeEvent event = new Container.ItemSetChangeEvent() {
+                public Container getContainer() {
+                    return BeanItemContainer.this;
+                }
+            };
+            for (int i = 0; i < l.length; i++) {
+                ((ItemSetChangeListener) l[i]).containerItemSetChange(event);
+            }
+        }
+    }
+
+    class Filter {
+
+        private final Object propertyId;
+        private final String filterString;
+        private final boolean onlyMatchPrefix;
+        private final boolean ignoreCase;
+
+        public Filter(Object propertyId, String filterString,
+                boolean ignoreCase, boolean onlyMatchPrefix) {
+            this.propertyId = propertyId;
+            this.ignoreCase = ignoreCase;
+            this.filterString = ignoreCase ? filterString.toLowerCase()
+                    : filterString;
+            this.onlyMatchPrefix = onlyMatchPrefix;
+        }
+
+    }
+
+    @SuppressWarnings("unchecked")
+    public void addContainerFilter(Object propertyId, String filterString,
+            boolean ignoreCase, boolean onlyMatchPrefix) {
+        if (filters == null) {
+            allItems = list;
+            list = (ArrayList<BT>) list.clone();
+            filters = new HashSet<Filter>();
+        }
+        Filter f = new Filter(propertyId, filterString, ignoreCase,
+                onlyMatchPrefix);
+        filter(f);
+        filters.add(f);
+        fireItemSetChange();
+    }
+
+    protected void filter(Filter f) {
+        for (Iterator<BT> iterator = list.iterator(); iterator.hasNext();) {
+            BT bean = iterator.next();
+            try {
+                String value = getContainerProperty(bean, f.propertyId)
+                        .getValue().toString();
+                if (f.ignoreCase) {
+                    value = value.toLowerCase();
+                }
+                if (f.onlyMatchPrefix) {
+                    if (!value.startsWith(f.filterString)) {
+                        iterator.remove();
+                    }
+                } else {
+                    if (!value.contains(f.filterString)) {
+                        iterator.remove();
+                    }
+                }
+            } catch (Exception e) {
+                iterator.remove();
+            }
+        }
+    }
+
+    public void removeAllContainerFilters() {
+        if (filters != null) {
+            filters = null;
+            list = allItems;
+            fireItemSetChange();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public void removeContainerFilters(Object propertyId) {
+        if (filters != null) {
+            for (Iterator<Filter> iterator = filters.iterator(); iterator
+                    .hasNext();) {
+                Filter f = iterator.next();
+                if (f.propertyId.equals(propertyId)) {
+                    iterator.remove();
+                }
+            }
+            list = (ArrayList<BT>) list.clone();
+            for (Filter f : filters) {
+                filter(f);
+            }
+            fireItemSetChange();
+        }
+    }
+
+}
diff --git a/src/com/itmill/toolkit/tests/containers/BeanItemContainerTest.java b/src/com/itmill/toolkit/tests/containers/BeanItemContainerTest.java
new file mode 100644 (file)
index 0000000..7cfb170
--- /dev/null
@@ -0,0 +1,60 @@
+package com.itmill.toolkit.tests.containers;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+import com.itmill.toolkit.data.util.BeanItemContainer;
+
+public class BeanItemContainerTest {
+
+    /**
+     * Test class for BeanItemContainer
+     * 
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     */
+    public static void main(String[] args) throws InstantiationException,
+            IllegalAccessException {
+        BeanItemContainer<Hello> c = new BeanItemContainer<Hello>(Hello.class);
+        c.addItem(new Hello());
+
+        Collection<Hello> col = new LinkedList<Hello>();
+        for (int i = 0; i < 100; i++) {
+            col.add(new Hello());
+        }
+
+        c = new BeanItemContainer<Hello>(col);
+
+        System.out.print(c + " contains " + c.size() + "objects");
+
+    }
+
+    public static class Hello {
+
+        public String first;
+        public String second;
+
+        public Hello() {
+            first = "f";
+            second = "l";
+        }
+
+        public String getFirst() {
+            return first;
+        }
+
+        public void setFirst(String first) {
+            this.first = first;
+        }
+
+        public String getSecond() {
+            return second;
+        }
+
+        public void setSecond(String second) {
+            this.second = second;
+        }
+
+    }
+
+}