1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162 |
- /*
- * Copyright 2000-2016 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
- package com.vaadin.v7.data.util;
-
- import java.io.Serializable;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.EventObject;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Set;
-
- import com.vaadin.data.provider.DataProvider;
- import com.vaadin.v7.data.Container;
- import com.vaadin.v7.data.Container.ItemSetChangeNotifier;
- import com.vaadin.v7.data.Item;
- import com.vaadin.v7.data.util.filter.SimpleStringFilter;
- import com.vaadin.v7.data.util.filter.UnsupportedFilterException;
-
- /**
- * Abstract {@link Container} class that handles common functionality for
- * in-memory containers. Concrete in-memory container classes can either inherit
- * this class, inherit {@link AbstractContainer}, or implement the
- * {@link Container} interface directly.
- *
- * Adding and removing items (if desired) must be implemented in subclasses by
- * overriding the appropriate add*Item() and remove*Item() and removeAllItems()
- * methods, calling the corresponding
- * {@link #internalAddItemAfter(Object, Object, Item)},
- * {@link #internalAddItemAt(int, Object, Item)},
- * {@link #internalAddItemAtEnd(Object, Item, boolean)},
- * {@link #internalRemoveItem(Object)} and {@link #internalRemoveAllItems()}
- * methods.
- *
- * By default, adding and removing container properties is not supported, and
- * subclasses need to implement {@link #getContainerPropertyIds()}. Optionally,
- * subclasses can override {@link #addContainerProperty(Object, Class, Object)}
- * and {@link #removeContainerProperty(Object)} to implement them.
- *
- * Features:
- * <ul>
- * <li>{@link Container.Ordered}
- * <li>{@link Container.Indexed}
- * <li>{@link Filterable} and {@link SimpleFilterable} (internal implementation,
- * does not implement the interface directly)
- * <li>{@link Sortable} (internal implementation, does not implement the
- * interface directly)
- * </ul>
- *
- * To implement {@link Sortable}, subclasses need to implement
- * {@link #getSortablePropertyIds()} and call the superclass method
- * {@link #sortContainer(Object[], boolean[])} in the method
- * <code>sort(Object[], boolean[])</code>.
- *
- * To implement {@link Filterable}, subclasses need to implement the methods
- * {@link Filterable#addContainerFilter(Container.Filter)} (calling
- * {@link #addFilter(Filter)}), {@link Filterable#removeAllContainerFilters()}
- * (calling {@link #removeAllFilters()}) and
- * {@link Filterable#removeContainerFilter(Container.Filter)} (calling
- * {@link #removeFilter(Container.Filter)}).
- *
- * To implement {@link SimpleFilterable}, subclasses also need to implement the
- * methods
- * {@link SimpleFilterable#addContainerFilter(Object, String, boolean, boolean)}
- * and {@link SimpleFilterable#removeContainerFilters(Object)} calling
- * {@link #addFilter(Container.Filter)} and {@link #removeFilters(Object)}
- * respectively.
- *
- * @param <ITEMIDTYPE>
- * the class of item identifiers in the container, use Object if can
- * be any class
- * @param <PROPERTYIDCLASS>
- * the class of property identifiers for the items in the container,
- * use Object if can be any class
- * @param <ITEMCLASS>
- * the (base) class of the Item instances in the container, use
- * {@link Item} if unknown
- *
- * @since 6.6
- *
- * @deprecated As of 8.0, replaced by {@link DataProvider}
- */
- @Deprecated
- public abstract class AbstractInMemoryContainer<ITEMIDTYPE, PROPERTYIDCLASS, ITEMCLASS extends Item>
- extends AbstractContainer
- implements ItemSetChangeNotifier, Container.Indexed {
-
- /**
- * An ordered {@link List} of all item identifiers in the container,
- * including those that have been filtered out.
- *
- * Must not be null.
- */
- private List<ITEMIDTYPE> allItemIds;
-
- /**
- * An ordered {@link List} of item identifiers in the container after
- * filtering, excluding those that have been filtered out.
- *
- * This is what the external API of the {@link Container} interface and its
- * subinterfaces shows (e.g. {@link #size()}, {@link #nextItemId(Object)}).
- *
- * If null, the full item id list is used instead.
- */
- private List<ITEMIDTYPE> filteredItemIds;
-
- /**
- * Filters that are applied to the container to limit the items visible in
- * it
- */
- private Set<Filter> filters = new HashSet<Filter>();
-
- /**
- * The item sorter which is used for sorting the container.
- */
- private ItemSorter itemSorter = new DefaultItemSorter();
-
- // Constructors
-
- /**
- * Constructor for an abstract in-memory container.
- */
- protected AbstractInMemoryContainer() {
- setAllItemIds(new ListSet<ITEMIDTYPE>());
- }
-
- // Container interface methods with more specific return class
-
- // default implementation, can be overridden
- @Override
- public ITEMCLASS getItem(Object itemId) {
- if (containsId(itemId)) {
- return getUnfilteredItem(itemId);
- } else {
- return null;
- }
- }
-
- private abstract static class BaseItemAddOrRemoveEvent extends EventObject
- implements Serializable {
- protected Object itemId;
- protected int index;
- protected int count;
-
- public BaseItemAddOrRemoveEvent(Container source, Object itemId,
- int index, int count) {
- super(source);
- this.itemId = itemId;
- this.index = index;
- this.count = count;
- }
-
- public Container getContainer() {
- return (Container) getSource();
- }
-
- public Object getFirstItemId() {
- return itemId;
- }
-
- public int getFirstIndex() {
- return index;
- }
-
- public int getAffectedItemsCount() {
- return count;
- }
- }
-
- /**
- * An <code>Event</code> object specifying information about the added
- * items.
- *
- * <p>
- * This class provides information about the first added item and the number
- * of added items.
- * </p>
- *
- * @since 7.4
- */
- @Deprecated
- protected static class BaseItemAddEvent extends BaseItemAddOrRemoveEvent
- implements Container.Indexed.ItemAddEvent {
-
- public BaseItemAddEvent(Container source, Object itemId, int index,
- int count) {
- super(source, itemId, index, count);
- }
-
- @Override
- public int getAddedItemsCount() {
- return getAffectedItemsCount();
- }
- }
-
- /**
- * An <code>Event</code> object specifying information about the removed
- * items.
- *
- * <p>
- * This class provides information about the first removed item and the
- * number of removed items.
- * </p>
- *
- * @since 7.4
- */
- @Deprecated
- protected static class BaseItemRemoveEvent extends BaseItemAddOrRemoveEvent
- implements Container.Indexed.ItemRemoveEvent {
-
- public BaseItemRemoveEvent(Container source, Object itemId, int index,
- int count) {
- super(source, itemId, index, count);
- }
-
- @Override
- public int getRemovedItemsCount() {
- return getAffectedItemsCount();
- }
- }
-
- /**
- * Get an item even if filtered out.
- *
- * For internal use only.
- *
- * @param itemId
- * @return
- */
- protected abstract ITEMCLASS getUnfilteredItem(Object itemId);
-
- // cannot override getContainerPropertyIds() and getItemIds(): if subclass
- // uses Object as ITEMIDCLASS or PROPERTYIDCLASS, Collection<Object> cannot
- // be cast to Collection<MyInterface>
-
- // public abstract Collection<PROPERTYIDCLASS> getContainerPropertyIds();
- // public abstract Collection<ITEMIDCLASS> getItemIds();
-
- // Container interface method implementations
-
- @Override
- public int size() {
- return getVisibleItemIds().size();
- }
-
- @Override
- public boolean containsId(Object itemId) {
- // only look at visible items after filtering
- if (itemId == null) {
- return false;
- } else {
- return getVisibleItemIds().contains(itemId);
- }
- }
-
- @Override
- public List<?> getItemIds() {
- return Collections.unmodifiableList(getVisibleItemIds());
- }
-
- // Container.Ordered
-
- @Override
- public ITEMIDTYPE nextItemId(Object itemId) {
- int index = indexOfId(itemId);
- if (index >= 0 && index < size() - 1) {
- return getIdByIndex(index + 1);
- } else {
- // out of bounds
- return null;
- }
- }
-
- @Override
- public ITEMIDTYPE prevItemId(Object itemId) {
- int index = indexOfId(itemId);
- if (index > 0) {
- return getIdByIndex(index - 1);
- } else {
- // out of bounds
- return null;
- }
- }
-
- @Override
- public ITEMIDTYPE firstItemId() {
- if (size() > 0) {
- return getIdByIndex(0);
- } else {
- return null;
- }
- }
-
- @Override
- public ITEMIDTYPE lastItemId() {
- if (size() > 0) {
- return getIdByIndex(size() - 1);
- } else {
- return null;
- }
- }
-
- @Override
- public boolean isFirstId(Object itemId) {
- if (itemId == null) {
- return false;
- }
- return itemId.equals(firstItemId());
- }
-
- @Override
- public boolean isLastId(Object itemId) {
- if (itemId == null) {
- return false;
- }
- return itemId.equals(lastItemId());
- }
-
- // Container.Indexed
-
- @Override
- public ITEMIDTYPE getIdByIndex(int index) {
- return getVisibleItemIds().get(index);
- }
-
- @Override
- public List<ITEMIDTYPE> getItemIds(int startIndex, int numberOfIds) {
- if (startIndex < 0) {
- throw new IndexOutOfBoundsException(
- "Start index cannot be negative! startIndex=" + startIndex);
- }
-
- if (startIndex > getVisibleItemIds().size()) {
- throw new IndexOutOfBoundsException(
- "Start index exceeds container size! startIndex="
- + startIndex + " containerLastItemIndex="
- + (getVisibleItemIds().size() - 1));
- }
-
- if (numberOfIds < 1) {
- if (numberOfIds == 0) {
- return Collections.emptyList();
- }
-
- throw new IllegalArgumentException(
- "Cannot get negative amount of items! numberOfItems="
- + numberOfIds);
- }
-
- int endIndex = startIndex + numberOfIds;
-
- if (endIndex > getVisibleItemIds().size()) {
- endIndex = getVisibleItemIds().size();
- }
-
- return Collections.unmodifiableList(
- getVisibleItemIds().subList(startIndex, endIndex));
-
- }
-
- @Override
- public int indexOfId(Object itemId) {
- return getVisibleItemIds().indexOf(itemId);
- }
-
- // methods that are unsupported by default, override to support
-
- @Override
- public Object addItemAt(int index) throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "Adding items not supported. Override the relevant addItem*() methods if required as specified in AbstractInMemoryContainer javadoc.");
- }
-
- @Override
- public Item addItemAt(int index, Object newItemId)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "Adding items not supported. Override the relevant addItem*() methods if required as specified in AbstractInMemoryContainer javadoc.");
- }
-
- @Override
- public Object addItemAfter(Object previousItemId)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "Adding items not supported. Override the relevant addItem*() methods if required as specified in AbstractInMemoryContainer javadoc.");
- }
-
- @Override
- public Item addItemAfter(Object previousItemId, Object newItemId)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "Adding items not supported. Override the relevant addItem*() methods if required as specified in AbstractInMemoryContainer javadoc.");
- }
-
- @Override
- public Item addItem(Object itemId) throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "Adding items not supported. Override the relevant addItem*() methods if required as specified in AbstractInMemoryContainer javadoc.");
- }
-
- @Override
- public Object addItem() throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "Adding items not supported. Override the relevant addItem*() methods if required as specified in AbstractInMemoryContainer javadoc.");
- }
-
- @Override
- public boolean removeItem(Object itemId)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "Removing items not supported. Override the removeItem() method if required as specified in AbstractInMemoryContainer javadoc.");
- }
-
- @Override
- public boolean removeAllItems() throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "Removing items not supported. Override the removeAllItems() method if required as specified in AbstractInMemoryContainer javadoc.");
- }
-
- @Override
- public boolean addContainerProperty(Object propertyId, Class<?> type,
- Object defaultValue) throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "Adding container properties not supported. Override the addContainerProperty() method if required.");
- }
-
- @Override
- public boolean removeContainerProperty(Object propertyId)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "Removing container properties not supported. Override the addContainerProperty() method if required.");
- }
-
- // ItemSetChangeNotifier
- /**
- * @deprecated As of 7.0, replaced by
- * {@link #addItemSetChangeListener(Container.ItemSetChangeListener)}
- **/
- @Deprecated
- @Override
- public void addListener(Container.ItemSetChangeListener listener) {
- addItemSetChangeListener(listener);
- }
-
- @Override
- public void addItemSetChangeListener(
- Container.ItemSetChangeListener listener) {
- super.addItemSetChangeListener(listener);
- }
-
- @Override
- public void removeItemSetChangeListener(
- Container.ItemSetChangeListener listener) {
- super.removeItemSetChangeListener(listener);
- }
-
- /**
- * @deprecated As of 7.0, replaced by
- * {@link #removeItemSetChangeListener(Container.ItemSetChangeListener)}
- **/
- @Deprecated
- @Override
- public void removeListener(Container.ItemSetChangeListener listener) {
- removeItemSetChangeListener(listener);
- }
-
- // internal methods
-
- // Filtering support
-
- /**
- * 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() {
- if (doFilterContainer(!getFilters().isEmpty())) {
- fireItemSetChange();
- }
- }
-
- /**
- * Filters the data in the container and updates internal data structures.
- * This method should reset any internal data structures and then repopulate
- * them so {@link #getItemIds()} and other methods only return the filtered
- * items.
- *
- * @param hasFilters
- * true if filters has been set for the container, false
- * otherwise
- * @return true if the item set has changed as a result of the filtering
- */
- protected boolean doFilterContainer(boolean hasFilters) {
- if (!hasFilters) {
- boolean changed = getAllItemIds().size() != getVisibleItemIds()
- .size();
- setFilteredItemIds(null);
- return changed;
- }
-
- // Reset filtered list
- List<ITEMIDTYPE> originalFilteredItemIds = getFilteredItemIds();
- boolean wasUnfiltered = false;
- if (originalFilteredItemIds == null) {
- originalFilteredItemIds = Collections.emptyList();
- wasUnfiltered = true;
- }
- setFilteredItemIds(new ListSet<ITEMIDTYPE>());
-
- // Filter
- boolean equal = true;
- Iterator<ITEMIDTYPE> origIt = originalFilteredItemIds.iterator();
- for (final Iterator<ITEMIDTYPE> i = getAllItemIds().iterator(); i
- .hasNext();) {
- final ITEMIDTYPE id = i.next();
- if (passesFilters(id)) {
- // filtered list comes from the full list, can use ==
- equal = equal && origIt.hasNext() && origIt.next() == id;
- getFilteredItemIds().add(id);
- }
- }
-
- return (wasUnfiltered && !getAllItemIds().isEmpty()) || !equal
- || origIt.hasNext();
- }
-
- /**
- * Checks if the given itemId passes the filters set for the container. The
- * caller should make sure the itemId exists in the container. For
- * non-existing itemIds the behavior is undefined.
- *
- * @param itemId
- * An itemId that exists in the container.
- * @return true if the itemId passes all filters or no filters are set,
- * false otherwise.
- */
- protected boolean passesFilters(Object itemId) {
- ITEMCLASS item = getUnfilteredItem(itemId);
- if (getFilters().isEmpty()) {
- return true;
- }
- final Iterator<Filter> i = getFilters().iterator();
- while (i.hasNext()) {
- final Filter f = i.next();
- if (!f.passesFilter(itemId, item)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Adds a container filter and re-filter the view.
- *
- * The filter must implement Filter and its sub-filters (if any) must also
- * be in-memory filterable.
- *
- * This can be used to implement
- * {@link Filterable#addContainerFilter(Container.Filter)} and optionally
- * also
- * {@link SimpleFilterable#addContainerFilter(Object, String, boolean, boolean)}
- * (with {@link SimpleStringFilter}).
- *
- * Note that in some cases, incompatible filters cannot be detected when
- * added and an {@link UnsupportedFilterException} may occur when performing
- * filtering.
- *
- * @throws UnsupportedFilterException
- * if the filter is detected as not supported by the container
- */
- protected void addFilter(Filter filter) throws UnsupportedFilterException {
- getFilters().add(filter);
- filterAll();
- }
-
- /**
- * Returns true if any filters have been applied to the container.
- *
- * @return true if the container has filters applied, false otherwise
- * @since 7.1
- */
- protected boolean hasContainerFilters() {
- return !getContainerFilters().isEmpty();
- }
-
- protected Collection<Filter> getContainerFilters() {
- return Collections.unmodifiableCollection(filters);
- }
-
- /**
- * Remove a specific container filter and re-filter the view (if necessary).
- *
- * This can be used to implement
- * {@link Filterable#removeContainerFilter(Container.Filter)} .
- */
- protected void removeFilter(Filter filter) {
- for (Iterator<Filter> iterator = getFilters().iterator(); iterator
- .hasNext();) {
- Filter f = iterator.next();
- if (f.equals(filter)) {
- iterator.remove();
- filterAll();
- return;
- }
- }
- }
-
- /**
- * Remove all container filters for all properties and re-filter the view.
- *
- * This can be used to implement
- * {@link Filterable#removeAllContainerFilters()}.
- */
- protected void removeAllFilters() {
- if (getFilters().isEmpty()) {
- return;
- }
- getFilters().clear();
- filterAll();
- }
-
- /**
- * Checks if there is a filter that applies to a given property.
- *
- * @param propertyId
- * @return true if there is an active filter for the property
- */
- protected boolean isPropertyFiltered(Object propertyId) {
- if (getFilters().isEmpty() || propertyId == null) {
- return false;
- }
- final Iterator<Filter> i = getFilters().iterator();
- while (i.hasNext()) {
- final Filter f = i.next();
- if (f.appliesToProperty(propertyId)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Remove all container filters for a given property identifier and
- * re-filter the view. This also removes filters applying to multiple
- * properties including the one identified by propertyId.
- *
- * This can be used to implement
- * {@link Filterable#removeContainerFilters(Object)}.
- *
- * @param propertyId
- * @return Collection<Filter> removed filters
- */
- protected Collection<Filter> removeFilters(Object propertyId) {
- if (getFilters().isEmpty() || propertyId == null) {
- return Collections.emptyList();
- }
- List<Filter> removedFilters = new LinkedList<Filter>();
- for (Iterator<Filter> iterator = getFilters().iterator(); iterator
- .hasNext();) {
- Filter f = iterator.next();
- if (f.appliesToProperty(propertyId)) {
- removedFilters.add(f);
- iterator.remove();
- }
- }
- if (!removedFilters.isEmpty()) {
- filterAll();
- return removedFilters;
- }
- return Collections.emptyList();
- }
-
- // sorting
-
- /**
- * Returns the ItemSorter used for comparing items in a sort. See
- * {@link #setItemSorter(ItemSorter)} for more information.
- *
- * @return The ItemSorter used for comparing two items in a sort.
- */
- protected ItemSorter getItemSorter() {
- return itemSorter;
- }
-
- /**
- * Sets the ItemSorter used for comparing items in a sort. The
- * {@link ItemSorter#compare(Object, Object)} method is called with item ids
- * to perform the sorting. A default ItemSorter is used if this is not
- * explicitly set.
- *
- * @param itemSorter
- * The ItemSorter used for comparing two items in a sort (not
- * null).
- */
- protected void setItemSorter(ItemSorter itemSorter) {
- this.itemSorter = itemSorter;
- }
-
- /**
- * Sort base implementation to be used to implement {@link Sortable}.
- *
- * Subclasses should call this from a public
- * {@link #sort(Object[], boolean[])} method when implementing Sortable.
- *
- * @see Container.Sortable#sort(java.lang.Object[], boolean[])
- */
- protected void sortContainer(Object[] propertyId, boolean[] ascending) {
- if (!(this instanceof Sortable)) {
- throw new UnsupportedOperationException(
- "Cannot sort a Container that does not implement Sortable");
- }
-
- // Set up the item sorter for the sort operation
- getItemSorter().setSortProperties((Sortable) this, propertyId,
- ascending);
-
- // Perform the actual sort
- doSort();
-
- // Post sort updates
- if (isFiltered()) {
- filterAll();
- } else {
- fireItemSetChange();
- }
-
- }
-
- /**
- * 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(getAllItemIds(), getItemSorter());
- }
-
- /**
- * Returns the sortable property identifiers for the container. Can be used
- * to implement {@link Sortable#getSortableContainerPropertyIds()}.
- */
- protected Collection<?> getSortablePropertyIds() {
- 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;
- }
-
- // removing items
-
- /**
- * Removes all items from the internal data structures of this class. This
- * can be used to implement {@link #removeAllItems()} in subclasses.
- *
- * No notification is sent, the caller has to fire a suitable item set
- * change notification.
- */
- protected void internalRemoveAllItems() {
- // Removes all Items
- getAllItemIds().clear();
- if (isFiltered()) {
- getFilteredItemIds().clear();
- }
- }
-
- /**
- * Removes a single item from the internal data structures of this class.
- * This can be used to implement {@link #removeItem(Object)} in subclasses.
- *
- * No notification is sent, the caller has to fire a suitable item set
- * change notification.
- *
- * @param itemId
- * the identifier of the item to remove
- * @return true if an item was successfully removed, false if failed to
- * remove or no such item
- */
- protected boolean internalRemoveItem(Object itemId) {
- if (itemId == null) {
- return false;
- }
-
- boolean result = getAllItemIds().remove(itemId);
- if (result && isFiltered()) {
- getFilteredItemIds().remove(itemId);
- }
-
- return result;
- }
-
- // adding items
-
- /**
- * Adds the bean to all internal data structures at the given position.
- * Fails if an item with itemId is already in the container. Returns a the
- * item if it was added successfully, null otherwise.
- *
- * <p>
- * Caller should initiate filtering after calling this method.
- * </p>
- *
- * For internal use only - subclasses should use
- * {@link #internalAddItemAtEnd(Object, Item, boolean)},
- * {@link #internalAddItemAt(int, Object, Item, boolean)} and
- * {@link #internalAddItemAfter(Object, Object, Item, boolean)} instead.
- *
- * @param position
- * The position at which the item should be inserted in the
- * unfiltered collection of items
- * @param itemId
- * The item identifier for the item to insert
- * @param item
- * The item to insert
- *
- * @return ITEMCLASS if the item was added successfully, null otherwise
- */
- private ITEMCLASS internalAddAt(int position, ITEMIDTYPE itemId,
- ITEMCLASS item) {
- if (position < 0 || position > getAllItemIds().size() || itemId == null
- || item == null) {
- return null;
- }
- // Make sure that the item has not been added previously
- if (getAllItemIds().contains(itemId)) {
- return null;
- }
-
- // "filteredList" will be updated in filterAll() which should be invoked
- // by the caller after calling this method.
- getAllItemIds().add(position, itemId);
- registerNewItem(position, itemId, item);
-
- return item;
- }
-
- /**
- * Add an item at the end of the container, and perform filtering if
- * necessary. An event is fired if the filtered view changes.
- *
- * @param newItemId
- * @param item
- * new item to add
- * @param filter
- * true to perform filtering and send event after adding the
- * item, false to skip these operations for batch inserts - if
- * false, caller needs to make sure these operations are
- * performed at the end of the batch
- * @return item added or null if no item was added
- */
- protected ITEMCLASS internalAddItemAtEnd(ITEMIDTYPE newItemId,
- ITEMCLASS item, boolean filter) {
- ITEMCLASS newItem = internalAddAt(getAllItemIds().size(), newItemId,
- item);
- if (newItem != null && filter) {
- // TODO filter only this item, use fireItemAdded()
- filterAll();
- if (!isFiltered()) {
- // TODO hack: does not detect change in filterAll() in this case
- fireItemAdded(indexOfId(newItemId), newItemId, item);
- }
- }
- return newItem;
- }
-
- /**
- * Add an item after a given (visible) item, and perform filtering. An event
- * is fired if the filtered view changes.
- *
- * The new item is added at the beginning if previousItemId is null.
- *
- * @param previousItemId
- * item id of a visible item after which to add the new item, or
- * null to add at the beginning
- * @param newItemId
- * @param item
- * new item to add
- * @param filter
- * true to perform filtering and send event after adding the
- * item, false to skip these operations for batch inserts - if
- * false, caller needs to make sure these operations are
- * performed at the end of the batch
- * @return item added or null if no item was added
- */
- protected ITEMCLASS internalAddItemAfter(ITEMIDTYPE previousItemId,
- ITEMIDTYPE newItemId, ITEMCLASS item, boolean filter) {
- // only add if the previous item is visible
- ITEMCLASS newItem = null;
- if (previousItemId == null) {
- newItem = internalAddAt(0, newItemId, item);
- } else if (containsId(previousItemId)) {
- newItem = internalAddAt(getAllItemIds().indexOf(previousItemId) + 1,
- newItemId, item);
- }
- if (newItem != null && filter) {
- // TODO filter only this item, use fireItemAdded()
- filterAll();
- if (!isFiltered()) {
- // TODO hack: does not detect change in filterAll() in this case
- fireItemAdded(indexOfId(newItemId), newItemId, item);
- }
- }
- return newItem;
- }
-
- /**
- * Add an item at a given (visible after filtering) item index, and perform
- * filtering. An event is fired if the filtered view changes.
- *
- * @param index
- * position where to add the item (visible/view index)
- * @param newItemId
- * @param item
- * new item to add
- * @param filter
- * true to perform filtering and send event after adding the
- * item, false to skip these operations for batch inserts - if
- * false, caller needs to make sure these operations are
- * performed at the end of the batch
- * @return item added or null if no item was added
- */
- protected ITEMCLASS internalAddItemAt(int index, ITEMIDTYPE newItemId,
- ITEMCLASS item, boolean filter) {
- if (index < 0 || index > size()) {
- return null;
- } else if (index == 0) {
- // add before any item, visible or not
- return internalAddItemAfter(null, newItemId, item, filter);
- } else {
- // if index==size(), adds immediately after last visible item
- return internalAddItemAfter(getIdByIndex(index - 1), newItemId,
- item, filter);
- }
- }
-
- /**
- * Registers a new item as having been added to the container. This can
- * involve storing the item or any relevant information about it in internal
- * container-specific collections if necessary, as well as registering
- * listeners etc.
- *
- * The full identifier list in {@link AbstractInMemoryContainer} has already
- * been updated to reflect the new item when this method is called.
- *
- * @param position
- * @param itemId
- * @param item
- */
- protected void registerNewItem(int position, ITEMIDTYPE itemId,
- ITEMCLASS item) {
- }
-
- // item set change notifications
-
- /**
- * Notify item set change listeners that an item has been added to the
- * container.
- *
- * @since 7.4
- *
- * @param position
- * position of the added item in the view
- * @param itemId
- * id of the added item
- * @param item
- * the added item
- */
- protected void fireItemAdded(int position, ITEMIDTYPE itemId,
- ITEMCLASS item) {
- fireItemsAdded(position, itemId, 1);
- }
-
- /**
- * Notify item set change listeners that items has been added to the
- * container.
- *
- * @param firstPosition
- * position of the first visible added item in the view
- * @param firstItemId
- * id of the first visible added item
- * @param numberOfItems
- * the number of visible added items
- */
- protected void fireItemsAdded(int firstPosition, ITEMIDTYPE firstItemId,
- int numberOfItems) {
- BaseItemAddEvent addEvent = new BaseItemAddEvent(this, firstItemId,
- firstPosition, numberOfItems);
- fireItemSetChange(addEvent);
- }
-
- /**
- * Notify item set change listeners that an item has been removed from the
- * container.
- *
- * @since 7.4
- *
- * @param position
- * position of the removed item in the view prior to removal (if
- * was visible)
- * @param itemId
- * id of the removed item, of type {@link Object} to satisfy
- * {@link Container#removeItem(Object)} API
- */
- protected void fireItemRemoved(int position, Object itemId) {
- fireItemsRemoved(position, itemId, 1);
- }
-
- /**
- * Notify item set change listeners that items has been removed from the
- * container.
- *
- * @param firstPosition
- * position of the first visible removed item in the view prior
- * to removal
- * @param firstItemId
- * id of the first visible removed item, of type {@link Object}
- * to satisfy {@link Container#removeItem(Object)} API
- * @param numberOfItems
- * the number of removed visible items
- *
- */
- protected void fireItemsRemoved(int firstPosition, Object firstItemId,
- int numberOfItems) {
- BaseItemRemoveEvent removeEvent = new BaseItemRemoveEvent(this,
- firstItemId, firstPosition, numberOfItems);
- fireItemSetChange(removeEvent);
- }
-
- // visible and filtered item identifier lists
-
- /**
- * Returns the internal list of visible item identifiers after filtering.
- *
- * For internal use only.
- */
- protected List<ITEMIDTYPE> getVisibleItemIds() {
- if (isFiltered()) {
- return getFilteredItemIds();
- } else {
- return getAllItemIds();
- }
- }
-
- /**
- * Returns the item id of the first visible item after filtering. 'Null' is
- * returned if there is no visible items.
- * <p>
- * For internal use only.
- *
- * @since 7.4
- *
- * @return item id of the first visible item
- */
- protected ITEMIDTYPE getFirstVisibleItem() {
- if (!getVisibleItemIds().isEmpty()) {
- return getVisibleItemIds().get(0);
- }
- return null;
- }
-
- /**
- * Returns true is the container has active filters.
- *
- * @return true if the container is currently filtered
- */
- protected boolean isFiltered() {
- return filteredItemIds != null;
- }
-
- /**
- * Internal helper method to set the internal list of filtered item
- * identifiers. Should not be used outside this class except for
- * implementing clone(), may disappear from future versions.
- *
- * @param filteredItemIds
- */
- @Deprecated
- protected void setFilteredItemIds(List<ITEMIDTYPE> filteredItemIds) {
- this.filteredItemIds = filteredItemIds;
- }
-
- /**
- * Internal helper method to get the internal list of filtered item
- * identifiers. Should not be used outside this class except for
- * implementing clone(), may disappear from future versions - use
- * {@link #getVisibleItemIds()} in other contexts.
- *
- * @return List<ITEMIDTYPE>
- */
- protected List<ITEMIDTYPE> getFilteredItemIds() {
- return filteredItemIds;
- }
-
- /**
- * Internal helper method to set the internal list of all item identifiers.
- * Should not be used outside this class except for implementing clone(),
- * may disappear from future versions.
- *
- * @param allItemIds
- */
- @Deprecated
- protected void setAllItemIds(List<ITEMIDTYPE> allItemIds) {
- this.allItemIds = allItemIds;
- }
-
- /**
- * Internal helper method to get the internal list of all item identifiers.
- * Avoid using this method outside this class, may disappear in future
- * versions.
- *
- * @return List<ITEMIDTYPE>
- */
- protected List<ITEMIDTYPE> getAllItemIds() {
- return allItemIds;
- }
-
- /**
- * Set the internal collection of filters without performing filtering.
- *
- * This method is mostly for internal use, use
- * {@link #addFilter(Container.Filter)} and <code>remove*Filter*</code>
- * (which also re-filter the container) instead when possible.
- *
- * @param filters
- */
- protected void setFilters(Set<Filter> filters) {
- this.filters = filters;
- }
-
- /**
- * Returns the internal collection of filters. The returned collection
- * should not be modified by callers outside this class.
- *
- * @return Set<Filter>
- */
- protected Set<Filter> getFilters() {
- return filters;
- }
-
- }
|