]> source.dussan.org Git - vaadin-framework.git/commitdiff
(Re)introduce server side sort for Grid.
authorDenis <denis@vaadin.com>
Thu, 15 Dec 2016 09:50:04 +0000 (11:50 +0200)
committerIlia Motornyi <elmot@vaadin.com>
Thu, 15 Dec 2016 09:50:04 +0000 (11:50 +0200)
Fixes vaadin/framework8-issues#557

server/src/main/java/com/vaadin/ui/Grid.java
server/src/test/java/com/vaadin/tests/server/component/grid/GridTest.java
uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java
uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridSortingTest.java

index 6136b54f42624ab95e3a84a9bed01d44a54d7d51..120640bd53e646e6700c466a517da97c06fba3aa 100644 (file)
@@ -15,7 +15,6 @@
  */
 package com.vaadin.ui;
 
-
 import java.io.Serializable;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
@@ -79,6 +78,7 @@ import com.vaadin.shared.ui.grid.GridStaticCellType;
 import com.vaadin.shared.ui.grid.HeightMode;
 import com.vaadin.shared.ui.grid.SectionState;
 import com.vaadin.shared.util.SharedUtil;
+import com.vaadin.ui.Grid.FooterRow;
 import com.vaadin.ui.components.grid.AbstractSelectionModel;
 import com.vaadin.ui.components.grid.EditorComponentGenerator;
 import com.vaadin.ui.components.grid.EditorImpl;
@@ -334,6 +334,31 @@ public class Grid<T> extends AbstractListing<T>
         void columnResize(ColumnResizeEvent event);
     }
 
+    /**
+     * Generates the sort orders when rows are sorted by a column.
+     * 
+     * @see Column#setSortOrderProvider
+     *
+     * @since 8.0
+     * @author Vaadin Ltd
+     */
+    @FunctionalInterface
+    public interface SortOrderProvider extends
+            SerializableFunction<SortDirection, Stream<SortOrder<String>>> {
+
+        /**
+         * Generates the sort orders when rows are sorted by a column.
+         *
+         * @param sortDirection
+         *            desired sort direction
+         *
+         * @return sort information
+         */
+        @Override
+        public Stream<SortOrder<String>> apply(SortDirection sortDirection);
+
+    }
+
     /**
      * An event that is fired when the columns are reordered.
      */
@@ -738,44 +763,14 @@ public class Grid<T> extends AbstractListing<T>
         public void sort(String[] columnIds, SortDirection[] directions,
                 boolean isUserOriginated) {
             assert columnIds.length == directions.length : "Column and sort direction counts don't match.";
-            sortOrder.clear();
-            if (columnIds.length == 0) {
-                // Grid is not sorted anymore.
-                getDataCommunicator()
-                        .setBackEndSorting(Collections.emptyList());
-                getDataCommunicator().setInMemorySorting(null);
-                return;
-            }
 
+            List<SortOrder<Column<T, ?>>> list = new ArrayList<>(
+                    directions.length);
             for (int i = 0; i < columnIds.length; ++i) {
                 Column<T, ?> column = columnKeys.get(columnIds[i]);
-                sortOrder.add(new SortOrder<>(column, directions[i]));
-            }
-
-            // Set sort orders
-            // In-memory comparator
-            BinaryOperator<SerializableComparator<T>> operator = (comparator1,
-                    comparator2) -> SerializableComparator.asInstance(
-                            (Comparator<T> & Serializable) comparator1
-                                    .thenComparing(comparator2));
-            SerializableComparator<T> comparator = sortOrder.stream()
-                    .map(order -> order.getSorted()
-                            .getComparator(order.getDirection()))
-                    .reduce((x, y) -> 0, operator);
-            getDataCommunicator().setInMemorySorting(comparator);
-
-            // Back-end sort properties
-            List<SortOrder<String>> sortProperties = new ArrayList<>();
-            sortOrder.stream()
-                    .map(order -> order.getSorted()
-                            .getSortOrder(order.getDirection()))
-                    .forEach(s -> s.forEach(sortProperties::add));
-            getDataCommunicator().setBackEndSorting(sortProperties);
-
-            // Close grid editor if it's open.
-            if (getEditor().isOpen()) {
-                getEditor().cancel();
+                list.add(new SortOrder<>(column, directions[i]));
             }
+            setSortOrder(list, isUserOriginated);
         }
 
         @Override
@@ -2499,8 +2494,7 @@ public class Grid<T> extends AbstractListing<T>
      *
      * @return the new column
      */
-    public Column<T, String> addColumn(
-            ValueProvider<T, String> valueProvider) {
+    public Column<T, String> addColumn(ValueProvider<T, String> valueProvider) {
         return addColumn(getGeneratedIdentifier(),
                 t -> String.valueOf(valueProvider.apply(t)),
                 new TextRenderer());
@@ -3406,6 +3400,61 @@ public class Grid<T> extends AbstractListing<T>
         return getSelectionModel().addSelectionListener(listener);
     }
 
+    /**
+     * Sort this Grid in ascending order by a specified column.
+     *
+     * @param column
+     *            a column to sort against
+     *
+     */
+    public void sort(Column<T, ?> column) {
+        sort(column, SortDirection.ASCENDING);
+    }
+
+    /**
+     * Sort this Grid in user-specified {@link SortOrder} by a column.
+     *
+     * @param column
+     *            a column to sort against
+     * @param direction
+     *            a sort order value (ascending/descending)
+     *
+     */
+    public void sort(Column<T, ?> column, SortDirection direction) {
+        setSortOrder(
+                Collections.singletonList(new SortOrder<>(column, direction)));
+    }
+
+    /**
+     * Clear the current sort order, and re-sort the grid.
+     */
+    public void clearSortOrder() {
+        sortOrder.clear();
+        sort(false);
+    }
+
+    /**
+     * Sets the sort order to use.
+     *
+     * @param order
+     *            a sort order list.
+     *
+     * @throws IllegalArgumentException
+     *             if order is null
+     */
+    public void setSortOrder(List<SortOrder<Column<T, ?>>> order) {
+        setSortOrder(order, false);
+    }
+
+    /**
+     * Get the current sort order list.
+     *
+     * @return a sort order list
+     */
+    public List<SortOrder<Column<T, ?>>> getSortOrder() {
+        return Collections.unmodifiableList(sortOrder);
+    }
+
     @Override
     protected GridState getState() {
         return getState(true);
@@ -3685,25 +3734,44 @@ public class Grid<T> extends AbstractListing<T>
         return result;
     }
 
-    /**
-     * Generates the sort orders when rows are sorted by a column.
-     * @see Column#setSortOrderProvider
-     *
-     * @since 8.0
-     * @author Vaadin Ltd
-     */
-    @FunctionalInterface
-    public interface SortOrderProvider extends SerializableFunction<SortDirection, Stream<SortOrder<String>>> {
+    private void setSortOrder(List<SortOrder<Column<T, ?>>> order,
+            boolean userOriginated) {
+        Objects.requireNonNull(order, "Sort order list cannot be null");
+        sortOrder.clear();
+        if (order.isEmpty()) {
+            // Grid is not sorted anymore.
+            getDataCommunicator().setBackEndSorting(Collections.emptyList());
+            getDataCommunicator().setInMemorySorting(null);
+            return;
+        }
 
-        /**
-         * Generates the sort orders when rows are sorted by a column.
-         *
-         * @param sortDirection desired sort direction
-         *
-         * @return sort information
-         */
-        @Override
-        public Stream<SortOrder<String>> apply(SortDirection sortDirection);
+        sortOrder.addAll(order);
+        sort(userOriginated);
+    }
+
+    private void sort(boolean userOriginated) {
+        // Set sort orders
+        // In-memory comparator
+        BinaryOperator<SerializableComparator<T>> operator = (comparator1,
+                comparator2) -> SerializableComparator
+                        .asInstance((Comparator<T> & Serializable) comparator1
+                                .thenComparing(comparator2));
+        SerializableComparator<T> comparator = sortOrder.stream().map(
+                order -> order.getSorted().getComparator(order.getDirection()))
+                .reduce((x, y) -> 0, operator);
+        getDataCommunicator().setInMemorySorting(comparator);
+
+        // Back-end sort properties
+        List<SortOrder<String>> sortProperties = new ArrayList<>();
+        sortOrder.stream().map(
+                order -> order.getSorted().getSortOrder(order.getDirection()))
+                .forEach(s -> s.forEach(sortProperties::add));
+        getDataCommunicator().setBackEndSorting(sortProperties);
 
+        // Close grid editor if it's open.
+        if (getEditor().isOpen()) {
+            getEditor().cancel();
+        }
     }
+
 }
index 56e8ad29f33ec885ab18fcc7a29fc8ed49aa3367..6955a99e91c5653c230de9f69bfc4d5b852c1de0 100644 (file)
@@ -4,6 +4,8 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.Optional;
 
 import org.easymock.Capture;
@@ -13,8 +15,11 @@ import org.junit.Test;
 
 import com.vaadin.data.ValueProvider;
 import com.vaadin.event.selection.SelectionEvent;
+import com.vaadin.server.data.SortOrder;
+import com.vaadin.shared.data.sort.SortDirection;
 import com.vaadin.shared.ui.grid.HeightMode;
 import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.Column;
 import com.vaadin.ui.Grid.SelectionMode;
 import com.vaadin.ui.renderers.NumberRenderer;
 
@@ -177,4 +182,53 @@ public class GridTest {
         grid.addSelectionListener(
                 event -> Assert.fail("never ever happens (tm)"));
     }
+
+    @Test
+    public void sortByColumn_sortOrderIsAscendingOneColumn() {
+        Column<String, ?> column = grid.getColumns().get(1);
+        grid.sort(column);
+
+        SortOrder<Column<String, ?>> sortOrder = grid.getSortOrder().get(0);
+        Assert.assertEquals(column, sortOrder.getSorted());
+        Assert.assertEquals(SortDirection.ASCENDING, sortOrder.getDirection());
+    }
+
+    @Test
+    public void sortByColumnDesc_sortOrderIsDescendingOneColumn() {
+        Column<String, ?> column = grid.getColumns().get(1);
+        grid.sort(column, SortDirection.DESCENDING);
+
+        SortOrder<Column<String, ?>> sortOrder = grid.getSortOrder().get(0);
+        Assert.assertEquals(column, sortOrder.getSorted());
+        Assert.assertEquals(SortDirection.DESCENDING, sortOrder.getDirection());
+    }
+
+    @Test
+    public void setSortOrder() {
+        Column<String, ?> column1 = grid.getColumns().get(1);
+        Column<String, ?> column2 = grid.getColumns().get(2);
+        List<SortOrder<Column<String, ?>>> order = Arrays.asList(
+                new SortOrder<>(column2, SortDirection.DESCENDING),
+                new SortOrder<>(column1, SortDirection.ASCENDING));
+        grid.setSortOrder(order);
+
+        List<SortOrder<Column<String, ?>>> sortOrder = grid.getSortOrder();
+        Assert.assertEquals(column2, sortOrder.get(0).getSorted());
+        Assert.assertEquals(SortDirection.DESCENDING,
+                sortOrder.get(0).getDirection());
+
+        Assert.assertEquals(column1, sortOrder.get(1).getSorted());
+        Assert.assertEquals(SortDirection.ASCENDING,
+                sortOrder.get(1).getDirection());
+    }
+
+    @Test
+    public void clearSortOrder() {
+        Column<String, ?> column = grid.getColumns().get(1);
+        grid.sort(column);
+
+        grid.clearSortOrder();
+
+        assertEquals(0, grid.getSortOrder().size());
+    }
 }
index ed82395c888f8e2d5368ed0032a36fa89967d219..c074bd4d14bbc247f86b70eb255c042c54eb2e85 100644 (file)
@@ -21,6 +21,7 @@ import com.vaadin.event.selection.MultiSelectionEvent;
 import com.vaadin.event.selection.SingleSelectionEvent;
 import com.vaadin.server.VaadinRequest;
 import com.vaadin.shared.Registration;
+import com.vaadin.shared.data.sort.SortDirection;
 import com.vaadin.shared.ui.grid.HeightMode;
 import com.vaadin.tests.components.AbstractTestUIWithLog;
 import com.vaadin.ui.Button;
@@ -338,7 +339,12 @@ public class GridBasics extends AbstractTestUIWithLog {
                     .setCheckable(true);
             columnMenu.addItem("Remove",
                     selectedItem -> grid.removeColumn(col));
+
+            columnMenu.addItem("Sort ASC", item -> grid.sort(col));
+            columnMenu.addItem("Sort DESC",
+                    item -> grid.sort(col, SortDirection.DESCENDING));
         }
+        columnsMenu.addItem("Clear sort", item -> grid.clearSortOrder());
     }
 
     private void createSizeMenu(MenuItem sizeMenu) {
index 9b97f8def4f857ea41f3a786969f072fb562d481..c172f53f3b7b174bc101078db22f06db44c4df4e 100644 (file)
@@ -2,6 +2,7 @@ package com.vaadin.tests.components.grid.basics;
 
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -57,4 +58,79 @@ public class GridSortingTest extends GridBasicsTest {
                     getGridElement().getCell(i++, 3).getText());
         }
     }
+
+    @Test
+    public void serverSideOrderByColumn0() {
+        selectMenuPath("Component", "Columns", "Column 0", "Sort ASC");
+
+        Comparator<String> comparator = Comparator.naturalOrder();
+
+        int i = 0;
+        for (String coord : getTestData().map(DataObject::getCoordinates)
+                .sorted(comparator).limit(5).collect(Collectors.toList())) {
+            Assert.assertEquals(
+                    "Grid was not sorted as expected, row number mismatch",
+                    coord, getGridElement().getCell(i++, 0).getText());
+        }
+        // self-verification
+        Assert.assertTrue(i > 0);
+
+        selectMenuPath("Component", "Columns", "Column 0", "Sort DESC");
+
+        i = 0;
+        for (String coord : getTestData().map(DataObject::getCoordinates)
+                .sorted(comparator.reversed()).limit(5)
+                .collect(Collectors.toList())) {
+            Assert.assertEquals(
+                    "Grid was not sorted as expected, row number mismatch",
+                    coord, getGridElement().getCell(i++, 0).getText());
+        }
+    }
+
+    @Test
+    public void serverSideOrderByDate() {
+        selectMenuPath("Component", "Columns", "Date", "Sort ASC");
+
+        Comparator<Date> comparator = Comparator.naturalOrder();
+
+        int i = 0;
+        for (Date date : getTestData().map(DataObject::getDate)
+                .sorted(comparator).limit(5).collect(Collectors.toList())) {
+            Assert.assertEquals(
+                    "Grid was not sorted as expected, row number mismatch",
+                    date.toString(),
+                    getGridElement().getCell(i++, 4).getText());
+        }
+        // self-verification
+        Assert.assertTrue(i > 0);
+
+        selectMenuPath("Component", "Columns", "Date", "Sort DESC");
+
+        i = 0;
+        for (Date date : getTestData().map(DataObject::getDate)
+                .sorted(comparator.reversed()).limit(5)
+                .collect(Collectors.toList())) {
+            Assert.assertEquals(
+                    "Grid was not sorted as expected, row number mismatch",
+                    date.toString(),
+                    getGridElement().getCell(i++, 4).getText());
+        }
+    }
+
+    @Test
+    public void serverSideClearOrder() {
+        selectMenuPath("Component", "Columns", "Column 0", "Sort ASC");
+        selectMenuPath("Component", "Columns", "Clear sort");
+
+        int i = 0;
+        for (String coord : getTestData().map(DataObject::getCoordinates)
+                .limit(5).collect(Collectors.toList())) {
+            Assert.assertEquals(
+                    "Grid was not sorted as expected, row number mismatch",
+                    coord, getGridElement().getCell(i++, 0).getText());
+        }
+        // self-verification
+        Assert.assertTrue(i > 0);
+    }
+
 }