From: Henri Sara Date: Wed, 1 Apr 2009 11:49:17 +0000 (+0000) Subject: #1061: merge to 6.0 of initial import of BeanItemContainer to the toolkit X-Git-Tag: 6.7.0.beta1~3038 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ceddbebb8c2ff96e0e27448fc2177f2422a37026;p=vaadin-framework.git #1061: merge to 6.0 of initial import of BeanItemContainer to the toolkit svn changeset:7268/svn branch:6.0 --- 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 @@ - @@ -693,9 +692,6 @@ - - - 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 @@ - 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. + *

+ * Bean objects act as identifiers. + * + * @param + */ +public class BeanItemContainer implements Indexed, Sortable, Filterable, + ItemSetChangeNotifier { + private ArrayList list = new ArrayList(); + private final HashMap beanToItem = new HashMap(); + private final Class type; + private final BeanItem model; + private LinkedList itemSetChangeListeners; + private ArrayList allItems; + private HashSet filters; + + public BeanItemContainer(Class 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 list) + throws InstantiationException, IllegalAccessException { + type = (Class) 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 getSortableContainerPropertyIds() { + LinkedList sortables = new LinkedList(); + 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() { + @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(); + } + 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) list.clone(); + filters = new HashSet(); + } + Filter f = new Filter(propertyId, filterString, ignoreCase, + onlyMatchPrefix); + filter(f); + filters.add(f); + fireItemSetChange(); + } + + protected void filter(Filter f) { + for (Iterator 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 iterator = filters.iterator(); iterator + .hasNext();) { + Filter f = iterator.next(); + if (f.propertyId.equals(propertyId)) { + iterator.remove(); + } + } + list = (ArrayList) 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 c = new BeanItemContainer(Hello.class); + c.addItem(new Hello()); + + Collection col = new LinkedList(); + for (int i = 0; i < 100; i++) { + col.add(new Hello()); + } + + c = new BeanItemContainer(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; + } + + } + +}