diff options
9 files changed, 574 insertions, 0 deletions
diff --git a/server/src/main/java/com/vaadin/server/data/DataSource.java b/server/src/main/java/com/vaadin/server/data/DataSource.java new file mode 100644 index 0000000000..d4e5e17aac --- /dev/null +++ b/server/src/main/java/com/vaadin/server/data/DataSource.java @@ -0,0 +1,96 @@ +/* + * 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.Arrays; +import java.util.Collection; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * A generic data source for any back end and Listing UI components. + * + * @param <T> + * data source data type + */ +public class DataSource<T> implements + Function<Query, Stream<T>>, java.io.Serializable { + + protected Function<Query, Stream<T>> request; + protected Function<Query, Integer> sizeCallback; + + protected DataSource() { + } + + /** + * 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 DataSource(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; + } + + /** + * This method creates a new {@link InMemoryDataSource} from a given + * Collection. The InMemoryDataSource creates a protective List copy of all + * the contents in the Collection. + * + * @param data + * collection of data + * @return in-memory data source + */ + public static <T> InMemoryDataSource<T> create(Collection<T> data) { + return new InMemoryDataSource<>(data); + } + + /** + * This method creates a new {@link InMemoryDataSource} from given + * objects.The InMemoryDataSource creates a protective List copy of all the + * contents in the array. + * + * @param data + * data objects + * @return in-memory data source + */ + @SafeVarargs + public static <T> InMemoryDataSource<T> create(T... 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; + } + +} diff --git a/server/src/main/java/com/vaadin/server/data/InMemoryDataSource.java b/server/src/main/java/com/vaadin/server/data/InMemoryDataSource.java new file mode 100644 index 0000000000..bbc5d738c6 --- /dev/null +++ b/server/src/main/java/com/vaadin/server/data/InMemoryDataSource.java @@ -0,0 +1,75 @@ +/* + * 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.Collection; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * {@link DataSource} wrapper for {@link Collection}s. This class does not + * actually handle the {@link Query} parameters. + * + * @param <T> + * data type + */ +public class InMemoryDataSource<T> extends DataSource<T> { + + private int size; + + /** + * Constructs a new ListDataSource. This method makes a protective copy of + * the contents of the Collection. + * + * @param collection + * initial data + */ + public InMemoryDataSource(Collection<T> collection) { + final List<T> backend = new ArrayList<>(collection); + request = query -> backend.stream(); + size = backend.size(); + } + + /** + * Chaining constructor for making modified {@link InMemoryDataSource}s. + * This Constructor is used internally for making sorted and filtered + * variants of a base data source with actual data. + * + * @param request + * request for the new data source + */ + protected InMemoryDataSource(Function<Query, Stream<T>> request) { + super(request,null); + } + + @Override + public boolean isInMemory() { + return true; + } + + /** + * {@inheritDoc} + * <p> + * For in-memory data source the query is not handled, and it will always + * return the full size. + */ + @Override + public int size(Query t) { + return size; + } +} diff --git a/server/src/main/java/com/vaadin/server/data/Query.java b/server/src/main/java/com/vaadin/server/data/Query.java new file mode 100644 index 0000000000..ac2482e460 --- /dev/null +++ b/server/src/main/java/com/vaadin/server/data/Query.java @@ -0,0 +1,120 @@ +/* + * 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.io.Serializable; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * Query object used to request data from a backend. Contains index limits, + * sorting and filtering information. + * + * @since + */ +public class Query implements Serializable { + + private final int offset; + private final int limit; + private final List<SortOrder<String>> sortOrders; + private final Set<Object> filters; + + /** + * Constructs a Query for all rows from 0 to {@link Integer#MAX_VALUE} + * without sorting and filtering. + */ + public Query() { + offset = 0; + limit = Integer.MAX_VALUE; + sortOrders = Collections.emptyList(); + filters = Collections.emptySet(); + } + + /** + * Constructs a Query for all rows from 0 to {@link Integer#MAX_VALUE} with + * filtering. + * + * @param filters + * set of back end filters + */ + public Query(Set<Object> filters) { + offset = 0; + limit = Integer.MAX_VALUE; + sortOrders = Collections.emptyList(); + this.filters = filters; + } + + /** + * Constructs a new Query object with given offset, limit, sorting and + * filtering. + * + * @param offset + * first index to fetch + * @param limit + * fetched item count + * @param sortOrders + * sorting order for fetching + * @param filters + * filtering for fetching + */ + public Query(int offset, int limit, List<SortOrder<String>> sortOrders, + Set<Object> filters) { + this.offset = offset; + this.limit = limit; + this.sortOrders = sortOrders; + this.filters = filters; + } + + /** + * Gets the first index of items to fetch. + * + * @return offset for data request + */ + public int getOffset() { + return offset; + } + + /** + * Gets the limit of items to fetch. + * <p> + * <strong>Note: </strong>It is possible that + * {@code offset + limit > item count} + * + * @return number of items to fetch + */ + public int getLimit() { + return limit; + } + + /** + * Gets the sorting for items to fetch. + * + * @return list of sort orders + */ + public List<SortOrder<String>> getSortOrders() { + return sortOrders; + } + + /** + * Gets the filters for items to fetch. + * + * @return set of filters + */ + public Set<Object> getFilters() { + return filters; + } +} diff --git a/server/src/main/java/com/vaadin/server/data/SortOrder.java b/server/src/main/java/com/vaadin/server/data/SortOrder.java new file mode 100644 index 0000000000..3b8fb65932 --- /dev/null +++ b/server/src/main/java/com/vaadin/server/data/SortOrder.java @@ -0,0 +1,39 @@ +/* + * 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.io.Serializable; + +import com.vaadin.shared.data.sort.SortDirection; + +public class SortOrder<T> implements Serializable { + + private T sorted; + private SortDirection direction; + + public SortOrder(T sorted, SortDirection direction) { + this.sorted = sorted; + this.direction = direction; + } + + public T getSorted() { + return sorted; + } + + public SortDirection getDirection() { + return direction; + } +} diff --git a/server/src/test/java/com/vaadin/server/data/datasource/InMemoryDataSourceTest.java b/server/src/test/java/com/vaadin/server/data/datasource/InMemoryDataSourceTest.java new file mode 100644 index 0000000000..9ab9731beb --- /dev/null +++ b/server/src/test/java/com/vaadin/server/data/datasource/InMemoryDataSourceTest.java @@ -0,0 +1,35 @@ +package com.vaadin.server.data.datasource; + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import com.vaadin.server.data.DataSource; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.server.data.InMemoryDataSource; +import com.vaadin.server.data.Query; + +public class InMemoryDataSourceTest { + + private InMemoryDataSource<StrBean> dataSource; + private List<StrBean> data; + + @Before + public void setUp() { + data = StrBean.generateRandomBeans(100); + dataSource = DataSource.create(data); + } + + @Test + public void testListContainsAllData() { + dataSource.apply(new Query()).forEach( + str -> assertTrue( + "Data source contained values not in original data", + data.remove(str))); + assertTrue("Not all values from original data were in data source", + data.isEmpty()); + } + +} diff --git a/server/src/test/java/com/vaadin/server/data/datasource/StrBean.java b/server/src/test/java/com/vaadin/server/data/datasource/StrBean.java new file mode 100644 index 0000000000..fb0ea8eb1e --- /dev/null +++ b/server/src/test/java/com/vaadin/server/data/datasource/StrBean.java @@ -0,0 +1,49 @@ +package com.vaadin.server.data.datasource; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +class StrBean implements Serializable { + + private static String[] values = new String[] { "Foo", "Bar", "Baz" }; + + private String value; + private final int id; + private final int randomNumber; + + public StrBean(String value, int id, int randomNumber) { + this.value = value; + this.id = id; + this.randomNumber = randomNumber; + } + + public String getValue() { + return value; + } + + public int getId() { + return id; + } + + public int getRandomNumber() { + return randomNumber; + } + + public static List<StrBean> generateRandomBeans(int max) { + List<StrBean> data = new ArrayList<StrBean>(); + Random r = new Random(13337); + data.add(new StrBean("Xyz", 10, max)); + for (int i = 0; i < max - 1; ++i) { + data.add(new StrBean(values[r.nextInt(values.length)], i, r + .nextInt(10))); + } + return data; + } + + @Override + public String toString() { + return "{ " + value + ", " + randomNumber + ", " + id + " }"; + } +}
\ No newline at end of file diff --git a/server/src/test/java/com/vaadin/server/data/datasource/bov/DataSourceBoVTest.java b/server/src/test/java/com/vaadin/server/data/datasource/bov/DataSourceBoVTest.java new file mode 100644 index 0000000000..a42657813a --- /dev/null +++ b/server/src/test/java/com/vaadin/server/data/datasource/bov/DataSourceBoVTest.java @@ -0,0 +1,89 @@ +/* + * 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.datasource.bov; + +import com.vaadin.server.data.DataSource; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Vaadin 8 Example from Book of Vaadin + * + * @author Vaadin Ltd + */ +public class DataSourceBoVTest { + + private PersonServiceImpl personService; + + public static class PersonServiceImpl implements PersonService{ + final Person[] persons; + + public PersonServiceImpl(Person... persons) { + this.persons = persons; + } + + @Override + public List<Person> fetchPersons(int offset, int limit) { + return Arrays.stream(persons) + .skip(offset) + .limit(limit) + .collect(Collectors.toList()); + } + + @Override + public int getPersonCount() { + return persons.length; + } + } + + @Test + public void testPersons() { + + DataSource<Person> dataSource = new DataSource<Person>( + // First callback fetches items based on a query + query -> { + // The index of the first item to load + int offset = query.getOffset(); + + // The number of items to load + int limit = query.getLimit(); + + List<Person> persons = getPersonService().fetchPersons(offset, limit); + + return persons.stream(); + }, + // Second callback fetches the number of items for a query + query -> getPersonService().getPersonCount() + ); + } + + public PersonServiceImpl getPersonService() { + return personService; + } + + @Before + public void buildService() { + personService = new PersonServiceImpl( + new Person("George Washington", 1732), + new Person("John Adams", 1735), + new Person("Thomas Jefferson", 1743), + new Person("James Madison", 1751)); + } +} diff --git a/server/src/test/java/com/vaadin/server/data/datasource/bov/Person.java b/server/src/test/java/com/vaadin/server/data/datasource/bov/Person.java new file mode 100644 index 0000000000..e8672999b4 --- /dev/null +++ b/server/src/test/java/com/vaadin/server/data/datasource/bov/Person.java @@ -0,0 +1,41 @@ +/* + * 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.datasource.bov; + +import java.io.Serializable; + +/** + * POJO + * + * @author Vaadin Ltd + */ +public class Person implements Serializable{ + private final String name; + private final int born; + + public Person(String name, int born) { + this.name = name; + this.born = born; + } + + public String getName() { + return name; + } + + public int getBorn() { + return born; + } +} diff --git a/server/src/test/java/com/vaadin/server/data/datasource/bov/PersonService.java b/server/src/test/java/com/vaadin/server/data/datasource/bov/PersonService.java new file mode 100644 index 0000000000..752cda4032 --- /dev/null +++ b/server/src/test/java/com/vaadin/server/data/datasource/bov/PersonService.java @@ -0,0 +1,30 @@ +/* + * 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.datasource.bov; + +import java.io.Serializable; +import java.util.List; + +/** + * TODO class description + * + * @author Vaadin Ltd + */ +public interface PersonService extends Serializable{ + List<Person> fetchPersons(int offset, int limit); + + int getPersonCount(); +} |