aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/data/util
diff options
context:
space:
mode:
authorMarc Englund <marc.englund@itmill.com>2009-11-27 08:38:54 +0000
committerMarc Englund <marc.englund@itmill.com>2009-11-27 08:38:54 +0000
commit929885236e1f91b271b2de54a9d22135e7bfac1a (patch)
treea21b94de0812158ed7b18f4893d07940478cc13b /src/com/vaadin/data/util
parent9d36ba611999791de9e0d57d91e21223e1642004 (diff)
downloadvaadin-framework-929885236e1f91b271b2de54a9d22135e7bfac1a.tar.gz
vaadin-framework-929885236e1f91b271b2de54a9d22135e7bfac1a.zip
Integrated patch that implements ItemSorter for IndexedContainer, #3434
svn changeset:10081/svn branch:6.2
Diffstat (limited to 'src/com/vaadin/data/util')
-rw-r--r--src/com/vaadin/data/util/BeanItemContainer.java71
-rw-r--r--src/com/vaadin/data/util/DefaultItemSorter.java197
-rw-r--r--src/com/vaadin/data/util/HierarchicalContainer.java12
-rw-r--r--src/com/vaadin/data/util/IndexedContainer.java121
-rw-r--r--src/com/vaadin/data/util/ItemSorter.java52
5 files changed, 326 insertions, 127 deletions
diff --git a/src/com/vaadin/data/util/BeanItemContainer.java b/src/com/vaadin/data/util/BeanItemContainer.java
index aaa7d9cd56..2575615232 100644
--- a/src/com/vaadin/data/util/BeanItemContainer.java
+++ b/src/com/vaadin/data/util/BeanItemContainer.java
@@ -5,7 +5,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -52,6 +51,11 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
private Set<Filter> filters = new HashSet<Filter>();
+ /**
+ * The item sorter which is used for sorting the container.
+ */
+ private ItemSorter itemSorter = new DefaultItemSorter();
+
/* Special serialization to handle method references */
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
@@ -385,46 +389,33 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
return sortables;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Container.Sortable#sort(java.lang.Object[],
+ * boolean[])
+ */
public void sort(Object[] propertyId, boolean[] ascending) {
- for (int i = 0; i < ascending.length; i++) {
- final boolean asc = ascending[i];
- final Object property = propertyId[i];
- // sort allItems, then filter and notify
- Collections.sort(allItems, new Comparator<BT>() {
- @SuppressWarnings("unchecked")
- public int compare(BT a, BT b) {
- Comparable va, vb;
- if (asc) {
- va = (Comparable) getItem(a).getItemProperty(property)
- .getValue();
- vb = (Comparable) getItem(b).getItemProperty(property)
- .getValue();
- } else {
- va = (Comparable) getItem(b).getItemProperty(property)
- .getValue();
- vb = (Comparable) getItem(a).getItemProperty(property)
- .getValue();
- }
-
- /*
- * Null values are considered less than all others. The
- * compareTo method cannot handle null values for the
- * standard types.
- */
- if (va == null) {
- return (vb == null) ? 0 : -1;
- } else if (vb == null) {
- return 1;
- }
-
- return va.compareTo(vb);
- }
- });
- }
+ itemSorter.setSortProperties(this, propertyId, ascending);
+
+ doSort();
+
// notifies if anything changes in the filtered list, including order
filterAll();
}
+ /**
+ * Perform the sorting of the data structures in the container. This is
+ * invoked when the <code>itemSorter</code> has been prepared for the sort
+ * operation. Typically this method calls
+ * <code>Collections.sort(aCollection, getItemSorter())</code> on all arrays
+ * (containing item ids) that need to be sorted.
+ *
+ */
+ protected void doSort() {
+ Collections.sort(allItems, getItemSorter());
+ }
+
public void addListener(ItemSetChangeListener listener) {
if (itemSetChangeListeners == null) {
itemSetChangeListeners = new LinkedList<ItemSetChangeListener>();
@@ -531,4 +522,12 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
filterAll();
}
+ public ItemSorter getItemSorter() {
+ return itemSorter;
+ }
+
+ public void setItemSorter(ItemSorter itemSorter) {
+ this.itemSorter = itemSorter;
+ }
+
}
diff --git a/src/com/vaadin/data/util/DefaultItemSorter.java b/src/com/vaadin/data/util/DefaultItemSorter.java
new file mode 100644
index 0000000000..4a99714212
--- /dev/null
+++ b/src/com/vaadin/data/util/DefaultItemSorter.java
@@ -0,0 +1,197 @@
+package com.vaadin.data.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.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)
+ */
+ public int compare(Object o1, Object o2) {
+ Item item1 = container.getItem(o1);
+ Item item2 = container.getItem(o2);
+
+ 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
+ */
+ 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[])
+ */
+ 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> {
+
+ public int compare(Object o1, Object o2) {
+ int r = 0;
+ // Normal non-null comparison
+ if (o1 != null && o2 != null) {
+ // FIXME: Use standard Boolean comparison as Boolean implements
+ // Comaprable since JDK1.5
+ if ((o1 instanceof Boolean) && (o2 instanceof Boolean)) {
+ if (o1.equals(o2)) {
+ r = 0; // both have the same boolean value
+ } else if (((Boolean) o1).booleanValue()) {
+ return 1; // true is greater than false
+ } else {
+ return -1;
+ }
+ } else {
+ // Assume the objects can be cast to Comparable, throw
+ // ClassCastException otherwise.
+ r = ((Comparable) 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/src/com/vaadin/data/util/HierarchicalContainer.java b/src/com/vaadin/data/util/HierarchicalContainer.java
index a6af0427ad..f5b65f1dad 100644
--- a/src/com/vaadin/data/util/HierarchicalContainer.java
+++ b/src/com/vaadin/data/util/HierarchicalContainer.java
@@ -308,12 +308,18 @@ public class HierarchicalContainer extends IndexedContainer implements
return success;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.util.IndexedContainer#doSort()
+ */
@Override
- void doSort() {
+ protected void doSort() {
super.doSort();
- Collections.sort(roots, this);
+
+ Collections.sort(roots, getItemSorter());
for (LinkedList<Object> childList : children.values()) {
- Collections.sort(childList, this);
+ Collections.sort(childList, getItemSorter());
}
}
diff --git a/src/com/vaadin/data/util/IndexedContainer.java b/src/com/vaadin/data/util/IndexedContainer.java
index 15c36953a1..609f488938 100644
--- a/src/com/vaadin/data/util/IndexedContainer.java
+++ b/src/com/vaadin/data/util/IndexedContainer.java
@@ -9,7 +9,6 @@ import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.EventObject;
import java.util.HashMap;
import java.util.HashSet;
@@ -17,7 +16,6 @@ import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
-import java.util.List;
import java.util.NoSuchElementException;
import com.vaadin.data.Container;
@@ -49,8 +47,8 @@ import com.vaadin.data.Property;
@SuppressWarnings("serial")
public class IndexedContainer implements Container.Indexed,
Container.ItemSetChangeNotifier, Container.PropertySetChangeNotifier,
- Property.ValueChangeNotifier, Container.Sortable, Comparator<Object>,
- Cloneable, Container.Filterable {
+ Property.ValueChangeNotifier, Container.Sortable, Cloneable,
+ Container.Filterable {
/* Internal structure */
@@ -108,14 +106,9 @@ public class IndexedContainer implements Container.Indexed,
private LinkedList itemSetChangeListeners = null;
/**
- * Temporary store for sorting property ids.
+ * The item sorter which is used for sorting the container.
*/
- private Object[] sortPropertyId;
-
- /**
- * Temporary store for sorting direction.
- */
- private boolean[] sortDirection;
+ private ItemSorter itemSorter = new DefaultItemSorter();
/**
* Filters that are applied to the container to limit the items visible in
@@ -1379,49 +1372,31 @@ public class IndexedContainer implements Container.Indexed,
* boolean[])
*/
public void sort(Object[] propertyId, boolean[] ascending) {
+ // Set up the item sorter for the sort operation
+ itemSorter.setSortProperties(this, propertyId, ascending);
- // Removes any non-sortable property ids
- final List ids = new ArrayList();
- final List<Boolean> orders = new ArrayList<Boolean>();
- final Collection sortable = 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));
- }
- }
-
- if (ids.size() == 0) {
- return;
- }
- sortPropertyId = ids.toArray();
- sortDirection = new boolean[orders.size()];
- for (int i = 0; i < sortDirection.length; i++) {
- sortDirection[i] = (orders.get(i)).booleanValue();
- }
-
+ // Perform the actual sort
doSort();
+ // Post sort updates
if (filteredItemIds != null) {
updateContainerFiltering();
} else {
fireContentsChange(-1);
}
- // Remove temporary references
- sortPropertyId = null;
- sortDirection = null;
-
}
/**
- * Perform the sorting of the container. Called when everything needed for
- * the compare function has been set up.
+ * Perform the sorting of the data structures in the container. This is
+ * invoked when the <code>itemSorter</code> has been prepared for the sort
+ * operation. Typically this method calls
+ * <code>Collections.sort(aCollection, getItemSorter())</code> on all arrays
+ * (containing item ids) that need to be sorted.
*
*/
- void doSort() {
- Collections.sort(itemIds, this);
+ protected void doSort() {
+ Collections.sort(itemIds, getItemSorter());
}
/*
@@ -1430,7 +1405,7 @@ public class IndexedContainer implements Container.Indexed,
* @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds
* ()
*/
- public Collection getSortableContainerPropertyIds() {
+ public Collection<?> getSortableContainerPropertyIds() {
final LinkedList list = new LinkedList();
for (final Iterator i = propertyIds.iterator(); i.hasNext();) {
@@ -1445,52 +1420,25 @@ public class IndexedContainer implements Container.Indexed,
}
/**
- * Compares two items for sorting.
+ * Returns the ItemSorter used for comparing items in a sort. See
+ * {@link #setItemSorter(ItemSorter)} for more information.
*
- * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
- * @see #sort((java.lang.Object[], boolean[])
+ * @return The ItemSorter used for comparing two items in a sort.
*/
- public int compare(Object o1, Object o2) {
-
- for (int i = 0; i < sortPropertyId.length; i++) {
-
- // Get the compared properties
- final Property pp1 = getContainerProperty(o1, sortPropertyId[i]);
- final Property pp2 = getContainerProperty(o2, sortPropertyId[i]);
-
- // Get the compared values
- final Object p1 = pp1 == null ? null : pp1.getValue();
- final Object p2 = pp2 == null ? null : pp2.getValue();
-
- // Result of the comparison
- int r = 0;
-
- // Normal non-null comparison
- if (p1 != null && p2 != null) {
- if ((p1 instanceof Boolean) && (p2 instanceof Boolean)) {
- r = p1.equals(p2) ? 0
- : ((sortDirection[i] ? 1 : -1) * (((Boolean) p1)
- .booleanValue() ? 1 : -1));
- } else {
- r = sortDirection[i] ? ((Comparable) p1).compareTo(p2)
- : -((Comparable) p1).compareTo(p2);
- }
- }
-
- // If both are nulls
- else if (p1 == p2) {
- r = 0;
- } else {
- r = (sortDirection[i] ? 1 : -1) * (p1 == null ? -1 : 1);
- }
-
- // If order can be decided
- if (r != 0) {
- return r;
- }
- }
+ public ItemSorter getItemSorter() {
+ return itemSorter;
+ }
- return 0;
+ /**
+ * Sets the ItemSorter used for comparing items in a sort. The ItemSorter is
+ * called for each collection that needs sorting. A default ItemSorter is
+ * used if this is not explicitly set.
+ *
+ * @param itemSorter
+ * The ItemSorter used for comparing two items in a sort.
+ */
+ public void setItemSorter(ItemSorter itemSorter) {
+ this.itemSorter = itemSorter;
}
/**
@@ -1524,10 +1472,7 @@ public class IndexedContainer implements Container.Indexed,
nc.singlePropertyValueChangeListeners = singlePropertyValueChangeListeners != null ? (Hashtable) singlePropertyValueChangeListeners
.clone()
: null;
- nc.sortDirection = sortDirection != null ? (boolean[]) sortDirection
- .clone() : null;
- nc.sortPropertyId = sortPropertyId != null ? (Object[]) sortPropertyId
- .clone() : null;
+
nc.types = types != null ? (Hashtable) types.clone() : null;
nc.filters = filters == null ? null : (HashSet<Filter>) filters.clone();
diff --git a/src/com/vaadin/data/util/ItemSorter.java b/src/com/vaadin/data/util/ItemSorter.java
new file mode 100644
index 0000000000..eb665b48cd
--- /dev/null
+++ b/src/com/vaadin/data/util/ItemSorter.java
@@ -0,0 +1,52 @@
+package com.vaadin.data.util;
+
+import java.util.Comparator;
+
+import com.vaadin.data.Container;
+import com.vaadin.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. The interface
+ */
+public interface ItemSorter extends Comparator<Object>, Cloneable {
+
+ /**
+ * 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)
+ */
+ int compare(Object itemId1, Object itemId2);
+
+}