summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenri Sara <henri.sara@itmill.com>2009-04-01 11:49:17 +0000
committerHenri Sara <henri.sara@itmill.com>2009-04-01 11:49:17 +0000
commitceddbebb8c2ff96e0e27448fc2177f2422a37026 (patch)
treed13dac73bb4fb210f54f5b13b338e83eaa5cc429
parent46f0510fcccca3e516b083d397de5a7715ed0336 (diff)
downloadvaadin-framework-ceddbebb8c2ff96e0e27448fc2177f2422a37026.tar.gz
vaadin-framework-ceddbebb8c2ff96e0e27448fc2177f2422a37026.zip
#1061: merge to 6.0 of initial import of BeanItemContainer to the toolkit
svn changeset:7268/svn branch:6.0
-rw-r--r--build/build.xml4
-rw-r--r--build/package/eclipse-classpath1
-rw-r--r--src/com/itmill/toolkit/data/util/BeanItemContainer.java354
-rw-r--r--src/com/itmill/toolkit/tests/containers/BeanItemContainerTest.java60
4 files changed, 414 insertions, 5 deletions
diff --git a/build/build.xml b/build/build.xml
index 38f305c830..04b96fe430 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -652,7 +652,6 @@
<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>
@@ -693,9 +692,6 @@
<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/**"/>
diff --git a/build/package/eclipse-classpath b/build/package/eclipse-classpath
index 9cd2ee212b..d5a181374d 100644
--- a/build/package/eclipse-classpath
+++ b/build/package/eclipse-classpath
@@ -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
index 0000000000..24b16573fc
--- /dev/null
+++ b/src/com/itmill/toolkit/data/util/BeanItemContainer.java
@@ -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
index 0000000000..7cfb17041d
--- /dev/null
+++ b/src/com/itmill/toolkit/tests/containers/BeanItemContainerTest.java
@@ -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;
+ }
+
+ }
+
+}