summaryrefslogtreecommitdiffstats
path: root/compatibility-server/src
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2016-08-19 08:25:29 +0300
committerVaadin Code Review <review@vaadin.com>2016-08-23 05:37:28 +0000
commit7daee066ae8b69ead326f6caccd17d6f0bfd9462 (patch)
treecf3b01efe74665c7d849e1d698a1ed857f47b28e /compatibility-server/src
parent8328038b3c695da27f6247fc9b33ed97c0e0d771 (diff)
downloadvaadin-framework-7daee066ae8b69ead326f6caccd17d6f0bfd9462.tar.gz
vaadin-framework-7daee066ae8b69ead326f6caccd17d6f0bfd9462.zip
Move Container to compatibility package
Change-Id: I32bbf4891d6aca9dc9ee8f1b7ae733bc28b4cd30
Diffstat (limited to 'compatibility-server/src')
-rw-r--r--compatibility-server/src/main/java/com/vaadin/event/DataBoundTransferable.java78
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/Collapsible.java80
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/Container.java1255
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/ContainerHelpers.java102
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/ContainerOrderedWrapper.java728
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/DefaultItemSorter.java221
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/HierarchicalContainerOrderedWrapper.java82
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/ItemSorter.java70
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/PropertyValueGenerator.java103
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/AbstractJunctionFilter.java88
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/And.java56
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Between.java106
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Compare.java370
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/IsNull.java96
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Like.java105
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Not.java82
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Or.java75
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/SimpleStringFilter.java167
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/UnsupportedFilterException.java47
19 files changed, 3911 insertions, 0 deletions
diff --git a/compatibility-server/src/main/java/com/vaadin/event/DataBoundTransferable.java b/compatibility-server/src/main/java/com/vaadin/event/DataBoundTransferable.java
new file mode 100644
index 0000000000..d4b4a5ba6b
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/event/DataBoundTransferable.java
@@ -0,0 +1,78 @@
+/*
+ * 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.event;
+
+import java.util.Map;
+
+import com.vaadin.ui.Component;
+import com.vaadin.v7.data.Container;
+
+/**
+ * Parent class for {@link Transferable} implementations that have a Vaadin
+ * container as a data source. The transfer is associated with an item
+ * (identified by its Id) and optionally also a property identifier (e.g. a
+ * table column identifier when transferring a single table cell).
+ *
+ * The component must implement the interface
+ * {@link com.vaadin.v7.data.Container.Viewer}.
+ *
+ * In most cases, receivers of data transfers should depend on this class
+ * instead of its concrete subclasses.
+ *
+ * @since 6.3
+ */
+public abstract class DataBoundTransferable extends TransferableImpl {
+
+ public DataBoundTransferable(Component sourceComponent,
+ Map<String, Object> rawVariables) {
+ super(sourceComponent, rawVariables);
+ }
+
+ /**
+ * Returns the identifier of the item being transferred.
+ *
+ * @return item identifier
+ */
+ public abstract Object getItemId();
+
+ /**
+ * Returns the optional property identifier that the transfer concerns.
+ *
+ * This can be e.g. the table column from which a drag operation originated.
+ *
+ * @return property identifier
+ */
+ public abstract Object getPropertyId();
+
+ /**
+ * Returns the container data source from which the transfer occurs.
+ *
+ * {@link com.vaadin.v7.data.Container.Viewer#getContainerDataSource()} is used
+ * to obtain the underlying container of the source component.
+ *
+ * @return Container
+ */
+ public Container getSourceContainer() {
+ Component sourceComponent = getSourceComponent();
+ if (sourceComponent instanceof Container.Viewer) {
+ return ((Container.Viewer) sourceComponent)
+ .getContainerDataSource();
+ } else {
+ // this should not happen
+ return null;
+ }
+ }
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/Collapsible.java b/compatibility-server/src/main/java/com/vaadin/v7/data/Collapsible.java
new file mode 100644
index 0000000000..a5d63c5a50
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/Collapsible.java
@@ -0,0 +1,80 @@
+/*
+ * 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;
+
+import com.vaadin.v7.data.Container.Hierarchical;
+import com.vaadin.v7.data.Container.Ordered;
+
+/**
+ * Container needed by large lazy loading hierarchies displayed e.g. in
+ * TreeTable.
+ * <p>
+ * Container of this type gets notified when a subtree is opened/closed in a
+ * component displaying its content. This allows container to lazy load subtrees
+ * and release memory when a sub-tree is no longer displayed.
+ * <p>
+ * Methods from {@link Container.Ordered} (and from {@linkContainer.Indexed} if
+ * implemented) are expected to work as in "preorder" of the currently visible
+ * hierarchy. This means for example that the return value of size method
+ * changes when subtree is collapsed/expanded. In other words items in collapsed
+ * sub trees should be "ignored" by container when the container is accessed
+ * with methods introduced in {@link Container.Ordered} or
+ * {@linkContainer.Indexed}. From the accessors point of view, items in
+ * collapsed subtrees don't exist.
+ * <p>
+ *
+ */
+public interface Collapsible extends Hierarchical, Ordered {
+
+ /**
+ * <p>
+ * Collapsing the {@link Item} indicated by <code>itemId</code> hides all
+ * children, and their respective children, from the {@link Container}.
+ * </p>
+ *
+ * <p>
+ * If called on a leaf {@link Item}, this method does nothing.
+ * </p>
+ *
+ * @param itemId
+ * the identifier of the collapsed {@link Item}
+ * @param collapsed
+ * <code>true</code> if you want to collapse the children below
+ * this {@link Item}. <code>false</code> if you want to
+ * uncollapse the children.
+ */
+ public void setCollapsed(Object itemId, boolean collapsed);
+
+ /**
+ * <p>
+ * Checks whether the {@link Item}, identified by <code>itemId</code> is
+ * collapsed or not.
+ * </p>
+ *
+ * <p>
+ * If an {@link Item} is "collapsed" its children are not included in
+ * methods used to list Items in this container.
+ * </p>
+ *
+ * @param itemId
+ * The {@link Item}'s identifier that is to be checked.
+ * @return <code>true</code> iff the {@link Item} identified by
+ * <code>itemId</code> is currently collapsed, otherwise
+ * <code>false</code>.
+ */
+ public boolean isCollapsed(Object itemId);
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/Container.java b/compatibility-server/src/main/java/com/vaadin/v7/data/Container.java
new file mode 100644
index 0000000000..c280525dcd
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/Container.java
@@ -0,0 +1,1255 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+
+import com.vaadin.v7.data.util.filter.SimpleStringFilter;
+import com.vaadin.v7.data.util.filter.UnsupportedFilterException;
+
+/**
+ * <p>
+ * A specialized set of identified Items. Basically the Container is a set of
+ * {@link Item}s, but it imposes certain constraints on its contents. These
+ * constraints state the following:
+ * </p>
+ *
+ * <ul>
+ * <li>All Items in the Container must have the same number of Properties.
+ * <li>All Items in the Container must have the same Property ID's (see
+ * {@link Item#getItemPropertyIds()}).
+ * <li>All Properties in the Items corresponding to the same Property ID must
+ * have the same data type.
+ * <li>All Items within a container are uniquely identified by their non-null
+ * IDs.
+ * </ul>
+ *
+ * <p>
+ * The Container can be visualized as a representation of a relational database
+ * table. Each Item in the Container represents a row in the table, and all
+ * cells in a column (identified by a Property ID) have the same data type. Note
+ * that as with the cells in a database table, no Property in a Container may be
+ * empty, though they may contain <code>null</code> values.
+ * </p>
+ *
+ * <p>
+ * Note that though uniquely identified, the Items in a Container are not
+ * necessarily {@link Container.Ordered ordered} or {@link Container.Indexed
+ * indexed}.
+ * </p>
+ *
+ * <p>
+ * Containers can derive Item ID's from the item properties or use other,
+ * container specific or user specified identifiers.
+ * </p>
+ *
+ * <p>
+ * If a container is {@link Filterable filtered} or {@link Sortable sorted},
+ * most of the the methods of the container interface and its subinterfaces
+ * (container size, {@link #containsId(Object)}, iteration and indices etc.)
+ * relate to the filtered and sorted view, not to the full container contents.
+ * See individual method javadoc for exceptions to this (adding and removing
+ * items).
+ * </p>
+ *
+ * <p>
+ * <img src=doc-files/Container_full.gif>
+ * </p>
+ *
+ * <p>
+ * The Container interface is split to several subinterfaces so that a class can
+ * implement only the ones it needs.
+ * </p>
+ *
+ * @author Vaadin Ltd
+ * @since 3.0
+ */
+public interface Container extends Serializable {
+
+ /**
+ * Gets the {@link Item} with the given Item ID from the Container. If the
+ * Container does not contain the requested Item, <code>null</code> is
+ * returned.
+ * <p>
+ * Containers should not return Items that are filtered out.
+ *
+ * @param itemId
+ * ID of the {@link Item} to retrieve
+ * @return the {@link Item} with the given ID or <code>null</code> if the
+ * Item is not found in the Container
+ */
+ public Item getItem(Object itemId);
+
+ /**
+ * Gets the ID's of all Properties stored in the Container. The ID's cannot
+ * be modified through the returned collection.
+ *
+ * @return unmodifiable collection of Property IDs
+ */
+ public Collection<?> getContainerPropertyIds();
+
+ /**
+ * Gets the ID's of all visible (after filtering and sorting) Items stored
+ * in the Container. The ID's cannot be modified through the returned
+ * collection.
+ * <p>
+ * If the container is {@link Ordered}, the collection returned by this
+ * method should follow that order. If the container is {@link Sortable},
+ * the items should be in the sorted order.
+ * <p>
+ * Calling this method for large lazy containers can be an expensive
+ * operation and should be avoided when practical.
+ *
+ * @return unmodifiable collection of Item IDs
+ */
+ public Collection<?> getItemIds();
+
+ /**
+ * Gets the Property identified by the given itemId and propertyId from the
+ * Container. If the Container does not contain the item or it is filtered
+ * out, or the Container does not have the Property, <code>null</code> is
+ * returned.
+ *
+ * @param itemId
+ * ID of the visible Item which contains the Property
+ * @param propertyId
+ * ID of the Property to retrieve
+ * @return Property with the given ID or <code>null</code>
+ */
+ public Property getContainerProperty(Object itemId, Object propertyId);
+
+ /**
+ * Gets the data type of all Properties identified by the given Property ID.
+ *
+ * @param propertyId
+ * ID identifying the Properties
+ * @return data type of the Properties
+ */
+ public Class<?> getType(Object propertyId);
+
+ /**
+ * Gets the number of visible Items in the Container.
+ * <p>
+ * Filtering can hide items so that they will not be visible through the
+ * container API.
+ *
+ * @return number of Items in the Container
+ */
+ public int size();
+
+ /**
+ * Tests if the Container contains the specified Item.
+ * <p>
+ * Filtering can hide items so that they will not be visible through the
+ * container API, and this method should respect visibility of items (i.e.
+ * only indicate visible items as being in the container) if feasible for
+ * the container.
+ *
+ * @param itemId
+ * ID the of Item to be tested
+ * @return boolean indicating if the Container holds the specified Item
+ */
+ public boolean containsId(Object itemId);
+
+ /**
+ * Creates a new Item with the given ID in the Container.
+ *
+ * <p>
+ * The new Item is returned, and it is ready to have its Properties
+ * modified. Returns <code>null</code> if the operation fails or the
+ * Container already contains a Item with the given ID.
+ * </p>
+ *
+ * <p>
+ * This functionality is optional.
+ * </p>
+ *
+ * @param itemId
+ * ID of the Item to be created
+ * @return Created new Item, or <code>null</code> in case of a failure
+ * @throws UnsupportedOperationException
+ * if adding an item with an explicit item ID is not supported
+ * by the container
+ */
+ public Item addItem(Object itemId) throws UnsupportedOperationException;
+
+ /**
+ * Creates a new Item into the Container, and assign it an automatic ID.
+ *
+ * <p>
+ * The new ID is returned, or <code>null</code> if the operation fails.
+ * After a successful call you can use the {@link #getItem(Object ItemId)
+ * <code>getItem</code>}method to fetch the Item.
+ * </p>
+ *
+ * <p>
+ * This functionality is optional.
+ * </p>
+ *
+ * @return ID of the newly created Item, or <code>null</code> in case of a
+ * failure
+ * @throws UnsupportedOperationException
+ * if adding an item without an explicit item ID is not
+ * supported by the container
+ */
+ public Object addItem() throws UnsupportedOperationException;
+
+ /**
+ * Removes the Item identified by <code>ItemId</code> from the Container.
+ *
+ * <p>
+ * Containers that support filtering should also allow removing an item that
+ * is currently filtered out.
+ * </p>
+ *
+ * <p>
+ * This functionality is optional.
+ * </p>
+ *
+ * @param itemId
+ * ID of the Item to remove
+ * @return <code>true</code> if the operation succeeded, <code>false</code>
+ * if not
+ * @throws UnsupportedOperationException
+ * if the container does not support removing individual items
+ */
+ public boolean removeItem(Object itemId)
+ throws UnsupportedOperationException;
+
+ /**
+ * Adds a new Property to all Items in the Container. The Property ID, data
+ * type and default value of the new Property are given as parameters.
+ * <p>
+ * This functionality is optional.
+ *
+ * @param propertyId
+ * ID of the Property
+ * @param type
+ * Data type of the new Property
+ * @param defaultValue
+ * The value all created Properties are initialized to
+ * @return <code>true</code> if the operation succeeded, <code>false</code>
+ * if not
+ * @throws UnsupportedOperationException
+ * if the container does not support explicitly adding container
+ * properties
+ */
+ public boolean addContainerProperty(Object propertyId, Class<?> type,
+ Object defaultValue) throws UnsupportedOperationException;
+
+ /**
+ * Removes a Property specified by the given Property ID from the Container.
+ * Note that the Property will be removed from all Items in the Container.
+ * <p>
+ * This functionality is optional.
+ *
+ * @param propertyId
+ * ID of the Property to remove
+ * @return <code>true</code> if the operation succeeded, <code>false</code>
+ * if not
+ * @throws UnsupportedOperationException
+ * if the container does not support removing container
+ * properties
+ */
+ public boolean removeContainerProperty(Object propertyId)
+ throws UnsupportedOperationException;
+
+ /**
+ * Removes all Items from the Container.
+ *
+ * <p>
+ * Note that Property ID and type information is preserved. This
+ * functionality is optional.
+ * </p>
+ *
+ * @return <code>true</code> if the operation succeeded, <code>false</code>
+ * if not
+ * @throws UnsupportedOperationException
+ * if the container does not support removing all items
+ */
+ public boolean removeAllItems() throws UnsupportedOperationException;
+
+ /**
+ * Interface for Container classes whose {@link Item}s can be traversed in
+ * order.
+ *
+ * <p>
+ * If the container is filtered or sorted, the traversal applies to the
+ * filtered and sorted view.
+ * </p>
+ * <p>
+ * The <code>addItemAfter()</code> methods should apply filters to the added
+ * item after inserting it, possibly hiding it immediately. If the container
+ * is being sorted, they may add items at the correct sorted position
+ * instead of the given position. See also {@link Filterable} and
+ * {@link Sortable} for more information.
+ * </p>
+ */
+ public interface Ordered extends Container {
+
+ /**
+ * Gets the ID of the Item following the Item that corresponds to
+ * <code>itemId</code>. If the given Item is the last or not found in
+ * the Container, <code>null</code> is returned.
+ *
+ * @param itemId
+ * ID of a visible Item in the Container
+ * @return ID of the next visible Item or <code>null</code>
+ */
+ public Object nextItemId(Object itemId);
+
+ /**
+ * Gets the ID of the Item preceding the Item that corresponds to
+ * <code>itemId</code>. If the given Item is the first or not found in
+ * the Container, <code>null</code> is returned.
+ *
+ * @param itemId
+ * ID of a visible Item in the Container
+ * @return ID of the previous visible Item or <code>null</code>
+ */
+ public Object prevItemId(Object itemId);
+
+ /**
+ * Gets the ID of the first Item in the Container.
+ *
+ * @return ID of the first visible Item in the Container
+ */
+ public Object firstItemId();
+
+ /**
+ * Gets the ID of the last Item in the Container..
+ *
+ * @return ID of the last visible Item in the Container
+ */
+ public Object lastItemId();
+
+ /**
+ * Tests if the Item corresponding to the given Item ID is the first
+ * Item in the Container.
+ *
+ * @param itemId
+ * ID of an Item in the Container
+ * @return <code>true</code> if the Item is first visible item in the
+ * Container, <code>false</code> if not
+ */
+ public boolean isFirstId(Object itemId);
+
+ /**
+ * Tests if the Item corresponding to the given Item ID is the last Item
+ * in the Container.
+ *
+ * @return <code>true</code> if the Item is last visible item in the
+ * Container, <code>false</code> if not
+ */
+ public boolean isLastId(Object itemId);
+
+ /**
+ * Adds a new item after the given item.
+ * <p>
+ * Adding an item after null item adds the item as first item of the
+ * ordered container.
+ * </p>
+ *
+ * @see Ordered Ordered: adding items in filtered or sorted containers
+ *
+ * @param previousItemId
+ * Id of the visible item in ordered container after which to
+ * insert the new item.
+ * @return item id the the created new item or null if the operation
+ * fails.
+ * @throws UnsupportedOperationException
+ * if the operation is not supported by the container
+ */
+ public Object addItemAfter(Object previousItemId)
+ throws UnsupportedOperationException;
+
+ /**
+ * Adds a new item after the given item.
+ * <p>
+ * Adding an item after null item adds the item as first item of the
+ * ordered container.
+ * </p>
+ *
+ * @see Ordered Ordered: adding items in filtered or sorted containers
+ *
+ * @param previousItemId
+ * Id of the visible item in ordered container after which to
+ * insert the new item.
+ * @param newItemId
+ * Id of the new item to be added.
+ * @return new item or null if the operation fails.
+ * @throws UnsupportedOperationException
+ * if the operation is not supported by the container
+ */
+ public Item addItemAfter(Object previousItemId, Object newItemId)
+ throws UnsupportedOperationException;
+
+ }
+
+ /**
+ * Interface for Container classes whose {@link Item}s can be sorted.
+ * <p>
+ * When an {@link Ordered} or {@link Indexed} container is sorted, all
+ * relevant operations of these interfaces should only use the filtered and
+ * sorted contents and the filtered indices to the container. Indices or
+ * item identifiers in the public API refer to the visible view unless
+ * otherwise stated. However, the <code>addItem*()</code> methods may add
+ * items that will be filtered out after addition or moved to another
+ * position based on sorting.
+ * </p>
+ * <p>
+ * How sorting is performed when a {@link Hierarchical} container implements
+ * {@link Sortable} is implementation specific and should be documented in
+ * the implementing class. However, the recommended approach is sorting the
+ * roots and the sets of children of each item separately.
+ * </p>
+ * <p>
+ * Depending on the container type, sorting a container may permanently
+ * change the internal order of items in the container.
+ * </p>
+ */
+ public interface Sortable extends Ordered {
+
+ /**
+ * Sorts the container items.
+ * <p>
+ * Sorting a container can irreversibly change the order of its items or
+ * only change the order temporarily, depending on the container.
+ *
+ * @param propertyId
+ * Array of container property IDs, whose values are used to
+ * sort the items in container as primary, secondary, ...
+ * sorting criterion. All of the item IDs must be in the
+ * collection returned by
+ * {@link #getSortableContainerPropertyIds()}
+ * @param ascending
+ * Array of sorting order flags corresponding to each
+ * property ID used in sorting. If this array is shorter than
+ * propertyId array, ascending order is assumed for items
+ * where the order is not specified. Use <code>true</code> to
+ * sort in ascending order, <code>false</code> to use
+ * descending order.
+ */
+ void sort(Object[] propertyId, boolean[] ascending);
+
+ /**
+ * Gets the container property IDs which can be used to sort the items.
+ *
+ * @return the IDs of the properties that can be used for sorting the
+ * container
+ */
+ Collection<?> getSortableContainerPropertyIds();
+
+ }
+
+ /**
+ * Interface for Container classes whose {@link Item}s can be accessed by
+ * their position in the container.
+ * <p>
+ * If the container is filtered or sorted, all indices refer to the filtered
+ * and sorted view. However, the <code>addItemAt()</code> methods may add
+ * items that will be filtered out after addition or moved to another
+ * position based on sorting.
+ * </p>
+ */
+ public interface Indexed extends Ordered {
+
+ /**
+ * Gets the index of the Item corresponding to the itemId. The following
+ * is <code>true</code> for the returned index: 0 <= index < size(), or
+ * index = -1 if there is no visible item with that id in the container.
+ *
+ * @param itemId
+ * ID of an Item in the Container
+ * @return index of the Item, or -1 if (the filtered and sorted view of)
+ * the Container does not include the Item
+ */
+ public int indexOfId(Object itemId);
+
+ /**
+ * Get the item id for the item at the position given by
+ * <code>index</code>.
+ * <p>
+ *
+ * @param index
+ * the index of the requested item id
+ * @return the item id of the item at the given index
+ * @throws IndexOutOfBoundsException
+ * if <code>index</code> is outside the range of the
+ * container. (i.e.
+ * <code>index &lt; 0 || container.size()-1 &lt; index</code>
+ * )
+ */
+ public Object getIdByIndex(int index);
+
+ /**
+ * Get <code>numberOfItems</code> consecutive item ids from the
+ * container, starting with the item id at <code>startIndex</code>.
+ * <p>
+ * Implementations should return at most <code>numberOfItems</code> item
+ * ids, but can contain less if the container has less items than
+ * required to fulfill the request. The returned list must hence contain
+ * all of the item ids from the range:
+ * <p>
+ * <code>startIndex</code> to
+ * <code>max(startIndex + (numberOfItems-1), container.size()-1)</code>.
+ * <p>
+ * For quick migration to new API see:
+ * {@link ContainerHelpers#getItemIdsUsingGetIdByIndex(int, int, Indexed)}
+ *
+ * @param startIndex
+ * the index for the first item which id to include
+ * @param numberOfItems
+ * the number of consecutive item ids to get from the given
+ * start index, must be >= 0
+ * @return List containing the requested item ids or empty list if
+ * <code>numberOfItems</code> == 0; not null
+ *
+ * @throws IllegalArgumentException
+ * if <code>numberOfItems</code> is < 0
+ * @throws IndexOutOfBoundsException
+ * if <code>startIndex</code> is outside the range of the
+ * container. (i.e.
+ * <code>startIndex &lt; 0 || container.size()-1 &lt; startIndex</code>
+ * )
+ *
+ * @since 7.0
+ */
+ public List<?> getItemIds(int startIndex, int numberOfItems);
+
+ /**
+ * Adds a new item at given index (in the filtered view).
+ * <p>
+ * The indices of the item currently in the given position and all the
+ * following items are incremented.
+ * </p>
+ * <p>
+ * This method should apply filters to the added item after inserting
+ * it, possibly hiding it immediately. If the container is being sorted,
+ * the item may be added at the correct sorted position instead of the
+ * given position. See {@link Indexed}, {@link Ordered},
+ * {@link Filterable} and {@link Sortable} for more information.
+ * </p>
+ *
+ * @param index
+ * Index (in the filtered and sorted view) to add the new
+ * item.
+ * @return item id of the created item or null if the operation fails.
+ * @throws UnsupportedOperationException
+ * if the operation is not supported by the container
+ */
+ public Object addItemAt(int index) throws UnsupportedOperationException;
+
+ /**
+ * Adds a new item at given index (in the filtered view).
+ * <p>
+ * The indexes of the item currently in the given position and all the
+ * following items are incremented.
+ * </p>
+ * <p>
+ * This method should apply filters to the added item after inserting
+ * it, possibly hiding it immediately. If the container is being sorted,
+ * the item may be added at the correct sorted position instead of the
+ * given position. See {@link Indexed}, {@link Filterable} and
+ * {@link Sortable} for more information.
+ * </p>
+ *
+ * @param index
+ * Index (in the filtered and sorted view) at which to add
+ * the new item.
+ * @param newItemId
+ * Id of the new item to be added.
+ * @return new {@link Item} or null if the operation fails.
+ * @throws UnsupportedOperationException
+ * if the operation is not supported by the container
+ */
+ public Item addItemAt(int index, Object newItemId)
+ throws UnsupportedOperationException;
+
+ /**
+ * An <code>Event</code> object specifying information about the added
+ * items.
+ *
+ * @since 7.4
+ */
+ public interface ItemAddEvent extends ItemSetChangeEvent {
+
+ /**
+ * Gets the item id of the first added item.
+ *
+ * @return item id of the first added item
+ */
+ public Object getFirstItemId();
+
+ /**
+ * Gets the index of the first added item.
+ *
+ * @return index of the first added item
+ */
+ public int getFirstIndex();
+
+ /**
+ * Gets the number of the added items.
+ *
+ * @return the number of added items.
+ */
+ public int getAddedItemsCount();
+ }
+
+ /**
+ * An <code>Event</code> object specifying information about the removed
+ * items.
+ *
+ * @since 7.4
+ */
+ public interface ItemRemoveEvent extends ItemSetChangeEvent {
+ /**
+ * Gets the item id of the first removed item.
+ *
+ * @return item id of the first removed item
+ */
+ public Object getFirstItemId();
+
+ /**
+ * Gets the index of the first removed item.
+ *
+ * @return index of the first removed item
+ */
+ public int getFirstIndex();
+
+ /**
+ * Gets the number of the removed items.
+ *
+ * @return the number of removed items
+ */
+ public int getRemovedItemsCount();
+ }
+ }
+
+ /**
+ * <p>
+ * Interface for <code>Container</code> classes whose Items can be arranged
+ * hierarchically. This means that the Items in the container belong in a
+ * tree-like structure, with the following quirks:
+ * </p>
+ *
+ * <ul>
+ * <li>The Item structure may have more than one root elements
+ * <li>The Items in the hierarchy can be declared explicitly to be able or
+ * unable to have children.
+ * </ul>
+ */
+ public interface Hierarchical extends Container {
+
+ /**
+ * Gets the IDs of all Items that are children of the specified Item.
+ * The returned collection is unmodifiable.
+ *
+ * @param itemId
+ * ID of the Item whose children the caller is interested in
+ * @return An unmodifiable {@link java.util.Collection collection}
+ * containing the IDs of all other Items that are children in
+ * the container hierarchy
+ */
+ public Collection<?> getChildren(Object itemId);
+
+ /**
+ * Gets the ID of the parent Item of the specified Item.
+ *
+ * @param itemId
+ * ID of the Item whose parent the caller wishes to find out.
+ * @return the ID of the parent Item. Will be <code>null</code> if the
+ * specified Item is a root element.
+ */
+ public Object getParent(Object itemId);
+
+ /**
+ * Gets the IDs of all Items in the container that don't have a parent.
+ * Such items are called <code>root</code> Items. The returned
+ * collection is unmodifiable.
+ *
+ * @return An unmodifiable {@link java.util.Collection collection}
+ * containing IDs of all root elements of the container
+ */
+ public Collection<?> rootItemIds();
+
+ /**
+ * <p>
+ * Sets the parent of an Item. The new parent item must exist and be
+ * able to have children. (
+ * <code>{@link #areChildrenAllowed(Object)} == true</code> ). It is
+ * also possible to detach a node from the hierarchy (and thus make it
+ * root) by setting the parent <code>null</code>.
+ * </p>
+ *
+ * <p>
+ * This operation is optional.
+ * </p>
+ *
+ * @param itemId
+ * ID of the item to be set as the child of the Item
+ * identified with <code>newParentId</code>
+ * @param newParentId
+ * ID of the Item that's to be the new parent of the Item
+ * identified with <code>itemId</code>
+ * @return <code>true</code> if the operation succeeded,
+ * <code>false</code> if not
+ */
+ public boolean setParent(Object itemId, Object newParentId)
+ throws UnsupportedOperationException;
+
+ /**
+ * Tests if the Item with given ID can have children.
+ *
+ * @param itemId
+ * ID of the Item in the container whose child capability is
+ * to be tested
+ * @return <code>true</code> if the specified Item exists in the
+ * Container and it can have children, <code>false</code> if
+ * it's not found from the container or it can't have children.
+ */
+ public boolean areChildrenAllowed(Object itemId);
+
+ /**
+ * <p>
+ * Sets the given Item's capability to have children. If the Item
+ * identified with <code>itemId</code> already has children and
+ * <code>{@link #areChildrenAllowed(Object)}</code> is false this method
+ * fails and <code>false</code> is returned.
+ * </p>
+ * <p>
+ * The children must be first explicitly removed with
+ * {@link #setParent(Object itemId, Object newParentId)}or
+ * {@link com.vaadin.v7.data.Container#removeItem(Object itemId)}.
+ * </p>
+ *
+ * <p>
+ * This operation is optional. If it is not implemented, the method
+ * always returns <code>false</code>.
+ * </p>
+ *
+ * @param itemId
+ * ID of the Item in the container whose child capability is
+ * to be set
+ * @param areChildrenAllowed
+ * boolean value specifying if the Item can have children or
+ * not
+ * @return <code>true</code> if the operation succeeded,
+ * <code>false</code> if not
+ */
+ public boolean setChildrenAllowed(Object itemId,
+ boolean areChildrenAllowed)
+ throws UnsupportedOperationException;
+
+ /**
+ * Tests if the Item specified with <code>itemId</code> is a root Item.
+ * The hierarchical container can have more than one root and must have
+ * at least one unless it is empty. The
+ * {@link #getParent(Object itemId)} method always returns
+ * <code>null</code> for root Items.
+ *
+ * @param itemId
+ * ID of the Item whose root status is to be tested
+ * @return <code>true</code> if the specified Item is a root,
+ * <code>false</code> if not
+ */
+ public boolean isRoot(Object itemId);
+
+ /**
+ * <p>
+ * Tests if the Item specified with <code>itemId</code> has child Items
+ * or if it is a leaf. The {@link #getChildren(Object itemId)} method
+ * always returns <code>null</code> for leaf Items.
+ * </p>
+ *
+ * <p>
+ * Note that being a leaf does not imply whether or not an Item is
+ * allowed to have children.
+ * </p>
+ *
+ * @param itemId
+ * ID of the Item to be tested
+ * @return <code>true</code> if the specified Item has children,
+ * <code>false</code> if not (is a leaf)
+ */
+ public boolean hasChildren(Object itemId);
+
+ /**
+ * <p>
+ * Removes the Item identified by <code>ItemId</code> from the
+ * Container.
+ * </p>
+ *
+ * <p>
+ * Note that this does not remove any children the item might have.
+ * </p>
+ *
+ * @param itemId
+ * ID of the Item to remove
+ * @return <code>true</code> if the operation succeeded,
+ * <code>false</code> if not
+ */
+ @Override
+ public boolean removeItem(Object itemId)
+ throws UnsupportedOperationException;
+ }
+
+ /**
+ * Interface that is implemented by containers which allow reducing their
+ * visible contents based on a set of filters. This interface has been
+ * renamed from {@link Filterable}, and implementing the new
+ * {@link Filterable} instead of or in addition to {@link SimpleFilterable}
+ * is recommended. This interface might be removed in future Vaadin
+ * versions.
+ * <p>
+ * When a set of filters are set, only items that match all 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.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * How filtering is performed when a {@link Hierarchical} container
+ * implements {@link SimpleFilterable} is implementation specific and should
+ * be documented in the implementing class.
+ * </p>
+ * <p>
+ * Adding items (if supported) to a filtered {@link Ordered} or
+ * {@link Indexed} container should insert them immediately after the
+ * indicated visible item. The unfiltered position of items added at index
+ * 0, at index {@link com.vaadin.v7.data.Container#size()} or at an undefined
+ * position is up to the implementation.
+ * </p>
+ * <p>
+ * The functionality of SimpleFilterable can be implemented using the
+ * {@link Filterable} API and {@link SimpleStringFilter}.
+ * </p>
+ *
+ * @since 5.0 (renamed from Filterable to SimpleFilterable in 6.6)
+ */
+ public interface SimpleFilterable extends Container, Serializable {
+
+ /**
+ * Add a filter for given property.
+ * <p>
+ * The API {@link Filterable#addContainerFilter(Filter)} is recommended
+ * instead of this method. A {@link SimpleStringFilter} can be used with
+ * the new API to implement the old string filtering functionality.
+ * <p>
+ * The filter accepts items for which toString() of the value of the
+ * given property contains or starts with given filterString. Other
+ * items are not visible in the container when filtered.
+ * <p>
+ * If a container has multiple filters, only items accepted by all
+ * filters are visible.
+ *
+ * @param propertyId
+ * Property for which the filter is applied to.
+ * @param filterString
+ * String that must match the value of the property
+ * @param ignoreCase
+ * Determine if the casing can be ignored when comparing
+ * strings.
+ * @param onlyMatchPrefix
+ * Only match prefixes; no other matches are included.
+ */
+ public void addContainerFilter(Object propertyId, String filterString,
+ boolean ignoreCase, boolean onlyMatchPrefix);
+
+ /**
+ * Remove all filters from all properties.
+ */
+ public void removeAllContainerFilters();
+
+ /**
+ * Remove all filters from the given property.
+ *
+ * @param propertyId
+ * for which to remove filters
+ */
+ public void removeContainerFilters(Object propertyId);
+ }
+
+ /**
+ * Filter interface for container filtering.
+ * <p>
+ * If a filter does not support in-memory filtering,
+ * {@link #passesFilter(Item)} should throw
+ * {@link UnsupportedOperationException}.
+ * <p>
+ * Lazy containers must be able to map filters to their internal
+ * representation (e.g. SQL or JPA 2.0 Criteria).
+ * <p>
+ * An {@link UnsupportedFilterException} can be thrown by the container if a
+ * particular filter is not supported by the container.
+ * <p>
+ * 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 itemId
+ * identifier of the item being filtered; may be null when
+ * the item is being added to the container
+ * @param item
+ * the item being filtered
+ * @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(Object itemId, 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.
+ * <p>
+ * When a set of filters are set, only items that match all 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.
+ * </p>
+ * <p>
+ * When an {@link Ordered} or {@link Indexed} container is filtered, all
+ * operations of these interfaces should only use the filtered and sorted
+ * contents and the filtered indices to the container. Indices or item
+ * identifiers in the public API refer to the visible view unless otherwise
+ * stated. However, the <code>addItem*()</code> methods may add items that
+ * will be filtered out after addition or moved to another position based on
+ * sorting.
+ * </p>
+ * <p>
+ * How filtering is performed when a {@link Hierarchical} container
+ * implements {@link Filterable} is implementation specific and should be
+ * documented in the implementing class.
+ * </p>
+ * <p>
+ * 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.v7.data.Container#size()} or at an
+ * undefined position is up to the implementation.
+ * </p>
+ *
+ * <p>
+ * This API replaces the old Filterable interface, renamed to
+ * {@link SimpleFilterable} in Vaadin 6.6.
+ * </p>
+ *
+ * @since 6.6
+ */
+ public interface Filterable extends Container, Serializable {
+ /**
+ * Adds a filter for the container.
+ * <p>
+ * If a container has multiple filters, only items accepted by all
+ * filters are visible.
+ *
+ * @throws UnsupportedFilterException
+ * if the filter is not supported by the container
+ */
+ public void addContainerFilter(Filter filter)
+ throws UnsupportedFilterException;
+
+ /**
+ * Removes a filter from the container.
+ * <p>
+ * This requires that the equals() method considers the filters as
+ * equivalent (same instance or properly implemented equals() method).
+ */
+ public void removeContainerFilter(Filter filter);
+
+ /**
+ * Remove all active filters from the container.
+ */
+ public void removeAllContainerFilters();
+
+ /**
+ * Returns the filters which have been applied to the container
+ *
+ * @return A collection of filters which have been applied to the
+ * container. An empty collection if no filters have been
+ * applied.
+ * @since 7.1
+ */
+ public Collection<Filter> getContainerFilters();
+ }
+
+ /**
+ * Interface implemented by viewer classes capable of using a Container as a
+ * data source.
+ */
+ public interface Viewer extends Serializable {
+
+ /**
+ * Sets the Container that serves as the data source of the viewer.
+ *
+ * @param newDataSource
+ * The new data source Item
+ */
+ public void setContainerDataSource(Container newDataSource);
+
+ /**
+ * Gets the Container serving as the data source of the viewer.
+ *
+ * @return data source Container
+ */
+ public Container getContainerDataSource();
+
+ }
+
+ /**
+ * <p>
+ * Interface implemented by the editor classes supporting editing the
+ * Container. Implementing this interface means that the Container serving
+ * as the data source of the editor can be modified through it.
+ * </p>
+ * <p>
+ * Note that not implementing the <code>Container.Editor</code> interface
+ * does not restrict the class from editing the Container contents
+ * internally.
+ * </p>
+ */
+ public interface Editor extends Container.Viewer, Serializable {
+
+ }
+
+ /* Contents change event */
+
+ /**
+ * An <code>Event</code> object specifying the Container whose Item set has
+ * changed (items added, removed or reordered).
+ *
+ * A simple property value change is not an item set change.
+ */
+ public interface ItemSetChangeEvent extends Serializable {
+
+ /**
+ * Gets the Property where the event occurred.
+ *
+ * @return source of the event
+ */
+ public Container getContainer();
+ }
+
+ /**
+ * Container Item set change listener interface.
+ * <p>
+ * An item set change refers to addition, removal or reordering of items in
+ * the container. A simple property value change is not an item set change.
+ */
+ public interface ItemSetChangeListener extends Serializable {
+
+ /**
+ * Lets the listener know a Containers visible (filtered and/or sorted,
+ * if applicable) Item set has changed.
+ *
+ * @param event
+ * change event text
+ */
+ public void containerItemSetChange(Container.ItemSetChangeEvent event);
+ }
+
+ /**
+ * The interface for adding and removing <code>ItemSetChangeEvent</code>
+ * listeners. By implementing this interface a class explicitly announces
+ * that it will generate a <code>ItemSetChangeEvent</code> when its contents
+ * are modified.
+ * <p>
+ * An item set change refers to addition, removal or reordering of items in
+ * the container. A simple property value change is not an item set change.
+ *
+ * <p>
+ * Note: The general Java convention is not to explicitly declare that a
+ * class generates events, but to directly define the
+ * <code>addListener</code> and <code>removeListener</code> methods. That
+ * way the caller of these methods has no real way of finding out if the
+ * class really will send the events, or if it just defines the methods to
+ * be able to implement an interface.
+ * </p>
+ */
+ public interface ItemSetChangeNotifier extends Serializable {
+
+ /**
+ * Adds an Item set change listener for the object.
+ *
+ * @param listener
+ * listener to be added
+ */
+ public void addItemSetChangeListener(
+ Container.ItemSetChangeListener listener);
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #addItemSetChangeListener(ItemSetChangeListener)}
+ **/
+ @Deprecated
+ public void addListener(Container.ItemSetChangeListener listener);
+
+ /**
+ * Removes the Item set change listener from the object.
+ *
+ * @param listener
+ * listener to be removed
+ */
+ public void removeItemSetChangeListener(
+ Container.ItemSetChangeListener listener);
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #removeItemSetChangeListener(ItemSetChangeListener)}
+ **/
+ @Deprecated
+ public void removeListener(Container.ItemSetChangeListener listener);
+ }
+
+ /* Property set change event */
+
+ /**
+ * An <code>Event</code> object specifying the Container whose Property set
+ * has changed.
+ * <p>
+ * A property set change means the addition, removal or other structural
+ * changes to the properties of a container. Changes concerning the set of
+ * items in the container and their property values are not property set
+ * changes.
+ */
+ public interface PropertySetChangeEvent extends Serializable {
+
+ /**
+ * Retrieves the Container whose contents have been modified.
+ *
+ * @return Source Container of the event.
+ */
+ public Container getContainer();
+ }
+
+ /**
+ * The listener interface for receiving <code>PropertySetChangeEvent</code>
+ * objects.
+ * <p>
+ * A property set change means the addition, removal or other structural
+ * change of the properties (supported property IDs) of a container. Changes
+ * concerning the set of items in the container and their property values
+ * are not property set changes.
+ */
+ public interface PropertySetChangeListener extends Serializable {
+
+ /**
+ * Notifies this listener that the set of property IDs supported by the
+ * Container has changed.
+ *
+ * @param event
+ * Change event.
+ */
+ public void containerPropertySetChange(
+ Container.PropertySetChangeEvent event);
+ }
+
+ /**
+ * <p>
+ * The interface for adding and removing <code>PropertySetChangeEvent</code>
+ * listeners. By implementing this interface a class explicitly announces
+ * that it will generate a <code>PropertySetChangeEvent</code> when the set
+ * of property IDs supported by the container is modified.
+ * </p>
+ *
+ * <p>
+ * A property set change means the addition, removal or other structural
+ * changes to the properties of a container. Changes concerning the set of
+ * items in the container and their property values are not property set
+ * changes.
+ * </p>
+ *
+ * <p>
+ * Note that the general Java convention is not to explicitly declare that a
+ * class generates events, but to directly define the
+ * <code>addListener</code> and <code>removeListener</code> methods. That
+ * way the caller of these methods has no real way of finding out if the
+ * class really will send the events, or if it just defines the methods to
+ * be able to implement an interface.
+ * </p>
+ */
+ public interface PropertySetChangeNotifier extends Serializable {
+
+ /**
+ * Registers a new Property set change listener for this Container.
+ *
+ * @param listener
+ * The new Listener to be registered
+ */
+ public void addPropertySetChangeListener(
+ Container.PropertySetChangeListener listener);
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #addPropertySetChangeListener(PropertySetChangeListener)}
+ **/
+ @Deprecated
+ public void addListener(Container.PropertySetChangeListener listener);
+
+ /**
+ * Removes a previously registered Property set change listener.
+ *
+ * @param listener
+ * Listener to be removed
+ */
+ public void removePropertySetChangeListener(
+ Container.PropertySetChangeListener listener);
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #removePropertySetChangeListener(PropertySetChangeListener)}
+ **/
+ @Deprecated
+ public void removeListener(
+ Container.PropertySetChangeListener listener);
+ }
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/ContainerHelpers.java b/compatibility-server/src/main/java/com/vaadin/v7/data/ContainerHelpers.java
new file mode 100644
index 0000000000..c782f33133
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/ContainerHelpers.java
@@ -0,0 +1,102 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.vaadin.v7.data.Container.Indexed;
+
+/**
+ * Contains helper methods for containers that can be used to ease development
+ * of containers in Vaadin.
+ *
+ * @since 7.0
+ */
+public class ContainerHelpers implements Serializable {
+
+ /**
+ * Get a range of item ids from the container using
+ * {@link Indexed#getIdByIndex(int)}. This is just a helper method to aid
+ * developers to quickly add the required functionality to a Container
+ * during development. This should not be used in a "finished product"
+ * unless fetching an id for an index is very inexpensive because a separate
+ * request will be performed for each index in the range.
+ *
+ * @param startIndex
+ * index of the first item id to get
+ * @param numberOfIds
+ * the number of consecutive items whose ids should be returned
+ * @param container
+ * the container from which the items should be fetched
+ * @return A list of item ids in the range specified
+ */
+ public static List<?> getItemIdsUsingGetIdByIndex(int startIndex,
+ int numberOfIds, Container.Indexed container) {
+
+ if (container == null) {
+ throw new IllegalArgumentException(
+ "The given container cannot be null!");
+ }
+
+ if (startIndex < 0) {
+ throw new IndexOutOfBoundsException(
+ "Start index cannot be negative! startIndex=" + startIndex);
+ }
+
+ if (startIndex > container.size()) {
+ throw new IndexOutOfBoundsException(
+ "Start index exceeds container size! startIndex="
+ + startIndex + " containerLastItemIndex="
+ + (container.size() - 1));
+ }
+
+ if (numberOfIds < 1) {
+ if (numberOfIds == 0) {
+ return Collections.emptyList();
+ }
+
+ throw new IllegalArgumentException(
+ "Cannot get negative amount of items! numberOfItems="
+ + numberOfIds);
+ }
+
+ // not included in the range
+ int endIndex = startIndex + numberOfIds;
+
+ if (endIndex > container.size()) {
+ endIndex = container.size();
+ }
+
+ ArrayList<Object> rangeOfIds = new ArrayList<Object>();
+ for (int i = startIndex; i < endIndex; i++) {
+ Object idByIndex = container.getIdByIndex(i);
+ if (idByIndex == null) {
+ throw new RuntimeException(
+ "Unable to get item id for index: " + i
+ + " from container using Container.Indexed#getIdByIndex() "
+ + "even though container.size() > endIndex. "
+ + "Returned item id was null. "
+ + "Check your container implementation!");
+ }
+ rangeOfIds.add(idByIndex);
+ }
+
+ return Collections.unmodifiableList(rangeOfIds);
+ }
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/ContainerOrderedWrapper.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/ContainerOrderedWrapper.java
new file mode 100644
index 0000000000..9ac8038f03
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/ContainerOrderedWrapper.java
@@ -0,0 +1,728 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.vaadin.v7.data.Container;
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Property;
+
+/**
+ * <p>
+ * A wrapper class for adding external ordering to containers not implementing
+ * the {@link com.vaadin.v7.data.Container.Ordered} interface.
+ * </p>
+ *
+ * <p>
+ * If the wrapped container is changed directly (that is, not through the
+ * wrapper), and does not implement Container.ItemSetChangeNotifier and/or
+ * Container.PropertySetChangeNotifier the hierarchy information must be updated
+ * with the {@link #updateOrderWrapper()} method.
+ * </p>
+ *
+ * @author Vaadin Ltd.
+ * @since 3.0
+ */
+@SuppressWarnings("serial")
+public class ContainerOrderedWrapper implements Container.Ordered,
+ Container.ItemSetChangeNotifier, Container.PropertySetChangeNotifier {
+
+ /**
+ * The wrapped container
+ */
+ private final Container container;
+
+ /**
+ * Ordering information, ie. the mapping from Item ID to the next item ID.
+ * The last item id should not be present
+ */
+ private Hashtable<Object, Object> next;
+
+ /**
+ * Reverse ordering information for convenience and performance reasons. The
+ * first item id should not be present
+ */
+ private Hashtable<Object, Object> prev;
+
+ /**
+ * ID of the first Item in the container.
+ */
+ private Object first;
+
+ /**
+ * ID of the last Item in the container.
+ */
+ private Object last;
+
+ /**
+ * Is the wrapped container ordered by itself, ie. does it implement the
+ * Container.Ordered interface by itself? If it does, this class will use
+ * the methods of the underlying container directly.
+ */
+ private boolean ordered = false;
+
+ /**
+ * The last known size of the wrapped container. Used to check whether items
+ * have been added or removed to the wrapped container, when the wrapped
+ * container does not send ItemSetChangeEvents.
+ */
+ private int lastKnownSize = -1;
+
+ /**
+ * Constructs a new ordered wrapper for an existing Container. Works even if
+ * the to-be-wrapped container already implements the Container.Ordered
+ * interface.
+ *
+ * @param toBeWrapped
+ * the container whose contents need to be ordered.
+ */
+ public ContainerOrderedWrapper(Container toBeWrapped) {
+
+ container = toBeWrapped;
+ ordered = container instanceof Container.Ordered;
+
+ // Checks arguments
+ if (container == null) {
+ throw new NullPointerException("Null can not be wrapped");
+ }
+
+ // Creates initial order if needed
+ updateOrderWrapper();
+ }
+
+ /**
+ * Removes the specified Item from the wrapper's internal hierarchy
+ * structure.
+ * <p>
+ * Note : The Item is not removed from the underlying Container.
+ * </p>
+ *
+ * @param id
+ * the ID of the Item to be removed from the ordering.
+ */
+ private void removeFromOrderWrapper(Object id) {
+ if (id != null) {
+ final Object pid = prev.get(id);
+ final Object nid = next.get(id);
+ if (first.equals(id)) {
+ first = nid;
+ }
+ if (last.equals(id)) {
+ last = pid;
+ }
+ if (nid != null) {
+ if (pid == null) {
+ prev.remove(nid);
+ } else {
+ prev.put(nid, pid);
+ }
+ }
+ if (pid != null) {
+ if (nid == null) {
+ next.remove(pid);
+ } else {
+ next.put(pid, nid);
+ }
+ }
+ next.remove(id);
+ prev.remove(id);
+ }
+ }
+
+ /**
+ * Registers the specified Item to the last position in the wrapper's
+ * internal ordering. The underlying container is not modified.
+ *
+ * @param id
+ * the ID of the Item to be added to the ordering.
+ */
+ private void addToOrderWrapper(Object id) {
+
+ // Adds the if to tail
+ if (last != null) {
+ next.put(last, id);
+ prev.put(id, last);
+ last = id;
+ } else {
+ first = last = id;
+ }
+ }
+
+ /**
+ * Registers the specified Item after the specified itemId in the wrapper's
+ * internal ordering. The underlying container is not modified. Given item
+ * id must be in the container, or must be null.
+ *
+ * @param id
+ * the ID of the Item to be added to the ordering.
+ * @param previousItemId
+ * the Id of the previous item.
+ */
+ private void addToOrderWrapper(Object id, Object previousItemId) {
+
+ if (last == previousItemId || last == null) {
+ addToOrderWrapper(id);
+ } else {
+ if (previousItemId == null) {
+ next.put(id, first);
+ prev.put(first, id);
+ first = id;
+ } else {
+ prev.put(id, previousItemId);
+ next.put(id, next.get(previousItemId));
+ prev.put(next.get(previousItemId), id);
+ next.put(previousItemId, id);
+ }
+ }
+ }
+
+ /**
+ * Updates the wrapper's internal ordering information to include all Items
+ * in the underlying container.
+ * <p>
+ * Note : If the contents of the wrapped container change without the
+ * wrapper's knowledge, this method needs to be called to update the
+ * ordering information of the Items.
+ * </p>
+ */
+ public void updateOrderWrapper() {
+
+ if (!ordered) {
+
+ final Collection<?> ids = container.getItemIds();
+
+ // Recreates ordering if some parts of it are missing
+ if (next == null || first == null || last == null || prev == null) {
+ first = null;
+ last = null;
+ next = new Hashtable<Object, Object>();
+ prev = new Hashtable<Object, Object>();
+ }
+
+ // Filter out all the missing items
+ final LinkedList<?> l = new LinkedList<Object>(next.keySet());
+ for (final Iterator<?> i = l.iterator(); i.hasNext();) {
+ final Object id = i.next();
+ if (!container.containsId(id)) {
+ removeFromOrderWrapper(id);
+ }
+ }
+
+ // Adds missing items
+ for (final Iterator<?> i = ids.iterator(); i.hasNext();) {
+ final Object id = i.next();
+ if (!next.containsKey(id) && last != id) {
+ addToOrderWrapper(id);
+ }
+ }
+ }
+ }
+
+ /*
+ * Gets the first item stored in the ordered container Don't add a JavaDoc
+ * comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public Object firstItemId() {
+ if (ordered) {
+ return ((Container.Ordered) container).firstItemId();
+ }
+ return first;
+ }
+
+ /*
+ * Tests if the given item is the first item in the container Don't add a
+ * JavaDoc comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public boolean isFirstId(Object itemId) {
+ if (ordered) {
+ return ((Container.Ordered) container).isFirstId(itemId);
+ }
+ return first != null && first.equals(itemId);
+ }
+
+ /*
+ * Tests if the given item is the last item in the container Don't add a
+ * JavaDoc comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public boolean isLastId(Object itemId) {
+ if (ordered) {
+ return ((Container.Ordered) container).isLastId(itemId);
+ }
+ return last != null && last.equals(itemId);
+ }
+
+ /*
+ * Gets the last item stored in the ordered container Don't add a JavaDoc
+ * comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public Object lastItemId() {
+ if (ordered) {
+ return ((Container.Ordered) container).lastItemId();
+ }
+ return last;
+ }
+
+ /*
+ * Gets the item that is next from the specified item. Don't add a JavaDoc
+ * comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public Object nextItemId(Object itemId) {
+ if (ordered) {
+ return ((Container.Ordered) container).nextItemId(itemId);
+ }
+ if (itemId == null) {
+ return null;
+ }
+ return next.get(itemId);
+ }
+
+ /*
+ * Gets the item that is previous from the specified item. Don't add a
+ * JavaDoc comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public Object prevItemId(Object itemId) {
+ if (ordered) {
+ return ((Container.Ordered) container).prevItemId(itemId);
+ }
+ if (itemId == null) {
+ return null;
+ }
+ return prev.get(itemId);
+ }
+
+ /**
+ * Registers a new Property to all Items in the Container.
+ *
+ * @param propertyId
+ * the ID of the new Property.
+ * @param type
+ * the Data type of the new Property.
+ * @param defaultValue
+ * the value all created Properties are initialized to.
+ * @return <code>true</code> if the operation succeeded, <code>false</code>
+ * if not
+ */
+ @Override
+ public boolean addContainerProperty(Object propertyId, Class<?> type,
+ Object defaultValue) throws UnsupportedOperationException {
+
+ return container.addContainerProperty(propertyId, type, defaultValue);
+ }
+
+ /**
+ * Creates a new Item into the Container, assigns it an automatic ID, and
+ * adds it to the ordering.
+ *
+ * @return the autogenerated ID of the new Item or <code>null</code> if the
+ * operation failed
+ * @throws UnsupportedOperationException
+ * if the addItem is not supported.
+ */
+ @Override
+ public Object addItem() throws UnsupportedOperationException {
+
+ final Object id = container.addItem();
+ if (!ordered && id != null) {
+ addToOrderWrapper(id);
+ }
+ return id;
+ }
+
+ /**
+ * Registers a new Item by its ID to the underlying container and to the
+ * ordering.
+ *
+ * @param itemId
+ * the ID of the Item to be created.
+ * @return the added Item or <code>null</code> if the operation failed
+ * @throws UnsupportedOperationException
+ * if the addItem is not supported.
+ */
+ @Override
+ public Item addItem(Object itemId) throws UnsupportedOperationException {
+ final Item item = container.addItem(itemId);
+ if (!ordered && item != null) {
+ addToOrderWrapper(itemId);
+ }
+ return item;
+ }
+
+ /**
+ * Removes all items from the underlying container and from the ordering.
+ *
+ * @return <code>true</code> if the operation succeeded, otherwise
+ * <code>false</code>
+ * @throws UnsupportedOperationException
+ * if the removeAllItems is not supported.
+ */
+ @Override
+ public boolean removeAllItems() throws UnsupportedOperationException {
+ final boolean success = container.removeAllItems();
+ if (!ordered && success) {
+ first = last = null;
+ next.clear();
+ prev.clear();
+ }
+ return success;
+ }
+
+ /**
+ * Removes an Item specified by the itemId from the underlying container and
+ * from the ordering.
+ *
+ * @param itemId
+ * the ID of the Item to be removed.
+ * @return <code>true</code> if the operation succeeded, <code>false</code>
+ * if not
+ * @throws UnsupportedOperationException
+ * if the removeItem is not supported.
+ */
+ @Override
+ public boolean removeItem(Object itemId)
+ throws UnsupportedOperationException {
+
+ final boolean success = container.removeItem(itemId);
+ if (!ordered && success) {
+ removeFromOrderWrapper(itemId);
+ }
+ return success;
+ }
+
+ /**
+ * Removes the specified Property from the underlying container and from the
+ * ordering.
+ * <p>
+ * Note : The Property will be removed from all the Items in the Container.
+ * </p>
+ *
+ * @param propertyId
+ * the ID of the Property to remove.
+ * @return <code>true</code> if the operation succeeded, <code>false</code>
+ * if not
+ * @throws UnsupportedOperationException
+ * if the removeContainerProperty is not supported.
+ */
+ @Override
+ public boolean removeContainerProperty(Object propertyId)
+ throws UnsupportedOperationException {
+ return container.removeContainerProperty(propertyId);
+ }
+
+ /*
+ * Does the container contain the specified Item? Don't add a JavaDoc
+ * comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public boolean containsId(Object itemId) {
+ return container.containsId(itemId);
+ }
+
+ /*
+ * Gets the specified Item from the container. Don't add a JavaDoc comment
+ * here, we use the default documentation from implemented interface.
+ */
+ @Override
+ public Item getItem(Object itemId) {
+ return container.getItem(itemId);
+ }
+
+ /*
+ * Gets the ID's of all Items stored in the Container Don't add a JavaDoc
+ * comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public Collection<?> getItemIds() {
+ if (ordered) {
+ return ((Container.Ordered) container).getItemIds();
+ } else if (first == null) {
+ return new ArrayList<Object>();
+ } else {
+ List<Object> itemIds = new ArrayList<Object>();
+ itemIds.add(first);
+ Object current = first;
+ while (next.containsKey(current)) {
+ current = next.get(current);
+ itemIds.add(current);
+ }
+ return itemIds;
+ }
+
+ }
+
+ /*
+ * Gets the Property identified by the given itemId and propertyId from the
+ * Container Don't add a JavaDoc comment here, we use the default
+ * documentation from implemented interface.
+ */
+ @Override
+ public Property getContainerProperty(Object itemId, Object propertyId) {
+ return container.getContainerProperty(itemId, propertyId);
+ }
+
+ /*
+ * Gets the ID's of all Properties stored in the Container Don't add a
+ * JavaDoc comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public Collection<?> getContainerPropertyIds() {
+ return container.getContainerPropertyIds();
+ }
+
+ /*
+ * Gets the data type of all Properties identified by the given Property ID.
+ * Don't add a JavaDoc comment here, we use the default documentation from
+ * implemented interface.
+ */
+ @Override
+ public Class<?> getType(Object propertyId) {
+ return container.getType(propertyId);
+ }
+
+ /*
+ * Gets the number of Items in the Container. Don't add a JavaDoc comment
+ * here, we use the default documentation from implemented interface.
+ */
+ @Override
+ public int size() {
+ int newSize = container.size();
+ assert newSize >= 0;
+ if (lastKnownSize != -1 && newSize != lastKnownSize
+ && !(container instanceof Container.ItemSetChangeNotifier)) {
+ // Update the internal cache when the size of the container changes
+ // and the container is incapable of sending ItemSetChangeEvents
+ updateOrderWrapper();
+ }
+ lastKnownSize = newSize;
+ return newSize;
+ }
+
+ /*
+ * Registers a new Item set change listener for this Container. Don't add a
+ * JavaDoc comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public void addItemSetChangeListener(
+ Container.ItemSetChangeListener listener) {
+ if (container instanceof Container.ItemSetChangeNotifier) {
+ ((Container.ItemSetChangeNotifier) container)
+ .addItemSetChangeListener(new PiggybackListener(listener));
+ }
+ }
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #addItemSetChangeListener(com.vaadin.v7.data.Container.ItemSetChangeListener)}
+ **/
+ @Override
+ @Deprecated
+ public void addListener(Container.ItemSetChangeListener listener) {
+ addItemSetChangeListener(listener);
+ }
+
+ /*
+ * Removes a Item set change listener from the object. Don't add a JavaDoc
+ * comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public void removeItemSetChangeListener(
+ Container.ItemSetChangeListener listener) {
+ if (container instanceof Container.ItemSetChangeNotifier) {
+ ((Container.ItemSetChangeNotifier) container)
+ .removeItemSetChangeListener(
+ new PiggybackListener(listener));
+ }
+ }
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #removeItemSetChangeListener(com.vaadin.v7.data.Container.ItemSetChangeListener)}
+ **/
+ @Override
+ @Deprecated
+ public void removeListener(Container.ItemSetChangeListener listener) {
+ removeItemSetChangeListener(listener);
+ }
+
+ /*
+ * Registers a new Property set change listener for this Container. Don't
+ * add a JavaDoc comment here, we use the default documentation from
+ * implemented interface.
+ */
+ @Override
+ public void addPropertySetChangeListener(
+ Container.PropertySetChangeListener listener) {
+ if (container instanceof Container.PropertySetChangeNotifier) {
+ ((Container.PropertySetChangeNotifier) container)
+ .addPropertySetChangeListener(
+ new PiggybackListener(listener));
+ }
+ }
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #addPropertySetChangeListener(com.vaadin.v7.data.Container.PropertySetChangeListener)}
+ **/
+ @Override
+ @Deprecated
+ public void addListener(Container.PropertySetChangeListener listener) {
+ addPropertySetChangeListener(listener);
+ }
+
+ /*
+ * Removes a Property set change listener from the object. Don't add a
+ * JavaDoc comment here, we use the default documentation from implemented
+ * interface.
+ */
+ @Override
+ public void removePropertySetChangeListener(
+ Container.PropertySetChangeListener listener) {
+ if (container instanceof Container.PropertySetChangeNotifier) {
+ ((Container.PropertySetChangeNotifier) container)
+ .removePropertySetChangeListener(
+ new PiggybackListener(listener));
+ }
+ }
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #removePropertySetChangeListener(com.vaadin.v7.data.Container.PropertySetChangeListener)}
+ **/
+ @Override
+ @Deprecated
+ public void removeListener(Container.PropertySetChangeListener listener) {
+ removePropertySetChangeListener(listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object,
+ * java.lang.Object)
+ */
+ @Override
+ public Item addItemAfter(Object previousItemId, Object newItemId)
+ throws UnsupportedOperationException {
+
+ // If the previous item is not in the container, fail
+ if (previousItemId != null && !containsId(previousItemId)) {
+ return null;
+ }
+
+ // Adds the item to container
+ final Item item = container.addItem(newItemId);
+
+ // Puts the new item to its correct place
+ if (!ordered && item != null) {
+ addToOrderWrapper(newItemId, previousItemId);
+ }
+
+ return item;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object)
+ */
+ @Override
+ public Object addItemAfter(Object previousItemId)
+ throws UnsupportedOperationException {
+
+ // If the previous item is not in the container, fail
+ if (previousItemId != null && !containsId(previousItemId)) {
+ return null;
+ }
+
+ // Adds the item to container
+ final Object id = container.addItem();
+
+ // Puts the new item to its correct place
+ if (!ordered && id != null) {
+ addToOrderWrapper(id, previousItemId);
+ }
+
+ return id;
+ }
+
+ /**
+ * This listener 'piggybacks' on the real listener in order to update the
+ * wrapper when needed. It proxies equals() and hashCode() to the real
+ * listener so that the correct listener gets removed.
+ *
+ */
+ private class PiggybackListener
+ implements Container.PropertySetChangeListener,
+ Container.ItemSetChangeListener {
+
+ Object listener;
+
+ public PiggybackListener(Object realListener) {
+ listener = realListener;
+ }
+
+ @Override
+ public void containerItemSetChange(ItemSetChangeEvent event) {
+ updateOrderWrapper();
+ ((Container.ItemSetChangeListener) listener)
+ .containerItemSetChange(event);
+
+ }
+
+ @Override
+ public void containerPropertySetChange(PropertySetChangeEvent event) {
+ updateOrderWrapper();
+ ((Container.PropertySetChangeListener) listener)
+ .containerPropertySetChange(event);
+
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj == listener || (obj != null && obj.equals(listener));
+ }
+
+ @Override
+ public int hashCode() {
+ return listener.hashCode();
+ }
+
+ }
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/DefaultItemSorter.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/DefaultItemSorter.java
new file mode 100644
index 0000000000..345d50614f
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/DefaultItemSorter.java
@@ -0,0 +1,221 @@
+/*
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+
+import com.vaadin.v7.data.Container;
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Property;
+import com.vaadin.v7.data.Container.Sortable;
+
+/**
+ * Provides a default implementation of an ItemSorter. The
+ * <code>DefaultItemSorter</code> adheres to the
+ * {@link Sortable#sort(Object[], boolean[])} rules and sorts the container
+ * according to the properties given using
+ * {@link #setSortProperties(Sortable, Object[], boolean[])}.
+ * <p>
+ * A Comparator is used for comparing the individual <code>Property</code>
+ * values. The comparator can be set using the constructor. If no comparator is
+ * provided a default comparator is used.
+ *
+ */
+public class DefaultItemSorter implements ItemSorter {
+
+ private java.lang.Object[] sortPropertyIds;
+ private boolean[] sortDirections;
+ private Container container;
+ private Comparator<Object> propertyValueComparator;
+
+ /**
+ * Constructs a DefaultItemSorter using the default <code>Comparator</code>
+ * for comparing <code>Property</code>values.
+ *
+ */
+ public DefaultItemSorter() {
+ this(new DefaultPropertyValueComparator());
+ }
+
+ /**
+ * Constructs a DefaultItemSorter which uses the <code>Comparator</code>
+ * indicated by the <code>propertyValueComparator</code> parameter for
+ * comparing <code>Property</code>values.
+ *
+ * @param propertyValueComparator
+ * The comparator to use when comparing individual
+ * <code>Property</code> values
+ */
+ public DefaultItemSorter(Comparator<Object> propertyValueComparator) {
+ this.propertyValueComparator = propertyValueComparator;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.util.ItemSorter#compare(java.lang.Object,
+ * java.lang.Object)
+ */
+ @Override
+ public int compare(Object o1, Object o2) {
+ Item item1 = container.getItem(o1);
+ Item item2 = container.getItem(o2);
+
+ /*
+ * Items can be null if the container is filtered. Null is considered
+ * "less" than not-null.
+ */
+ if (item1 == null) {
+ if (item2 == null) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else if (item2 == null) {
+ return -1;
+ }
+
+ for (int i = 0; i < sortPropertyIds.length; i++) {
+
+ int result = compareProperty(sortPropertyIds[i], sortDirections[i],
+ item1, item2);
+
+ // If order can be decided
+ if (result != 0) {
+ return result;
+ }
+
+ }
+
+ return 0;
+ }
+
+ /**
+ * Compares the property indicated by <code>propertyId</code> in the items
+ * indicated by <code>item1</code> and <code>item2</code> for order. Returns
+ * a negative integer, zero, or a positive integer as the property value in
+ * the first item is less than, equal to, or greater than the property value
+ * in the second item. If the <code>sortDirection</code> is false the
+ * returned value is negated.
+ * <p>
+ * The comparator set for this <code>DefaultItemSorter</code> is used for
+ * comparing the two property values.
+ *
+ * @param propertyId
+ * The property id for the property that is used for comparison.
+ * @param sortDirection
+ * The direction of the sort. A false value negates the result.
+ * @param item1
+ * The first item to compare.
+ * @param item2
+ * The second item to compare.
+ * @return a negative, zero, or positive integer if the property value in
+ * the first item is less than, equal to, or greater than the
+ * property value in the second item. Negated if
+ * {@code sortDirection} is false.
+ */
+ protected int compareProperty(Object propertyId, boolean sortDirection,
+ Item item1, Item item2) {
+
+ // Get the properties to compare
+ final Property<?> property1 = item1.getItemProperty(propertyId);
+ final Property<?> property2 = item2.getItemProperty(propertyId);
+
+ // Get the values to compare
+ final Object value1 = (property1 == null) ? null : property1.getValue();
+ final Object value2 = (property2 == null) ? null : property2.getValue();
+
+ // Result of the comparison
+ int r = 0;
+ if (sortDirection) {
+ r = propertyValueComparator.compare(value1, value2);
+ } else {
+ r = propertyValueComparator.compare(value2, value1);
+ }
+
+ return r;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.util.ItemSorter#setSortProperties(com.vaadin.data.
+ * Container .Sortable, java.lang.Object[], boolean[])
+ */
+ @Override
+ public void setSortProperties(Container.Sortable container,
+ Object[] propertyId, boolean[] ascending) {
+ this.container = container;
+
+ // Removes any non-sortable property ids
+ final List<Object> ids = new ArrayList<Object>();
+ final List<Boolean> orders = new ArrayList<Boolean>();
+ final Collection<?> sortable = container
+ .getSortableContainerPropertyIds();
+ for (int i = 0; i < propertyId.length; i++) {
+ if (sortable.contains(propertyId[i])) {
+ ids.add(propertyId[i]);
+ orders.add(Boolean
+ .valueOf(i < ascending.length ? ascending[i] : true));
+ }
+ }
+
+ sortPropertyIds = ids.toArray();
+ sortDirections = new boolean[orders.size()];
+ for (int i = 0; i < sortDirections.length; i++) {
+ sortDirections[i] = (orders.get(i)).booleanValue();
+ }
+
+ }
+
+ /**
+ * Provides a default comparator used for comparing {@link Property} values.
+ * The <code>DefaultPropertyValueComparator</code> assumes all objects it
+ * compares can be cast to Comparable.
+ *
+ */
+ public static class DefaultPropertyValueComparator
+ implements Comparator<Object>, Serializable {
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public int compare(Object o1, Object o2) {
+ int r = 0;
+ // Normal non-null comparison
+ if (o1 != null && o2 != null) {
+ // Assume the objects can be cast to Comparable, throw
+ // ClassCastException otherwise.
+ r = ((Comparable<Object>) o1).compareTo(o2);
+ } else if (o1 == o2) {
+ // Objects are equal if both are null
+ r = 0;
+ } else {
+ if (o1 == null) {
+ r = -1; // null is less than non-null
+ } else {
+ r = 1; // non-null is greater than null
+ }
+ }
+
+ return r;
+ }
+ }
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/HierarchicalContainerOrderedWrapper.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/HierarchicalContainerOrderedWrapper.java
new file mode 100644
index 0000000000..f25842aec9
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/HierarchicalContainerOrderedWrapper.java
@@ -0,0 +1,82 @@
+/*
+ * 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.util.Collection;
+
+import com.vaadin.v7.data.Container.Hierarchical;
+
+/**
+ * A wrapper class for adding external ordering to containers not implementing
+ * the {@link com.vaadin.v7.data.Container.Ordered} interface while retaining
+ * {@link Hierarchical} features.
+ *
+ * @see ContainerOrderedWrapper
+ */
+@SuppressWarnings({ "serial" })
+public class HierarchicalContainerOrderedWrapper extends ContainerOrderedWrapper
+ implements Hierarchical {
+
+ private Hierarchical hierarchical;
+
+ public HierarchicalContainerOrderedWrapper(Hierarchical toBeWrapped) {
+ super(toBeWrapped);
+ hierarchical = toBeWrapped;
+ }
+
+ @Override
+ public boolean areChildrenAllowed(Object itemId) {
+ return hierarchical.areChildrenAllowed(itemId);
+ }
+
+ @Override
+ public Collection<?> getChildren(Object itemId) {
+ return hierarchical.getChildren(itemId);
+ }
+
+ @Override
+ public Object getParent(Object itemId) {
+ return hierarchical.getParent(itemId);
+ }
+
+ @Override
+ public boolean hasChildren(Object itemId) {
+ return hierarchical.hasChildren(itemId);
+ }
+
+ @Override
+ public boolean isRoot(Object itemId) {
+ return hierarchical.isRoot(itemId);
+ }
+
+ @Override
+ public Collection<?> rootItemIds() {
+ return hierarchical.rootItemIds();
+ }
+
+ @Override
+ public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed)
+ throws UnsupportedOperationException {
+ return hierarchical.setChildrenAllowed(itemId, areChildrenAllowed);
+ }
+
+ @Override
+ public boolean setParent(Object itemId, Object newParentId)
+ throws UnsupportedOperationException {
+ return hierarchical.setParent(itemId, newParentId);
+ }
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/ItemSorter.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/ItemSorter.java
new file mode 100644
index 0000000000..9ca21ca137
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/ItemSorter.java
@@ -0,0 +1,70 @@
+/*
+ * 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.Comparator;
+
+import com.vaadin.v7.data.Container;
+import com.vaadin.v7.data.Container.Sortable;
+
+/**
+ * An item comparator which is compatible with the {@link Sortable} interface.
+ * The <code>ItemSorter</code> interface can be used in <code>Sortable</code>
+ * implementations to provide a custom sorting method.
+ */
+public interface ItemSorter
+ extends Comparator<Object>, Cloneable, Serializable {
+
+ /**
+ * Sets the parameters for an upcoming sort operation. The parameters
+ * determine what container to sort and how the <code>ItemSorter</code>
+ * sorts the container.
+ *
+ * @param container
+ * The container that will be sorted. The container must contain
+ * the propertyIds given in the <code>propertyId</code>
+ * parameter.
+ * @param propertyId
+ * The property ids used for sorting. The property ids must exist
+ * in the container and should only be used if they are also
+ * sortable, i.e include in the collection returned by
+ * <code>container.getSortableContainerPropertyIds()</code>. See
+ * {@link Sortable#sort(Object[], boolean[])} for more
+ * information.
+ * @param ascending
+ * Sorting order flags for each property id. See
+ * {@link Sortable#sort(Object[], boolean[])} for more
+ * information.
+ */
+ void setSortProperties(Container.Sortable container, Object[] propertyId,
+ boolean[] ascending);
+
+ /**
+ * Compares its two arguments for order. Returns a negative integer, zero,
+ * or a positive integer as the first argument is less than, equal to, or
+ * greater than the second.
+ * <p>
+ * The parameters for the <code>ItemSorter</code> <code>compare()</code>
+ * method must always be item ids which exist in the container set using
+ * {@link #setSortProperties(Sortable, Object[], boolean[])}.
+ *
+ * @see Comparator#compare(Object, Object)
+ */
+ @Override
+ int compare(Object itemId1, Object itemId2);
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/PropertyValueGenerator.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/PropertyValueGenerator.java
new file mode 100644
index 0000000000..8cc4e7ac10
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/PropertyValueGenerator.java
@@ -0,0 +1,103 @@
+/*
+ * 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 com.vaadin.data.sort.SortOrder;
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Property;
+import com.vaadin.v7.data.Container.Filter;
+import com.vaadin.v7.data.util.filter.UnsupportedFilterException;
+
+/**
+ * PropertyValueGenerator for GeneratedPropertyContainer.
+ *
+ * @param <T>
+ * Property data type
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public abstract class PropertyValueGenerator<T> implements Serializable {
+
+ /**
+ * Returns value for given Item. Used by GeneratedPropertyContainer when
+ * generating new properties.
+ *
+ * @param item
+ * currently handled item
+ * @param itemId
+ * item id for currently handled item
+ * @param propertyId
+ * id for this property
+ * @return generated value
+ */
+ public abstract T getValue(Item item, Object itemId, Object propertyId);
+
+ /**
+ * Return Property type for this generator. This function is called when
+ * {@link Property#getType()} is called for generated property.
+ *
+ * @return type of generated property
+ */
+ public abstract Class<T> getType();
+
+ /**
+ * Translates sorting of the generated property in a specific direction to a
+ * set of property ids and directions in the underlying container.
+ * <p>
+ * SortOrder is similar to (or the same as) the SortOrder already defined
+ * for Grid.
+ * <p>
+ * The default implementation of this method returns an empty array, which
+ * means that the property will not be included in
+ * getSortableContainerPropertyIds(). Attempting to sort by that column
+ * throws UnsupportedOperationException.
+ *
+ * Returning null is not allowed.
+ *
+ * @param order
+ * a sort order for this property
+ * @return an array of sort orders describing how this property is sorted
+ */
+ public SortOrder[] getSortProperties(SortOrder order) {
+ return new SortOrder[] {};
+ }
+
+ /**
+ * Return an updated filter that should be compatible with the underlying
+ * container.
+ * <p>
+ * This function is called when setting a filter for this generated
+ * property. Returning null from this function causes
+ * GeneratedPropertyContainer to discard the filter and not use it.
+ * <p>
+ * By default this function throws UnsupportedFilterException.
+ *
+ * @param filter
+ * original filter for this property
+ * @return modified filter that is compatible with the underlying container
+ * @throws UnsupportedFilterException
+ * if the implementation doesn't support modifying the provided
+ * filter
+ */
+ public Filter modifyFilter(Filter filter)
+ throws UnsupportedFilterException {
+ throw new UnsupportedFilterException(
+ "Filter" + filter + " is not supported");
+ }
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/AbstractJunctionFilter.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/AbstractJunctionFilter.java
new file mode 100644
index 0000000000..17b708a22c
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/AbstractJunctionFilter.java
@@ -0,0 +1,88 @@
+/*
+ * 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.filter;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import com.vaadin.v7.data.Container.Filter;
+
+/**
+ * Abstract base class for filters that are composed of multiple sub-filters.
+ *
+ * The method {@link #appliesToProperty(Object)} is provided to help
+ * implementing {@link Filter} for in-memory filters.
+ *
+ * @since 6.6
+ */
+public abstract class AbstractJunctionFilter implements Filter {
+
+ protected final Collection<Filter> filters;
+
+ public AbstractJunctionFilter(Filter... filters) {
+ this.filters = Collections
+ .unmodifiableCollection(Arrays.asList(filters));
+ }
+
+ /**
+ * Returns an unmodifiable collection of the sub-filters of this composite
+ * filter.
+ *
+ * @return
+ */
+ public Collection<Filter> getFilters() {
+ return filters;
+ }
+
+ /**
+ * Returns true if a change in the named property may affect the filtering
+ * result. If some of the sub-filters are not in-memory filters, true is
+ * returned.
+ *
+ * By default, all sub-filters are iterated to check if any of them applies.
+ * If there are no sub-filters, false is returned - override in subclasses
+ * to change this behavior.
+ */
+ @Override
+ public boolean appliesToProperty(Object propertyId) {
+ for (Filter filter : getFilters()) {
+ if (filter.appliesToProperty(propertyId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !getClass().equals(obj.getClass())) {
+ return false;
+ }
+ AbstractJunctionFilter other = (AbstractJunctionFilter) obj;
+ // contents comparison with equals()
+ return Arrays.equals(filters.toArray(), other.filters.toArray());
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = getFilters().size();
+ for (Filter filter : filters) {
+ hash = (hash << 1) ^ filter.hashCode();
+ }
+ return hash;
+ }
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/And.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/And.java
new file mode 100644
index 0000000000..b7b5a18f3d
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/And.java
@@ -0,0 +1,56 @@
+/*
+ * 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.filter;
+
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Container.Filter;
+
+/**
+ * A compound {@link Filter} that accepts an item if all of its filters accept
+ * the item.
+ *
+ * If no filters are given, the filter should accept all items.
+ *
+ * This filter also directly supports in-memory filtering when all sub-filters
+ * do so.
+ *
+ * @see Or
+ *
+ * @since 6.6
+ */
+public final class And extends AbstractJunctionFilter {
+
+ /**
+ *
+ * @param filters
+ * filters of which the And filter will be composed
+ */
+ public And(Filter... filters) {
+ super(filters);
+ }
+
+ @Override
+ public boolean passesFilter(Object itemId, Item item)
+ throws UnsupportedFilterException {
+ for (Filter filter : getFilters()) {
+ if (!filter.passesFilter(itemId, item)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Between.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Between.java
new file mode 100644
index 0000000000..ec0e468554
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Between.java
@@ -0,0 +1,106 @@
+/*
+ * 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.filter;
+
+import java.util.Arrays;
+
+import com.vaadin.shared.util.SharedUtil;
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Container.Filter;
+
+public class Between implements Filter {
+
+ private final Object propertyId;
+ private final Comparable<?> startValue;
+ private final Comparable<?> endValue;
+
+ public Between(Object propertyId, Comparable<?> startValue,
+ Comparable<?> endValue) {
+ this.propertyId = propertyId;
+ this.startValue = startValue;
+ this.endValue = endValue;
+ }
+
+ public Object getPropertyId() {
+ return propertyId;
+ }
+
+ public Comparable<?> getStartValue() {
+ return startValue;
+ }
+
+ public Comparable<?> getEndValue() {
+ return endValue;
+ }
+
+ @Override
+ public boolean passesFilter(Object itemId, Item item)
+ throws UnsupportedOperationException {
+ Object value = item.getItemProperty(getPropertyId()).getValue();
+ if (value instanceof Comparable) {
+ Comparable comparable = (Comparable) value;
+ return isAfterStartValue(comparable)
+ && isBeforeEndValue(comparable);
+ } else if (value == null) {
+ return getStartValue() == null && getEndValue() == null;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean appliesToProperty(Object propertyId) {
+ return getPropertyId() != null && getPropertyId().equals(propertyId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(new Object[] { getPropertyId(), getStartValue(),
+ getEndValue() });
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ // Only objects of the same class can be equal
+ if (!getClass().equals(obj.getClass())) {
+ return false;
+ }
+ final Between o = (Between) obj;
+
+ // Checks the properties one by one
+ boolean propertyIdEqual = SharedUtil.equals(getPropertyId(),
+ o.getPropertyId());
+ boolean startValueEqual = SharedUtil.equals(getStartValue(),
+ o.getStartValue());
+ boolean endValueEqual = SharedUtil.equals(getEndValue(),
+ o.getEndValue());
+ return propertyIdEqual && startValueEqual && endValueEqual;
+
+ }
+
+ private boolean isAfterStartValue(Comparable comparable) {
+ return getStartValue() == null
+ || comparable.compareTo(getStartValue()) >= 0;
+ }
+
+ private boolean isBeforeEndValue(Comparable comparable) {
+ return getEndValue() == null
+ || comparable.compareTo(getEndValue()) <= 0;
+ }
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Compare.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Compare.java
new file mode 100644
index 0000000000..5b945ff411
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Compare.java
@@ -0,0 +1,370 @@
+/*
+ * 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.filter;
+
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Property;
+import com.vaadin.v7.data.Container.Filter;
+
+/**
+ * Simple container filter comparing an item property value against a given
+ * constant value. Use the nested classes {@link Equal}, {@link Greater},
+ * {@link Less}, {@link GreaterOrEqual} and {@link LessOrEqual} instead of this
+ * class directly.
+ *
+ * This filter also directly supports in-memory filtering.
+ *
+ * The reference and actual values must implement {@link Comparable} and the
+ * class of the actual property value must be assignable from the class of the
+ * reference value.
+ *
+ * @since 6.6
+ */
+public abstract class Compare implements Filter {
+
+ public enum Operation {
+ EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL
+ }
+
+ private final Object propertyId;
+ private final Operation operation;
+ private final Object value;
+
+ /**
+ * A {@link Compare} filter that accepts items for which the identified
+ * property value is equal to <code>value</code>.
+ *
+ * For in-memory filters, {@link Comparable#compareTo(Object)} or, if not
+ * Comparable, {@link #equals(Object)} is used for the comparison. For other
+ * containers, the comparison implementation is container dependent and may
+ * use e.g. database comparison operations.
+ *
+ * @since 6.6
+ */
+ public static final class Equal extends Compare {
+ /**
+ * Construct a filter that accepts items for which the identified
+ * property value is equal to <code>value</code>.
+ *
+ * For in-memory filters, equals() is used for the comparison. For other
+ * containers, the comparison implementation is container dependent and
+ * may use e.g. database comparison operations.
+ *
+ * @param propertyId
+ * the identifier of the property whose value to compare
+ * against value, not null
+ * @param value
+ * the value to compare against - null values may or may not
+ * be supported depending on the container
+ */
+ public Equal(Object propertyId, Object value) {
+ super(propertyId, value, Operation.EQUAL);
+ }
+ }
+
+ /**
+ * A {@link Compare} filter that accepts items for which the identified
+ * property value is greater than <code>value</code>.
+ *
+ * For in-memory filters, the values must implement {@link Comparable} and
+ * {@link Comparable#compareTo(Object)} is used for the comparison. For
+ * other containers, the comparison implementation is container dependent
+ * and may use e.g. database comparison operations.
+ *
+ * @since 6.6
+ */
+ public static final class Greater extends Compare {
+ /**
+ * Construct a filter that accepts items for which the identified
+ * property value is greater than <code>value</code>.
+ *
+ * For in-memory filters, the values must implement {@link Comparable}
+ * and {@link Comparable#compareTo(Object)} is used for the comparison.
+ * For other containers, the comparison implementation is container
+ * dependent and may use e.g. database comparison operations.
+ *
+ * @param propertyId
+ * the identifier of the property whose value to compare
+ * against value, not null
+ * @param value
+ * the value to compare against - null values may or may not
+ * be supported depending on the container
+ */
+ public Greater(Object propertyId, Object value) {
+ super(propertyId, value, Operation.GREATER);
+ }
+ }
+
+ /**
+ * A {@link Compare} filter that accepts items for which the identified
+ * property value is less than <code>value</code>.
+ *
+ * For in-memory filters, the values must implement {@link Comparable} and
+ * {@link Comparable#compareTo(Object)} is used for the comparison. For
+ * other containers, the comparison implementation is container dependent
+ * and may use e.g. database comparison operations.
+ *
+ * @since 6.6
+ */
+ public static final class Less extends Compare {
+ /**
+ * Construct a filter that accepts items for which the identified
+ * property value is less than <code>value</code>.
+ *
+ * For in-memory filters, the values must implement {@link Comparable}
+ * and {@link Comparable#compareTo(Object)} is used for the comparison.
+ * For other containers, the comparison implementation is container
+ * dependent and may use e.g. database comparison operations.
+ *
+ * @param propertyId
+ * the identifier of the property whose value to compare
+ * against value, not null
+ * @param value
+ * the value to compare against - null values may or may not
+ * be supported depending on the container
+ */
+ public Less(Object propertyId, Object value) {
+ super(propertyId, value, Operation.LESS);
+ }
+ }
+
+ /**
+ * A {@link Compare} filter that accepts items for which the identified
+ * property value is greater than or equal to <code>value</code>.
+ *
+ * For in-memory filters, the values must implement {@link Comparable} and
+ * {@link Comparable#compareTo(Object)} is used for the comparison. For
+ * other containers, the comparison implementation is container dependent
+ * and may use e.g. database comparison operations.
+ *
+ * @since 6.6
+ */
+ public static final class GreaterOrEqual extends Compare {
+ /**
+ * Construct a filter that accepts items for which the identified
+ * property value is greater than or equal to <code>value</code>.
+ *
+ * For in-memory filters, the values must implement {@link Comparable}
+ * and {@link Comparable#compareTo(Object)} is used for the comparison.
+ * For other containers, the comparison implementation is container
+ * dependent and may use e.g. database comparison operations.
+ *
+ * @param propertyId
+ * the identifier of the property whose value to compare
+ * against value, not null
+ * @param value
+ * the value to compare against - null values may or may not
+ * be supported depending on the container
+ */
+ public GreaterOrEqual(Object propertyId, Object value) {
+ super(propertyId, value, Operation.GREATER_OR_EQUAL);
+ }
+ }
+
+ /**
+ * A {@link Compare} filter that accepts items for which the identified
+ * property value is less than or equal to <code>value</code>.
+ *
+ * For in-memory filters, the values must implement {@link Comparable} and
+ * {@link Comparable#compareTo(Object)} is used for the comparison. For
+ * other containers, the comparison implementation is container dependent
+ * and may use e.g. database comparison operations.
+ *
+ * @since 6.6
+ */
+ public static final class LessOrEqual extends Compare {
+ /**
+ * Construct a filter that accepts items for which the identified
+ * property value is less than or equal to <code>value</code>.
+ *
+ * For in-memory filters, the values must implement {@link Comparable}
+ * and {@link Comparable#compareTo(Object)} is used for the comparison.
+ * For other containers, the comparison implementation is container
+ * dependent and may use e.g. database comparison operations.
+ *
+ * @param propertyId
+ * the identifier of the property whose value to compare
+ * against value, not null
+ * @param value
+ * the value to compare against - null values may or may not
+ * be supported depending on the container
+ */
+ public LessOrEqual(Object propertyId, Object value) {
+ super(propertyId, value, Operation.LESS_OR_EQUAL);
+ }
+ }
+
+ /**
+ * Constructor for a {@link Compare} filter that compares the value of an
+ * item property with the given constant <code>value</code>.
+ *
+ * This constructor is intended to be used by the nested static classes only
+ * ({@link Equal}, {@link Greater}, {@link Less}, {@link GreaterOrEqual},
+ * {@link LessOrEqual}).
+ *
+ * For in-memory filtering, comparisons except EQUAL require that the values
+ * implement {@link Comparable} and {@link Comparable#compareTo(Object)} is
+ * used for the comparison. The equality comparison is performed using
+ * {@link Object#equals(Object)}.
+ *
+ * For other containers, the comparison implementation is container
+ * dependent and may use e.g. database comparison operations. Therefore, the
+ * behavior of comparisons might differ in some cases between in-memory and
+ * other containers.
+ *
+ * @param propertyId
+ * the identifier of the property whose value to compare against
+ * value, not null
+ * @param value
+ * the value to compare against - null values may or may not be
+ * supported depending on the container
+ * @param operation
+ * the comparison {@link Operation} to use
+ */
+ Compare(Object propertyId, Object value, Operation operation) {
+ this.propertyId = propertyId;
+ this.value = value;
+ this.operation = operation;
+ }
+
+ @Override
+ public boolean passesFilter(Object itemId, Item item) {
+ final Property<?> p = item.getItemProperty(getPropertyId());
+ if (null == p) {
+ return false;
+ }
+ Object value = p.getValue();
+ switch (getOperation()) {
+ case EQUAL:
+ return compareEquals(value);
+ case GREATER:
+ return compareValue(value) > 0;
+ case LESS:
+ return compareValue(value) < 0;
+ case GREATER_OR_EQUAL:
+ return compareValue(value) >= 0;
+ case LESS_OR_EQUAL:
+ return compareValue(value) <= 0;
+ }
+ // all cases should have been processed above
+ return false;
+ }
+
+ /**
+ * Checks if the this value equals the given value. Favors Comparable over
+ * equals to better support e.g. BigDecimal where equals is stricter than
+ * compareTo.
+ *
+ * @param otherValue
+ * The value to compare to
+ * @return true if the values are equal, false otherwise
+ */
+ private boolean compareEquals(Object otherValue) {
+ if (value == null || otherValue == null) {
+ return (otherValue == value);
+ } else if (value == otherValue) {
+ return true;
+ } else if (value instanceof Comparable && otherValue.getClass()
+ .isAssignableFrom(getValue().getClass())) {
+ return ((Comparable) value).compareTo(otherValue) == 0;
+ } else {
+ return value.equals(otherValue);
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected int compareValue(Object value1) {
+ if (null == value) {
+ return null == value1 ? 0 : -1;
+ } else if (null == value1) {
+ return 1;
+ } else if (getValue() instanceof Comparable) {
+ if (value1.getClass().isInstance(getValue())) {
+ return -((Comparable) getValue()).compareTo(value1);
+ } else if (getValue().getClass().isInstance(value1)) {
+ // isInstance returns true if value1 is a sub-type of
+ // getValue(), i.e. value1 must here be Comparable
+ return ((Comparable) value1).compareTo(getValue());
+ }
+
+ }
+ throw new IllegalArgumentException("Could not compare the arguments: "
+ + value1 + ", " + getValue());
+ }
+
+ @Override
+ public boolean appliesToProperty(Object propertyId) {
+ return getPropertyId().equals(propertyId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ // Only objects of the same class can be equal
+ if (!getClass().equals(obj.getClass())) {
+ return false;
+ }
+ final Compare o = (Compare) obj;
+
+ // Checks the properties one by one
+ if (getPropertyId() != o.getPropertyId() && null != o.getPropertyId()
+ && !o.getPropertyId().equals(getPropertyId())) {
+ return false;
+ }
+ if (getOperation() != o.getOperation()) {
+ return false;
+ }
+ return (null == getValue()) ? null == o.getValue()
+ : getValue().equals(o.getValue());
+ }
+
+ @Override
+ public int hashCode() {
+ return (null != getPropertyId() ? getPropertyId().hashCode() : 0)
+ ^ (null != getValue() ? getValue().hashCode() : 0);
+ }
+
+ /**
+ * Returns the property id of the property to compare against the fixed
+ * value.
+ *
+ * @return property id (not null)
+ */
+ public Object getPropertyId() {
+ return propertyId;
+ }
+
+ /**
+ * Returns the comparison operation.
+ *
+ * @return {@link Operation}
+ */
+ public Operation getOperation() {
+ return operation;
+ }
+
+ /**
+ * Returns the value to compare the property against.
+ *
+ * @return comparison reference value
+ */
+ public Object getValue() {
+ return value;
+ }
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/IsNull.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/IsNull.java
new file mode 100644
index 0000000000..0a7e115255
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/IsNull.java
@@ -0,0 +1,96 @@
+/*
+ * 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.filter;
+
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Property;
+import com.vaadin.v7.data.Container.Filter;
+
+/**
+ * Simple container filter checking whether an item property value is null.
+ *
+ * This filter also directly supports in-memory filtering.
+ *
+ * @since 6.6
+ */
+public final class IsNull implements Filter {
+
+ private final Object propertyId;
+
+ /**
+ * Constructor for a filter that compares the value of an item property with
+ * null.
+ *
+ * For in-memory filtering, a simple == check is performed. For other
+ * containers, the comparison implementation is container dependent but
+ * should correspond to the in-memory null check.
+ *
+ * @param propertyId
+ * the identifier (not null) of the property whose value to check
+ */
+ public IsNull(Object propertyId) {
+ this.propertyId = propertyId;
+ }
+
+ @Override
+ public boolean passesFilter(Object itemId, Item item)
+ throws UnsupportedOperationException {
+ final Property<?> p = item.getItemProperty(getPropertyId());
+ if (null == p) {
+ return false;
+ }
+ return null == p.getValue();
+ }
+
+ @Override
+ public boolean appliesToProperty(Object propertyId) {
+ return getPropertyId().equals(propertyId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ // Only objects of the same class can be equal
+ if (!getClass().equals(obj.getClass())) {
+ return false;
+ }
+ final IsNull o = (IsNull) obj;
+
+ // Checks the properties one by one
+ return (null != getPropertyId())
+ ? getPropertyId().equals(o.getPropertyId())
+ : null == o.getPropertyId();
+ }
+
+ @Override
+ public int hashCode() {
+ return (null != getPropertyId() ? getPropertyId().hashCode() : 0);
+ }
+
+ /**
+ * Returns the property id of the property tested by the filter, not null
+ * for valid filters.
+ *
+ * @return property id (not null)
+ */
+ public Object getPropertyId() {
+ return propertyId;
+ }
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Like.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Like.java
new file mode 100644
index 0000000000..5d92271afe
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Like.java
@@ -0,0 +1,105 @@
+/*
+ * 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.filter;
+
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Container.Filter;
+
+public class Like implements Filter {
+ private final Object propertyId;
+ private final String value;
+ private boolean caseSensitive;
+
+ public Like(Object propertyId, String value) {
+ this(propertyId, value, true);
+ }
+
+ public Like(Object propertyId, String value, boolean caseSensitive) {
+ this.propertyId = propertyId;
+ this.value = value;
+ setCaseSensitive(caseSensitive);
+ }
+
+ public Object getPropertyId() {
+ return propertyId;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setCaseSensitive(boolean caseSensitive) {
+ this.caseSensitive = caseSensitive;
+ }
+
+ public boolean isCaseSensitive() {
+ return caseSensitive;
+ }
+
+ @Override
+ public boolean passesFilter(Object itemId, Item item)
+ throws UnsupportedOperationException {
+ if (!item.getItemProperty(getPropertyId()).getType()
+ .isAssignableFrom(String.class)) {
+ // We can only handle strings
+ return false;
+ }
+ String colValue = (String) item.getItemProperty(getPropertyId())
+ .getValue();
+
+ // Fix issue #10167 - avoid NPE and drop null property values
+ if (colValue == null) {
+ return false;
+ }
+
+ String pattern = getValue().replace("%", ".*");
+ if (isCaseSensitive()) {
+ return colValue.matches(pattern);
+ }
+ return colValue.toUpperCase().matches(pattern.toUpperCase());
+ }
+
+ @Override
+ public boolean appliesToProperty(Object propertyId) {
+ return getPropertyId() != null && getPropertyId().equals(propertyId);
+ }
+
+ @Override
+ public int hashCode() {
+ return getPropertyId().hashCode() + getValue().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ // Only objects of the same class can be equal
+ if (!getClass().equals(obj.getClass())) {
+ return false;
+ }
+ final Like o = (Like) obj;
+
+ // Checks the properties one by one
+ boolean propertyIdEqual = (null != getPropertyId())
+ ? getPropertyId().equals(o.getPropertyId())
+ : null == o.getPropertyId();
+ boolean valueEqual = (null != getValue())
+ ? getValue().equals(o.getValue()) : null == o.getValue();
+ return propertyIdEqual && valueEqual;
+ }
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Not.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Not.java
new file mode 100644
index 0000000000..d0680eb481
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Not.java
@@ -0,0 +1,82 @@
+/*
+ * 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.filter;
+
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Container.Filter;
+
+/**
+ * Negating filter that accepts the items rejected by another filter.
+ *
+ * This filter directly supports in-memory filtering when the negated filter
+ * does so.
+ *
+ * @since 6.6
+ */
+public final class Not implements Filter {
+ private final Filter filter;
+
+ /**
+ * Constructs a filter that negates a filter.
+ *
+ * @param filter
+ * {@link Filter} to negate, not-null
+ */
+ public Not(Filter filter) {
+ this.filter = filter;
+ }
+
+ /**
+ * Returns the negated filter.
+ *
+ * @return Filter
+ */
+ public Filter getFilter() {
+ return filter;
+ }
+
+ @Override
+ public boolean passesFilter(Object itemId, Item item)
+ throws UnsupportedOperationException {
+ return !filter.passesFilter(itemId, item);
+ }
+
+ /**
+ * Returns true if a change in the named property may affect the filtering
+ * result. Return value is the same as {@link #appliesToProperty(Object)}
+ * for the negated filter.
+ *
+ * @return boolean
+ */
+ @Override
+ public boolean appliesToProperty(Object propertyId) {
+ return filter.appliesToProperty(propertyId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !getClass().equals(obj.getClass())) {
+ return false;
+ }
+ return filter.equals(((Not) obj).getFilter());
+ }
+
+ @Override
+ public int hashCode() {
+ return filter.hashCode();
+ }
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Or.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Or.java
new file mode 100644
index 0000000000..5062e6d987
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/Or.java
@@ -0,0 +1,75 @@
+/*
+ * 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.filter;
+
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Container.Filter;
+
+/**
+ * A compound {@link Filter} that accepts an item if any of its filters accept
+ * the item.
+ *
+ * If no filters are given, the filter should reject all items.
+ *
+ * This filter also directly supports in-memory filtering when all sub-filters
+ * do so.
+ *
+ * @see And
+ *
+ * @since 6.6
+ */
+public final class Or extends AbstractJunctionFilter {
+
+ /**
+ *
+ * @param filters
+ * filters of which the Or filter will be composed
+ */
+ public Or(Filter... filters) {
+ super(filters);
+ }
+
+ @Override
+ public boolean passesFilter(Object itemId, Item item)
+ throws UnsupportedFilterException {
+ for (Filter filter : getFilters()) {
+ if (filter.passesFilter(itemId, item)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if a change in the named property may affect the filtering
+ * result. If some of the sub-filters are not in-memory filters, true is
+ * returned.
+ *
+ * By default, all sub-filters are iterated to check if any of them applies.
+ * If there are no sub-filters, true is returned as an empty Or rejects all
+ * items.
+ */
+ @Override
+ public boolean appliesToProperty(Object propertyId) {
+ if (getFilters().isEmpty()) {
+ // empty Or filters out everything
+ return true;
+ } else {
+ return super.appliesToProperty(propertyId);
+ }
+ }
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/SimpleStringFilter.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/SimpleStringFilter.java
new file mode 100644
index 0000000000..b3f7d032e1
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/SimpleStringFilter.java
@@ -0,0 +1,167 @@
+/*
+ * 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.filter;
+
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Property;
+import com.vaadin.v7.data.Container.Filter;
+
+/**
+ * Simple string filter for matching items that start with or contain a
+ * specified string. The matching can be case-sensitive or case-insensitive.
+ *
+ * This filter also directly supports in-memory filtering. When performing
+ * in-memory filtering, values of other types are converted using toString(),
+ * but other (lazy container) implementations do not need to perform such
+ * conversions and might not support values of different types.
+ *
+ * Note that this filter is modeled after the pre-6.6 filtering mechanisms, and
+ * might not be very efficient e.g. for database filtering.
+ *
+ * TODO this might still change
+ *
+ * @since 6.6
+ */
+public final class SimpleStringFilter implements Filter {
+
+ final Object propertyId;
+ final String filterString;
+ final boolean ignoreCase;
+ final boolean onlyMatchPrefix;
+
+ public SimpleStringFilter(Object propertyId, String filterString,
+ boolean ignoreCase, boolean onlyMatchPrefix) {
+ this.propertyId = propertyId;
+ this.filterString = ignoreCase ? filterString.toLowerCase()
+ : filterString;
+ this.ignoreCase = ignoreCase;
+ this.onlyMatchPrefix = onlyMatchPrefix;
+ }
+
+ @Override
+ public boolean passesFilter(Object itemId, Item item) {
+ final Property<?> p = item.getItemProperty(propertyId);
+ if (p == null) {
+ return false;
+ }
+ Object propertyValue = p.getValue();
+ if (propertyValue == null) {
+ return false;
+ }
+ final String value = ignoreCase ? propertyValue.toString().toLowerCase()
+ : propertyValue.toString();
+ if (onlyMatchPrefix) {
+ if (!value.startsWith(filterString)) {
+ return false;
+ }
+ } else {
+ if (!value.contains(filterString)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean appliesToProperty(Object propertyId) {
+ return this.propertyId.equals(propertyId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ // Only ones of the objects of the same class can be equal
+ if (!(obj instanceof SimpleStringFilter)) {
+ return false;
+ }
+ final SimpleStringFilter o = (SimpleStringFilter) obj;
+
+ // Checks the properties one by one
+ if (propertyId != o.propertyId && o.propertyId != null
+ && !o.propertyId.equals(propertyId)) {
+ return false;
+ }
+ if (filterString != o.filterString && o.filterString != null
+ && !o.filterString.equals(filterString)) {
+ return false;
+ }
+ if (ignoreCase != o.ignoreCase) {
+ return false;
+ }
+ if (onlyMatchPrefix != o.onlyMatchPrefix) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return (propertyId != null ? propertyId.hashCode() : 0)
+ ^ (filterString != null ? filterString.hashCode() : 0);
+ }
+
+ /**
+ * Returns the property identifier to which this filter applies.
+ *
+ * @return property id
+ */
+ public Object getPropertyId() {
+ return propertyId;
+ }
+
+ /**
+ * Returns the filter string.
+ *
+ * Note: this method is intended only for implementations of lazy string
+ * filters and may change in the future.
+ *
+ * @return filter string given to the constructor
+ */
+ public String getFilterString() {
+ return filterString;
+ }
+
+ /**
+ * Returns whether the filter is case-insensitive or case-sensitive.
+ *
+ * Note: this method is intended only for implementations of lazy string
+ * filters and may change in the future.
+ *
+ * @return true if performing case-insensitive filtering, false for
+ * case-sensitive
+ */
+ public boolean isIgnoreCase() {
+ return ignoreCase;
+ }
+
+ /**
+ * Returns true if the filter only applies to the beginning of the value
+ * string, false for any location in the value.
+ *
+ * Note: this method is intended only for implementations of lazy string
+ * filters and may change in the future.
+ *
+ * @return true if checking for matches at the beginning of the value only,
+ * false if matching any part of value
+ */
+ public boolean isOnlyMatchPrefix() {
+ return onlyMatchPrefix;
+ }
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/UnsupportedFilterException.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/UnsupportedFilterException.java
new file mode 100644
index 0000000000..68e18da32a
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/filter/UnsupportedFilterException.java
@@ -0,0 +1,47 @@
+/*
+ * 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.filter;
+
+import java.io.Serializable;
+
+/**
+ * Exception for cases where a container does not support a specific type of
+ * filters.
+ *
+ * If possible, this should be thrown already when adding a filter to a
+ * container. If a problem is not detected at that point, an
+ * {@link UnsupportedOperationException} can be throws when attempting to
+ * perform filtering.
+ *
+ * @since 6.6
+ */
+public class UnsupportedFilterException extends RuntimeException
+ implements Serializable {
+ public UnsupportedFilterException() {
+ }
+
+ public UnsupportedFilterException(String message) {
+ super(message);
+ }
+
+ public UnsupportedFilterException(Exception cause) {
+ super(cause);
+ }
+
+ public UnsupportedFilterException(String message, Exception cause) {
+ super(message, cause);
+ }
+}