From 13443562ccbd633ceb561bb87893014f65437ad1 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Fri, 25 Nov 2016 16:53:26 +0200 Subject: Provide in-memory sorting information in Query Change-Id: Iebafff6079816c08e5a4d144f6891d1379751f12 --- .../vaadin/server/data/BackEndDataProvider.java | 18 +++++------ .../com/vaadin/server/data/DataCommunicator.java | 17 ++--------- .../java/com/vaadin/server/data/DataProvider.java | 4 +-- .../server/data/FilteringDataProviderWrapper.java | 20 ++++++------- .../com/vaadin/server/data/ListDataProvider.java | 20 +++++++++---- .../main/java/com/vaadin/server/data/Query.java | 35 +++++++++++++++++++--- .../server/data/AbstractDataProviderTest.java | 4 +-- .../component/combobox/ComboBoxFilteringTest.java | 9 +++--- 8 files changed, 75 insertions(+), 52 deletions(-) (limited to 'server') diff --git a/server/src/main/java/com/vaadin/server/data/BackEndDataProvider.java b/server/src/main/java/com/vaadin/server/data/BackEndDataProvider.java index 0f83710d90..9c6433bc4d 100644 --- a/server/src/main/java/com/vaadin/server/data/BackEndDataProvider.java +++ b/server/src/main/java/com/vaadin/server/data/BackEndDataProvider.java @@ -32,8 +32,8 @@ import com.vaadin.server.SerializableFunction; */ public class BackEndDataProvider extends AbstractDataProvider { - private final SerializableFunction, Stream> request; - private final SerializableFunction, Integer> sizeCallback; + private final SerializableFunction, Stream> request; + private final SerializableFunction, Integer> sizeCallback; /** * Constructs a new DataProvider to request data from an arbitrary back end @@ -45,8 +45,8 @@ public class BackEndDataProvider extends AbstractDataProvider { * function that return the amount of data in back end for query */ public BackEndDataProvider( - SerializableFunction, Stream> request, - SerializableFunction, Integer> sizeCallback) { + SerializableFunction, Stream> request, + SerializableFunction, Integer> sizeCallback) { Objects.requireNonNull(request, "Request function can't be null"); Objects.requireNonNull(sizeCallback, "Size callback can't be null"); this.request = request; @@ -54,12 +54,12 @@ public class BackEndDataProvider extends AbstractDataProvider { } @Override - public Stream fetch(Query query) { + public Stream fetch(Query query) { return request.apply(query); } @Override - public int size(Query query) { + public int size(Query query) { return sizeCallback.apply(query); } @@ -77,9 +77,9 @@ public class BackEndDataProvider extends AbstractDataProvider { List> queryOrder = new ArrayList<>( query.getSortOrders()); queryOrder.addAll(sortOrders); - return request - .apply(new Query<>(query.getLimit(), query.getOffset(), - queryOrder, query.getFilter().orElse(null))); + return request.apply(new Query<>(query.getLimit(), + query.getOffset(), queryOrder, query.getInMemorySorting(), + query.getFilter().orElse(null))); }, sizeCallback); } diff --git a/server/src/main/java/com/vaadin/server/data/DataCommunicator.java b/server/src/main/java/com/vaadin/server/data/DataCommunicator.java index 2628c79058..61545ada83 100644 --- a/server/src/main/java/com/vaadin/server/data/DataCommunicator.java +++ b/server/src/main/java/com/vaadin/server/data/DataCommunicator.java @@ -237,20 +237,9 @@ public class DataCommunicator extends AbstractExtension { int offset = pushRows.getStart(); int limit = pushRows.length(); - Stream rowsToPush; - - if (getDataProvider().isInMemory()) { - // TODO: Move in-memory sorting to Query. - // We can safely request all the data when in memory - rowsToPush = getDataProvider().fetch(new Query<>(filter)); - if (inMemorySorting != null) { - rowsToPush = rowsToPush.sorted(inMemorySorting); - } - rowsToPush = rowsToPush.skip(offset).limit(limit); - } else { - rowsToPush = getDataProvider().fetch( - new Query<>(offset, limit, backEndSorting, filter)); - } + Stream rowsToPush = getDataProvider().fetch(new Query<>(offset, + limit, backEndSorting, inMemorySorting, filter)); + pushData(offset, rowsToPush); } diff --git a/server/src/main/java/com/vaadin/server/data/DataProvider.java b/server/src/main/java/com/vaadin/server/data/DataProvider.java index 0975a02c94..a373128358 100644 --- a/server/src/main/java/com/vaadin/server/data/DataProvider.java +++ b/server/src/main/java/com/vaadin/server/data/DataProvider.java @@ -57,7 +57,7 @@ public interface DataProvider extends Serializable { * query with sorting and filtering * @return the size of the data provider */ - int size(Query t); + int size(Query t); /** * Fetches data from this DataProvider using given {@code query}. @@ -67,7 +67,7 @@ public interface DataProvider extends Serializable { * @return the result of the query request: a stream of data objects, not * {@code null} */ - Stream fetch(Query query); + Stream fetch(Query query); /** * Refreshes all data based on currently available data in the underlying diff --git a/server/src/main/java/com/vaadin/server/data/FilteringDataProviderWrapper.java b/server/src/main/java/com/vaadin/server/data/FilteringDataProviderWrapper.java index 08a76d4904..b888fd79c7 100644 --- a/server/src/main/java/com/vaadin/server/data/FilteringDataProviderWrapper.java +++ b/server/src/main/java/com/vaadin/server/data/FilteringDataProviderWrapper.java @@ -100,15 +100,15 @@ public abstract class FilteringDataProviderWrapper } @Override - public int size(Query t) { - return dataProvider.size(new Query(t.getOffset(), t.getLimit(), - t.getSortOrders(), getFilter(t))); + public int size(Query t) { + return dataProvider.size(new Query<>(t.getOffset(), t.getLimit(), + t.getSortOrders(), t.getInMemorySorting(), getFilter(t))); } @Override - public Stream fetch(Query t) { - return dataProvider.fetch(new Query(t.getOffset(), t.getLimit(), - t.getSortOrders(), getFilter(t))); + public Stream fetch(Query t) { + return dataProvider.fetch(new Query<>(t.getOffset(), t.getLimit(), + t.getSortOrders(), t.getInMemorySorting(), getFilter(t))); } /** @@ -118,7 +118,7 @@ public abstract class FilteringDataProviderWrapper * the current query * @return filter for the modified Query */ - protected abstract M getFilter(Query query); + protected abstract M getFilter(Query query); /** * Creates a data provider wrapper with a static filter set to each Query. @@ -144,7 +144,7 @@ public abstract class FilteringDataProviderWrapper return new FilteringDataProviderWrapper(dataProvider) { @Override - protected F getFilter(Query query) { + protected F getFilter(Query query) { return filter; } }; @@ -176,7 +176,7 @@ public abstract class FilteringDataProviderWrapper return new FilteringDataProviderWrapper(dataProvider) { @Override - protected M getFilter(Query query) { + protected M getFilter(Query query) { return query.getFilter().map(mapper).orElse(null); } }; @@ -203,7 +203,7 @@ public abstract class FilteringDataProviderWrapper return new AppendableFilterDataProviderWrapper(dataProvider) { @Override - protected F getFilter(Query query) { + protected F getFilter(Query query) { return combineFilters(filter, query.getFilter()); } }; diff --git a/server/src/main/java/com/vaadin/server/data/ListDataProvider.java b/server/src/main/java/com/vaadin/server/data/ListDataProvider.java index 7d2fa5c1f3..5665ac5f29 100644 --- a/server/src/main/java/com/vaadin/server/data/ListDataProvider.java +++ b/server/src/main/java/com/vaadin/server/data/ListDataProvider.java @@ -18,6 +18,7 @@ package com.vaadin.server.data; import java.util.Collection; import java.util.Comparator; import java.util.Objects; +import java.util.Optional; import java.util.function.Function; import java.util.stream.Stream; @@ -34,7 +35,7 @@ public class ListDataProvider extends AbstractDataProvider> implements AppendableFilterDataProvider> { - private Comparator sortOrder; + private Comparator sortOrder = null; private final Collection backend; /** @@ -67,13 +68,20 @@ public class ListDataProvider } @Override - public Stream fetch(Query> query) { + public Stream fetch(Query> query) { Stream stream = backend.stream() .filter(t -> query.getFilter().orElse(p -> true).test(t)); - if (sortOrder != null) { - stream = stream.sorted(sortOrder); + + Optional> comparing = Stream + .of(sortOrder, query.getInMemorySorting()) + .filter(c -> c != null) + .reduce((c1, c2) -> c1.thenComparing(c2)); + + if (comparing.isPresent()) { + stream = stream.sorted(comparing.get()); } - return stream; + + return stream.skip(query.getOffset()).limit(query.getLimit()); } /** @@ -116,7 +124,7 @@ public class ListDataProvider } @Override - public int size(Query> query) { + public int size(Query> query) { return (int) backend.stream() .filter(t -> query.getFilter().orElse(p -> true).test(t)) .count(); diff --git a/server/src/main/java/com/vaadin/server/data/Query.java b/server/src/main/java/com/vaadin/server/data/Query.java index 3aeaac6acc..6415af0e2d 100644 --- a/server/src/main/java/com/vaadin/server/data/Query.java +++ b/server/src/main/java/com/vaadin/server/data/Query.java @@ -17,6 +17,7 @@ package com.vaadin.server.data; import java.io.Serializable; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Optional; @@ -24,16 +25,19 @@ import java.util.Optional; * Immutable query object used to request data from a backend. Contains index * limits, sorting and filtering information. * + * @param + * bean type * @param * filter type * * @since 8.0 */ -public class Query implements Serializable { +public class Query implements Serializable { private final int offset; private final int limit; private final List> sortOrders; + private final Comparator inMemorySorting; private final F filter; /** @@ -44,6 +48,7 @@ public class Query implements Serializable { offset = 0; limit = Integer.MAX_VALUE; sortOrders = Collections.emptyList(); + inMemorySorting = null; filter = null; } @@ -59,6 +64,7 @@ public class Query implements Serializable { offset = 0; limit = Integer.MAX_VALUE; sortOrders = Collections.emptyList(); + inMemorySorting = null; this.filter = filter; } @@ -71,15 +77,18 @@ public class Query implements Serializable { * @param limit * fetched item count * @param sortOrders - * sorting order for fetching + * sorting order for fetching; used for sorting backends + * @param inMemorySorting + * comparator for sorting in-memory data * @param filter * filtering for fetching; can be null */ public Query(int offset, int limit, List> sortOrders, - F filter) { + Comparator inMemorySorting, F filter) { this.offset = offset; this.limit = limit; this.sortOrders = sortOrders; + this.inMemorySorting = inMemorySorting; this.filter = filter; } @@ -105,7 +114,12 @@ public class Query implements Serializable { } /** - * Gets the sorting for items to fetch. + * Gets the sorting for items to fetch. This list of sort orders is used for + * sorting backends. + *

+ * Note: Sort orders and in-memory sorting are mutually + * exclusive. If the {@link DataProvider} handles one, it should ignore the + * other. * * @return list of sort orders */ @@ -121,4 +135,17 @@ public class Query implements Serializable { public Optional getFilter() { return Optional.ofNullable(filter); } + + /** + * Gets the comparator for sorting in-memory data. + *

+ * Note: Sort orders and in-memory sorting are mutually + * exclusive. If the {@link DataProvider} handles one, it should ignore the + * other. + * + * @return sorting comparator + */ + public Comparator getInMemorySorting() { + return inMemorySorting; + } } diff --git a/server/src/test/java/com/vaadin/server/data/AbstractDataProviderTest.java b/server/src/test/java/com/vaadin/server/data/AbstractDataProviderTest.java index db2f704e2d..b6033ad098 100644 --- a/server/src/test/java/com/vaadin/server/data/AbstractDataProviderTest.java +++ b/server/src/test/java/com/vaadin/server/data/AbstractDataProviderTest.java @@ -32,12 +32,12 @@ public class AbstractDataProviderTest { private static class TestDataProvider extends AbstractDataProvider { @Override - public Stream fetch(Query t) { + public Stream fetch(Query t) { return null; } @Override - public int size(Query t) { + public int size(Query t) { return 0; } diff --git a/server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxFilteringTest.java b/server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxFilteringTest.java index 54ea367fca..de03684307 100644 --- a/server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxFilteringTest.java +++ b/server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxFilteringTest.java @@ -156,16 +156,15 @@ public class ComboBoxFilteringTest { Assert.assertEquals( "ComboBox filtered out results with no filter applied", - totalMatches, dataProvider.size(new Query())); + totalMatches, dataProvider.size(new Query<>())); Assert.assertEquals( "ComboBox filtered out results with empty filter string", - totalMatches, dataProvider.size(new Query(""))); + totalMatches, dataProvider.size(new Query<>(""))); Assert.assertEquals("ComboBox filtered out wrong number of results", - matchingResults, - dataProvider.size(new Query(filterText))); + matchingResults, dataProvider.size(new Query<>(filterText))); Assert.assertEquals( "ComboBox should have no results with a non-matching filter", 0, - dataProvider.size(new Query(nonMatchingFilterText))); + dataProvider.size(new Query<>(nonMatchingFilterText))); } private List getPersonCollection() { -- cgit v1.2.3