You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DefaultItemSorter.java 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * Copyright 2000-2014 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.data.util;
  17. import java.io.Serializable;
  18. import java.util.ArrayList;
  19. import java.util.Collection;
  20. import java.util.Comparator;
  21. import java.util.List;
  22. import com.vaadin.data.Container;
  23. import com.vaadin.data.Container.Sortable;
  24. import com.vaadin.data.Item;
  25. import com.vaadin.data.Property;
  26. /**
  27. * Provides a default implementation of an ItemSorter. The
  28. * <code>DefaultItemSorter</code> adheres to the
  29. * {@link Sortable#sort(Object[], boolean[])} rules and sorts the container
  30. * according to the properties given using
  31. * {@link #setSortProperties(Sortable, Object[], boolean[])}.
  32. * <p>
  33. * A Comparator is used for comparing the individual <code>Property</code>
  34. * values. The comparator can be set using the constructor. If no comparator is
  35. * provided a default comparator is used.
  36. *
  37. */
  38. public class DefaultItemSorter implements ItemSorter {
  39. private java.lang.Object[] sortPropertyIds;
  40. private boolean[] sortDirections;
  41. private Container container;
  42. private Comparator<Object> propertyValueComparator;
  43. /**
  44. * Constructs a DefaultItemSorter using the default <code>Comparator</code>
  45. * for comparing <code>Property</code>values.
  46. *
  47. */
  48. public DefaultItemSorter() {
  49. this(new DefaultPropertyValueComparator());
  50. }
  51. /**
  52. * Constructs a DefaultItemSorter which uses the <code>Comparator</code>
  53. * indicated by the <code>propertyValueComparator</code> parameter for
  54. * comparing <code>Property</code>values.
  55. *
  56. * @param propertyValueComparator
  57. * The comparator to use when comparing individual
  58. * <code>Property</code> values
  59. */
  60. public DefaultItemSorter(Comparator<Object> propertyValueComparator) {
  61. this.propertyValueComparator = propertyValueComparator;
  62. }
  63. /*
  64. * (non-Javadoc)
  65. *
  66. * @see com.vaadin.data.util.ItemSorter#compare(java.lang.Object,
  67. * java.lang.Object)
  68. */
  69. @Override
  70. public int compare(Object o1, Object o2) {
  71. Item item1 = container.getItem(o1);
  72. Item item2 = container.getItem(o2);
  73. /*
  74. * Items can be null if the container is filtered. Null is considered
  75. * "less" than not-null.
  76. */
  77. if (item1 == null) {
  78. if (item2 == null) {
  79. return 0;
  80. } else {
  81. return 1;
  82. }
  83. } else if (item2 == null) {
  84. return -1;
  85. }
  86. for (int i = 0; i < sortPropertyIds.length; i++) {
  87. int result = compareProperty(sortPropertyIds[i], sortDirections[i],
  88. item1, item2);
  89. // If order can be decided
  90. if (result != 0) {
  91. return result;
  92. }
  93. }
  94. return 0;
  95. }
  96. /**
  97. * Compares the property indicated by <code>propertyId</code> in the items
  98. * indicated by <code>item1</code> and <code>item2</code> for order. Returns
  99. * a negative integer, zero, or a positive integer as the property value in
  100. * the first item is less than, equal to, or greater than the property value
  101. * in the second item. If the <code>sortDirection</code> is false the
  102. * returned value is negated.
  103. * <p>
  104. * The comparator set for this <code>DefaultItemSorter</code> is used for
  105. * comparing the two property values.
  106. *
  107. * @param propertyId
  108. * The property id for the property that is used for comparison.
  109. * @param sortDirection
  110. * The direction of the sort. A false value negates the result.
  111. * @param item1
  112. * The first item to compare.
  113. * @param item2
  114. * The second item to compare.
  115. * @return a negative, zero, or positive integer if the property value in
  116. * the first item is less than, equal to, or greater than the
  117. * property value in the second item. Negated if
  118. * {@code sortDirection} is false.
  119. */
  120. protected int compareProperty(Object propertyId, boolean sortDirection,
  121. Item item1, Item item2) {
  122. // Get the properties to compare
  123. final Property<?> property1 = item1.getItemProperty(propertyId);
  124. final Property<?> property2 = item2.getItemProperty(propertyId);
  125. // Get the values to compare
  126. final Object value1 = (property1 == null) ? null : property1.getValue();
  127. final Object value2 = (property2 == null) ? null : property2.getValue();
  128. // Result of the comparison
  129. int r = 0;
  130. if (sortDirection) {
  131. r = propertyValueComparator.compare(value1, value2);
  132. } else {
  133. r = propertyValueComparator.compare(value2, value1);
  134. }
  135. return r;
  136. }
  137. /*
  138. * (non-Javadoc)
  139. *
  140. * @see
  141. * com.vaadin.data.util.ItemSorter#setSortProperties(com.vaadin.data.Container
  142. * .Sortable, java.lang.Object[], boolean[])
  143. */
  144. @Override
  145. public void setSortProperties(Container.Sortable container,
  146. Object[] propertyId, boolean[] ascending) {
  147. this.container = container;
  148. // Removes any non-sortable property ids
  149. final List<Object> ids = new ArrayList<Object>();
  150. final List<Boolean> orders = new ArrayList<Boolean>();
  151. final Collection<?> sortable = container
  152. .getSortableContainerPropertyIds();
  153. for (int i = 0; i < propertyId.length; i++) {
  154. if (sortable.contains(propertyId[i])) {
  155. ids.add(propertyId[i]);
  156. orders.add(Boolean.valueOf(i < ascending.length ? ascending[i]
  157. : true));
  158. }
  159. }
  160. sortPropertyIds = ids.toArray();
  161. sortDirections = new boolean[orders.size()];
  162. for (int i = 0; i < sortDirections.length; i++) {
  163. sortDirections[i] = (orders.get(i)).booleanValue();
  164. }
  165. }
  166. /**
  167. * Provides a default comparator used for comparing {@link Property} values.
  168. * The <code>DefaultPropertyValueComparator</code> assumes all objects it
  169. * compares can be cast to Comparable.
  170. *
  171. */
  172. public static class DefaultPropertyValueComparator implements
  173. Comparator<Object>, Serializable {
  174. @Override
  175. @SuppressWarnings("unchecked")
  176. public int compare(Object o1, Object o2) {
  177. int r = 0;
  178. // Normal non-null comparison
  179. if (o1 != null && o2 != null) {
  180. // Assume the objects can be cast to Comparable, throw
  181. // ClassCastException otherwise.
  182. r = ((Comparable<Object>) o1).compareTo(o2);
  183. } else if (o1 == o2) {
  184. // Objects are equal if both are null
  185. r = 0;
  186. } else {
  187. if (o1 == null) {
  188. r = -1; // null is less than non-null
  189. } else {
  190. r = 1; // non-null is greater than null
  191. }
  192. }
  193. return r;
  194. }
  195. }
  196. }