* A specialized set of identified Items. Basically the Container is a set of
@@ -34,7 +36,7 @@ import java.util.Collection;
*
*
* Note that though uniquely identified, the Items in a Container are not
- * neccessarily {@link Container.Ordered ordered}or {@link Container.Indexed
+ * necessarily {@link Container.Ordered ordered} or {@link Container.Indexed
* indexed}.
*
* How filtering is performed when a {@link Hierarchical} container
- * implements {@link Filterable} is implementation specific and should be
- * documented in the implementing class.
+ * implements {@link SimpleFilterable} is implementation specific and should
+ * be documented in the implementing class.
*
*
* Adding items (if supported) to a filtered {@link Ordered} or
@@ -593,8 +595,10 @@ public interface Container extends Serializable {
*
*
* @since 5.0
+ * @deprecated use {@link Filterable}
*/
- public interface Filterable extends Container, Serializable {
+ @Deprecated
+ public interface SimpleFilterable extends Container, Serializable {
/**
* Add a filter for given property.
@@ -611,17 +615,132 @@ public interface Container extends Serializable {
* strings.
* @param onlyMatchPrefix
* Only match prefixes; no other matches are included.
+ *
+ * @deprecated use {@link Filterable#addContainerFilter(Filter)}
*/
+ @Deprecated
public void addContainerFilter(Object propertyId, String filterString,
boolean ignoreCase, boolean onlyMatchPrefix);
/** Remove all filters from all properties. */
public void removeAllContainerFilters();
- /** Remove all filters from given property. */
+ /**
+ * Remove all filters from given property.
+ *
+ * @deprecated use {@link Filterable#removeContainerFilter(Filter)}
+ */
+ @Deprecated
public void removeContainerFilters(Object propertyId);
}
+ /**
+ * Filter interface for container filtering.
+ *
+ * If a filter does not support in-memory filtering,
+ * {@link #passesFilter(Item)} should throw
+ * {@link UnsupportedOperationException}.
+ *
+ * Lazy containers must be able to map filters to their internal
+ * representation (e.g. SQL or JPA 2.0 Criteria).
+ *
+ * An {@link UnsupportedFilterException} can be thrown by the container if a
+ * particular filter is not supported by the container.
+ *
+ * An {@link Filter} should implement {@link #equals(Object)} and
+ * {@link #hashCode()} correctly to avoid duplicate filter registrations
+ * etc.
+ *
+ * @see Filterable
+ *
+ * @since 6.6
+ */
+ public interface Filter extends Serializable {
+
+ /**
+ * Check if an item passes the filter (in-memory filtering).
+ *
+ * @param item
+ * @return true if the item is accepted by this filter
+ * @throws UnsupportedOperationException
+ * if the filter cannot be used for in-memory filtering
+ */
+ public boolean passesFilter(Item item)
+ throws UnsupportedOperationException;
+
+ /**
+ * Check if a change in the value of a property can affect the filtering
+ * result. May always return true, at the cost of performance.
+ *
+ * If the filter cannot determine whether it may depend on the property
+ * or not, should return true.
+ *
+ * @param propertyId
+ * @return true if the filtering result may/does change based on changes
+ * to the property identified by propertyId
+ */
+ public boolean appliesToProperty(Object propertyId);
+
+ }
+
+ /**
+ * Interface that is implemented by containers which allow reducing their
+ * visible contents based on a set of filters.
+ *
+ * When a set of filters are set, only items that match the filters are
+ * included in the visible contents of the container. Still new items that
+ * do not match filters can be added to the container. Multiple filters can
+ * be added and the container remembers the state of the filters. When
+ * multiple filters are added, all filters must match for an item to be
+ * visible in the container.
+ *
+ *
+ * When an {@link Ordered} or {@link Indexed} container is filtered, all
+ * operations of these interfaces should only use the filtered contents and
+ * the filtered indices to the container.
+ *
+ *
+ * How filtering is performed when a {@link Hierarchical} container
+ * implements {@link Filterable} is implementation specific and should be
+ * documented in the implementing class.
+ *
+ *
+ * Adding items (if supported) to a filtered {@link Ordered} or
+ * {@link Indexed} container should insert them immediately after the
+ * indicated visible item. However, the unfiltered position of items added
+ * at index 0, at index {@link com.vaadin.data.Container#size()} or at an
+ * undefined position is up to the implementation.
+ *
+ *
+ *
+ * This API replaces the old Filterable interface, renamed to
+ * {@link SimpleFilterable} in Vaadin 6.6. Currently this interface extends
+ * {@link SimpleFilterable} for backwards compatibility, but might not do so
+ * in future versions. removeAllContainerFilters() will remain
+ * a part of the API.
+ *
+ *
+ * @since 6.6
+ */
+ public interface Filterable extends SimpleFilterable, Serializable {
+ /**
+ * Adds a filter for the container.
+ *
+ * @throws UnsupportedFilterException
+ * if the filter is not supported by the container
+ */
+ public void addContainerFilter(Filter filter)
+ throws UnsupportedFilterException;
+
+ /**
+ * Removes a filter from the container.
+ *
+ * This requires that the equals() method considers the filters as
+ * equivalent (same instance or properly implemented equals() method).
+ */
+ public void removeContainerFilter(Filter filter);
+ }
+
/**
* Interface implemented by viewer classes capable of using a Container as a
* data source.
diff --git a/src/com/vaadin/data/util/AbstractBeanContainer.java b/src/com/vaadin/data/util/AbstractBeanContainer.java
index 9853b10150..f5bd836485 100644
--- a/src/com/vaadin/data/util/AbstractBeanContainer.java
+++ b/src/com/vaadin/data/util/AbstractBeanContainer.java
@@ -20,6 +20,8 @@ import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.Property.ValueChangeNotifier;
+import com.vaadin.data.util.filter.SimpleStringFilter;
+import com.vaadin.data.util.filter.UnsupportedFilterException;
/**
* An abstract base class for in-memory containers for JavaBeans.
@@ -326,8 +328,13 @@ public abstract class AbstractBeanContainer extends
*/
public void addContainerFilter(Object propertyId, String filterString,
boolean ignoreCase, boolean onlyMatchPrefix) {
- addFilter(new Filter(propertyId, filterString, ignoreCase,
- onlyMatchPrefix));
+ try {
+ addFilter(new SimpleStringFilter(propertyId, filterString,
+ ignoreCase, onlyMatchPrefix));
+ } catch (UnsupportedFilterException e) {
+ // the filter instance created here is always valid for in-memory
+ // containers
+ }
}
/*
@@ -352,7 +359,7 @@ public abstract class AbstractBeanContainer extends
* .Object)
*/
public void removeContainerFilters(Object propertyId) {
- Collection removedFilters = super.removeFilters(propertyId);
+ Collection removedFilters = super.removeFilters(propertyId);
if (!removedFilters.isEmpty()) {
// stop listening to change events for the property
for (Item item : itemIdToItem.values()) {
@@ -361,6 +368,15 @@ public abstract class AbstractBeanContainer extends
}
}
+ public void addContainerFilter(Filter filter)
+ throws UnsupportedFilterException {
+ addFilter(filter);
+ }
+
+ public void removeContainerFilter(Filter filter) {
+ removeFilter(filter);
+ }
+
/**
* Make this container listen to the given property provided it notifies
* when its value changes.
@@ -445,7 +461,7 @@ public abstract class AbstractBeanContainer extends
// add listeners to be able to update filtering on property
// changes
- for (ItemFilter filter : getFilters()) {
+ for (Filter filter : getFilters()) {
for (String propertyId : getContainerPropertyIds()) {
if (filter.appliesToProperty(propertyId)) {
// addValueChangeListener avoids adding duplicates
diff --git a/src/com/vaadin/data/util/AbstractInMemoryContainer.java b/src/com/vaadin/data/util/AbstractInMemoryContainer.java
index 978aac6d0e..df0e860b24 100644
--- a/src/com/vaadin/data/util/AbstractInMemoryContainer.java
+++ b/src/com/vaadin/data/util/AbstractInMemoryContainer.java
@@ -1,6 +1,5 @@
package com.vaadin.data.util;
-import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -12,6 +11,7 @@ import java.util.Set;
import com.vaadin.data.Container;
import com.vaadin.data.Container.ItemSetChangeNotifier;
import com.vaadin.data.Item;
+import com.vaadin.data.util.filter.UnsupportedFilterException;
/**
* Abstract {@link Container} class that handles common functionality for
@@ -49,7 +49,7 @@ import com.vaadin.data.Item;
* sort(Object[], boolean[]).
*
* To implement Filterable, subclasses need to implement the methods
- * addContainerFilter() (calling {@link #addFilter(ItemFilter)}),
+ * addContainerFilter() (calling {@link #addFilter(Filter)}),
* removeAllContainerFilters() (calling {@link #removeAllFilters()}
* ) and removeContainerFilters(Object) (calling
* {@link #removeFilters(Object)}).
@@ -70,38 +70,6 @@ public abstract class AbstractInMemoryContainer filters = new HashSet();
+ private Set filters = new HashSet();
/**
* The item sorter which is used for sorting the container.
@@ -395,9 +363,9 @@ public abstract class AbstractInMemoryContainer i = getFilters().iterator();
+ final Iterator i = getFilters().iterator();
while (i.hasNext()) {
- final ItemFilter f = i.next();
+ final Filter f = i.next();
if (!f.passesFilter(item)) {
return false;
}
@@ -406,16 +374,45 @@ public abstract class AbstractInMemoryContainer 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.
*
@@ -440,9 +437,9 @@ public abstract class AbstractInMemoryContainer i = getFilters().iterator();
+ final Iterator i = getFilters().iterator();
while (i.hasNext()) {
- final ItemFilter f = i.next();
+ final Filter f = i.next();
if (f.appliesToProperty(propertyId)) {
return true;
}
@@ -461,14 +458,14 @@ public abstract class AbstractInMemoryContainer removed filters
*/
- protected Collection removeFilters(Object propertyId) {
+ protected Collection removeFilters(Object propertyId) {
if (getFilters().isEmpty() || propertyId == null) {
return Collections.emptyList();
}
- List removedFilters = new LinkedList();
- for (Iterator iterator = getFilters().iterator(); iterator
+ List removedFilters = new LinkedList();
+ for (Iterator iterator = getFilters().iterator(); iterator
.hasNext();) {
- ItemFilter f = iterator.next();
+ Filter f = iterator.next();
if (f.appliesToProperty(propertyId)) {
removedFilters.add(f);
iterator.remove();
@@ -860,7 +857,7 @@ public abstract class AbstractInMemoryContainer filters) {
+ protected void setFilters(Set filters) {
this.filters = filters;
}
@@ -868,9 +865,9 @@ public abstract class AbstractInMemoryContainer
+ * @return Set
*/
- protected Set getFilters() {
+ protected Set getFilters() {
return filters;
}
diff --git a/src/com/vaadin/data/util/IndexedContainer.java b/src/com/vaadin/data/util/IndexedContainer.java
index c87417a75f..78df8b2cc2 100644
--- a/src/com/vaadin/data/util/IndexedContainer.java
+++ b/src/com/vaadin/data/util/IndexedContainer.java
@@ -21,6 +21,8 @@ import java.util.Map;
import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
+import com.vaadin.data.util.filter.SimpleStringFilter;
+import com.vaadin.data.util.filter.UnsupportedFilterException;
/**
* An implementation of the {@link Container.Indexed} interface
@@ -1014,7 +1016,7 @@ public class IndexedContainer extends
nc.types = types != null ? (Hashtable