From: Artur Signell Date: Tue, 2 Mar 2010 13:52:40 +0000 (+0000) Subject: svn changeset:11591/svn branch:6.3 X-Git-Tag: 6.7.0.beta1~2002 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=44ca84275d8e3858dfc605e02852c2c670d99cfc;p=vaadin-framework.git svn changeset:11591/svn branch:6.3 --- diff --git a/src/com/vaadin/data/util/BeanItemContainer.java b/src/com/vaadin/data/util/BeanItemContainer.java index 59ffdbfce1..0efbdd3416 100644 --- a/src/com/vaadin/data/util/BeanItemContainer.java +++ b/src/com/vaadin/data/util/BeanItemContainer.java @@ -38,9 +38,23 @@ import com.vaadin.data.Property.ValueChangeNotifier; @SuppressWarnings("serial") public class BeanItemContainer implements Indexed, Sortable, Filterable, ItemSetChangeNotifier, ValueChangeListener { - // filtered and unfiltered item IDs - private ArrayList filteredItems = new ArrayList(); - private ArrayList allItems = new ArrayList(); + /** + * 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 filteredItems = new ListSet(); + + /** + * The allItems variable always contains all the items in the container. + * Some or all of these are also in the filteredItems list. + */ + private ListSet allItems = new ListSet(); + + /** + * Maps all pojos (item ids) in the container (including filtered) to their + * corresponding BeanItem. + */ private final Map> beanToItem = new HashMap>(); // internal data model to obtain property IDs etc. @@ -89,6 +103,7 @@ public class BeanItemContainer implements Indexed, Sortable, Filterable, * @throws IllegalArgumentException * If the collection is null or empty. */ + @SuppressWarnings("unchecked") public BeanItemContainer(Collection collection) throws IllegalArgumentException { if (collection == null || collection.isEmpty()) { @@ -98,10 +113,22 @@ public class BeanItemContainer implements Indexed, Sortable, Filterable, type = (Class) collection.iterator().next().getClass(); model = BeanItem.getPropertyDescriptors(type); - int i = 0; - for (BT bt : collection) { - addItemAt(i++, bt); + addAll(collection); + } + + private void addAll(Collection 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++; + } } + + // Filter the contents when all items have been added + filterAll(); } /** @@ -147,30 +174,58 @@ public class BeanItemContainer implements Indexed, Sortable, Filterable, * @return Returns new item or null if the operation fails. */ private BeanItem addItemAtInternalIndex(int index, Object newItemId) { - // Make sure that the Item has not been created yet - if (allItems.contains(newItemId)) { + BeanItem beanItem = internalAddAt(index, (BT) newItemId); + if (beanItem != null) { + filterAll(); + } + + 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 the new BeanItem if the bean was added successfully. + * + *

+ * Caller should call {@link #filterAll()} after calling this method to + * ensure the filtered list is updated. + *

+ * + * @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 + */ + private BeanItem internalAddAt(int position, BT bean) { + // Make sure that the item has not been added previously + if (allItems.contains(bean)) { return null; } - if (type.isAssignableFrom(newItemId.getClass())) { - BT pojo = (BT) newItemId; - // "list" will be updated in filterAll() - allItems.add(index, pojo); - BeanItem beanItem = new BeanItem(pojo, model); - beanToItem.put(pojo, beanItem); - // add listeners to be able to update filtering on property changes - for (Filter filter : filters) { - // addValueChangeListener avoids adding duplicates - addValueChangeListener(beanItem, filter.propertyId); - } - // it is somewhat suboptimal to filter all items - filterAll(); - return beanItem; - } else { + 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 beanItem = new BeanItem(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; + } + @SuppressWarnings("unchecked") public BT getIdByIndex(int index) { return filteredItems.get(index); } @@ -311,6 +366,7 @@ public class BeanItemContainer implements Indexed, Sortable, Filterable, return beanToItem.get(itemId); } + @SuppressWarnings("unchecked") public Collection getItemIds() { return (Collection) filteredItems.clone(); } @@ -445,7 +501,7 @@ public class BeanItemContainer implements Indexed, Sortable, Filterable, public void addContainerFilter(Object propertyId, String filterString, boolean ignoreCase, boolean onlyMatchPrefix) { if (filters.isEmpty()) { - filteredItems = (ArrayList) allItems.clone(); + filteredItems = (ListSet) allItems.clone(); } // listen to change events to be able to update filtering for (BeanItem item : beanToItem.values()) { @@ -467,7 +523,7 @@ public class BeanItemContainer implements Indexed, Sortable, Filterable, // avoid notification if the filtering had no effect List originalItems = filteredItems; // it is somewhat inefficient to do a (shallow) clone() every time - filteredItems = (ArrayList) allItems.clone(); + filteredItems = (ListSet) allItems.clone(); for (Filter f : filters) { filter(f); }