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.

ListSorter.java 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * Copyright 2000-2016 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.v7.client.widget.grid.datasources;
  17. import java.util.Comparator;
  18. import java.util.HashMap;
  19. import java.util.List;
  20. import java.util.Map;
  21. import com.google.gwt.event.shared.HandlerRegistration;
  22. import com.vaadin.client.data.DataSource;
  23. import com.vaadin.shared.data.sort.SortDirection;
  24. import com.vaadin.v7.client.widget.grid.sort.SortEvent;
  25. import com.vaadin.v7.client.widget.grid.sort.SortHandler;
  26. import com.vaadin.v7.client.widget.grid.sort.SortOrder;
  27. import com.vaadin.v7.client.widgets.Grid;
  28. /**
  29. * Provides sorting facility from Grid for the {@link ListDataSource} in-memory
  30. * data source.
  31. *
  32. * @author Vaadin Ltd
  33. * @param <T>
  34. * Grid row data type
  35. * @since 7.4
  36. */
  37. public class ListSorter<T> {
  38. private Grid<T> grid;
  39. private Map<Grid.Column<?, T>, Comparator<?>> comparators;
  40. private HandlerRegistration sortHandlerRegistration;
  41. public ListSorter(Grid<T> grid) {
  42. if (grid == null) {
  43. throw new IllegalArgumentException("Grid can not be null");
  44. }
  45. this.grid = grid;
  46. comparators = new HashMap<Grid.Column<?, T>, Comparator<?>>();
  47. sortHandlerRegistration = grid.addSortHandler(new SortHandler<T>() {
  48. @Override
  49. public void sort(SortEvent<T> event) {
  50. ListSorter.this.sort(event.getOrder());
  51. }
  52. });
  53. }
  54. /**
  55. * Detach this Sorter from the Grid. This unregisters the sort event handler
  56. * which was used to apply sorting to the ListDataSource.
  57. */
  58. public void removeFromGrid() {
  59. sortHandlerRegistration.removeHandler();
  60. }
  61. /**
  62. * Assign or remove a comparator for a column. This comparator method, if
  63. * defined, is always used in favour of 'natural' comparison of objects
  64. * (i.e. the compareTo of objects implementing the Comparable interface,
  65. * which includes all standard data classes like String, Number derivatives
  66. * and Dates). Any existing comparator can be removed by passing in a
  67. * non-null GridColumn and a null Comparator.
  68. *
  69. * @param column
  70. * a grid column. May not be null.
  71. * @param comparator
  72. * comparator method for the values returned by the grid column.
  73. * If null, any existing comparator is removed.
  74. */
  75. public <C> void setComparator(Grid.Column<C, T> column,
  76. Comparator<C> comparator) {
  77. if (column == null) {
  78. throw new IllegalArgumentException(
  79. "Column reference can not be null");
  80. }
  81. if (comparator == null) {
  82. comparators.remove(column);
  83. } else {
  84. comparators.put(column, comparator);
  85. }
  86. }
  87. /**
  88. * Retrieve the comparator assigned for a specific grid column.
  89. *
  90. * @param column
  91. * a grid column. May not be null.
  92. * @return a comparator, or null if no comparator for the specified grid
  93. * column has been set.
  94. */
  95. @SuppressWarnings("unchecked")
  96. public <C> Comparator<C> getComparator(Grid.Column<C, T> column) {
  97. if (column == null) {
  98. throw new IllegalArgumentException(
  99. "Column reference can not be null");
  100. }
  101. return (Comparator<C>) comparators.get(column);
  102. }
  103. /**
  104. * Remove all comparator mappings. Useful if the data source has changed but
  105. * this Sorter is being re-used.
  106. */
  107. public void clearComparators() {
  108. comparators.clear();
  109. }
  110. /**
  111. * Apply sorting to the current ListDataSource.
  112. *
  113. * @param order
  114. * the sort order list provided by the grid sort event
  115. */
  116. private void sort(final List<SortOrder> order) {
  117. DataSource<T> ds = grid.getDataSource();
  118. if (!(ds instanceof ListDataSource)) {
  119. throw new IllegalStateException(
  120. "Grid " + grid + " data source is not a ListDataSource!");
  121. }
  122. ((ListDataSource<T>) ds).sort(new Comparator<T>() {
  123. @Override
  124. @SuppressWarnings({ "rawtypes", "unchecked" })
  125. public int compare(T a, T b) {
  126. for (SortOrder o : order) {
  127. Grid.Column column = o.getColumn();
  128. Comparator cmp = ListSorter.this.comparators.get(column);
  129. int result = 0;
  130. Object value_a = column.getValue(a);
  131. Object value_b = column.getValue(b);
  132. if (cmp != null) {
  133. result = cmp.compare(value_a, value_b);
  134. } else {
  135. if (!(value_a instanceof Comparable)) {
  136. throw new IllegalStateException("Column " + column
  137. + " has no assigned comparator and value "
  138. + value_a + " isn't naturally comparable");
  139. }
  140. result = ((Comparable) value_a).compareTo(value_b);
  141. }
  142. if (result != 0) {
  143. return o.getDirection() == SortDirection.ASCENDING
  144. ? result
  145. : -result;
  146. }
  147. }
  148. if (!order.isEmpty()) {
  149. return order.get(0)
  150. .getDirection() == SortDirection.ASCENDING
  151. ? a.hashCode() - b.hashCode()
  152. : b.hashCode() - a.hashCode();
  153. }
  154. return a.hashCode() - b.hashCode();
  155. }
  156. });
  157. }
  158. }