summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHenri Sara <henri.sara@itmill.com>2010-11-25 14:14:34 +0000
committerHenri Sara <henri.sara@itmill.com>2010-11-25 14:14:34 +0000
commit18c306c7c4e28d9399ad236bdcbb7810c8c5c0a1 (patch)
tree4f9aa166f00f96e8ec1e2e7e41b50cd6c83d4c65 /src
parente8f90db0eb1ac1cb319af6d18f360d9e271550a2 (diff)
downloadvaadin-framework-18c306c7c4e28d9399ad236bdcbb7810c8c5c0a1.tar.gz
vaadin-framework-18c306c7c4e28d9399ad236bdcbb7810c8c5c0a1.zip
Refactor BeanItemContainer, splitting out the superclass AbstractBeanContainer that does not assume that the item ids are the beans.
Addresses #5713 (partly) BeanItemContainer should not require the bean to implement equals() and hashCode() in a certain way #5233 and #5946 Collection constructor of BeanItemContainer is problematic svn changeset:16162/svn branch:6.5
Diffstat (limited to 'src')
-rw-r--r--src/com/vaadin/data/util/AbstractBeanContainer.java823
-rw-r--r--src/com/vaadin/data/util/BeanItemContainer.java784
2 files changed, 908 insertions, 699 deletions
diff --git a/src/com/vaadin/data/util/AbstractBeanContainer.java b/src/com/vaadin/data/util/AbstractBeanContainer.java
new file mode 100644
index 0000000000..47743cced2
--- /dev/null
+++ b/src/com/vaadin/data/util/AbstractBeanContainer.java
@@ -0,0 +1,823 @@
+/*
+@ITMillApache2LicenseForJavaFiles@
+ */
+package com.vaadin.data.util;
+
+import java.beans.PropertyDescriptor;
+import java.io.IOException;
+import java.io.Serializable;
+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;
+import java.util.Set;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Container.Filterable;
+import com.vaadin.data.Container.Indexed;
+import com.vaadin.data.Container.ItemSetChangeNotifier;
+import com.vaadin.data.Container.Sortable;
+import com.vaadin.data.Property;
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.data.Property.ValueChangeNotifier;
+
+/**
+ * An abstract base class for in-memory containers for JavaBeans.
+ *
+ * <p>
+ * The properties of the container are determined automatically by introspecting
+ * the used JavaBean class. Only beans of the same type can be added to the
+ * container.
+ * </p>
+ *
+ * <p>
+ * Subclasses should implement adding items to the container, typically calling
+ * the protected methods {@link #addItem(Object, Object)},
+ * {@link #addItemAfter(Object, Object, Object)} and
+ * {@link #addItemAt(int, Object, Object)}, and if necessary,
+ * {@link #internalAddAt(int, Object, Object)} and
+ * {@link #internalIndexOf(Object)}.
+ * </p>
+ *
+ * <p>
+ * It is not possible to add additional properties to the container and nested
+ * bean properties are not supported.
+ * </p>
+ *
+ * @param <IDTYPE>
+ * The type of the item identifier
+ * @param <BT>
+ * The type of the Bean
+ *
+ * @since 6.5
+ */
+public abstract class AbstractBeanContainer<IDTYPE, BT> implements Indexed,
+ Filterable, Sortable, ValueChangeListener, ItemSetChangeNotifier {
+
+ /**
+ * The item sorter which is used for sorting the container.
+ */
+ private ItemSorter itemSorter = new DefaultItemSorter();
+
+ /**
+ * Filters currently applied to the container.
+ */
+ private Set<Filter> filters = new HashSet<Filter>();
+
+ /**
+ * The filteredItems variable contains the ids for items that are visible
+ * outside the container. If filters are enabled this contains a subset of
+ * allItems, if no filters are set this contains the same items as allItems.
+ */
+ private ListSet<IDTYPE> filteredItemIds = new ListSet<IDTYPE>();
+
+ /**
+ * The allItems variable always contains the ids for all the items in the
+ * container. Some or all of these are also in the filteredItems list.
+ */
+ private ListSet<IDTYPE> allItemIds = new ListSet<IDTYPE>();
+
+ /**
+ * Maps all item ids in the container (including filtered) to their
+ * corresponding BeanItem.
+ */
+ private final Map<IDTYPE, BeanItem<BT>> itemIdToItem = new HashMap<IDTYPE, BeanItem<BT>>();
+
+ /**
+ * The type of the beans in the container.
+ */
+ private final Class<? extends BT> type;
+
+ /**
+ * A description of the properties found in beans of type {@link #type}.
+ * Determines the property ids that are present in the container.
+ */
+ private transient LinkedHashMap<String, PropertyDescriptor> model;
+
+ /**
+ * Collection of listeners interested in
+ * {@link Container.ItemSetChangeEvent ItemSetChangeEvent} events.
+ */
+ private List<ItemSetChangeListener> itemSetChangeListeners;
+
+ /**
+ * Constructs a {@code AbstractBeanContainer} for beans of the given type.
+ *
+ * @param type
+ * the type of the beans that will be added to the container.
+ * @throws IllegalArgumentException
+ * If {@code type} is null
+ */
+ public AbstractBeanContainer(Class<? extends BT> type) {
+ if (type == null) {
+ throw new IllegalArgumentException(
+ "The bean type passed to AbstractBeanContainer must not be null");
+ }
+ this.type = type;
+ model = BeanItem.getPropertyDescriptors(type);
+ }
+
+ /**
+ * A special deserialization method that resolves {@link #model} is needed
+ * as PropertyDescriptor is not {@link Serializable}.
+ */
+ private void readObject(java.io.ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+ in.defaultReadObject();
+ model = BeanItem.getPropertyDescriptors(type);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container#getType(java.lang.Object)
+ */
+ public Class<?> getType(Object propertyId) {
+ return model.get(propertyId).getPropertyType();
+ }
+
+ /**
+ * Create a BeanItem for a bean using pre-parsed bean metadata (based on
+ * {@link #getBeanType()}).
+ *
+ * @param bean
+ * @return
+ */
+ protected BeanItem<BT> createBeanItem(BT bean) {
+ return new BeanItem<BT>(bean, model);
+ }
+
+ /**
+ * Returns the type of beans this Container can contain.
+ *
+ * This comes from the bean type constructor parameter, and bean metadata
+ * (including container properties) is based on this.
+ *
+ * @return
+ */
+ public Class<? extends BT> getBeanType() {
+ return type;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container#getContainerPropertyIds()
+ */
+ public Collection<String> getContainerPropertyIds() {
+ return model.keySet();
+ }
+
+ /**
+ * Unsupported operation. Properties are determined by the introspecting the
+ * bean class.
+ */
+ public boolean addContainerProperty(Object propertyId, Class<?> type,
+ Object defaultValue) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unsupported operation. Properties are determined by the introspecting the
+ * bean class.
+ */
+ public boolean removeContainerProperty(Object propertyId)
+ throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.data.Container.ItemSetChangeNotifier#addListener(com.vaadin
+ * .data.Container.ItemSetChangeListener)
+ */
+ public void addListener(ItemSetChangeListener listener) {
+ if (itemSetChangeListeners == null) {
+ itemSetChangeListeners = new LinkedList<ItemSetChangeListener>();
+ }
+ itemSetChangeListeners.add(listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.data.Container.ItemSetChangeNotifier#removeListener(com.vaadin
+ * .data.Container.ItemSetChangeListener)
+ */
+ public void removeListener(ItemSetChangeListener listener) {
+ if (itemSetChangeListeners != null) {
+ itemSetChangeListeners.remove(listener);
+ }
+ }
+
+ /**
+ * Send an ItemSetChange event to all listeners.
+ */
+ protected void fireItemSetChange() {
+ if (itemSetChangeListeners != null) {
+ final Container.ItemSetChangeEvent event = new Container.ItemSetChangeEvent() {
+ public Container getContainer() {
+ return AbstractBeanContainer.this;
+ }
+ };
+ for (ItemSetChangeListener listener : itemSetChangeListeners) {
+ listener.containerItemSetChange(event);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container#size()
+ */
+ public int size() {
+ return filteredItemIds.size();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container#removeAllItems()
+ */
+ public boolean removeAllItems() {
+ allItemIds.clear();
+ filteredItemIds.clear();
+ // detach listeners from all BeanItems
+ for (BeanItem<BT> item : itemIdToItem.values()) {
+ removeAllValueChangeListeners(item);
+ }
+ itemIdToItem.clear();
+ fireItemSetChange();
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container#containsId(java.lang.Object)
+ */
+ public boolean containsId(Object itemId) {
+ // only look at visible items after filtering
+ return filteredItemIds.contains(itemId);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container#getItem(java.lang.Object)
+ */
+ public BeanItem<BT> getItem(Object itemId) {
+ return itemIdToItem.get(itemId);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container#getItemIds()
+ */
+ @SuppressWarnings("unchecked")
+ public Collection<IDTYPE> getItemIds() {
+ return (Collection<IDTYPE>) filteredItemIds.clone();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container#getContainerProperty(java.lang.Object,
+ * java.lang.Object)
+ */
+ public Property getContainerProperty(Object itemId, Object propertyId) {
+ BeanItem<BT> item = getItem(itemId);
+ if (item == null) {
+ return null;
+ }
+ return item.getItemProperty(propertyId);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container#removeItem(java.lang.Object)
+ */
+ public boolean removeItem(Object itemId) {
+ if (!allItemIds.remove(itemId)) {
+ return false;
+ }
+ // detach listeners from Item
+ removeAllValueChangeListeners(getItem(itemId));
+ // remove item
+ itemIdToItem.remove(itemId);
+ filteredItemIds.remove(itemId);
+ fireItemSetChange();
+ return true;
+ }
+
+ /**
+ * Re-filter the container when one of the monitored properties changes.
+ */
+ public void valueChange(ValueChangeEvent event) {
+ // if a property that is used in a filter is changed, refresh filtering
+ filterAll();
+ }
+
+ /**
+ * Filter the view to recreate the visible item list from the unfiltered
+ * items, and send a notification if the set of visible items changed in any
+ * way.
+ */
+ protected void filterAll() {
+ // avoid notification if the filtering had no effect
+ List<IDTYPE> originalItems = filteredItemIds;
+ // it is somewhat inefficient to do a (shallow) clone() every time
+ filteredItemIds = (ListSet<IDTYPE>) allItemIds.clone();
+ for (Filter f : filters) {
+ filter(f);
+ }
+ // check if exactly the same items are there after filtering to avoid
+ // unnecessary notifications
+ // this may be slow in some cases as it uses BT.equals()
+ if (!originalItems.equals(filteredItemIds)) {
+ fireItemSetChange();
+ }
+ }
+
+ /**
+ * Returns an unmodifiable collection of filters in use by the container.
+ *
+ * @return
+ */
+ protected Set<Filter> getFilters() {
+ return Collections.unmodifiableSet(filters);
+ }
+
+ /**
+ * Remove (from the filtered list) any items that do not match the given
+ * filter.
+ *
+ * @param f
+ * The filter used to determine if items should be removed
+ */
+ protected void filter(Filter f) {
+ Iterator<IDTYPE> iterator = filteredItemIds.iterator();
+ while (iterator.hasNext()) {
+ IDTYPE itemId = iterator.next();
+ if (!f.passesFilter(getItem(itemId))) {
+ iterator.remove();
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.data.Container.Filterable#addContainerFilter(java.lang.Object,
+ * java.lang.String, boolean, boolean)
+ */
+ public void addContainerFilter(Object propertyId, String filterString,
+ boolean ignoreCase, boolean onlyMatchPrefix) {
+ if (filters.isEmpty()) {
+ filteredItemIds = (ListSet<IDTYPE>) allItemIds.clone();
+ }
+ // listen to change events to be able to update filtering
+ for (BeanItem<BT> item : itemIdToItem.values()) {
+ addValueChangeListener(item, propertyId);
+ }
+ Filter f = new Filter(propertyId, filterString, ignoreCase,
+ onlyMatchPrefix);
+ filter(f);
+ filters.add(f);
+ fireItemSetChange();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Filterable#removeAllContainerFilters()
+ */
+ public void removeAllContainerFilters() {
+ if (!filters.isEmpty()) {
+ filters = new HashSet<Filter>();
+ // stop listening to change events for any property
+ for (BeanItem<BT> item : itemIdToItem.values()) {
+ removeAllValueChangeListeners(item);
+ }
+ filterAll();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.data.Container.Filterable#removeContainerFilters(java.lang
+ * .Object)
+ */
+ public void removeContainerFilters(Object propertyId) {
+ if (!filters.isEmpty()) {
+ boolean filteringChanged = false;
+ for (Iterator<Filter> iterator = filters.iterator(); iterator
+ .hasNext();) {
+ Filter f = iterator.next();
+ if (f.propertyId.equals(propertyId)) {
+ iterator.remove();
+ filteringChanged = true;
+ }
+ }
+ if (filteringChanged) {
+ // stop listening to change events for the property
+ for (BeanItem<BT> item : itemIdToItem.values()) {
+ removeValueChangeListener(item, propertyId);
+ }
+ filterAll();
+ }
+ }
+ }
+
+ /**
+ * Make this container listen to the given property provided it notifies
+ * when its value changes.
+ *
+ * @param beanItem
+ * The BeanItem that contains the property
+ * @param propertyId
+ * The id of the property
+ */
+ private void addValueChangeListener(BeanItem<BT> beanItem, Object propertyId) {
+ Property property = beanItem.getItemProperty(propertyId);
+ if (property instanceof ValueChangeNotifier) {
+ // avoid multiple notifications for the same property if
+ // multiple filters are in use
+ ValueChangeNotifier notifier = (ValueChangeNotifier) property;
+ notifier.removeListener(this);
+ notifier.addListener(this);
+ }
+ }
+
+ /**
+ * Remove this container as a listener for the given property.
+ *
+ * @param item
+ * The BeanItem that contains the property
+ * @param propertyId
+ * The id of the property
+ */
+ private void removeValueChangeListener(BeanItem<BT> item, Object propertyId) {
+ Property property = item.getItemProperty(propertyId);
+ if (property instanceof ValueChangeNotifier) {
+ ((ValueChangeNotifier) property).removeListener(this);
+ }
+ }
+
+ /**
+ * Remove this contains as a listener for all the properties in the given
+ * BeanItem.
+ *
+ * @param item
+ * The BeanItem that contains the properties
+ */
+ private void removeAllValueChangeListeners(BeanItem<BT> item) {
+ for (Object propertyId : item.getItemPropertyIds()) {
+ removeValueChangeListener(item, propertyId);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object)
+ */
+ public IDTYPE nextItemId(Object itemId) {
+ int index = indexOfId(itemId);
+ if (index >= 0 && index < size() - 1) {
+ return getIdByIndex(index + 1);
+ } else {
+ // out of bounds
+ return null;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object)
+ */
+ public IDTYPE prevItemId(Object itemId) {
+ int index = indexOfId(itemId);
+ if (index > 0) {
+ return getIdByIndex(index - 1);
+ } else {
+ // out of bounds
+ return null;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Ordered#firstItemId()
+ */
+ public IDTYPE firstItemId() {
+ if (size() > 0) {
+ return getIdByIndex(0);
+ } else {
+ return null;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Ordered#lastItemId()
+ */
+ public IDTYPE lastItemId() {
+ if (size() > 0) {
+ return getIdByIndex(size() - 1);
+ } else {
+ return null;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object)
+ */
+ public boolean isFirstId(Object itemId) {
+ return firstItemId() == itemId;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object)
+ */
+ public boolean isLastId(Object itemId) {
+ return lastItemId() == itemId;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Indexed#getIdByIndex(int)
+ */
+ public IDTYPE getIdByIndex(int index) {
+ return filteredItemIds.get(index);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Indexed#indexOfId(java.lang.Object)
+ */
+ public int indexOfId(Object itemId) {
+ return filteredItemIds.indexOf(itemId);
+ }
+
+ /**
+ * Unsupported operation. Use other methods to add items.
+ */
+ public Object addItemAfter(Object previousItemId)
+ throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unsupported operation. Beans should be added through
+ * {@code addItemAt(int, ...)}.
+ */
+ public Object addItemAt(int index) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds()
+ */
+ public Collection<Object> getSortableContainerPropertyIds() {
+ LinkedList<Object> sortables = new LinkedList<Object>();
+ for (Object propertyId : getContainerPropertyIds()) {
+ Class<?> propertyType = getType(propertyId);
+ if (Comparable.class.isAssignableFrom(propertyType)
+ || propertyType.isPrimitive()) {
+ sortables.add(propertyId);
+ }
+ }
+ return sortables;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Sortable#sort(java.lang.Object[],
+ * boolean[])
+ */
+ public void sort(Object[] propertyId, boolean[] ascending) {
+ itemSorter.setSortProperties(this, propertyId, ascending);
+
+ doSort();
+
+ // notifies if anything changes in the filtered list, including order
+ filterAll();
+ }
+
+ /**
+ * Perform the sorting of the data structures in the container. This is
+ * invoked when the <code>itemSorter</code> has been prepared for the sort
+ * operation. Typically this method calls
+ * <code>Collections.sort(aCollection, getItemSorter())</code> on all arrays
+ * (containing item ids) that need to be sorted.
+ *
+ */
+ protected void doSort() {
+ Collections.sort(allItemIds, getItemSorter());
+ }
+
+ /**
+ * Returns the ItemSorter that is used for sorting the container.
+ *
+ * @see #setItemSorter(ItemSorter)
+ *
+ * @return The ItemSorter that is used for sorting the container
+ */
+ public ItemSorter getItemSorter() {
+ return itemSorter;
+ }
+
+ /**
+ * Sets the ItemSorter that is used for sorting the container. The
+ * {@link ItemSorter#compare(Object, Object)} method is called to compare
+ * two beans (item ids).
+ *
+ * @param itemSorter
+ * The ItemSorter to use when sorting the container
+ */
+ public void setItemSorter(ItemSorter itemSorter) {
+ this.itemSorter = itemSorter;
+ }
+
+ /**
+ * Unsupported operation. See subclasses of {@link AbstractBeanContainer}
+ * for the correct way to add items.
+ */
+ public Object addItem() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Adds the bean to all internal data structures at the given position.
+ * Fails if the bean is already in the container or is not assignable to the
+ * correct type. Returns a new BeanItem if the bean was added successfully.
+ *
+ * <p>
+ * Caller should call {@link #filterAll()} after calling this method to
+ * ensure the filtered list is updated.
+ * </p>
+ *
+ * For internal use by subclasses only.
+ *
+ * @param position
+ * The position at which the bean should be inserted in the
+ * unfiltered collection of items
+ * @param itemId
+ * The item identifier for the bean to insert
+ * @param bean
+ * The bean to insert
+ *
+ * @return true if the bean was added successfully, false otherwise
+ */
+ protected BeanItem<BT> internalAddAt(int position, IDTYPE itemId, BT bean) {
+ // Make sure that the item has not been added previously
+ if (allItemIds.contains(bean)) {
+ return null;
+ }
+
+ if (!getBeanType().isAssignableFrom(bean.getClass())) {
+ return null;
+ }
+
+ // "filteredList" will be updated in filterAll() which should be invoked
+ // by the caller after calling this method.
+ allItemIds.add(position, itemId);
+ BeanItem<BT> beanItem = createBeanItem(bean);
+ itemIdToItem.put(itemId, beanItem);
+
+ // add listeners to be able to update filtering on property
+ // changes
+ for (Filter filter : getFilters()) {
+ // addValueChangeListener avoids adding duplicates
+ addValueChangeListener(beanItem, filter.propertyId);
+ }
+
+ return beanItem;
+ }
+
+ /**
+ * Returns the index of an item within the unfiltered collection of items.
+ *
+ * For internal use in subclasses only.
+ *
+ * @param itemId
+ * @return
+ */
+ protected int internalIndexOf(IDTYPE itemId) {
+ return allItemIds.indexOf(itemId);
+ }
+
+ /**
+ * Adds a bean at the given index of the internal (unfiltered) list.
+ * <p>
+ * The item is also added in the visible part of the list if it passes the
+ * filters.
+ * </p>
+ *
+ * @param index
+ * Internal index to add the new item.
+ * @param newItemId
+ * Id of the new item to be added.
+ * @param bean
+ * bean to be added
+ * @return Returns new item or null if the operation fails.
+ */
+ protected BeanItem<BT> addItemAtInternalIndex(int index, IDTYPE newItemId,
+ BT bean) {
+ BeanItem<BT> beanItem = internalAddAt(index, newItemId, bean);
+ if (beanItem != null) {
+ filterAll();
+ }
+
+ return beanItem;
+ }
+
+ /**
+ * Adds the bean to the Container.
+ *
+ * @see com.vaadin.data.Container#addItem(Object)
+ */
+ protected BeanItem<BT> addItem(IDTYPE itemId, BT bean) {
+ if (size() > 0) {
+ // add immediately after last visible item
+ int lastIndex = internalIndexOf(lastItemId());
+ return addItemAtInternalIndex(lastIndex + 1, itemId, bean);
+ } else {
+ return addItemAtInternalIndex(0, itemId, bean);
+ }
+ }
+
+ /**
+ * Adds the bean after the given bean.
+ *
+ * @see com.vaadin.data.Container.Ordered#addItemAfter(Object, Object)
+ */
+ protected BeanItem<BT> addItemAfter(IDTYPE previousItemId,
+ IDTYPE newItemId, BT bean) {
+ // only add if the previous item is visible
+ if (previousItemId == null) {
+ return addItemAtInternalIndex(0, newItemId, bean);
+ } else if (containsId(previousItemId)) {
+ return addItemAtInternalIndex(internalIndexOf(previousItemId) + 1,
+ newItemId, bean);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Adds a new bean at the given index.
+ *
+ * The bean is used both as the item contents and as the item identifier.
+ *
+ * @param index
+ * Index at which the bean should be added.
+ * @param newItemId
+ * The item id for the bean to add to the container.
+ * @param bean
+ * The bean to add to the container.
+ *
+ * @return Returns the new BeanItem or null if the operation fails.
+ */
+ protected BeanItem<BT> addItemAt(int index, IDTYPE newItemId, BT bean)
+ throws UnsupportedOperationException {
+ if (index < 0 || index > size()) {
+ return null;
+ } else if (index == 0) {
+ // add before any item, visible or not
+ return addItemAtInternalIndex(0, newItemId, bean);
+ } else {
+ // if index==size(), adds immediately after last visible item
+ return addItemAfter(getIdByIndex(index - 1), newItemId, bean);
+ }
+ }
+
+}
diff --git a/src/com/vaadin/data/util/BeanItemContainer.java b/src/com/vaadin/data/util/BeanItemContainer.java
index abfb3bc9a9..005b2007f7 100644
--- a/src/com/vaadin/data/util/BeanItemContainer.java
+++ b/src/com/vaadin/data/util/BeanItemContainer.java
@@ -3,29 +3,7 @@
*/
package com.vaadin.data.util;
-import java.beans.PropertyDescriptor;
-import java.io.IOException;
-import java.io.Serializable;
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;
-import java.util.Set;
-
-import com.vaadin.data.Container;
-import com.vaadin.data.Container.Filterable;
-import com.vaadin.data.Container.Indexed;
-import com.vaadin.data.Container.ItemSetChangeNotifier;
-import com.vaadin.data.Container.Sortable;
-import com.vaadin.data.Property;
-import com.vaadin.data.Property.ValueChangeEvent;
-import com.vaadin.data.Property.ValueChangeListener;
-import com.vaadin.data.Property.ValueChangeNotifier;
/**
* An in-memory container for JavaBeans.
@@ -56,65 +34,7 @@ import com.vaadin.data.Property.ValueChangeNotifier;
* @since 5.4
*/
@SuppressWarnings("serial")
-public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
- ItemSetChangeNotifier, ValueChangeListener {
- /**
- * The filteredItems variable contains the items that are visible outside
- * the container. If filters are enabled this contains a subset of allItems,
- * if no filters are set this contains the same items as allItems.
- */
- private ListSet<BT> filteredItems = new ListSet<BT>();
-
- /**
- * The allItems variable always contains all the items in the container.
- * Some or all of these are also in the filteredItems list.
- */
- private ListSet<BT> allItems = new ListSet<BT>();
-
- /**
- * Maps all beans (item ids) in the container (including filtered) to their
- * corresponding BeanItem. This requires the beans to implement
- * {@link Object#equals(Object)} and {@link Object#hashCode()} so it is not
- * affected by the contents of the bean.
- */
- private final Map<BT, BeanItem<BT>> beanToItem = new HashMap<BT, BeanItem<BT>>();
-
- /**
- * The type of the beans in the container.
- */
- private final Class<? extends BT> type;
-
- /**
- * A description of the properties found in beans of type {@link #type}.
- * Determines the property ids that are present in the container.
- */
- private transient LinkedHashMap<String, PropertyDescriptor> model;
-
- /**
- * Collection of listeners interested in
- * {@link Container.ItemSetChangeEvent ItemSetChangeEvent} events.
- */
- private List<ItemSetChangeListener> itemSetChangeListeners;
-
- /**
- * Filters currently applied to the container.
- */
- private Set<Filter> filters = new HashSet<Filter>();
-
- /**
- * The item sorter which is used for sorting the container.
- */
- private ItemSorter itemSorter = new DefaultItemSorter();
-
- /**
- * A special deserialization method that resolves {@link #model} is needed
- * as PropertyDescriptor is not {@link Serializable}.
- */
- private void readObject(java.io.ObjectInputStream in) throws IOException,
- ClassNotFoundException {
- in.defaultReadObject();
- model = BeanItem.getPropertyDescriptors(type);
- }
+public class BeanItemContainer<BT> extends AbstractBeanContainer<BT, BT> {
/**
* Constructs a {@code BeanItemContainer} for beans of the given type.
@@ -125,12 +45,7 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
* If {@code type} is null
*/
public BeanItemContainer(Class<? extends BT> type) {
- if (type == null) {
- throw new IllegalArgumentException(
- "The type passed to BeanItemContainer must not be null");
- }
- this.type = type;
- model = BeanItem.getPropertyDescriptors(type);
+ super(type);
}
/**
@@ -150,286 +65,127 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
* a non empty {@link Collection} of beans.
* @throws IllegalArgumentException
* If the collection is null or empty.
+ *
+ * @deprecated use {@link #BeanItemContainer(Class, Collection)} instead
*/
- @SuppressWarnings("unchecked")
+ @Deprecated
public BeanItemContainer(Collection<? extends BT> collection)
throws IllegalArgumentException {
- if (collection == null || collection.isEmpty()) {
- throw new IllegalArgumentException(
- "The collection passed to BeanItemContainer must not be null or empty");
- }
+ super(getBeanClassForCollection(collection));
- type = (Class<? extends BT>) collection.iterator().next().getClass();
- model = BeanItem.getPropertyDescriptors(type);
addAll(collection);
}
/**
- * Adds all the beans in {@code collection} in one go. More efficient than
- * adding them one by one.
+ * Internal helper method to support the deprecated {@link Collection}
+ * container.
*
+ * @param <BT>
* @param collection
- * The collection of beans to add. Must not be null.
+ * @return
+ * @throws IllegalArgumentException
*/
- private void addAll(Collection<? extends BT> collection) {
- // Pre-allocate space for the collection
- allItems.ensureCapacity(allItems.size() + collection.size());
-
- int idx = size();
- for (BT bean : collection) {
- if (internalAddAt(idx, bean) != null) {
- idx++;
- }
+ @Deprecated
+ private static <BT> Class<? extends BT> getBeanClassForCollection(
+ Collection<? extends BT> collection)
+ throws IllegalArgumentException {
+ if (collection == null || collection.isEmpty()) {
+ throw new IllegalArgumentException(
+ "The collection passed to BeanItemContainer must not be null or empty");
}
-
- // Filter the contents when all items have been added
- filterAll();
- }
-
- /**
- * Unsupported operation. Beans should be added through
- * {@link #addItemAt(int, Object)}.
- */
- public Object addItemAt(int index) throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
+ return (Class<? extends BT>) collection.iterator().next().getClass();
}
/**
- * Adds a new bean at the given index.
- *
- * The bean is used both as the item contents and as the item identifier.
+ * Constructs a {@code BeanItemContainer} and adds the given beans to it.
*
- * @param index
- * Index at which the bean should be added.
- * @param newItemId
- * The bean to add to the container.
- * @return Returns the new BeanItem or null if the operation fails.
+ * @param type
+ * the type of the beans that will be added to the container.
+ * @param collection
+ * a {@link Collection} of beans (can be empty or null).
+ * @throws IllegalArgumentException
+ * If {@code type} is null
*/
- public BeanItem<BT> addItemAt(int index, Object newItemId)
- throws UnsupportedOperationException {
- if (index < 0 || index > size()) {
- return null;
- } else if (index == 0) {
- // add before any item, visible or not
- return addItemAtInternalIndex(0, newItemId);
- } else {
- // if index==size(), adds immediately after last visible item
- return addItemAfter(getIdByIndex(index - 1), newItemId);
- }
- }
+ public BeanItemContainer(Class<? extends BT> type,
+ Collection<? extends BT> collection)
+ throws IllegalArgumentException {
+ super(type);
- /**
- * Adds a bean at the given index of the internal (unfiltered) list.
- * <p>
- * The item is also added in the visible part of the list if it passes the
- * filters.
- * </p>
- *
- * @param index
- * Internal index to add the new item.
- * @param newItemId
- * Id of the new item to be added.
- * @return Returns new item or null if the operation fails.
- */
- private BeanItem<BT> addItemAtInternalIndex(int index, Object newItemId) {
- BeanItem<BT> beanItem = internalAddAt(index, (BT) newItemId);
- if (beanItem != null) {
- filterAll();
+ if (collection != null) {
+ addAll(collection);
}
-
- return beanItem;
}
/**
- * Adds the bean to all internal data structures at the given position.
- * Fails if the bean is already in the container or is not assignable to the
- * correct type. Returns a new BeanItem if the bean was added successfully.
- *
- * <p>
- * Caller should call {@link #filterAll()} after calling this method to
- * ensure the filtered list is updated.
- * </p>
- *
- * @param position
- * The position at which the bean should be inserted
- * @param bean
- * The bean to insert
- *
- * @return true if the bean was added successfully, false otherwise
+ * Unsupported operation. Use {@link #addBean(Object)} instead.
*/
- private BeanItem<BT> internalAddAt(int position, BT bean) {
- // Make sure that the item has not been added previously
- if (allItems.contains(bean)) {
- return null;
- }
-
- if (!type.isAssignableFrom(bean.getClass())) {
- return null;
- }
-
- // "filteredList" will be updated in filterAll() which should be invoked
- // by the caller after calling this method.
- allItems.add(position, bean);
- BeanItem<BT> beanItem = new BeanItem<BT>(bean, model);
- beanToItem.put(bean, beanItem);
-
- // add listeners to be able to update filtering on property
- // changes
- for (Filter filter : filters) {
- // addValueChangeListener avoids adding duplicates
- addValueChangeListener(beanItem, filter.propertyId);
- }
-
- return beanItem;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container.Indexed#getIdByIndex(int)
- */
- public BT getIdByIndex(int index) {
- return filteredItems.get(index);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container.Indexed#indexOfId(java.lang.Object)
- */
- public int indexOfId(Object itemId) {
- return filteredItems.indexOf(itemId);
+ // overridden for javadoc only
+ @Override
+ public Object addItem() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
}
/**
* Unsupported operation. Use {@link #addItemAfter(Object, Object)}.
*/
+ // overridden for javadoc only
+ @Override
public Object addItemAfter(Object previousItemId)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
- * Adds the bean after the given bean.
- *
- * The bean is used both as the item contents and as the item identifier.
- *
- * @see com.vaadin.data.Container.Ordered#addItemAfter(Object, Object)
- */
- public BeanItem<BT> addItemAfter(Object previousItemId, Object newItemId)
- throws UnsupportedOperationException {
- // only add if the previous item is visible
- if (previousItemId == null) {
- return addItemAtInternalIndex(0, newItemId);
- } else if (containsId(previousItemId)) {
- return addItemAtInternalIndex(allItems.indexOf(previousItemId) + 1,
- newItemId);
- } else {
- return null;
- }
- }
-
- /*
- * (non-Javadoc)
+ * Adds all the beans from a {@link Collection} in one go. More efficient
+ * than adding them one by one.
*
- * @see com.vaadin.data.Container.Ordered#firstItemId()
+ * @param collection
+ * The collection of beans to add. Must not be null.
*/
- public BT firstItemId() {
- if (size() > 0) {
- return getIdByIndex(0);
- } else {
- return null;
+ private void addAll(Collection<? extends BT> collection) {
+ int idx = size();
+ for (BT bean : collection) {
+ if (internalAddAt(idx, bean, bean) != null) {
+ idx++;
+ }
}
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object)
- */
- public boolean isFirstId(Object itemId) {
- return firstItemId() == itemId;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object)
- */
- public boolean isLastId(Object itemId) {
- return lastItemId() == itemId;
- }
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container.Ordered#lastItemId()
- */
- public BT lastItemId() {
- if (size() > 0) {
- return getIdByIndex(size() - 1);
- } else {
- return null;
- }
+ // Filter the contents when all items have been added
+ filterAll();
}
- /*
- * (non-Javadoc)
+ /**
+ * Adds the bean after the given bean.
*
- * @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object)
- */
- public BT nextItemId(Object itemId) {
- int index = indexOfId(itemId);
- if (index >= 0 && index < size() - 1) {
- return getIdByIndex(index + 1);
- } else {
- // out of bounds
- return null;
- }
- }
-
- /*
- * (non-Javadoc)
+ * The bean is used both as the item contents and as the item identifier.
*
- * @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object)
- */
- public BT prevItemId(Object itemId) {
- int index = indexOfId(itemId);
- if (index > 0) {
- return getIdByIndex(index - 1);
- } else {
- // out of bounds
- return null;
- }
- }
-
- /**
- * Unsupported operation. Properties are determined by the introspecting the
- * bean class.
- */
- public boolean addContainerProperty(Object propertyId, Class<?> type,
- Object defaultValue) throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Unsupported operation. Use {@link #addBean(Object)}.
+ * @param previousItemId
+ * the bean (of type BT) after which to add newItemId
+ * @param newItemId
+ * the bean (of type BT) to add
*
- * @see com.vaadin.data.Container#addItem()
+ * @see com.vaadin.data.Container.Ordered#addItemAfter(Object, Object)
*/
- public Object addItem() throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
+ public BeanItem<BT> addItemAfter(Object previousItemId, Object newItemId)
+ throws UnsupportedOperationException {
+ return super.addItemAfter((BT) previousItemId, (BT) newItemId,
+ (BT) newItemId);
}
/**
- * Adds the bean to the Container.
+ * Adds a new bean at the given index.
*
* The bean is used both as the item contents and as the item identifier.
*
- * @see com.vaadin.data.Container#addItem(Object)
+ * @param index
+ * Index at which the bean should be added.
+ * @param newItemId
+ * The bean to add to the container.
+ * @return Returns the new BeanItem or null if the operation fails.
*/
- public BeanItem<BT> addBean(BT bean) {
- return addItem(bean);
+ public BeanItem<BT> addItemAt(int index, Object newItemId)
+ throws UnsupportedOperationException {
+ return super.addItemAt(index, (BT) newItemId, (BT) newItemId);
}
/**
@@ -441,403 +197,33 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
*/
public BeanItem<BT> addItem(Object itemId)
throws UnsupportedOperationException {
+ BeanItem<BT> beanItem = null;
+
if (size() > 0) {
// add immediately after last visible item
- int lastIndex = allItems.indexOf(lastItemId());
- return addItemAtInternalIndex(lastIndex + 1, itemId);
+ int lastIndex = internalIndexOf(lastItemId());
+ beanItem = internalAddAt(lastIndex + 1, (BT) itemId, (BT) itemId);
} else {
- return addItemAtInternalIndex(0, itemId);
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container#containsId(java.lang.Object)
- */
- public boolean containsId(Object itemId) {
- // only look at visible items after filtering
- return filteredItems.contains(itemId);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container#getContainerProperty(java.lang.Object,
- * java.lang.Object)
- */
- public Property getContainerProperty(Object itemId, Object propertyId) {
- BeanItem<BT> item = getItem(itemId);
- if (item == null) {
- return null;
- }
- return item.getItemProperty(propertyId);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container#getContainerPropertyIds()
- */
- public Collection<String> getContainerPropertyIds() {
- return model.keySet();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container#getItem(java.lang.Object)
- */
- public BeanItem<BT> getItem(Object itemId) {
- return beanToItem.get(itemId);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container#getItemIds()
- */
- @SuppressWarnings("unchecked")
- public Collection<BT> getItemIds() {
- return (Collection<BT>) filteredItems.clone();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container#getType(java.lang.Object)
- */
- public Class<?> getType(Object propertyId) {
- return model.get(propertyId).getPropertyType();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container#removeAllItems()
- */
- public boolean removeAllItems() throws UnsupportedOperationException {
- allItems.clear();
- filteredItems.clear();
- // detach listeners from all BeanItems
- for (BeanItem<BT> item : beanToItem.values()) {
- removeAllValueChangeListeners(item);
- }
- beanToItem.clear();
- fireItemSetChange();
- return true;
- }
-
- /**
- * Unsupported operation. Properties are determined by the introspecting the
- * bean class.
- */
- public boolean removeContainerProperty(Object propertyId)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container#removeItem(java.lang.Object)
- */
- public boolean removeItem(Object itemId)
- throws UnsupportedOperationException {
- if (!allItems.remove(itemId)) {
- return false;
- }
- // detach listeners from Item
- removeAllValueChangeListeners(getItem(itemId));
- // remove item
- beanToItem.remove(itemId);
- filteredItems.remove(itemId);
- fireItemSetChange();
- return true;
- }
-
- /**
- * Make this container listen to the given property provided it notifies
- * when its value changes.
- *
- * @param beanItem
- * The BeanItem that contains the property
- * @param propertyId
- * The id of the property
- */
- private void addValueChangeListener(BeanItem<BT> beanItem, Object propertyId) {
- Property property = beanItem.getItemProperty(propertyId);
- if (property instanceof ValueChangeNotifier) {
- // avoid multiple notifications for the same property if
- // multiple filters are in use
- ValueChangeNotifier notifier = (ValueChangeNotifier) property;
- notifier.removeListener(this);
- notifier.addListener(this);
- }
- }
-
- /**
- * Remove this container as a listener for the given property.
- *
- * @param item
- * The BeanItem that contains the property
- * @param propertyId
- * The id of the property
- */
- private void removeValueChangeListener(BeanItem<BT> item, Object propertyId) {
- Property property = item.getItemProperty(propertyId);
- if (property instanceof ValueChangeNotifier) {
- ((ValueChangeNotifier) property).removeListener(this);
- }
- }
-
- /**
- * Remove this contains as a listener for all the properties in the given
- * BeanItem.
- *
- * @param item
- * The BeanItem that contains the properties
- */
- private void removeAllValueChangeListeners(BeanItem<BT> item) {
- for (Object propertyId : item.getItemPropertyIds()) {
- removeValueChangeListener(item, propertyId);
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container#size()
- */
- public int size() {
- return filteredItems.size();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds()
- */
- public Collection<Object> getSortableContainerPropertyIds() {
- LinkedList<Object> sortables = new LinkedList<Object>();
- for (Object propertyId : getContainerPropertyIds()) {
- Class<?> propertyType = getType(propertyId);
- if (Comparable.class.isAssignableFrom(propertyType)
- || propertyType.isPrimitive()) {
- sortables.add(propertyId);
- }
+ // add at the beginning of an empty container
+ beanItem = internalAddAt(0, (BT) itemId, (BT) itemId);
}
- return sortables;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container.Sortable#sort(java.lang.Object[],
- * boolean[])
- */
- public void sort(Object[] propertyId, boolean[] ascending) {
- itemSorter.setSortProperties(this, propertyId, ascending);
- doSort();
-
- // notifies if anything changes in the filtered list, including order
- filterAll();
- }
-
- /**
- * Perform the sorting of the data structures in the container. This is
- * invoked when the <code>itemSorter</code> has been prepared for the sort
- * operation. Typically this method calls
- * <code>Collections.sort(aCollection, getItemSorter())</code> on all arrays
- * (containing item ids) that need to be sorted.
- *
- */
- protected void doSort() {
- Collections.sort(allItems, getItemSorter());
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.Container.ItemSetChangeNotifier#addListener(com.vaadin
- * .data.Container.ItemSetChangeListener)
- */
- public void addListener(ItemSetChangeListener listener) {
- if (itemSetChangeListeners == null) {
- itemSetChangeListeners = new LinkedList<ItemSetChangeListener>();
- }
- itemSetChangeListeners.add(listener);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.Container.ItemSetChangeNotifier#removeListener(com.vaadin
- * .data.Container.ItemSetChangeListener)
- */
- public void removeListener(ItemSetChangeListener listener) {
- if (itemSetChangeListeners != null) {
- itemSetChangeListeners.remove(listener);
- }
- }
-
- /**
- * Send an ItemSetChange event to all listeners.
- */
- protected void fireItemSetChange() {
- if (itemSetChangeListeners != null) {
- final Container.ItemSetChangeEvent event = new Container.ItemSetChangeEvent() {
- public Container getContainer() {
- return BeanItemContainer.this;
- }
- };
- for (ItemSetChangeListener listener : itemSetChangeListeners) {
- listener.containerItemSetChange(event);
- }
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.Container.Filterable#addContainerFilter(java.lang.Object,
- * java.lang.String, boolean, boolean)
- */
- public void addContainerFilter(Object propertyId, String filterString,
- boolean ignoreCase, boolean onlyMatchPrefix) {
- if (filters.isEmpty()) {
- filteredItems = (ListSet<BT>) allItems.clone();
- }
- // listen to change events to be able to update filtering
- for (BeanItem<BT> item : beanToItem.values()) {
- addValueChangeListener(item, propertyId);
- }
- Filter f = new Filter(propertyId, filterString, ignoreCase,
- onlyMatchPrefix);
- filter(f);
- filters.add(f);
- fireItemSetChange();
- }
-
- /**
- * Filter the view to recreate the visible item list from the unfiltered
- * items, and send a notification if the set of visible items changed in any
- * way.
- */
- protected void filterAll() {
- // avoid notification if the filtering had no effect
- List<BT> originalItems = filteredItems;
- // it is somewhat inefficient to do a (shallow) clone() every time
- filteredItems = (ListSet<BT>) allItems.clone();
- for (Filter f : filters) {
- filter(f);
- }
- // check if exactly the same items are there after filtering to avoid
- // unnecessary notifications
- // this may be slow in some cases as it uses BT.equals()
- if (!originalItems.equals(filteredItems)) {
- fireItemSetChange();
- }
- }
-
- /**
- * Remove (from the filtered list) any items that do not match the given
- * filter.
- *
- * @param f
- * The filter used to determine if items should be removed
- */
- protected void filter(Filter f) {
- Iterator<BT> iterator = filteredItems.iterator();
- while (iterator.hasNext()) {
- BT bean = iterator.next();
- if (!f.passesFilter(getItem(bean))) {
- iterator.remove();
- }
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container.Filterable#removeAllContainerFilters()
- */
- public void removeAllContainerFilters() {
- if (!filters.isEmpty()) {
- filters = new HashSet<Filter>();
- // stop listening to change events for any property
- for (BeanItem<BT> item : beanToItem.values()) {
- removeAllValueChangeListeners(item);
- }
+ if (beanItem != null) {
filterAll();
}
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.Container.Filterable#removeContainerFilters(java.lang
- * .Object)
- */
- public void removeContainerFilters(Object propertyId) {
- if (!filters.isEmpty()) {
- boolean filteringChanged = false;
- for (Iterator<Filter> iterator = filters.iterator(); iterator
- .hasNext();) {
- Filter f = iterator.next();
- if (f.propertyId.equals(propertyId)) {
- iterator.remove();
- filteringChanged = true;
- }
- }
- if (filteringChanged) {
- // stop listening to change events for the property
- for (BeanItem<BT> item : beanToItem.values()) {
- removeValueChangeListener(item, propertyId);
- }
- filterAll();
- }
- }
- }
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.Property.ValueChangeListener#valueChange(com.vaadin.data
- * .Property.ValueChangeEvent)
- */
- public void valueChange(ValueChangeEvent event) {
- // if a property that is used in a filter is changed, refresh filtering
- filterAll();
+ return beanItem;
}
/**
- * Returns the ItemSorter that is used for sorting the container.
- *
- * @see #setItemSorter(ItemSorter)
+ * Adds the bean to the Container.
*
- * @return The ItemSorter that is used for sorting the container
- */
- public ItemSorter getItemSorter() {
- return itemSorter;
- }
-
- /**
- * Sets the ItemSorter that is used for sorting the container. The
- * {@link ItemSorter#compare(Object, Object)} method is called to compare
- * two beans (item ids).
+ * The bean is used both as the item contents and as the item identifier.
*
- * @param itemSorter
- * The ItemSorter to use when sorting the container
+ * @see com.vaadin.data.Container#addItem(Object)
*/
- public void setItemSorter(ItemSorter itemSorter) {
- this.itemSorter = itemSorter;
+ public BeanItem<BT> addBean(BT bean) {
+ return addItem(bean);
}
}