Skip to content

Commit

Permalink
DataSource backend sorting
Browse files Browse the repository at this point in the history
Change-Id: Ic9e12534cf85f7793a57436e63bd67b6f920f722
  • Loading branch information
elmot authored and Teemu Suo-Anttila committed Aug 17, 2016
1 parent d96a634 commit 7373b23
Show file tree
Hide file tree
Showing 8 changed files with 340 additions and 58 deletions.
12 changes: 6 additions & 6 deletions documentation/datamodel/datamodel-datasources.asciidoc
Expand Up @@ -152,7 +152,7 @@ Information about which items to fetch as well as some additional details are ma


[source, java] [source, java]
---- ----
DataSource<Person> dataSource = new DataSource<>( DataSource<Person> dataSource = new BackendDataSource<>(
// First callback fetches items based on a query // First callback fetches items based on a query
query -> { query -> {
// The index of the first item to load // The index of the first item to load
Expand Down Expand Up @@ -197,7 +197,7 @@ public interface PersonService {
int getPersonCount(); int getPersonCount();
static PersonSort createSort( PersonSort createSort(
String propertyName, String propertyName,
boolean descending); boolean descending);
} }
Expand All @@ -208,19 +208,19 @@ The sorting options set through the component will be available through [interfa


[source, java] [source, java]
---- ----
DataSource<Person> dataSource = new DataSource<>( DataSource<Person> dataSource = new BackEndDataSource<>(
query -> { query -> {
List<PersonSort> sortOrders = new ArrayList<>(); List<PersonSort> sortOrders = new ArrayList<>();
for(SortOrder<String> queryOrder : query.getSortOrders()) { for(SortOrder<String> queryOrder : query.getSortOrders()) {
PersonSort sort = PersonService.createSort( PersonSort sort = getPersonService().createSort(
// The name of the sorted property // The name of the sorted property
queryOrder.getSorted(), queryOrder.getSorted(),
// The sort direction for this property // The sort direction for this property
queryOrder.getDirection() == SortDirection.DESCENDING); queryOrder.getDirection() == SortDirection.DESCENDING);
sortOrders.add(sort); sortOrders.add(sort);
} }
return service.fetchPersons( return getPersonService().fetchPersons(
query.getOffset(), query.getOffset(),
query.getLimit(), query.getLimit(),
sortOrders sortOrders
Expand Down Expand Up @@ -329,7 +329,7 @@ We can create a helper method for handling the filter since the same logic is ne


[source, java] [source, java]
---- ----
DataSource<Person> dataSource = new DataSource<>( DataSource<Person> dataSource = new BackEndDataSource<>(
query -> { query -> {
BackendFilter filter = query.getFilter(); BackendFilter filter = query.getFilter();
Expand Down
85 changes: 85 additions & 0 deletions server/src/main/java/com/vaadin/server/data/BackEndDataSource.java
@@ -0,0 +1,85 @@
/*
* Copyright 2000-2014 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.server.data;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Stream;

/**
* A {@link DataSource} for any back end.
*
* @param <T>
* data source data type
*/
public class BackEndDataSource<T> implements
DataSource<T> {

private Function<Query, Stream<T>> request;
private Function<Query, Integer> sizeCallback;

/**
* Constructs a new DataSource to request data from an arbitrary back end
* request function.
*
* @param request
* function that requests data from back end based on query
* @param sizeCallback
* function that return the amount of data in back end for query
*/
public BackEndDataSource(Function<Query, Stream<T>> request,
Function<Query, Integer> sizeCallback) {
Objects.requireNonNull(request, "Request function can't be null");
Objects.requireNonNull(sizeCallback, "Size callback can't be null");
this.request = request;
this.sizeCallback = sizeCallback;
}

@Override
public Stream<T> apply(Query t) {
return request.apply(t);
}

@Override
public int size(Query t) {
return sizeCallback.apply(t);
}

/**
* Sets a default sorting order to the data source.
*
* @param sortOrders
* a list of sorting information containing field ids and directions
* @return new data source with modified sorting
*/
public BackEndDataSource<T> sortingBy(List<SortOrder<String>> sortOrders) {
return new BackEndDataSource<>(query -> {
List<SortOrder<String>> queryOrder = new ArrayList<>(
query.getSortOrders());
queryOrder.addAll(sortOrders);
return request.apply(new Query(query.getLimit(), query.getOffset(),
queryOrder, query.getFilters()));
}, sizeCallback);
}

@Override
public boolean isInMemory() {
return false;
}

}
65 changes: 25 additions & 40 deletions server/src/main/java/com/vaadin/server/data/DataSource.java
Expand Up @@ -15,43 +15,42 @@
*/ */
package com.vaadin.server.data; package com.vaadin.server.data;


import java.io.Serializable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Stream;


/** /**
* A generic data source for any back end and Listing UI components. * Minimal DataSource API for communication between the DataProvider and a back
* * end service.
*
* @since
* @param <T> * @param <T>
* data source data type * data type
*
* @see InMemoryDataSource
* @see BackEndDataSource
*/ */
public class DataSource<T> implements public interface DataSource<T> extends Function<Query, Stream<T>>,
Function<Query, Stream<T>>, java.io.Serializable { Serializable {

protected Function<Query, Stream<T>> request;
protected Function<Query, Integer> sizeCallback;


protected DataSource() { /**
} * Gets whether the DataSource content all available in memory or does it
* use some external backend.
*
* @return {@code true} if all data is in memory; {@code false} if not
*/
boolean isInMemory();


/** /**
* Constructs a new DataSource to request data from an arbitrary back end * Gets the amount of data in this DataSource.
* request function. *
* * @param t
* @param request * query with sorting and filtering
* function that requests data from back end based on query * @return the size of the data source
* @param sizeCallback
* function that return the amount of data in back end for query
*/ */
public DataSource(Function<Query, Stream<T>> request, int size(Query t);
Function<Query, Integer> sizeCallback) {
Objects.requireNonNull(request, "Request function can't be null");
Objects.requireNonNull(sizeCallback, "Size callback can't be null");
this.request = request;
this.sizeCallback = sizeCallback;
}


/** /**
* This method creates a new {@link InMemoryDataSource} from a given * This method creates a new {@link InMemoryDataSource} from a given
Expand Down Expand Up @@ -79,18 +78,4 @@ public static <T> InMemoryDataSource<T> create(Collection<T> data) {
public static <T> InMemoryDataSource<T> create(T... data) { public static <T> InMemoryDataSource<T> create(T... data) {
return new InMemoryDataSource<>(Arrays.asList(data)); return new InMemoryDataSource<>(Arrays.asList(data));
} }

}
@Override
public Stream<T> apply(Query t) {
return request.apply(t);
}

public int size(Query t) {
return sizeCallback.apply(t);
}

public boolean isInMemory() {
return false;
}

}
Expand Up @@ -17,6 +17,7 @@


import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Stream;
Expand All @@ -28,14 +29,15 @@
* @param <T> * @param <T>
* data type * data type
*/ */
public class InMemoryDataSource<T> extends DataSource<T> { public class InMemoryDataSource<T> implements DataSource<T> {


private Function<Query, Stream<T>> request;
private int size; private int size;


/** /**
* Constructs a new ListDataSource. This method makes a protective copy of * Constructs a new ListDataSource. This method makes a protective copy of
* the contents of the Collection. * the contents of the Collection.
* *
* @param collection * @param collection
* initial data * initial data
*/ */
Expand All @@ -49,12 +51,44 @@ public InMemoryDataSource(Collection<T> collection) {
* Chaining constructor for making modified {@link InMemoryDataSource}s. * Chaining constructor for making modified {@link InMemoryDataSource}s.
* This Constructor is used internally for making sorted and filtered * This Constructor is used internally for making sorted and filtered
* variants of a base data source with actual data. * variants of a base data source with actual data.
* *
* @param request * @param request
* request for the new data source * request for the new data source
*/ */
protected InMemoryDataSource(Function<Query, Stream<T>> request) { protected InMemoryDataSource(Function<Query, Stream<T>> request) {
super(request,null); this.request = request;
}

@Override
public Stream<T> apply(Query query) {
return request.apply(query);
}

/**
* Sets a default sorting order to the data source.
*
* @param sortOrder
* a {@link Comparator} providing the needed sorting order
* @return new data source with modified sorting
*/
public InMemoryDataSource<T> sortingBy(Comparator<T> sortOrder) {
return new InMemoryDataSource<>(q -> request.apply(q)
.sorted(sortOrder));
}

/**
* Sets a default sorting order to the data source. This method is a
* short-hand for {@code sortingBy(Comparator.comparing(sortOrder))}.
*
* @param sortOrder
* function to sort by
* @param <U>
* the type of the Comparable sort key
* @return new data source with modified sorting
*/
public <U extends Comparable<? super U>> InMemoryDataSource<T> sortingBy(
Function<T, U> sortOrder) {
return sortingBy(Comparator.comparing(sortOrder));
} }


@Override @Override
Expand Down
27 changes: 25 additions & 2 deletions server/src/main/java/com/vaadin/server/data/SortOrder.java
Expand Up @@ -19,20 +19,43 @@


import com.vaadin.shared.data.sort.SortDirection; import com.vaadin.shared.data.sort.SortDirection;


/**
* Sorting information for one field.
*
* @see Query
*/
public class SortOrder<T> implements Serializable { public class SortOrder<T> implements Serializable {


private T sorted; private final T sorted;
private SortDirection direction; private final SortDirection direction;


/**
* Constructs a field sorting information
*
* @param sorted
* sorting information, usually field id or {@link java.util.Comparator}
* @param direction
* sorting direction
*/
public SortOrder(T sorted, SortDirection direction) { public SortOrder(T sorted, SortDirection direction) {
this.sorted = sorted; this.sorted = sorted;
this.direction = direction; this.direction = direction;
} }


/**
* Sorting information
*
* @return sorting entity, usually field id or {@link java.util.Comparator}
*/
public T getSorted() { public T getSorted() {
return sorted; return sorted;
} }


/**
* Sorting direction
*
* @return sorting direction
*/
public SortDirection getDirection() { public SortDirection getDirection() {
return direction; return direction;
} }
Expand Down

0 comments on commit 7373b23

Please sign in to comment.