include::datamodel-forms.asciidoc[leveloffset=+2]
-include::datamodel-datasources.asciidoc[leveloffset=+2]
+include::datamodel-providers.asciidoc[leveloffset=+2]
include::datamodel-selection.asciidoc[leveloffset=+2]
(((range="endofrange", startref="term.datamodel")))
+++ /dev/null
----
-title: Showing Many Items in a Listing
-order: 4
-layout: page
----
-
-[[datamodel.datasources]]
-= Showing Many Items in a Listing
-
-A common pattern in applications is that the user is first presented with a list of items, from which she selects one or several items to continue working with.
-These items could be inventory records to survey, messages to respond to or blog drafts to edit or publish.
-
-A [interfacename]#Listing# is a component that displays one or several properties from a list of item, allowing the user to inspect the data, mark items as selected and in some cases even edit the item directly through the component.
-While each listing component has it's own API for configuring exactly how the data is represented and how it can be manipulated, they all share the same mechanisms for receiving data to show.
-
-The items are generally either loaded directly from memory or lazy loaded from some kind of backend.
-Regardless of how the items are loaded, the component is configured with one or several callbacks or JavaBean property names that define how the item should be displayed.
-
-In the following example, a [classname]#ComboBox# that lists status items is configured to use the [classname]#Status#.[methodname]#getCaption()# method to represent each status.
-There is also a [classname]#Grid#, which is configured with one column from the person's name and another column that converts the year of birth to a string for displaying.
-
-[source, java]
-----
-ComboBox<Status> comboBox = new ComboBox<>();
-comboBox.setItemCaptionProvider(Status::getCaption);
-
-Grid<Person> grid = new Grid<>();
-grid.addColumn("Name", Person::getName);
-grid.addColumn("Year of birth",
- person -> Integer.toString(person.getYearOfBirth()));
-----
-
-[NOTE]
-In this example, it would not even be necessary to define any item caption provider for the combo box if [classname]#Status#.[methodname]#toString()# would be implemented to return a suitable text. [classname]#ComboBox# is by default configured to use [methodname]#toString()# for finding a caption to show.
-
-[NOTE]
-The `Year of birth` column will use [classname]#Grid#'s default [classname]#TextRenderer# which requires the column value to be a [classname]#String#. We could for instance use a [classname]#NumberRenderer# instead, and then the renderer would take care of converting the the number according to its configuration.
-
-After we have told the component how the data should be shown, we only need to give it some data to actually show. The easiest way of doing that is as a [interfacename]#java.util.Collection# of item instances.
-
-[source, java]
-----
-comboBox.setItems(EnumSet.allOf(Status.class));
-
-List<Person> persons = Arrays.asList(
- new Person("George Washington", 1732),
- new Person("John Adams", 1735),
- new Person("Thomas Jefferson", 1743),
- new Person("James Madison", 1751));
-
-grid.setItems(persons);
-----
-
-Listing components that allow the user to control the display order of the items are automatically able to sort data by any property as long as the property type implements [classname]#Comparable#.
-
-We can also define a custom [classname]#Comparator# if we want to customize the way a specific column is sorted. The comparator can either be based on the item instances or on the values of the property that is being shown.
-
-[source, java]
-----
-grid.addColumn("Name", Person::getName)
- // Override default natural sorting
- .setValueComparator(
- Comparator.comparing(String::toLowerCase));
-
-grid.addColumn("Year of birth",
- person -> Integer.toString(person.getYearOfBirth()))
- // Sort numerically instead of alphabetically by the string
- .setItemComparator(
- Comparator.comparing(Person::getYearOfBirth));
-----
-
-With listing components that let the user filter items, we can in the same way define our own [interfacename]#BiPredicate# that is used to decide whether a specific item should be shown when the user has entered a specific text into the text field.
-
-[source, java]
-----
-comboBox.setFilter((filterText, item) ->
- item.getCaption().equalsIgnoreCase(filterText));
-----
-
-Instead of directly assigning the item collection as the items that a component should be using, we can instead create a [classname]#ListDataSource# that contains the items.
-The list data source can be shared between different components in the same [classname]#VaadinSession# since it is stateless.
-We can also apply different sorting options for each component, without affecting how data is shown in the other components.
-
-[source, java]
-----
-ListDataSource<Person> dataSource =
- new ListDataSource<>(persons);
-
-ComboBox<Person> comboBox = new ComboBox<>();
-// The combo box shows the person sorted by name
-comboBox.setDataSource(
- dataSource.sortedBy(Person::getName));
-
-Grid<Person> grid = new Grid<>();
-// The grid shows the same persons sorted by year of birth
-grid.setDataSource(
- dataSource.sortedBy(Person::getYearOfBirth));
-----
-
-The [classname]#Listing# component cannot automatically know about changes to the list of items or to any individual item.
-We must notify the data source when items are changed, added or removed so that components using the data will show the new values.
-
-[source, java]
-----
-ListDataSource<Person> dataSource =
- new ListDataSource<>(persons);
-
-Button addPersonButton = new Button("Add person",
- clickEvent -> {
- // Keep track of the index where the person will be added
- int addIndex = persons.size();
-
- persons.add(new Person("James Monroe", 1758));
-
- dataSource.notifyAdd(addIndex);
-});
-
-Button modifyPersonButton = new Button("Modify person",
- clickEvent -> {
- Person personToChange = persons.get(0);
-
- personToChange.setName("Changed person");
-
- dataSource.refresh(0);
-});
-----
-
-[TIP]
-There might be situations where we cannot tell exactly how the data has changed, but only that some parts might have been modified. We can then use the [methodname]#refreshAll()# method, which will make the components reload all the data.
-
-== Lazy Loading Data to a Listing
-
-All the previous examples have shown cases with a limited amount of data that can be loaded as item instances in memory.
-There are also situations where it is more efficient to only load the items that will currently be displayed.
-This includes situations where all available data would use lots of memory or when it would take a long time to load all the items.
-
-[NOTE]
-Regardless of how we make the items available to the listing component on the server, components like [classname]#Grid# will always take care of only sending the currently needed items to the browser.
-
-For example, if we have the following existing backend service that fetches items from a database or a REST service .
-
-[source, java]
-----
-public interface PersonService {
- List<Person> fetchPersons(int offset, int limit);
- int getPersonCount();
-}
-----
-
-To use this service with a listing component, we need to define one callback for loading specific items and one callback for finding how many items are currently available.
-Information about which items to fetch as well as some additional details are made available in a [interfacename]#Query# object that is passed to both callbacks.
-
-[source, java]
-----
-DataSource<Person> dataSource = new BackendDataSource<>(
- // 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()
-);
-
-Grid<Person> grid = new Grid<>();
-grid.setDataSource(dataSource);
-
-// Columns are configured in the same way as before
-...
-----
-
-[NOTE]
-The results of the first and second callback must be symmetric so that fetching all available items using the first callback returns the number of items indicated by the second callback. Thus if you impose any restrictions on e.g. a database query in the first callback, you must also add the same restrictions for the second callback.
-
-=== Sorting
-
-It is not practical to order items based on a [interfacename]#Comparator# when the items are loaded on demand, since it would require all items to be loaded and inspected.
-
-Each backend has its own way of defining how the fetched items should be ordered, but they are in general based on a list of property names and information on whether ordering should be ascending or descending.
-
-As an example, there could be a service interface which looks like the following.
-
-[source, java]
-----
-public interface PersonService {
- List<Person> fetchPersons(
- int offset,
- int limit,
- List<PersonSort> sortOrders);
-
- int getPersonCount();
-
- PersonSort createSort(
- String propertyName,
- boolean descending);
-}
-----
-
-With the above service interface, our data source can be enhanced to convert the provided sorting options into a format expected by the service.
-The sorting options set through the component will be available through [interfacename]#Query#.[methodname]#getSortOrders()#.
-
-[source, java]
-----
-DataSource<Person> dataSource = new BackEndDataSource<>(
- query -> {
- List<PersonSort> sortOrders = new ArrayList<>();
- for(SortOrder<String> queryOrder : query.getSortOrders()) {
- PersonSort sort = getPersonService().createSort(
- // The name of the sorted property
- queryOrder.getSorted(),
- // The sort direction for this property
- queryOrder.getDirection() == SortDirection.DESCENDING);
- sortOrders.add(sort);
- }
-
- return getPersonService().fetchPersons(
- query.getOffset(),
- query.getLimit(),
- sortOrders
- ).stream();
- },
- // The number of persons is the same regardless of ordering
- query -> persons.getPersonCount()
-);
-----
-
-We also need to configure our grid so that it can know what property name should be included in the query when the user wants to sort by a specific column.
-When a data source that does lazy loading is used, [classname]#Grid# and other similar components will only let the user sort by columns for which a sort property name is provided.
-
-[source, java]
-----
-Grid<Person> grid = new Grid<>();
-
-grid.setDataSource(dataSource);
-
-// Will be sortable by the user
-// When sorting by this column, the query will have a SortOrder
-// where getSorted() returns "name"
-grid.addColumn("Name", Person::getName)
- .setSortProperty("name");
-
-// Will not be sortable since no sorting info is given
-grid.addColumn("Year of birth",
- person -> Integer.toString(person.getYearOfBirth()));
-----
-
-There might also be cases where a single property name is not enough for sorting.
-This might be the case if the backend needs to sort by multiple properties for one column in the user interface or if the backend sort order should be inverted compared to the sort order defined by the user.
-In such cases, we can define a callback that generates suitable [classname]#SortOrder# values for the given column.
-
-[source, java]
-----
-grid.addColumn("Name",
- person -> person.getFirstName() + " " + person.getLastName())
- .setSortBuilder(
- // Sort according to last name, then first name
- direction -> Stream.of(
- new SortOrder("lastName", direction),
- new SortOrder("firstName", direction)
- ));
-----
-
-=== Filtering
-
-A similar approach is also needed with filtering in cases such as [classname]#ComboBox# where the user can control how items are filtered.
-
-The filtering of a data source query is represented as a [interfacename]#BackendFilter# instance. There are existing implementations for some common filtering cases, such as requiring a named property to not be null or a SQL `LIKE` comparison.
-
-[source, java]
-----
-ComboBox<Person> comboBox = new ComboBox<>();
-
-comboBox.setItemCaptionProvider(Person::getName);
-
-comboBox.setFilter(
- // corresponds to this SQL: WHERE name LIKE [filterText]
- filterText -> new Like("name", filterText));
-----
-
-If we have a service interface that only supports some specific filtering option, the implementation might become simpler if we define our own [interfacename]#BackendFilter# instead of implementing our backend to use the generic built-in filter types.
-
-As an example, our service interface with support for filtering could look like this. Ordering support has been omitted in these examples to keep focus on filtering.
-
-[source, java]
-----
-public interface PersonService {
- List<Person> fetchPersons(
- int offset,
- int limit,
- String namePrefix);
- int getPersonCount(String namePrefix);
-}
-----
-
-For the filtering needs of this service, we could define a [classname]#NamePrefixFilter# that corresponds to the only filtering option available.
-
-[source, java]
-----
-public class NamePrefixFilter implements BackendFilter {
- private final String prefix;
-
- public NamePrefixFilter(String prefix) {
- this.prefix = prefix;
- }
-
- public String getPrefix() {
- return prefix;
- }
-}
-----
-
-In the case of [classname]#ComboBox#, we have to define what kind of [interfacename]#BackendFilter# to use when the user has entered some text that should be used for filtering the displayed items.
-
-[source, java]
-----
-comboBox.setFilter(
- filterText -> new NamePrefixFilter(filterText));
-----
-
-We can then implement our data source to look for this special filter implementation and pass the name prefix to the service.
-We can create a helper method for handling the filter since the same logic is needed both for fetching and counting items.
-
-[source, java]
-----
-DataSource<Person> dataSource = new BackEndDataSource<>(
- query -> {
-
- BackendFilter filter = query.getFilter();
-
- String namePrefix = filterToNamePrefix(filter);
-
- return service.fetchPersons(
- query.getOffset(),
- query.getLimit(),
- namePrefix
- ).stream();
- },
- query -> persons.getPersonCount(
- filterToNamePrefix(query.getFilter))
-);
-
-public static String filterToNamePrefix(BackendFilter filter) {
- if (filter == null) {
- return null;
- }
-
- if (filter instanceof NamePrefixFilter)) {
- return ((NamePrefixFilter) filter).getPrefix();
- } else {
- throw new UnsupportedOperationException(
- "This data source only supports NamePrefixFilter");
- }
-}
-----
-
-[TIP]
-If the amount of data in the backend is small enough, it might be better to load all the items into a list and use a [classname]#ListDataSource# instead of implementing filtering or sorting support in a custom [classname]#DataSource# class and configuring the components accordingly.
-
-We can also create a base data source and then use different variations for different components, similarly to the previous examples with [classname]#ListDataSource#.
-
-[source, java]
-----
-DataSource<Person> dataSource = ...
-
-grid.setDataSource(dataSource
- .filteredBy(new Like("name", "Ge%"))
- .sortedBy(new SortOrder(
- "yearOfBirth", SortDirection.ASCENDING)));
-
-comboBox.setDataSource(dataSource
- .sortedBy(new SortOrder(
- "name", SortOrder.DESCENDING)));
-
-----
-
-=== Special Fetching Cases
-
-In some cases it might be necessary directly extend [classname]#BackendDataSource# instead of constructing an instance based the two simple callback methods shown above.
-
-One such case is if the backend loads items based on a page index and a page size so that the start index in the query always needs to be a multiple of the page size. As an example, our service interface made for paging could look like this.
-
-[source, java]
-----
-public interface PersonService {
- List<Person> fetchPersons(
- int pageIndex,
- int pageSize);
- int getPersonCount();
-}
-----
-
-We can use this kind of backend service as long as we also make the data source declare that queries should always be done for whole pages.
-Components using this data source will take the information into account when querying for data.
-
-[source, java]
-----
-public class PersonDataSource
- extends BackendDataSource<Person> {
-
- @Override
- public boolean alignQueries() {
- // Informs the part that fetches items that the query offset
- // must be a multiple of the query limit, i.e. that only full
- // pages should be requested
- return true;
- }
-
- @Override
- public void fetch(Query<Person> query,
- FetchResult<Person> result) {
- int pageSize = query.getLimit();
-
- // Caller guarantees that query.getOffset() % pageSize == 0
- int pageIndex = query.getOffset() / pageSize;
-
- result.setItems(getPersonService().fetchPersons(pageIndex, pageSize));
- }
-
- @Override
- public int getCount(Query<Person> query) {
- return getPersonService().getPersonCount();
- }
-}
-----
-
-Some backends may also have limitations on how many (or few) items can be fetched at once.
-While our data source implementation could deal with that limitation internally by sending multiple requests to the backend and then assembling the results together before returning the result, we can also make the data source indicate that the responsibility for splitting up the query is on the caller instead.
-
-[source, java]
-----
-public class PersonDataSource
- extends BackendDataSource<Person> {
-
- @Override
- public int getMaxLimit() {
- // Informs the part that fetches items that the maximum
- // supported query limit size is 30
- return 30;
- }
-
- @Override
- public void fetch(Query<Person> query,
- FetchResult<Person> result) {
- List<Person> persons = getPersonService().fetchPersons(
- query.getOffset(),
- query.getLimit());
- result.setItems(persons);
- }
-
- @Override
- public int getCount(Query<Person> query) {
- return getPersonService().getPersonCount();
- }
-}
-----
-
-[TIP]
-You can set the max limit and the min limit to the same value if you are using a backend that has a hardcoded page size. You can also combine this with aligned queries.
-
-Yet another case that benefits from custom querying options is backends that perform better if items are fetched relative to a previously executed query instead of by skipping items based on an absolute offset.
-
-To help with this, the provided query object will automatically contain a reference to the item immediately before the start of the first new item to fetch if available.
-The item immediately after the end of the range to fetch might also be available in some cases if the user is scrolling through the data backwards. There are, however, no guarantees that either item will be available in all queries, so the implementation should always also support fetching by offset.
--- /dev/null
+---
+title: Showing Many Items in a Listing
+order: 4
+layout: page
+---
+
+[[datamodel.dataproviders]]
+= Showing Many Items in a Listing
+
+A common pattern in applications is that the user is first presented with a list of items, from which she selects one or several items to continue working with.
+These items could be inventory records to survey, messages to respond to or blog drafts to edit or publish.
+
+A [interfacename]#Listing# is a component that displays one or several properties from a list of item, allowing the user to inspect the data, mark items as selected and in some cases even edit the item directly through the component.
+While each listing component has it's own API for configuring exactly how the data is represented and how it can be manipulated, they all share the same mechanisms for receiving data to show.
+
+The items are generally either loaded directly from memory or lazy loaded from some kind of backend.
+Regardless of how the items are loaded, the component is configured with one or several callbacks or JavaBean property names that define how the item should be displayed.
+
+In the following example, a [classname]#ComboBox# that lists status items is configured to use the [classname]#Status#.[methodname]#getCaption()# method to represent each status.
+There is also a [classname]#Grid#, which is configured with one column from the person's name and another column that converts the year of birth to a string for displaying.
+
+[source, java]
+----
+ComboBox<Status> comboBox = new ComboBox<>();
+comboBox.setItemCaptionProvider(Status::getCaption);
+
+Grid<Person> grid = new Grid<>();
+grid.addColumn("Name", Person::getName);
+grid.addColumn("Year of birth",
+ person -> Integer.toString(person.getYearOfBirth()));
+----
+
+[NOTE]
+In this example, it would not even be necessary to define any item caption provider for the combo box if [classname]#Status#.[methodname]#toString()# would be implemented to return a suitable text. [classname]#ComboBox# is by default configured to use [methodname]#toString()# for finding a caption to show.
+
+[NOTE]
+The `Year of birth` column will use [classname]#Grid#'s default [classname]#TextRenderer# which requires the column value to be a [classname]#String#. We could for instance use a [classname]#NumberRenderer# instead, and then the renderer would take care of converting the the number according to its configuration.
+
+After we have told the component how the data should be shown, we only need to give it some data to actually show. The easiest way of doing that is as a [interfacename]#java.util.Collection# of item instances.
+
+[source, java]
+----
+comboBox.setItems(EnumSet.allOf(Status.class));
+
+List<Person> persons = Arrays.asList(
+ new Person("George Washington", 1732),
+ new Person("John Adams", 1735),
+ new Person("Thomas Jefferson", 1743),
+ new Person("James Madison", 1751));
+
+grid.setItems(persons);
+----
+
+Listing components that allow the user to control the display order of the items are automatically able to sort data by any property as long as the property type implements [classname]#Comparable#.
+
+We can also define a custom [classname]#Comparator# if we want to customize the way a specific column is sorted. The comparator can either be based on the item instances or on the values of the property that is being shown.
+
+[source, java]
+----
+grid.addColumn("Name", Person::getName)
+ // Override default natural sorting
+ .setValueComparator(
+ Comparator.comparing(String::toLowerCase));
+
+grid.addColumn("Year of birth",
+ person -> Integer.toString(person.getYearOfBirth()))
+ // Sort numerically instead of alphabetically by the string
+ .setItemComparator(
+ Comparator.comparing(Person::getYearOfBirth));
+----
+
+With listing components that let the user filter items, we can in the same way define our own [interfacename]#BiPredicate# that is used to decide whether a specific item should be shown when the user has entered a specific text into the text field.
+
+[source, java]
+----
+comboBox.setFilter((filterText, item) ->
+ item.getCaption().equalsIgnoreCase(filterText));
+----
+
+Instead of directly assigning the item collection as the items that a component should be using, we can instead create a [classname]#ListDataProvider# that contains the items.
+The list data source can be shared between different components in the same [classname]#VaadinSession# since it is stateless.
+We can also apply different sorting options for each component, without affecting how data is shown in the other components.
+
+[source, java]
+----
+ListDataProvider<Person> dataProvider =
+ new ListDataProvider<>(persons);
+
+ComboBox<Person> comboBox = new ComboBox<>();
+// The combo box shows the person sorted by name
+comboBox.setDataProvider(
+ dataProvider.sortedBy(Person::getName));
+
+Grid<Person> grid = new Grid<>();
+// The grid shows the same persons sorted by year of birth
+grid.setDataProvider(
+ dataProvider.sortedBy(Person::getYearOfBirth));
+----
+
+The [classname]#Listing# component cannot automatically know about changes to the list of items or to any individual item.
+We must notify the data source when items are changed, added or removed so that components using the data will show the new values.
+
+[source, java]
+----
+ListDataProvider<Person> dataProvider =
+ new ListDataProvider<>(persons);
+
+Button addPersonButton = new Button("Add person",
+ clickEvent -> {
+ // Keep track of the index where the person will be added
+ int addIndex = persons.size();
+
+ persons.add(new Person("James Monroe", 1758));
+
+ dataProvider.notifyAdd(addIndex);
+});
+
+Button modifyPersonButton = new Button("Modify person",
+ clickEvent -> {
+ Person personToChange = persons.get(0);
+
+ personToChange.setName("Changed person");
+
+ dataProvider.refresh(0);
+});
+----
+
+[TIP]
+There might be situations where we cannot tell exactly how the data has changed, but only that some parts might have been modified. We can then use the [methodname]#refreshAll()# method, which will make the components reload all the data.
+
+== Lazy Loading Data to a Listing
+
+All the previous examples have shown cases with a limited amount of data that can be loaded as item instances in memory.
+There are also situations where it is more efficient to only load the items that will currently be displayed.
+This includes situations where all available data would use lots of memory or when it would take a long time to load all the items.
+
+[NOTE]
+Regardless of how we make the items available to the listing component on the server, components like [classname]#Grid# will always take care of only sending the currently needed items to the browser.
+
+For example, if we have the following existing backend service that fetches items from a database or a REST service .
+
+[source, java]
+----
+public interface PersonService {
+ List<Person> fetchPersons(int offset, int limit);
+ int getPersonCount();
+}
+----
+
+To use this service with a listing component, we need to define one callback for loading specific items and one callback for finding how many items are currently available.
+Information about which items to fetch as well as some additional details are made available in a [interfacename]#Query# object that is passed to both callbacks.
+
+[source, java]
+----
+DataProvider<Person> dataProvider = new BackendDataProvider<>(
+ // 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()
+);
+
+Grid<Person> grid = new Grid<>();
+grid.setDataProvider(dataProvider);
+
+// Columns are configured in the same way as before
+...
+----
+
+[NOTE]
+The results of the first and second callback must be symmetric so that fetching all available items using the first callback returns the number of items indicated by the second callback. Thus if you impose any restrictions on e.g. a database query in the first callback, you must also add the same restrictions for the second callback.
+
+=== Sorting
+
+It is not practical to order items based on a [interfacename]#Comparator# when the items are loaded on demand, since it would require all items to be loaded and inspected.
+
+Each backend has its own way of defining how the fetched items should be ordered, but they are in general based on a list of property names and information on whether ordering should be ascending or descending.
+
+As an example, there could be a service interface which looks like the following.
+
+[source, java]
+----
+public interface PersonService {
+ List<Person> fetchPersons(
+ int offset,
+ int limit,
+ List<PersonSort> sortOrders);
+
+ int getPersonCount();
+
+ PersonSort createSort(
+ String propertyName,
+ boolean descending);
+}
+----
+
+With the above service interface, our data source can be enhanced to convert the provided sorting options into a format expected by the service.
+The sorting options set through the component will be available through [interfacename]#Query#.[methodname]#getSortOrders()#.
+
+[source, java]
+----
+DataProvider<Person> dataProvider = new BackEndDataProvider<>(
+ query -> {
+ List<PersonSort> sortOrders = new ArrayList<>();
+ for(SortOrder<String> queryOrder : query.getSortOrders()) {
+ PersonSort sort = getPersonService().createSort(
+ // The name of the sorted property
+ queryOrder.getSorted(),
+ // The sort direction for this property
+ queryOrder.getDirection() == SortDirection.DESCENDING);
+ sortOrders.add(sort);
+ }
+
+ return getPersonService().fetchPersons(
+ query.getOffset(),
+ query.getLimit(),
+ sortOrders
+ ).stream();
+ },
+ // The number of persons is the same regardless of ordering
+ query -> persons.getPersonCount()
+);
+----
+
+We also need to configure our grid so that it can know what property name should be included in the query when the user wants to sort by a specific column.
+When a data source that does lazy loading is used, [classname]#Grid# and other similar components will only let the user sort by columns for which a sort property name is provided.
+
+[source, java]
+----
+Grid<Person> grid = new Grid<>();
+
+grid.setDataProvider(dataProvider);
+
+// Will be sortable by the user
+// When sorting by this column, the query will have a SortOrder
+// where getSorted() returns "name"
+grid.addColumn("Name", Person::getName)
+ .setSortProperty("name");
+
+// Will not be sortable since no sorting info is given
+grid.addColumn("Year of birth",
+ person -> Integer.toString(person.getYearOfBirth()));
+----
+
+There might also be cases where a single property name is not enough for sorting.
+This might be the case if the backend needs to sort by multiple properties for one column in the user interface or if the backend sort order should be inverted compared to the sort order defined by the user.
+In such cases, we can define a callback that generates suitable [classname]#SortOrder# values for the given column.
+
+[source, java]
+----
+grid.addColumn("Name",
+ person -> person.getFirstName() + " " + person.getLastName())
+ .setSortBuilder(
+ // Sort according to last name, then first name
+ direction -> Stream.of(
+ new SortOrder("lastName", direction),
+ new SortOrder("firstName", direction)
+ ));
+----
+
+=== Filtering
+
+A similar approach is also needed with filtering in cases such as [classname]#ComboBox# where the user can control how items are filtered.
+
+The filtering of a data source query is represented as a [interfacename]#BackendFilter# instance. There are existing implementations for some common filtering cases, such as requiring a named property to not be null or a SQL `LIKE` comparison.
+
+[source, java]
+----
+ComboBox<Person> comboBox = new ComboBox<>();
+
+comboBox.setItemCaptionProvider(Person::getName);
+
+comboBox.setFilter(
+ // corresponds to this SQL: WHERE name LIKE [filterText]
+ filterText -> new Like("name", filterText));
+----
+
+If we have a service interface that only supports some specific filtering option, the implementation might become simpler if we define our own [interfacename]#BackendFilter# instead of implementing our backend to use the generic built-in filter types.
+
+As an example, our service interface with support for filtering could look like this. Ordering support has been omitted in these examples to keep focus on filtering.
+
+[source, java]
+----
+public interface PersonService {
+ List<Person> fetchPersons(
+ int offset,
+ int limit,
+ String namePrefix);
+ int getPersonCount(String namePrefix);
+}
+----
+
+For the filtering needs of this service, we could define a [classname]#NamePrefixFilter# that corresponds to the only filtering option available.
+
+[source, java]
+----
+public class NamePrefixFilter implements BackendFilter {
+ private final String prefix;
+
+ public NamePrefixFilter(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+}
+----
+
+In the case of [classname]#ComboBox#, we have to define what kind of [interfacename]#BackendFilter# to use when the user has entered some text that should be used for filtering the displayed items.
+
+[source, java]
+----
+comboBox.setFilter(
+ filterText -> new NamePrefixFilter(filterText));
+----
+
+We can then implement our data source to look for this special filter implementation and pass the name prefix to the service.
+We can create a helper method for handling the filter since the same logic is needed both for fetching and counting items.
+
+[source, java]
+----
+DataProvider<Person> dataProvider = new BackEndDataProvider<>(
+ query -> {
+
+ BackendFilter filter = query.getFilter();
+
+ String namePrefix = filterToNamePrefix(filter);
+
+ return service.fetchPersons(
+ query.getOffset(),
+ query.getLimit(),
+ namePrefix
+ ).stream();
+ },
+ query -> persons.getPersonCount(
+ filterToNamePrefix(query.getFilter))
+);
+
+public static String filterToNamePrefix(BackendFilter filter) {
+ if (filter == null) {
+ return null;
+ }
+
+ if (filter instanceof NamePrefixFilter)) {
+ return ((NamePrefixFilter) filter).getPrefix();
+ } else {
+ throw new UnsupportedOperationException(
+ "This data source only supports NamePrefixFilter");
+ }
+}
+----
+
+[TIP]
+If the amount of data in the backend is small enough, it might be better to load all the items into a list and use a [classname]#ListDataProvider# instead of implementing filtering or sorting support in a custom [classname]#DataProvider# class and configuring the components accordingly.
+
+We can also create a base data source and then use different variations for different components, similarly to the previous examples with [classname]#ListDataProvider#.
+
+[source, java]
+----
+DataProvider<Person> dataProvider = ...
+
+grid.setDataProvider(dataProvider
+ .filteredBy(new Like("name", "Ge%"))
+ .sortedBy(new SortOrder(
+ "yearOfBirth", SortDirection.ASCENDING)));
+
+comboBox.setDataProvider(dataProvider
+ .sortedBy(new SortOrder(
+ "name", SortOrder.DESCENDING)));
+
+----
+
+=== Special Fetching Cases
+
+In some cases it might be necessary directly extend [classname]#BackendDataProvider# instead of constructing an instance based the two simple callback methods shown above.
+
+One such case is if the backend loads items based on a page index and a page size so that the start index in the query always needs to be a multiple of the page size. As an example, our service interface made for paging could look like this.
+
+[source, java]
+----
+public interface PersonService {
+ List<Person> fetchPersons(
+ int pageIndex,
+ int pageSize);
+ int getPersonCount();
+}
+----
+
+We can use this kind of backend service as long as we also make the data source declare that queries should always be done for whole pages.
+Components using this data source will take the information into account when querying for data.
+
+[source, java]
+----
+public class PersonDataProvider
+ extends BackendDataProvider<Person> {
+
+ @Override
+ public boolean alignQueries() {
+ // Informs the part that fetches items that the query offset
+ // must be a multiple of the query limit, i.e. that only full
+ // pages should be requested
+ return true;
+ }
+
+ @Override
+ public void fetch(Query<Person> query,
+ FetchResult<Person> result) {
+ int pageSize = query.getLimit();
+
+ // Caller guarantees that query.getOffset() % pageSize == 0
+ int pageIndex = query.getOffset() / pageSize;
+
+ result.setItems(getPersonService().fetchPersons(pageIndex, pageSize));
+ }
+
+ @Override
+ public int getCount(Query<Person> query) {
+ return getPersonService().getPersonCount();
+ }
+}
+----
+
+Some backends may also have limitations on how many (or few) items can be fetched at once.
+While our data source implementation could deal with that limitation internally by sending multiple requests to the backend and then assembling the results together before returning the result, we can also make the data source indicate that the responsibility for splitting up the query is on the caller instead.
+
+[source, java]
+----
+public class PersonDataProvider
+ extends BackendDataProvider<Person> {
+
+ @Override
+ public int getMaxLimit() {
+ // Informs the part that fetches items that the maximum
+ // supported query limit size is 30
+ return 30;
+ }
+
+ @Override
+ public void fetch(Query<Person> query,
+ FetchResult<Person> result) {
+ List<Person> persons = getPersonService().fetchPersons(
+ query.getOffset(),
+ query.getLimit());
+ result.setItems(persons);
+ }
+
+ @Override
+ public int getCount(Query<Person> query) {
+ return getPersonService().getPersonCount();
+ }
+}
+----
+
+[TIP]
+You can set the max limit and the min limit to the same value if you are using a backend that has a hardcoded page size. You can also combine this with aligned queries.
+
+Yet another case that benefits from custom querying options is backends that perform better if items are fetched relative to a previously executed query instead of by skipping items based on an absolute offset.
+
+To help with this, the provided query object will automatically contain a reference to the item immediately before the start of the first new item to fetch if available.
+The item immediately after the end of the range to fetch might also be available in some cases if the user is scrolling through the data backwards. There are, however, no guarantees that either item will be available in all queries, so the implementation should always also support fetching by offset.
import java.io.Serializable;
import java.util.Collection;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
/**
* A generic interface for components that show a list of data.
/**
* Returns the source of data items used by this listing.
*
- * @return the data source, not null
+ * @return the data provider, not null
*/
- DataSource<T> getDataSource();
+ DataProvider<T> getDataProvider();
/**
- * Sets the source of data items used by this listing. The data source is
+ * Sets the source of data items used by this listing. The data provider is
* queried for displayed items as needed.
*
- * @param dataSource
- * the data source, not null
+ * @param dataProvider
+ * the data provider, not null
*/
- void setDataSource(DataSource<T> dataSource);
+ void setDataProvider(DataProvider<T> dataProvider);
/**
* Sets the collection of data items of this listing.
*
*/
default void setItems(Collection<T> items) {
- setDataSource(DataSource.create(items));
+ setDataProvider(DataProvider.create(items));
}
/**
* the data items to display
*/
default void setItems(@SuppressWarnings("unchecked") T... items) {
- setDataSource(DataSource.create(items));
+ setDataProvider(DataProvider.create(items));
}
}
--- /dev/null
+/*
+ * Copyright 2000-2016 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.lang.reflect.Method;
+import java.util.EventObject;
+
+import com.vaadin.event.EventRouter;
+import com.vaadin.shared.Registration;
+
+/**
+ * Abstract data provider implementation which takes care of refreshing data from
+ * the underlying data provider.
+ *
+ * @author Vaadin Ltd
+ * @since 8.0
+ *
+ */
+public abstract class AbstractDataProvider<T> implements DataProvider<T> {
+
+ private EventRouter eventRouter;
+
+ @Override
+ public Registration addDataProviderListener(DataProviderListener listener) {
+ addListener(DataChangeEvent.class, listener,
+ DataProviderListener.class.getMethods()[0]);
+ return () -> removeListener(DataChangeEvent.class, listener);
+ }
+
+ @Override
+ public void refreshAll() {
+ fireEvent(new DataChangeEvent(this));
+ }
+
+ /**
+ * Registers a new listener with the specified activation method to listen
+ * events generated by this component. If the activation method does not
+ * have any arguments the event object will not be passed to it when it's
+ * called.
+ *
+ * @param eventType
+ * the type of the listened event. Events of this type or its
+ * subclasses activate the listener.
+ * @param listener
+ * the object instance who owns the activation method.
+ * @param method
+ * the activation method.
+ *
+ */
+ protected void addListener(Class<?> eventType, DataProviderListener listener,
+ Method method) {
+ if (eventRouter == null) {
+ eventRouter = new EventRouter();
+ }
+ eventRouter.addListener(eventType, listener, method);
+ }
+
+ /**
+ * Removes all registered listeners matching the given parameters. Since
+ * this method receives the event type and the listener object as
+ * parameters, it will unregister all <code>object</code>'s methods that are
+ * registered to listen to events of type <code>eventType</code> generated
+ * by this component.
+ *
+ * @param eventType
+ * the exact event type the <code>object</code> listens to.
+ * @param listener
+ * the target object that has registered to listen to events of
+ * type <code>eventType</code> with one or more methods.
+ */
+ protected void removeListener(Class<?> eventType,
+ DataProviderListener listener) {
+ if (eventRouter != null) {
+ eventRouter.removeListener(eventType, listener);
+ }
+ }
+
+ /**
+ * Sends the event to all listeners.
+ *
+ * @param event
+ * the Event to be sent to all listeners.
+ */
+ protected void fireEvent(EventObject event) {
+ if (eventRouter != null) {
+ eventRouter.fireEvent(event);
+ }
+ }
+}
+++ /dev/null
-/*
- * Copyright 2000-2016 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.lang.reflect.Method;
-import java.util.EventObject;
-import java.util.Objects;
-
-import com.vaadin.event.EventRouter;
-import com.vaadin.shared.Registration;
-
-/**
- * Abstract data source implementation which takes care of refreshing data from
- * the underlying data provider.
- *
- * @author Vaadin Ltd
- * @since 8.0
- *
- */
-public abstract class AbstractDataSource<T> implements DataSource<T> {
-
- private EventRouter eventRouter;
-
- @Override
- public Registration addDataSourceListener(DataSourceListener listener) {
- addListener(DataChangeEvent.class, listener,
- DataSourceListener.class.getMethods()[0]);
- return () -> removeListener(DataChangeEvent.class, listener);
- }
-
- @Override
- public void refreshAll() {
- fireEvent(new DataChangeEvent(this));
- }
-
- /**
- * Registers a new listener with the specified activation method to listen
- * events generated by this component. If the activation method does not
- * have any arguments the event object will not be passed to it when it's
- * called.
- *
- * @param eventType
- * the type of the listened event. Events of this type or its
- * subclasses activate the listener.
- * @param listener
- * the object instance who owns the activation method.
- * @param method
- * the activation method.
- *
- */
- protected void addListener(Class<?> eventType, DataSourceListener listener,
- Method method) {
- if (eventRouter == null) {
- eventRouter = new EventRouter();
- }
- eventRouter.addListener(eventType, listener, method);
- }
-
- /**
- * Removes all registered listeners matching the given parameters. Since
- * this method receives the event type and the listener object as
- * parameters, it will unregister all <code>object</code>'s methods that are
- * registered to listen to events of type <code>eventType</code> generated
- * by this component.
- *
- * @param eventType
- * the exact event type the <code>object</code> listens to.
- * @param listener
- * the target object that has registered to listen to events of
- * type <code>eventType</code> with one or more methods.
- */
- protected void removeListener(Class<?> eventType,
- DataSourceListener listener) {
- if (eventRouter != null) {
- eventRouter.removeListener(eventType, listener);
- }
- }
-
- /**
- * Sends the event to all listeners.
- *
- * @param event
- * the Event to be sent to all listeners.
- */
- protected void fireEvent(EventObject event) {
- if (eventRouter != null) {
- eventRouter.fireEvent(event);
- }
- }
-}
--- /dev/null
+/*
+ * Copyright 2000-2016 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.stream.Stream;
+
+import com.vaadin.server.SerializableFunction;
+
+/**
+ * A {@link DataProvider} for any back end.
+ *
+ * @param <T>
+ * data provider data type
+ */
+public class BackEndDataProvider<T> extends AbstractDataProvider<T> {
+
+ private final SerializableFunction<Query, Stream<T>> request;
+ private final SerializableFunction<Query, Integer> sizeCallback;
+
+ /**
+ * Constructs a new DataProvider 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 BackEndDataProvider(SerializableFunction<Query, Stream<T>> request,
+ SerializableFunction<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> fetch(Query query) {
+ return request.apply(query);
+ }
+
+ @Override
+ public int size(Query query) {
+ return sizeCallback.apply(query);
+ }
+
+ /**
+ * Sets a default sorting order to the data provider.
+ *
+ * @param sortOrders
+ * a list of sorting information containing field ids and
+ * directions
+ * @return new data provider with modified sorting
+ */
+ public BackEndDataProvider<T> sortingBy(List<SortOrder<String>> sortOrders) {
+ return new BackEndDataProvider<>(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;
+ }
+
+}
+++ /dev/null
-/*
- * Copyright 2000-2016 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.stream.Stream;
-
-import com.vaadin.server.SerializableFunction;
-
-/**
- * A {@link DataSource} for any back end.
- *
- * @param <T>
- * data source data type
- */
-public class BackEndDataSource<T> extends AbstractDataSource<T> {
-
- private final SerializableFunction<Query, Stream<T>> request;
- private final SerializableFunction<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(SerializableFunction<Query, Stream<T>> request,
- SerializableFunction<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> fetch(Query query) {
- return request.apply(query);
- }
-
- @Override
- public int size(Query query) {
- return sizeCallback.apply(query);
- }
-
- /**
- * 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;
- }
-
-}
import java.util.EventObject;
/**
- * An event fired when the data of a {@code DataSource} changes.
+ * An event fired when the data of a {@code DataProvider} changes.
*
*
- * @see DataSourceListener
+ * @see DataProviderListener
*
* @author Vaadin Ltd
* @since 8.0
/**
* Creates a new {@code DataChangeEvent} event originating from the given
- * data source.
+ * data provider.
*
* @param source
- * the data source, not null
+ * the data provider, not null
*/
- public DataChangeEvent(DataSource<?> source) {
+ public DataChangeEvent(DataProvider<?> source) {
super(source);
}
@Override
- public DataSource<?> getSource() {
- return (DataSource<?>) super.getSource();
+ public DataProvider<?> getSource() {
+ return (DataProvider<?>) super.getSource();
}
}
*/
public class DataCommunicator<T> extends AbstractExtension {
- private Registration dataSourceUpdateRegistration;
+ private Registration dataProviderUpdateRegistration;
/**
* Simple implementation of collection data provider communication. All data
private final Collection<DataGenerator<T>> generators = new LinkedHashSet<>();
private final ActiveDataHandler handler = new ActiveDataHandler();
- private DataSource<T> dataSource = DataSource.create();
+ private DataProvider<T> dataProvider = DataProvider.create();
private final DataKeyMapper<T> keyMapper;
private boolean reset = false;
@Override
public void attach() {
super.attach();
- attachDataSourceListener();
+ attachDataProviderListener();
}
@Override
public void detach() {
super.detach();
- detachDataSourceListener();
+ detachDataProviderListener();
}
/**
public void beforeClientResponse(boolean initial) {
super.beforeClientResponse(initial);
- if (getDataSource() == null) {
+ if (getDataProvider() == null) {
return;
}
Set<Object> filters = Collections.emptySet();
if (initial || reset) {
- int dataSourceSize;
- if (getDataSource().isInMemory() && inMemoryFilter != null) {
- dataSourceSize = (int) getDataSource().fetch(new Query())
+ int dataProviderSize;
+ if (getDataProvider().isInMemory() && inMemoryFilter != null) {
+ dataProviderSize = (int) getDataProvider().fetch(new Query())
.filter(inMemoryFilter).count();
} else {
- dataSourceSize = getDataSource().size(new Query(filters));
+ dataProviderSize = getDataProvider().size(new Query(filters));
}
- rpc.reset(dataSourceSize);
+ rpc.reset(dataProviderSize);
}
if (!pushRows.isEmpty()) {
Stream<T> rowsToPush;
- if (getDataSource().isInMemory()) {
+ if (getDataProvider().isInMemory()) {
// We can safely request all the data when in memory
- rowsToPush = getDataSource().fetch(new Query());
+ rowsToPush = getDataProvider().fetch(new Query());
if (inMemoryFilter != null) {
rowsToPush = rowsToPush.filter(inMemoryFilter);
}
rowsToPush = rowsToPush.skip(offset).limit(limit);
} else {
Query query = new Query(offset, limit, backEndSorting, filters);
- rowsToPush = getDataSource().fetch(query);
+ rowsToPush = getDataProvider().fetch(query);
}
pushData(offset, rowsToPush);
}
}
/**
- * Gets the current data source from this DataCommunicator.
+ * Gets the current data provider from this DataCommunicator.
*
- * @return the data source
+ * @return the data provider
*/
- public DataSource<T> getDataSource() {
- return dataSource;
+ public DataProvider<T> getDataProvider() {
+ return dataProvider;
}
/**
- * Sets the current data source for this DataCommunicator.
+ * Sets the current data provider for this DataCommunicator.
*
- * @param dataSource
- * the data source to set, not null
+ * @param dataProvider
+ * the data provider to set, not null
*/
- public void setDataSource(DataSource<T> dataSource) {
- Objects.requireNonNull(dataSource, "data source cannot be null");
- this.dataSource = dataSource;
- detachDataSourceListener();
+ public void setDataProvider(DataProvider<T> dataProvider) {
+ Objects.requireNonNull(dataProvider, "data provider cannot be null");
+ this.dataProvider = dataProvider;
+ detachDataProviderListener();
if (isAttached()) {
- attachDataSourceListener();
+ attachDataProviderListener();
}
reset();
}
- private void attachDataSourceListener() {
- dataSourceUpdateRegistration = getDataSource()
- .addDataSourceListener(event -> reset());
+ private void attachDataProviderListener() {
+ dataProviderUpdateRegistration = getDataProvider()
+ .addDataProviderListener(event -> reset());
}
- private void detachDataSourceListener() {
- if (dataSourceUpdateRegistration != null) {
- dataSourceUpdateRegistration.remove();
- dataSourceUpdateRegistration = null;
+ private void detachDataProviderListener() {
+ if (dataProviderUpdateRegistration != null) {
+ dataProviderUpdateRegistration.remove();
+ dataProviderUpdateRegistration = null;
}
}
}
/**
* Adds custom data for the given item to its serialized {@code JsonObject}
- * representation. This JSON object will be sent to client-side DataSource.
+ * representation. This JSON object will be sent to client-side DataProvider.
*
* @param item
* the data item being serialized
--- /dev/null
+/*
+ * Copyright 2000-2016 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.Arrays;
+import java.util.Collection;
+import java.util.stream.Stream;
+
+import com.vaadin.shared.Registration;
+
+/**
+ * Minimal DataProvider API for communication between the DataProvider and a back
+ * end service.
+ *
+ * @author Vaadin Ltd.
+ *
+ * @param <T>
+ * data type
+ *
+ * @see ListDataProvider
+ * @see BackEndDataProvider
+ *
+ * @since 8.0
+ */
+public interface DataProvider<T> extends Serializable {
+
+ /**
+ * Gets whether the DataProvider 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();
+
+ /**
+ * Gets the amount of data in this DataProvider.
+ *
+ * @param t
+ * query with sorting and filtering
+ * @return the size of the data provider
+ */
+ int size(Query t);
+
+ /**
+ * Fetches data from this DataProvider using given {@code query}.
+ *
+ * @param query
+ * given query to request data
+ * @return the result of the query request: a stream of data objects, not
+ * {@code null}
+ */
+ Stream<T> fetch(Query query);
+
+ /**
+ * Refreshes all data based on currently available data in the underlying
+ * provider.
+ */
+ void refreshAll();
+
+ /**
+ * Adds a data provider listener. The listener is called when some piece of
+ * data is updated.
+ * <p>
+ * The {@link #refreshAll()} method fires {@link DataChangeEvent} each time
+ * when it's called. It allows to update UI components when user changes
+ * something in the underlying data.
+ *
+ * @see #refreshAll()
+ * @param listener
+ * the data change listener, not null
+ * @return a registration for the listener
+ */
+ Registration addDataProviderListener(DataProviderListener listener);
+
+ /**
+ * This method creates a new {@link ListDataProvider} from a given Collection.
+ * The ListDataProvider creates a protective List copy of all the contents in
+ * the Collection.
+ *
+ * @param <T>
+ * the data item type
+ * @param items
+ * the collection of data, not null
+ * @return a new list data provider
+ */
+ public static <T> ListDataProvider<T> create(Collection<T> items) {
+ return new ListDataProvider<>(items);
+ }
+
+ /**
+ * This method creates a new {@link ListDataProvider} from given objects.The
+ * ListDataProvider creates a protective List copy of all the contents in the
+ * array.
+ *
+ * @param <T>
+ * the data item type
+ * @param items
+ * the data items
+ * @return a new list data provider
+ */
+ @SafeVarargs
+ public static <T> ListDataProvider<T> create(T... items) {
+ return new ListDataProvider<>(Arrays.asList(items));
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 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;
+
+/**
+ * Interface for listening for a data change events fired by a
+ * {@link DataProvider}.
+ *
+ * @author Vaadin Ltd
+ * @since 8.0
+ */
+public interface DataProviderListener extends Serializable {
+
+ /**
+ * Invoked when this listener receives a data change event from a data
+ * source to which it has been added.
+ * <p>
+ * This event is fired when something has changed in the underlying data. It
+ * doesn't allow to distinguish different kind of events
+ * (add/remove/update). It means that the method implementation normally
+ * just reloads the whole data to refresh.
+ *
+ * @param event
+ * the received event, not null
+ */
+ void onDataChange(DataChangeEvent event);
+}
+++ /dev/null
-/*
- * Copyright 2000-2016 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.Arrays;
-import java.util.Collection;
-import java.util.stream.Stream;
-
-import com.vaadin.shared.Registration;
-
-/**
- * Minimal DataSource API for communication between the DataProvider and a back
- * end service.
- *
- * @author Vaadin Ltd.
- *
- * @param <T>
- * data type
- *
- * @see ListDataSource
- * @see BackEndDataSource
- *
- * @since 8.0
- */
-public interface DataSource<T> extends Serializable {
-
- /**
- * 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();
-
- /**
- * Gets the amount of data in this DataSource.
- *
- * @param t
- * query with sorting and filtering
- * @return the size of the data source
- */
- int size(Query t);
-
- /**
- * Fetches data from this DataSource using given {@code query}.
- *
- * @param query
- * given query to request data
- * @return the result of the query request: a stream of data objects, not
- * {@code null}
- */
- Stream<T> fetch(Query query);
-
- /**
- * Refreshes all data based on currently available data in the underlying
- * provider.
- */
- void refreshAll();
-
- /**
- * Adds a data source listener. The listener is called when some piece of
- * data is updated.
- * <p>
- * The {@link #refreshAll()} method fires {@link DataChangeEvent} each time
- * when it's called. It allows to update UI components when user changes
- * something in the underlying data.
- *
- * @see #refreshAll()
- * @param listener
- * the data change listener, not null
- * @return a registration for the listener
- */
- Registration addDataSourceListener(DataSourceListener listener);
-
- /**
- * This method creates a new {@link ListDataSource} from a given Collection.
- * The ListDataSource creates a protective List copy of all the contents in
- * the Collection.
- *
- * @param <T>
- * the data item type
- * @param items
- * the collection of data, not null
- * @return a new list data source
- */
- public static <T> ListDataSource<T> create(Collection<T> items) {
- return new ListDataSource<>(items);
- }
-
- /**
- * This method creates a new {@link ListDataSource} from given objects.The
- * ListDataSource creates a protective List copy of all the contents in the
- * array.
- *
- * @param <T>
- * the data item type
- * @param items
- * the data items
- * @return a new list data source
- */
- @SafeVarargs
- public static <T> ListDataSource<T> create(T... items) {
- return new ListDataSource<>(Arrays.asList(items));
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2016 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;
-
-/**
- * Interface for listening for a data change events fired by a
- * {@link DataSource}.
- *
- * @author Vaadin Ltd
- * @since 8.0
- */
-public interface DataSourceListener extends Serializable {
-
- /**
- * Invoked when this listener receives a data change event from a data
- * source to which it has been added.
- * <p>
- * This event is fired when something has changed in the underlying data. It
- * doesn't allow to distinguish different kind of events
- * (add/remove/update). It means that the method implementation normally
- * just reloads the whole data to refresh.
- *
- * @param event
- * the received event, not null
- */
- void onDataChange(DataChangeEvent event);
-}
--- /dev/null
+/*
+ * Copyright 2000-2016 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.Collection;
+import java.util.Comparator;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * {@link DataProvider} wrapper for {@link Collection}s. This class does not
+ * actually handle the {@link Query} parameters.
+ *
+ * @param <T>
+ * data type
+ */
+public class ListDataProvider<T> extends AbstractDataProvider<T> {
+
+ private Comparator<T> sortOrder;
+ private final Collection<T> backend;
+
+ /**
+ * Constructs a new ListDataProvider. This method makes a protective copy of
+ * the contents of the Collection.
+ *
+ * @param items
+ * the initial data, not null
+ */
+ public ListDataProvider(Collection<T> items) {
+ Objects.requireNonNull(items, "items cannot be null");
+ backend = items;
+ sortOrder = null;
+ }
+
+ /**
+ * Chaining constructor for making modified {@link ListDataProvider}s. This
+ * Constructor is used internally for making sorted and filtered variants of
+ * a base data provider with actual data.
+ *
+ * @param items
+ * the backend data from the original list data provider
+ * @param sortOrder
+ * a {@link Comparator} providing the needed sorting order
+ *
+ */
+ protected ListDataProvider(Collection<T> items, Comparator<T> sortOrder) {
+ this(items);
+ this.sortOrder = sortOrder;
+ }
+
+ @Override
+ public Stream<T> fetch(Query query) {
+ Stream<T> stream = backend.stream();
+ if (sortOrder != null) {
+ stream = stream.sorted(sortOrder);
+ }
+ return stream;
+ }
+
+ /**
+ * Creates a new list data provider based on this list data provider with the
+ * given sort order.
+ * <p>
+ * <b>NOTE</b>: this data provider is not modified in any way.
+ *
+ * @param sortOrder
+ * a {@link Comparator} providing the needed sorting order
+ * @return new data provider with modified sorting
+ */
+ public ListDataProvider<T> sortingBy(Comparator<T> sortOrder) {
+ return new ListDataProvider<>(backend, sortOrder);
+ }
+
+ /**
+ * Creates a new list data provider based on this list data provider with the
+ * given sort order.
+ * <p>
+ * <b>NOTE</b>: this data provider is not modified in any way.
+ * <p>
+ * 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 provider with modified sorting
+ */
+ public <U extends Comparable<? super U>> ListDataProvider<T> sortingBy(
+ Function<T, U> sortOrder) {
+ return sortingBy(Comparator.comparing(sortOrder));
+ }
+
+ @Override
+ public boolean isInMemory() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * For in-memory data provider the query is not handled, and it will always
+ * return the full size.
+ */
+ @Override
+ public int size(Query query) {
+ return backend.size();
+ }
+
+}
+++ /dev/null
-/*
- * Copyright 2000-2016 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.Collection;
-import java.util.Comparator;
-import java.util.Objects;
-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 ListDataSource<T> extends AbstractDataSource<T> {
-
- private Comparator<T> sortOrder;
- private final Collection<T> backend;
-
- /**
- * Constructs a new ListDataSource. This method makes a protective copy of
- * the contents of the Collection.
- *
- * @param items
- * the initial data, not null
- */
- public ListDataSource(Collection<T> items) {
- Objects.requireNonNull(items, "items cannot be null");
- backend = items;
- sortOrder = null;
- }
-
- /**
- * Chaining constructor for making modified {@link ListDataSource}s. This
- * Constructor is used internally for making sorted and filtered variants of
- * a base data source with actual data.
- *
- * @param items
- * the backend data from the original list data source
- * @param sortOrder
- * a {@link Comparator} providing the needed sorting order
- *
- */
- protected ListDataSource(Collection<T> items, Comparator<T> sortOrder) {
- this(items);
- this.sortOrder = sortOrder;
- }
-
- @Override
- public Stream<T> fetch(Query query) {
- Stream<T> stream = backend.stream();
- if (sortOrder != null) {
- stream = stream.sorted(sortOrder);
- }
- return stream;
- }
-
- /**
- * Creates a new list data source based on this list data source with the
- * given sort order.
- * <p>
- * <b>NOTE</b>: this data source is not modified in any way.
- *
- * @param sortOrder
- * a {@link Comparator} providing the needed sorting order
- * @return new data source with modified sorting
- */
- public ListDataSource<T> sortingBy(Comparator<T> sortOrder) {
- return new ListDataSource<>(backend, sortOrder);
- }
-
- /**
- * Creates a new list data source based on this list data source with the
- * given sort order.
- * <p>
- * <b>NOTE</b>: this data source is not modified in any way.
- * <p>
- * 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>> ListDataSource<T> sortingBy(
- Function<T, U> sortOrder) {
- return sortingBy(Comparator.comparing(sortOrder));
- }
-
- @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 query) {
- return backend.size();
- }
-
-}
import com.vaadin.server.AbstractExtension;
import com.vaadin.server.data.DataCommunicator;
import com.vaadin.server.data.DataGenerator;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
/**
* A base class for listing components. Provides common handling for fetching
}
@Override
- public void setDataSource(DataSource<T> dataSource) {
- getDataCommunicator().setDataSource(dataSource);
+ public void setDataProvider(DataProvider<T> dataProvider) {
+ getDataCommunicator().setDataProvider(dataProvider);
}
@Override
- public DataSource<T> getDataSource() {
- return getDataCommunicator().getDataSource();
+ public DataProvider<T> getDataProvider() {
+ return getDataCommunicator().getDataProvider();
}
/**
private SerializablePredicate<T> itemEnabledProvider = item -> true;
/**
- * Creates a new multi select with an empty data source.
+ * Creates a new multi select with an empty data provider.
*/
protected AbstractMultiSelect() {
registerRpc(new MultiSelectServerRpcImpl());
* the item to select or {@code null} to clear selection
*/
protected void setSelectedFromServer(T item) {
- // TODO creates a key if item not in data source
+ // TODO creates a key if item not in data provider
String key = itemToKey(item);
if (isKeySelected(key) || isSelected(item)) {
if (item == null) {
return null;
} else {
- // TODO creates a key if item not in data source
+ // TODO creates a key if item not in data provider
return getDataCommunicator().getKeyMapper().key(item);
}
}
import com.vaadin.event.FieldEvents.FocusListener;
import com.vaadin.event.FieldEvents.FocusNotifier;
import com.vaadin.server.SerializablePredicate;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.optiongroup.CheckBoxGroupState;
/**
* A group of Checkboxes. Individual checkboxes are made from items supplied by
- * a {@link DataSource}. Checkboxes may have captions and icons.
+ * a {@link DataProvider}. Checkboxes may have captions and icons.
*
* @param <T>
* item type
*
* @param caption
* caption text
- * @see Listing#setDataSource(DataSource)
+ * @see Listing#setDataProvider(DataProvider)
*/
public CheckBoxGroup(String caption) {
this();
}
/**
- * Constructs a new CheckBoxGroup with caption and DataSource.
+ * Constructs a new CheckBoxGroup with caption and DataProvider.
*
* @param caption
* the caption text
- * @param dataSource
- * the data source, not null
- * @see Listing#setDataSource(DataSource)
+ * @param dataProvider
+ * the data provider, not null
+ * @see Listing#setDataProvider(DataProvider)
*/
- public CheckBoxGroup(String caption, DataSource<T> dataSource) {
+ public CheckBoxGroup(String caption, DataProvider<T> dataProvider) {
this(caption);
- setDataSource(dataSource);
+ setDataProvider(dataProvider);
}
/**
- * Constructs a new CheckBoxGroup with caption and DataSource containing
+ * Constructs a new CheckBoxGroup with caption and DataProvider containing
* given items.
*
* @param caption
* the caption text
* @param items
* the data items to use, not null
- * @see Listing#setDataSource(DataSource)
+ * @see Listing#setDataProvider(DataProvider)
*/
public CheckBoxGroup(String caption, Collection<T> items) {
- this(caption, DataSource.create(items));
+ this(caption, DataProvider.create(items));
}
/**
* Constructs a new CheckBoxGroup.
*
- * @see Listing#setDataSource(DataSource)
+ * @see Listing#setDataProvider(DataProvider)
*/
public CheckBoxGroup() {
registerRpc(new FocusAndBlurServerRpcDecorator(this, this::fireEvent));
import com.vaadin.server.ResourceReference;
import com.vaadin.server.data.DataCommunicator;
import com.vaadin.server.data.DataKeyMapper;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.DataCommunicatorConstants;
import com.vaadin.shared.ui.combobox.ComboBoxConstants;
/**
* Constructs an empty combo box without a caption. The content of the combo
- * box can be set with {@link #setDataSource(DataSource)} or
+ * box can be set with {@link #setDataProvider(DataProvider)} or
* {@link #setItems(Collection)}
*/
public ComboBox() {
/**
* Constructs an empty combo box, whose content can be set with
- * {@link #setDataSource(DataSource)} or {@link #setItems(Collection)}.
+ * {@link #setDataProvider(DataProvider)} or {@link #setItems(Collection)}.
*
* @param caption
* the caption to show in the containing layout, null for no
}
/**
- * Constructs a combo box with a static in-memory data source with the given
+ * Constructs a combo box with a static in-memory data provider with the given
* options.
*
* @param caption
* collection of options, not null
*/
public ComboBox(String caption, Collection<T> options) {
- this(caption, DataSource.create(options));
+ this(caption, DataProvider.create(options));
}
/**
- * Constructs a combo box with the given data source.
+ * Constructs a combo box with the given data provider.
*
* @param caption
* the caption to show in the containing layout, null for no
* caption
- * @param dataSource
- * the data source to use, not null
+ * @param dataProvider
+ * the data provider to use, not null
*/
- public ComboBox(String caption, DataSource<T> dataSource) {
+ public ComboBox(String caption, DataProvider<T> dataProvider) {
this(caption);
- setDataSource(dataSource);
+ setDataProvider(dataProvider);
}
/**
/**
* Returns the handler called when the user enters a new item (not present
- * in the data source).
+ * in the data provider).
*
* @return new item handler or null if none specified
*/
import java.util.Collection;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.shared.ui.listselect.ListSelectState;
/**
}
/**
- * Constructs a new ListSelect with caption and data source for options.
+ * Constructs a new ListSelect with caption and data provider for options.
*
* @param caption
* the caption to set, can be {@code null}
- * @param dataSource
- * the data source, not {@code null}
+ * @param dataProvider
+ * the data provider, not {@code null}
*/
- public ListSelect(String caption, DataSource<T> dataSource) {
+ public ListSelect(String caption, DataProvider<T> dataProvider) {
this(caption);
- setDataSource(dataSource);
+ setDataProvider(dataProvider);
}
/**
* the options, cannot be {@code null}
*/
public ListSelect(String caption, Collection<T> options) {
- this(caption, DataSource.create(options));
+ this(caption, DataProvider.create(options));
}
/**
import com.vaadin.event.FieldEvents.FocusEvent;
import com.vaadin.event.FieldEvents.FocusListener;
import com.vaadin.event.FieldEvents.FocusNotifier;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.DataCommunicatorConstants;
import com.vaadin.shared.ui.nativeselect.NativeSelectState;
/**
* Creates a new {@code NativeSelect} with the given caption, using the
- * given {@code DataSource} as the source of data items.
+ * given {@code DataProvider} as the source of data items.
*
* @param caption
* the component caption to set, null for no caption
- * @param dataSource
+ * @param dataProvider
* the source of data items to use, not null
*/
- public NativeSelect(String caption, DataSource<T> dataSource) {
+ public NativeSelect(String caption, DataProvider<T> dataProvider) {
this(caption);
- setDataSource(dataSource);
+ setDataProvider(dataProvider);
}
@Override
import com.vaadin.server.ResourceReference;
import com.vaadin.server.SerializablePredicate;
import com.vaadin.server.data.DataGenerator;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.ListingJsonConstants;
import com.vaadin.shared.ui.optiongroup.RadioButtonGroupState;
/**
* A group of RadioButtons. Individual radiobuttons are made from items supplied
- * by a {@link DataSource}. RadioButtons may have captions and icons.
+ * by a {@link DataProvider}. RadioButtons may have captions and icons.
*
* @param <T>
* item type
*
* @param caption
* caption text
- * @see Listing#setDataSource(DataSource)
+ * @see Listing#setDataProvider(DataProvider)
*/
public RadioButtonGroup(String caption) {
this();
}
/**
- * Constructs a new RadioButtonGroup with caption and DataSource.
+ * Constructs a new RadioButtonGroup with caption and DataProvider.
*
* @param caption
* the caption text
- * @param dataSource
- * the data source, not null
- * @see Listing#setDataSource(DataSource)
+ * @param dataProvider
+ * the data provider, not null
+ * @see Listing#setDataProvider(DataProvider)
*/
- public RadioButtonGroup(String caption, DataSource<T> dataSource) {
+ public RadioButtonGroup(String caption, DataProvider<T> dataProvider) {
this(caption);
- setDataSource(dataSource);
+ setDataProvider(dataProvider);
}
/**
- * Constructs a new RadioButtonGroup with caption and DataSource containing
+ * Constructs a new RadioButtonGroup with caption and DataProvider containing
* given items.
*
* @param caption
* the caption text
* @param items
* the data items to use, not null
- * @see Listing#setDataSource(DataSource)
+ * @see Listing#setDataProvider(DataProvider)
*/
public RadioButtonGroup(String caption, Collection<T> items) {
- this(caption, DataSource.create(items));
+ this(caption, DataProvider.create(items));
}
/**
* Constructs a new RadioButtonGroup.
*
- * @see Listing#setDataSource(DataSource)
+ * @see Listing#setDataProvider(DataProvider)
*/
public RadioButtonGroup() {
registerRpc(new FocusAndBlurServerRpcDecorator(this, this::fireEvent));
import java.util.Collection;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.shared.ui.twincolselect.TwinColSelectState;
/**
}
/**
- * Constructs a new TwinColSelect with caption and data source for options.
+ * Constructs a new TwinColSelect with caption and data provider for options.
*
* @param caption
* the caption to set, can be {@code null}
- * @param dataSource
- * the data source, not {@code null}
+ * @param dataProvider
+ * the data provider, not {@code null}
*/
- public TwinColSelect(String caption, DataSource<T> dataSource) {
+ public TwinColSelect(String caption, DataProvider<T> dataProvider) {
this(caption);
- setDataSource(dataSource);
+ setDataProvider(dataProvider);
}
/**
* the options, cannot be {@code null}
*/
public TwinColSelect(String caption, Collection<T> options) {
- this(caption, DataSource.create(options));
+ this(caption, DataProvider.create(options));
}
/**
* the item to select or {@code null} to clear selection
*/
protected void setSelectedFromServer(T item) {
- // TODO creates a key if item not in data source
+ // TODO creates a key if item not in data provider
String key = itemToKey(item);
if (isSelected(item) || isKeySelected(key)) {
if (item == null) {
return null;
} else {
- // TODO creates a key if item not in data source
+ // TODO creates a key if item not in data provider
return grid.getDataCommunicator().getKeyMapper().key(item);
}
}
}
};
}
-}
\ No newline at end of file
+}
/**
* Determines whether the container data of a component should be written
* out by delegating to a {@link ShouldWriteDataDelegate}. The default
- * delegate assumes that all component data is provided by a data source
+ * delegate assumes that all component data is provided by a data provider
* connected to a back end system and that the data should thus not be
* written.
*
/**
* The default delegate implementation that assumes that all component data
- * is provided by a data source connected to a back end system and that the
+ * is provided by a data provider connected to a back end system and that the
* data should thus not be written.
*/
public static final ShouldWriteDataDelegate DEFAULT = (
--- /dev/null
+/*
+ * Copyright 2000-2016 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.concurrent.atomic.AtomicReference;
+import java.util.stream.Stream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.shared.Registration;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class AbstractDataProviderTest {
+
+ private static class TestDataProvider extends AbstractDataProvider<Object> {
+ @Override
+ public Stream<Object> fetch(Query t) {
+ return null;
+ }
+
+ @Override
+ public int size(Query t) {
+ return 0;
+ }
+
+ @Override
+ public boolean isInMemory() {
+ return false;
+ }
+ }
+
+ @Test
+ public void refreshAll_notifyListeners() {
+ AbstractDataProvider<Object> dataProvider = new TestDataProvider();
+ AtomicReference<DataChangeEvent> event = new AtomicReference<>();
+ dataProvider.addDataProviderListener(ev -> {
+ Assert.assertNull(event.get());
+ event.set(ev);
+ });
+ dataProvider.refreshAll();
+ Assert.assertNotNull(event.get());
+ Assert.assertEquals(dataProvider, event.get().getSource());
+ }
+
+ @Test
+ public void removeListener_listenerIsNotNotified() {
+ AbstractDataProvider<Object> dataProvider = new TestDataProvider();
+ AtomicReference<DataChangeEvent> event = new AtomicReference<>();
+ Registration registration = dataProvider
+ .addDataProviderListener(ev -> event.set(ev));
+ registration.remove();
+ dataProvider.refreshAll();
+ Assert.assertNull(event.get());
+ }
+}
+++ /dev/null
-/*
- * Copyright 2000-2016 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.concurrent.atomic.AtomicReference;
-import java.util.stream.Stream;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.vaadin.shared.Registration;
-
-/**
- * @author Vaadin Ltd
- *
- */
-public class AbstractDataSourceTest {
-
- private static class TestDataSource extends AbstractDataSource<Object> {
- @Override
- public Stream<Object> fetch(Query t) {
- return null;
- }
-
- @Override
- public int size(Query t) {
- return 0;
- }
-
- @Override
- public boolean isInMemory() {
- return false;
- }
- }
-
- @Test
- public void refreshAll_notifyListeners() {
- AbstractDataSource<Object> dataSource = new TestDataSource();
- AtomicReference<DataChangeEvent> event = new AtomicReference<>();
- dataSource.addDataSourceListener(ev -> {
- Assert.assertNull(event.get());
- event.set(ev);
- });
- dataSource.refreshAll();
- Assert.assertNotNull(event.get());
- Assert.assertEquals(dataSource, event.get().getSource());
- }
-
- @Test
- public void removeListener_listenerIsNotNotified() {
- AbstractDataSource<Object> dataSource = new TestDataSource();
- AtomicReference<DataChangeEvent> event = new AtomicReference<>();
- Registration registration = dataSource
- .addDataSourceListener(ev -> event.set(ev));
- registration.remove();
- dataSource.refreshAll();
- Assert.assertNull(event.get());
- }
-}
}
}
- private static class TestDataSource extends ListDataSource<Object>
+ private static class TestDataProvider extends ListDataProvider<Object>
implements Registration {
private Registration registration;
- public TestDataSource() {
+ public TestDataProvider() {
super(Collections.singleton(new Object()));
}
@Override
- public Registration addDataSourceListener(DataSourceListener listener) {
- registration = super.addDataSourceListener(listener);
+ public Registration addDataProviderListener(DataProviderListener listener) {
+ registration = super.addDataProviderListener(listener);
return this;
}
Mockito.mock(VaadinService.class));
@Test
- public void attach_dataSourceListenerIsNotAddedBeforeAttachAndAddedAfter() {
+ public void attach_dataProviderListenerIsNotAddedBeforeAttachAndAddedAfter() {
session.lock();
UI ui = new TestUI(session);
TestDataCommunicator communicator = new TestDataCommunicator();
- TestDataSource dataSource = new TestDataSource();
- communicator.setDataSource(dataSource);
+ TestDataProvider dataProvider = new TestDataProvider();
+ communicator.setDataProvider(dataProvider);
- Assert.assertFalse(dataSource.isListenerAdded());
+ Assert.assertFalse(dataProvider.isListenerAdded());
communicator.extend(ui);
- Assert.assertTrue(dataSource.isListenerAdded());
+ Assert.assertTrue(dataProvider.isListenerAdded());
}
@Test
- public void detach_dataSourceListenerIsRemovedAfterDetach() {
+ public void detach_dataProviderListenerIsRemovedAfterDetach() {
session.lock();
UI ui = new TestUI(session);
TestDataCommunicator communicator = new TestDataCommunicator();
- TestDataSource dataSource = new TestDataSource();
- communicator.setDataSource(dataSource);
+ TestDataProvider dataProvider = new TestDataProvider();
+ communicator.setDataProvider(dataProvider);
communicator.extend(ui);
- Assert.assertTrue(dataSource.isListenerAdded());
+ Assert.assertTrue(dataProvider.isListenerAdded());
communicator.detach();
- Assert.assertFalse(dataSource.isListenerAdded());
+ Assert.assertFalse(dataProvider.isListenerAdded());
}
}
+++ /dev/null
-package com.vaadin.server.data.datasource;
-
-import static org.junit.Assert.assertTrue;
-
-import java.util.Comparator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.vaadin.server.data.DataSource;
-import com.vaadin.server.data.ListDataSource;
-import com.vaadin.server.data.Query;
-
-public class ListDataSourceTest {
-
- private ListDataSource<StrBean> dataSource;
- private List<StrBean> data;
-
- @Before
- public void setUp() {
- data = StrBean.generateRandomBeans(100);
- dataSource = DataSource.create(data);
- }
-
- @Test
- public void testListContainsAllData() {
- List<StrBean> list = new LinkedList<>(data);
- dataSource.fetch(new Query())
- .forEach(str -> assertTrue(
- "Data source contained values not in original data",
- list.remove(str)));
- assertTrue("Not all values from original data were in data source",
- list.isEmpty());
- }
-
- @Test
- public void testSortByComparatorListsDiffer() {
- Comparator<StrBean> comp = Comparator.comparing(StrBean::getValue)
- .thenComparing(StrBean::getRandomNumber)
- .thenComparing(StrBean::getId);
- List<StrBean> list = dataSource.sortingBy(comp).fetch(new Query())
- .collect(Collectors.toList());
-
- // First value in data is { Xyz, 10, 100 } which should be last in list
- Assert.assertNotEquals("First value should not match", data.get(0),
- list.get(0));
-
- Assert.assertEquals("Sorted data and original data sizes don't match",
- data.size(), list.size());
-
- data.sort(comp);
- for (int i = 0; i < data.size(); ++i) {
- Assert.assertEquals("Sorting result differed", data.get(i),
- list.get(i));
- }
- }
-
- @Test
- public void testDefatulSortWithSpecifiedPostSort() {
- Comparator<StrBean> comp = Comparator.comparing(StrBean::getValue)
- .thenComparing(Comparator.comparing(StrBean::getId).reversed());
- List<StrBean> list = dataSource.sortingBy(comp).fetch(new Query())
- // The sort here should come e.g from a Component
- .sorted(Comparator.comparing(StrBean::getRandomNumber))
- .collect(Collectors.toList());
-
- Assert.assertEquals("Sorted data and original data sizes don't match",
- data.size(), list.size());
-
- for (int i = 1; i < list.size(); ++i) {
- StrBean prev = list.get(i - 1);
- StrBean cur = list.get(i);
- // Test specific sort
- Assert.assertTrue(prev.getRandomNumber() <= cur.getRandomNumber());
-
- if (prev.getRandomNumber() == cur.getRandomNumber()) {
- // Test default sort
- Assert.assertTrue(
- prev.getValue().compareTo(cur.getValue()) <= 0);
- if (prev.getValue().equals(cur.getValue())) {
- Assert.assertTrue(prev.getId() > cur.getId());
- }
- }
- }
- }
-
- @Test
- public void testDefatulSortWithFunction() {
- List<StrBean> list = dataSource.sortingBy(StrBean::getValue)
- .fetch(new Query()).collect(Collectors.toList());
-
- Assert.assertEquals("Sorted data and original data sizes don't match",
- data.size(), list.size());
-
- for (int i = 1; i < list.size(); ++i) {
- StrBean prev = list.get(i - 1);
- StrBean cur = list.get(i);
-
- // Test default sort
- Assert.assertTrue(prev.getValue().compareTo(cur.getValue()) <= 0);
- }
- }
-
- @Test
- public void refreshAll_changeBeanInstance() {
- StrBean bean = new StrBean("foo", -1, hashCode());
- Query query = new Query();
- int size = dataSource.size(query);
-
- data.set(0, bean);
- dataSource.refreshAll();
-
- List<StrBean> list = dataSource.fetch(query)
- .collect(Collectors.toList());
- StrBean first = list.get(0);
- Assert.assertEquals(bean.getValue(), first.getValue());
- Assert.assertEquals(bean.getRandomNumber(), first.getRandomNumber());
- Assert.assertEquals(bean.getId(), first.getId());
-
- Assert.assertEquals(size, dataSource.size(query));
- }
-
- @Test
- public void refreshAll_updateBean() {
- Query query = new Query();
- int size = dataSource.size(query);
-
- StrBean bean = data.get(0);
- bean.setValue("foo");
- dataSource.refreshAll();
-
- List<StrBean> list = dataSource.fetch(query)
- .collect(Collectors.toList());
- StrBean first = list.get(0);
- Assert.assertEquals("foo", first.getValue());
-
- Assert.assertEquals(size, dataSource.size(query));
- }
-
- @Test
- public void refreshAll_sortingBy_changeBeanInstance() {
- StrBean bean = new StrBean("foo", -1, hashCode());
- Query query = new Query();
- int size = dataSource.size(query);
-
- data.set(0, bean);
-
- ListDataSource<StrBean> dSource = dataSource
- .sortingBy(Comparator.comparing(StrBean::getId));
- dSource.refreshAll();
-
- List<StrBean> list = dSource.fetch(query).collect(Collectors.toList());
- StrBean first = list.get(0);
- Assert.assertEquals(bean.getValue(), first.getValue());
- Assert.assertEquals(bean.getRandomNumber(), first.getRandomNumber());
- Assert.assertEquals(bean.getId(), first.getId());
-
- Assert.assertEquals(size, dataSource.size(query));
- }
-
- @Test
- public void refreshAll_addBeanInstance() {
- StrBean bean = new StrBean("foo", -1, hashCode());
-
- Query query = new Query();
- int size = dataSource.size(query);
-
- data.add(0, bean);
- dataSource.refreshAll();
-
- List<StrBean> list = dataSource.fetch(query)
- .collect(Collectors.toList());
- StrBean first = list.get(0);
- Assert.assertEquals(bean.getValue(), first.getValue());
- Assert.assertEquals(bean.getRandomNumber(), first.getRandomNumber());
- Assert.assertEquals(bean.getId(), first.getId());
-
- Assert.assertEquals(size + 1, dataSource.size(query));
- }
-
- @Test
- public void refreshAll_removeBeanInstance() {
- Query query = new Query();
- int size = dataSource.size(query);
-
- data.remove(0);
- dataSource.refreshAll();
-
- Assert.assertEquals(size - 1, dataSource.size(query));
- }
-}
+++ /dev/null
-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 final 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 void setValue(String value) {
- this.value = value;
- }
-
- public static List<StrBean> generateRandomBeans(int max) {
- List<StrBean> data = new ArrayList<>();
- 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
+++ /dev/null
-/*
- * Copyright 2000-2016 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.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.vaadin.server.data.BackEndDataSource;
-import com.vaadin.server.data.DataSource;
-import com.vaadin.server.data.SortOrder;
-import com.vaadin.shared.data.sort.SortDirection;
-
-/**
- * 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 List<Person> fetchPersons(int offset, int limit,
- Collection<PersonSort> personSorts) {
- Stream<Person> personStream = Arrays.stream(persons).skip(offset)
- .limit(limit);
- if (personSorts != null) {
- for (PersonSort personSort : personSorts) {
- personStream = personStream.sorted(personSort);
- }
- }
- return personStream.collect(Collectors.toList());
- }
-
- @Override
- public int getPersonCount() {
- return persons.length;
- }
-
- @Override
- public PersonSort createSort(String propertyName, boolean descending) {
- PersonSort result;
- switch (propertyName) {
- case "name":
- result = (person1, person2) -> String.CASE_INSENSITIVE_ORDER
- .compare(person1.getName(), person2.getName());
- break;
- case "born":
- result = (person1, person2) -> person2.getBorn()
- - person1.getBorn();
- break;
- default:
- throw new IllegalArgumentException(
- "wrong field name " + propertyName);
- }
- if (descending) {
- return (person1, person2) -> result.compare(person2, person1);
- } else {
- return result;
- }
- }
- }
-
- @Test
- public void testPersons() {
- DataSource<Person> dataSource = createUnsortedDatasource();
- // TODO test if the datasource contains all defined Persons in
- // correct(unchanged) order
- }
-
- private DataSource<Person> createUnsortedDatasource() {
- DataSource<Person> dataSource = new BackEndDataSource<>(
- // 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());
- return dataSource;
- }
-
- @Test
- public void testSortedPersons() {
-
- DataSource<Person> dataSource = createSortedDataSource();
- // TODO test if datasource contains all defined Persons in correct order
- // TODO test Query.sortOrders correctness
- }
-
- private DataSource<Person> createSortedDataSource() {
- DataSource<Person> dataSource = new BackEndDataSource<>(
- // First callback fetches items based on a query
- query -> {
- List<PersonService.PersonSort> sortOrders = new ArrayList<>();
- for (SortOrder<String> queryOrder : query.getSortOrders()) {
- PersonService.PersonSort sort = personService
- .createSort(
- // The name of the sorted property
- queryOrder.getSorted(),
- // The sort direction for this property
- queryOrder
- .getDirection() == SortDirection.DESCENDING);
- sortOrders.add(sort);
- }
- return getPersonService().fetchPersons(query.getOffset(),
- query.getLimit(), sortOrders).stream();
- },
- // Second callback fetches the number of items for a query
- query -> getPersonService().getPersonCount());
- return dataSource;
- }
-
- 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));
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2016 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;
- }
-
- @Override
- public String toString() {
- return name + "(" + born + ")";
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2016 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.Collection;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * Data access service example.
- *
- * @author Vaadin Ltd
- * @see Person
- */
-public interface PersonService extends Serializable {
- List<Person> fetchPersons(int offset, int limit);
-
- List<Person> fetchPersons(int offset, int limit,
- Collection<PersonSort> personSorts);
-
- int getPersonCount();
-
- public interface PersonSort extends Comparator<Person>, Serializable {
- }
-
- PersonSort createSort(String propertyName, boolean descending);
-}
--- /dev/null
+package com.vaadin.server.data.provider;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.vaadin.server.data.DataProvider;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.server.data.ListDataProvider;
+import com.vaadin.server.data.Query;
+
+public class ListDataProviderTest {
+
+ private ListDataProvider<StrBean> dataProvider;
+ private List<StrBean> data;
+
+ @Before
+ public void setUp() {
+ data = StrBean.generateRandomBeans(100);
+ dataProvider = DataProvider.create(data);
+ }
+
+ @Test
+ public void testListContainsAllData() {
+ List<StrBean> list = new LinkedList<>(data);
+ dataProvider.fetch(new Query())
+ .forEach(str -> assertTrue(
+ "Data provider contained values not in original data",
+ list.remove(str)));
+ assertTrue("Not all values from original data were in data provider",
+ list.isEmpty());
+ }
+
+ @Test
+ public void testSortByComparatorListsDiffer() {
+ Comparator<StrBean> comp = Comparator.comparing(StrBean::getValue)
+ .thenComparing(StrBean::getRandomNumber)
+ .thenComparing(StrBean::getId);
+ List<StrBean> list = dataProvider.sortingBy(comp).fetch(new Query())
+ .collect(Collectors.toList());
+
+ // First value in data is { Xyz, 10, 100 } which should be last in list
+ Assert.assertNotEquals("First value should not match", data.get(0),
+ list.get(0));
+
+ Assert.assertEquals("Sorted data and original data sizes don't match",
+ data.size(), list.size());
+
+ data.sort(comp);
+ for (int i = 0; i < data.size(); ++i) {
+ Assert.assertEquals("Sorting result differed", data.get(i),
+ list.get(i));
+ }
+ }
+
+ @Test
+ public void testDefatulSortWithSpecifiedPostSort() {
+ Comparator<StrBean> comp = Comparator.comparing(StrBean::getValue)
+ .thenComparing(Comparator.comparing(StrBean::getId).reversed());
+ List<StrBean> list = dataProvider.sortingBy(comp).fetch(new Query())
+ // The sort here should come e.g from a Component
+ .sorted(Comparator.comparing(StrBean::getRandomNumber))
+ .collect(Collectors.toList());
+
+ Assert.assertEquals("Sorted data and original data sizes don't match",
+ data.size(), list.size());
+
+ for (int i = 1; i < list.size(); ++i) {
+ StrBean prev = list.get(i - 1);
+ StrBean cur = list.get(i);
+ // Test specific sort
+ Assert.assertTrue(prev.getRandomNumber() <= cur.getRandomNumber());
+
+ if (prev.getRandomNumber() == cur.getRandomNumber()) {
+ // Test default sort
+ Assert.assertTrue(
+ prev.getValue().compareTo(cur.getValue()) <= 0);
+ if (prev.getValue().equals(cur.getValue())) {
+ Assert.assertTrue(prev.getId() > cur.getId());
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testDefatulSortWithFunction() {
+ List<StrBean> list = dataProvider.sortingBy(StrBean::getValue)
+ .fetch(new Query()).collect(Collectors.toList());
+
+ Assert.assertEquals("Sorted data and original data sizes don't match",
+ data.size(), list.size());
+
+ for (int i = 1; i < list.size(); ++i) {
+ StrBean prev = list.get(i - 1);
+ StrBean cur = list.get(i);
+
+ // Test default sort
+ Assert.assertTrue(prev.getValue().compareTo(cur.getValue()) <= 0);
+ }
+ }
+
+ @Test
+ public void refreshAll_changeBeanInstance() {
+ StrBean bean = new StrBean("foo", -1, hashCode());
+ Query query = new Query();
+ int size = dataProvider.size(query);
+
+ data.set(0, bean);
+ dataProvider.refreshAll();
+
+ List<StrBean> list = dataProvider.fetch(query)
+ .collect(Collectors.toList());
+ StrBean first = list.get(0);
+ Assert.assertEquals(bean.getValue(), first.getValue());
+ Assert.assertEquals(bean.getRandomNumber(), first.getRandomNumber());
+ Assert.assertEquals(bean.getId(), first.getId());
+
+ Assert.assertEquals(size, dataProvider.size(query));
+ }
+
+ @Test
+ public void refreshAll_updateBean() {
+ Query query = new Query();
+ int size = dataProvider.size(query);
+
+ StrBean bean = data.get(0);
+ bean.setValue("foo");
+ dataProvider.refreshAll();
+
+ List<StrBean> list = dataProvider.fetch(query)
+ .collect(Collectors.toList());
+ StrBean first = list.get(0);
+ Assert.assertEquals("foo", first.getValue());
+
+ Assert.assertEquals(size, dataProvider.size(query));
+ }
+
+ @Test
+ public void refreshAll_sortingBy_changeBeanInstance() {
+ StrBean bean = new StrBean("foo", -1, hashCode());
+ Query query = new Query();
+ int size = dataProvider.size(query);
+
+ data.set(0, bean);
+
+ ListDataProvider<StrBean> dSource = dataProvider
+ .sortingBy(Comparator.comparing(StrBean::getId));
+ dSource.refreshAll();
+
+ List<StrBean> list = dSource.fetch(query).collect(Collectors.toList());
+ StrBean first = list.get(0);
+ Assert.assertEquals(bean.getValue(), first.getValue());
+ Assert.assertEquals(bean.getRandomNumber(), first.getRandomNumber());
+ Assert.assertEquals(bean.getId(), first.getId());
+
+ Assert.assertEquals(size, dataProvider.size(query));
+ }
+
+ @Test
+ public void refreshAll_addBeanInstance() {
+ StrBean bean = new StrBean("foo", -1, hashCode());
+
+ Query query = new Query();
+ int size = dataProvider.size(query);
+
+ data.add(0, bean);
+ dataProvider.refreshAll();
+
+ List<StrBean> list = dataProvider.fetch(query)
+ .collect(Collectors.toList());
+ StrBean first = list.get(0);
+ Assert.assertEquals(bean.getValue(), first.getValue());
+ Assert.assertEquals(bean.getRandomNumber(), first.getRandomNumber());
+ Assert.assertEquals(bean.getId(), first.getId());
+
+ Assert.assertEquals(size + 1, dataProvider.size(query));
+ }
+
+ @Test
+ public void refreshAll_removeBeanInstance() {
+ Query query = new Query();
+ int size = dataProvider.size(query);
+
+ data.remove(0);
+ dataProvider.refreshAll();
+
+ Assert.assertEquals(size - 1, dataProvider.size(query));
+ }
+}
--- /dev/null
+package com.vaadin.server.data.provider;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+class StrBean implements Serializable {
+
+ private static final 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 void setValue(String value) {
+ this.value = value;
+ }
+
+ public static List<StrBean> generateRandomBeans(int max) {
+ List<StrBean> data = new ArrayList<>();
+ 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 + " }";
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 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.provider.bov;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.vaadin.server.data.BackEndDataProvider;
+import com.vaadin.server.data.DataProvider;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.server.data.SortOrder;
+import com.vaadin.shared.data.sort.SortDirection;
+
+/**
+ * Vaadin 8 Example from Book of Vaadin
+ *
+ * @author Vaadin Ltd
+ */
+public class DataProviderBoVTest {
+
+ 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 List<Person> fetchPersons(int offset, int limit,
+ Collection<PersonSort> personSorts) {
+ Stream<Person> personStream = Arrays.stream(persons).skip(offset)
+ .limit(limit);
+ if (personSorts != null) {
+ for (PersonSort personSort : personSorts) {
+ personStream = personStream.sorted(personSort);
+ }
+ }
+ return personStream.collect(Collectors.toList());
+ }
+
+ @Override
+ public int getPersonCount() {
+ return persons.length;
+ }
+
+ @Override
+ public PersonSort createSort(String propertyName, boolean descending) {
+ PersonSort result;
+ switch (propertyName) {
+ case "name":
+ result = (person1, person2) -> String.CASE_INSENSITIVE_ORDER
+ .compare(person1.getName(), person2.getName());
+ break;
+ case "born":
+ result = (person1, person2) -> person2.getBorn()
+ - person1.getBorn();
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "wrong field name " + propertyName);
+ }
+ if (descending) {
+ return (person1, person2) -> result.compare(person2, person1);
+ } else {
+ return result;
+ }
+ }
+ }
+
+ @Test
+ public void testPersons() {
+ DataProvider<Person> dataProvider = createUnsortedDataProvider();
+ // TODO test if the provider contains all defined Persons in
+ // correct(unchanged) order
+ }
+
+ private DataProvider<Person> createUnsortedDataProvider() {
+ DataProvider<Person> dataProvider = new BackEndDataProvider<>(
+ // 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());
+ return dataProvider;
+ }
+
+ @Test
+ public void testSortedPersons() {
+
+ DataProvider<Person> dataProvider = createSortedDataProvider();
+ // TODO test if provider contains all defined Persons in correct order
+ // TODO test Query.sortOrders correctness
+ }
+
+ private DataProvider<Person> createSortedDataProvider() {
+ DataProvider<Person> dataProvider = new BackEndDataProvider<>(
+ // First callback fetches items based on a query
+ query -> {
+ List<PersonService.PersonSort> sortOrders = new ArrayList<>();
+ for (SortOrder<String> queryOrder : query.getSortOrders()) {
+ PersonService.PersonSort sort = personService
+ .createSort(
+ // The name of the sorted property
+ queryOrder.getSorted(),
+ // The sort direction for this property
+ queryOrder
+ .getDirection() == SortDirection.DESCENDING);
+ sortOrders.add(sort);
+ }
+ return getPersonService().fetchPersons(query.getOffset(),
+ query.getLimit(), sortOrders).stream();
+ },
+ // Second callback fetches the number of items for a query
+ query -> getPersonService().getPersonCount());
+ return dataProvider;
+ }
+
+ 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));
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 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.provider.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;
+ }
+
+ @Override
+ public String toString() {
+ return name + "(" + born + ")";
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 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.provider.bov;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Data access service example.
+ *
+ * @author Vaadin Ltd
+ * @see Person
+ */
+public interface PersonService extends Serializable {
+ List<Person> fetchPersons(int offset, int limit);
+
+ List<Person> fetchPersons(int offset, int limit,
+ Collection<PersonSort> personSorts);
+
+ int getPersonCount();
+
+ public interface PersonSort extends Comparator<Person>, Serializable {
+ }
+
+ PersonSort createSort(String propertyName, boolean descending);
+}
import com.vaadin.data.HasValue.ValueChangeEvent;
import com.vaadin.event.selection.SingleSelectionEvent;
import com.vaadin.event.selection.SingleSelectionListener;
-import com.vaadin.server.data.datasource.bov.Person;
+import com.vaadin.server.data.provider.bov.Person;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.DataCommunicatorClientRpc;
import com.vaadin.ui.Grid;
@Before
public void setUp() {
- excludedMethods.add(Label.class.getName() + "getDataSourceValue");
+ excludedMethods.add(Label.class.getName() + "getDataProviderValue");
excludedMethods.add("getConnectorId");
}
import java.util.List;
import java.util.stream.Stream;
+import com.vaadin.server.data.BackEndDataProvider;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import com.vaadin.server.data.BackEndDataSource;
-import com.vaadin.server.data.DataSource;
-import com.vaadin.server.data.ListDataSource;
+import com.vaadin.server.data.DataProvider;
+import com.vaadin.server.data.ListDataProvider;
import com.vaadin.server.data.Query;
import com.vaadin.ui.AbstractListing.AbstractListingExtension;
public void testSetItemsWithCollection() {
listing.setItems(items);
List<String> list = new LinkedList<>(items);
- listing.getDataSource().fetch(new Query()).forEach(
- str -> Assert.assertTrue("Unexpected item in data source",
+ listing.getDataProvider().fetch(new Query()).forEach(
+ str -> Assert.assertTrue("Unexpected item in data provider",
list.remove(str)));
- Assert.assertTrue("Not all items from list were in data source",
+ Assert.assertTrue("Not all items from list were in data provider",
list.isEmpty());
}
@Test
public void testSetItemsWithVarargs() {
listing.setItems(ITEM_ARRAY);
- listing.getDataSource().fetch(new Query()).forEach(
- str -> Assert.assertTrue("Unexpected item in data source",
+ listing.getDataProvider().fetch(new Query()).forEach(
+ str -> Assert.assertTrue("Unexpected item in data provider",
items.remove(str)));
- Assert.assertTrue("Not all items from list were in data source",
+ Assert.assertTrue("Not all items from list were in data provider",
items.isEmpty());
}
@Test
- public void testSetDataSource() {
- ListDataSource<String> dataSource = DataSource.create(items);
- listing.setDataSource(dataSource);
- Assert.assertEquals("setDataSource did not set data source", dataSource,
- listing.getDataSource());
- listing.setDataSource(new BackEndDataSource<>(q -> Stream.of(ITEM_ARRAY)
+ public void testSetDataProvider() {
+ ListDataProvider<String> dataProvider = DataProvider.create(items);
+ listing.setDataProvider(dataProvider);
+ Assert.assertEquals("setDataProvider did not set data provider", dataProvider,
+ listing.getDataProvider());
+ listing.setDataProvider(new BackEndDataProvider<>(q -> Stream.of(ITEM_ARRAY)
.skip(q.getOffset()).limit(q.getLimit()),
q -> ITEM_ARRAY.length));
- Assert.assertNotEquals("setDataSource did not replace data source",
- dataSource, listing.getDataSource());
+ Assert.assertNotEquals("setDataProvider did not replace data provider",
+ dataProvider, listing.getDataProvider());
}
@Test
- public void testAddDataGeneratorBeforeDataSource() {
+ public void testAddDataGeneratorBeforeDataProvider() {
CountGenerator generator = new CountGenerator();
generator.extend(listing);
listing.setItems("Foo");
}
@Test
- public void testAddDataGeneratorAfterDataSource() {
+ public void testAddDataGeneratorAfterDataProvider() {
CountGenerator generator = new CountGenerator();
listing.setItems("Foo");
generator.extend(listing);
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import com.vaadin.server.data.DataProvider;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import com.vaadin.data.HasValue.ValueChangeEvent;
import com.vaadin.event.selection.MultiSelectionEvent;
import com.vaadin.event.selection.MultiSelectionListener;
-import com.vaadin.server.data.DataSource;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.selection.MultiSelectServerRpc;
public void setUp() {
selectToTest.deselectAll();
// Intentional deviation from upcoming selection order
- selectToTest.setDataSource(
- DataSource.create("3", "2", "1", "5", "8", "7", "4", "6"));
+ selectToTest.setDataProvider(
+ DataProvider.create("3", "2", "1", "5", "8", "7", "4", "6"));
rpc = ComponentTest.getRpcProxy(selectToTest,
MultiSelectServerRpc.class);
}
import com.vaadin.data.HasValue.ValueChangeEvent;
import com.vaadin.event.selection.SingleSelectionEvent;
import com.vaadin.event.selection.SingleSelectionListener;
-import com.vaadin.server.data.datasource.bov.Person;
+import com.vaadin.server.data.provider.bov.Person;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.DataCommunicatorClientRpc;
import org.junit.Test;
import com.vaadin.data.SelectionModel.Multi;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.shared.data.selection.SelectionServerRpc;
public class RadioButtonGroupTest {
radioButtonGroup = new RadioButtonGroup<>();
// Intentional deviation from upcoming selection order
radioButtonGroup
- .setDataSource(DataSource.create("Third", "Second", "First"));
+ .setDataProvider(DataProvider.create("Third", "Second", "First"));
}
@Test
options.put("10000", 10000);
options.put("100000", 100000);
- createSelectAction("Items", "Data source", options, "20",
+ createSelectAction("Items", "Data provider", options, "20",
(c, number, data) -> {
c.setItems(createItems(number));
});
"None", (abstractMultiSelect, captionGenerator, data) -> {
abstractMultiSelect
.setItemCaptionGenerator(captionGenerator);
- abstractMultiSelect.getDataSource().refreshAll();
+ abstractMultiSelect.getDataProvider().refreshAll();
}, true);
}
} else {
group.setItemIconGenerator(DEFAULT_ICON_GENERATOR);
}
- group.getDataSource().refreshAll();
+ group.getDataProvider().refreshAll();
}
private int getIndex(Object item) {
import com.vaadin.server.FontAwesome;
import com.vaadin.server.VaadinRequest;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.tests.components.AbstractReindeerTestUI;
import com.vaadin.ui.ComboBox;
@Override
protected void setup(VaadinRequest request) {
final ComboBox<String> combo = new ComboBox<>(null,
- DataSource.create("A", "B", "C"));
+ DataProvider.create("A", "B", "C"));
combo.setItemIconGenerator(item -> FontAwesome.ALIGN_CENTER);
combo.setTextInputAllowed(false);
addComponent(combo);
package com.vaadin.tests.components.combobox;
import com.vaadin.server.VaadinRequest;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.tests.components.AbstractReindeerTestUI;
import com.vaadin.ui.ComboBox;
@Override
protected void setup(VaadinRequest request) {
ComboBox<String> comboBox = new ComboBox<>(null,
- DataSource.create("foo", "bar"));
+ DataProvider.create("foo", "bar"));
addComponent(comboBox);
}
package com.vaadin.tests.components.combobox;
import com.vaadin.tests.components.TestBase;
-import com.vaadin.tests.util.ItemDataSource;
+import com.vaadin.tests.util.ItemDataProvider;
import com.vaadin.ui.ComboBox;
public class ComboBoxEnablesComboBox extends TestBase {
@Override
protected void setup() {
ComboBox<String> cb = new ComboBox<>("Always enabled",
- new ItemDataSource(10));
+ new ItemDataProvider(10));
cb.addValueChangeListener(event -> cb2.setEnabled(true));
cb2 = new ComboBox<String>("Initially disabled",
- new ItemDataSource(10));
+ new ItemDataProvider(10));
cb2.setEnabled(false);
addComponent(cb);
package com.vaadin.tests.components.combobox;
import com.vaadin.event.ShortcutAction.KeyCode;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
private Component createComboBox() {
return new ComboBox<String>("A combo box",
- DataSource.create("Yes", "No", "Maybe"));
+ DataProvider.create("Yes", "No", "Maybe"));
}
@Override
package com.vaadin.tests.components.combobox;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.tests.components.TestBase;
import com.vaadin.tests.util.Log;
import com.vaadin.ui.Button;
public class ComboBoxInvalidNullSelection extends TestBase {
private static final Object CAPTION = "C";
- private DataSource<String> ds1;
- private DataSource<String> ds2;
+ private DataProvider<String> ds1;
+ private DataProvider<String> ds2;
private ComboBox<String> combo;
private Log log = new Log(5);
@Override
protected void setup() {
- createDataSources();
+ createDataProviders();
- Button b = new Button("Swap data source");
+ Button b = new Button("Swap data provider");
b.addClickListener(event -> {
- if (combo.getDataSource() == ds1) {
- combo.setDataSource(ds2);
+ if (combo.getDataProvider() == ds1) {
+ combo.setDataProvider(ds2);
} else {
- combo.setDataSource(ds1);
+ combo.setDataProvider(ds1);
}
combo.setValue("Item 3");
});
combo = new ComboBox<>();
- combo.setDataSource(ds1);
+ combo.setDataProvider(ds1);
combo.addValueChangeListener(
event -> log.log("Value is now: " + combo.getValue()));
addComponent(log);
addComponent(new Button("Dummy for TestBench"));
}
- private void createDataSources() {
- ds1 = DataSource.create("Item 1", "Item 2", "Item 3", "Item 4");
+ private void createDataProviders() {
+ ds1 = DataProvider.create("Item 1", "Item 2", "Item 3", "Item 4");
- ds2 = DataSource.create("Item 3");
+ ds2 = DataProvider.create("Item 3");
}
@Override
protected String getDescription() {
- return "Select \"Item 3\" in the ComboBox, change the data source, focus and blur the ComboBox. The value should temporarily change to null when changing data source but not when focusing and blurring the ComboBox";
+ return "Select \"Item 3\" in the ComboBox, change the data provider, focus and blur the ComboBox. The value should temporarily change to null when changing data provider but not when focusing and blurring the ComboBox";
}
@Override
import java.util.Date;
import com.vaadin.server.ThemeResource;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.ComboBox;
@Override
protected void setup() {
ComboBox<String> cb = new ComboBox<String>(null,
- DataSource.create("folder-add", "folder-delete", "arrow-down",
+ DataProvider.create("folder-add", "folder-delete", "arrow-down",
"arrow-left", "arrow-right", "arrow-up", "document-add",
"document-delete", "document-doc", "document-edit",
"document-image", "document-pdf", "document-ppt",
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractReindeerTestUI;
-import com.vaadin.tests.util.ItemDataSource;
+import com.vaadin.tests.util.ItemDataProvider;
import com.vaadin.ui.ComboBox;
/**
}
private ComboBox<String> createComboBox(String caption) {
- ComboBox<String> cb = new ComboBox<>(caption, new ItemDataSource(100));
+ ComboBox<String> cb = new ComboBox<>(caption, new ItemDataProvider(100));
cb.setId(caption);
return cb;
}
package com.vaadin.tests.components.combobox;
import com.vaadin.tests.components.TestBase;
-import com.vaadin.tests.util.ItemDataSource;
+import com.vaadin.tests.util.ItemDataProvider;
import com.vaadin.ui.ComboBox;
public class ComboBoxNavigation extends TestBase {
@Override
protected void setup() {
- ComboBox<String> cb = new ComboBox<>(null, new ItemDataSource(100));
+ ComboBox<String> cb = new ComboBox<>(null, new ItemDataProvider(100));
addComponent(cb);
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractReindeerTestUI;
-import com.vaadin.tests.util.ItemDataSource;
+import com.vaadin.tests.util.ItemDataProvider;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Label;
.add("body.v-generated-body { overflow: auto;height:auto;}");
getPage().getStyles().add(
"body.v-generated-body .v-ui.v-scrollable{ overflow: visible;height:auto !important;}");
- ComboBox<String> cb = new ComboBox<>(null, new ItemDataSource(10));
+ ComboBox<String> cb = new ComboBox<>(null, new ItemDataProvider(10));
Label spacer = new Label("foo");
spacer.setHeight("2000px");
});
comboBox.addValueChangeListener(event -> label.setValue(
- String.valueOf(comboBox.getDataSource().size(new Query()))));
+ String.valueOf(comboBox.getDataProvider().size(new Query()))));
addComponent(label);
}
import com.vaadin.server.ThemeResource;
import com.vaadin.tests.components.TestBase;
-import com.vaadin.tests.util.ItemDataSource;
+import com.vaadin.tests.util.ItemDataProvider;
import com.vaadin.ui.ComboBox;
public class ComboBoxUndefinedWidthAndIcon extends TestBase {
@Override
protected void setup() {
- ComboBox<String> cb = new ComboBox<>(null, new ItemDataSource(200));
+ ComboBox<String> cb = new ComboBox<>(null, new ItemDataProvider(200));
cb.setItemIconGenerator(
item -> new ThemeResource("../runo/icons/16/users.png"));
package com.vaadin.tests.components.combobox;
import com.vaadin.tests.components.TestBase;
-import com.vaadin.tests.util.ItemDataSource;
+import com.vaadin.tests.util.ItemDataProvider;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.TextField;
import com.vaadin.v7.data.util.ObjectProperty;
protected void setup() {
ComboBox<String> cb = new ComboBox<>("Combobox",
- new ItemDataSource(100));
+ new ItemDataProvider(100));
cb.setPlaceholder("Enter text");
cb.setDescription("Some Combobox");
addComponent(cb);
import com.vaadin.server.Page;
import com.vaadin.server.VaadinRequest;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.tests.components.AbstractReindeerTestUI;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.HorizontalLayout;
HorizontalLayout layout = new HorizontalLayout();
layout.setSpacing(true);
ComboBox<String> combo = new ComboBox<>(null,
- DataSource.create("1", "2", "3"));
+ DataProvider.create("1", "2", "3"));
layout.addComponent(combo);
MenuBar menubar = getMenubar();
package com.vaadin.tests.components.combobox;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
@Override
protected void setup() {
final ComboBox<String> box = new ComboBox(null,
- DataSource.create("Value 1", "Value 2", "Value 3", "Value 4"));
+ DataProvider.create("Value 1", "Value 2", "Value 3", "Value 4"));
box.setPrimaryStyleName("my-combobox");
addComponent(box);
package com.vaadin.tests.components.combobox;
import com.vaadin.server.VaadinRequest;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.tests.components.AbstractTestUIWithLog;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
@Override
protected void setup(VaadinRequest request) {
- final ComboBox<String> cbFoo = new ComboBox<>(null, DataSource.create(
+ final ComboBox<String> cbFoo = new ComboBox<>(null, DataProvider.create(
"A really long string that causes an inline width to be set"));
cbFoo.setSizeUndefined();
import com.vaadin.server.SerializableFunction;
import com.vaadin.server.VaadinRequest;
-import com.vaadin.server.data.DataSource;
+import com.vaadin.server.data.DataProvider;
import com.vaadin.tests.components.AbstractTestUI;
import com.vaadin.ui.Button;
import com.vaadin.ui.Grid;
addComponent(grid);
Button button = new Button("Filter Test item",
- event -> filter(grid.getDataSource(), data));
+ event -> filter(grid.getDataProvider(), data));
addComponent(button);
}
- private void filter(DataSource<String> dataSource, List<String> data) {
+ private void filter(DataProvider<String> dataProvider, List<String> data) {
String last = data.get(data.size() - 1);
data.clear();
data.add(last);
- dataSource.refreshAll();
+ dataProvider.refreshAll();
}
-}
\ No newline at end of file
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 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.tests.components.grid.basics;
+
+import java.util.List;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.data.DataProvider;
+import com.vaadin.server.data.ListDataProvider;
+import com.vaadin.tests.components.AbstractReindeerTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Grid;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class RefreshDataProvider extends AbstractReindeerTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Grid<DataObject> grid = new Grid<>();
+ List<DataObject> data = DataObject.generateObjects();
+
+ ListDataProvider<DataObject> dataProvider = DataProvider.create(data);
+ grid.setDataProvider(dataProvider);
+
+ grid.setDataProvider(dataProvider);
+ grid.addColumn("Coordinates", DataObject::getCoordinates);
+ addComponent(grid);
+
+ Button update = new Button("Update data",
+ event -> updateData(dataProvider, data));
+ update.setId("update");
+ addComponent(update);
+
+ Button add = new Button("Add data", event -> addData(dataProvider, data));
+ add.setId("add");
+ addComponent(add);
+
+ Button remove = new Button("Remove data",
+ event -> removeData(dataProvider, data));
+ remove.setId("remove");
+ addComponent(remove);
+ }
+
+ private void updateData(DataProvider<DataObject> dataProvider,
+ List<DataObject> data) {
+ data.get(0).setCoordinates("Updated coordinates");
+ dataProvider.refreshAll();
+ }
+
+ private void addData(DataProvider<DataObject> dataProvider,
+ List<DataObject> data) {
+ DataObject dataObject = new DataObject();
+ dataObject.setCoordinates("Added");
+ data.add(0, dataObject);
+ dataProvider.refreshAll();
+ }
+
+ private void removeData(DataProvider<DataObject> dataProvider,
+ List<DataObject> data) {
+ data.remove(0);
+ dataProvider.refreshAll();
+ }
+}
+++ /dev/null
-/*
- * Copyright 2000-2016 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.tests.components.grid.basics;
-
-import java.util.List;
-
-import com.vaadin.server.VaadinRequest;
-import com.vaadin.server.data.DataSource;
-import com.vaadin.server.data.ListDataSource;
-import com.vaadin.tests.components.AbstractReindeerTestUI;
-import com.vaadin.ui.Button;
-import com.vaadin.ui.Grid;
-
-/**
- * @author Vaadin Ltd
- *
- */
-public class RefreshDataSource extends AbstractReindeerTestUI {
-
- @Override
- protected void setup(VaadinRequest request) {
- Grid<DataObject> grid = new Grid<>();
- List<DataObject> data = DataObject.generateObjects();
-
- ListDataSource<DataObject> dataSource = DataSource.create(data);
- grid.setDataSource(dataSource);
-
- grid.setDataSource(dataSource);
- grid.addColumn("Coordinates", DataObject::getCoordinates);
- addComponent(grid);
-
- Button update = new Button("Update data",
- event -> updateData(dataSource, data));
- update.setId("update");
- addComponent(update);
-
- Button add = new Button("Add data", event -> addData(dataSource, data));
- add.setId("add");
- addComponent(add);
-
- Button remove = new Button("Remove data",
- event -> removeData(dataSource, data));
- remove.setId("remove");
- addComponent(remove);
- }
-
- private void updateData(DataSource<DataObject> dataSource,
- List<DataObject> data) {
- data.get(0).setCoordinates("Updated coordinates");
- dataSource.refreshAll();
- }
-
- private void addData(DataSource<DataObject> dataSource,
- List<DataObject> data) {
- DataObject dataObject = new DataObject();
- dataObject.setCoordinates("Added");
- data.add(0, dataObject);
- dataSource.refreshAll();
- }
-
- private void removeData(DataSource<DataObject> dataSource,
- List<DataObject> data) {
- data.remove(0);
- dataSource.refreshAll();
- }
-}
import java.util.stream.Collectors;
import com.vaadin.server.VaadinRequest;
-import com.vaadin.server.data.ListDataSource;
+import com.vaadin.server.data.ListDataProvider;
import com.vaadin.tests.components.AbstractTestUIWithLog;
import com.vaadin.ui.Button;
import com.vaadin.ui.ListSelect;
-// FIXME this test should be updated once the datasource supports CRUD operations #77
+// FIXME this test should be updated once the provider supports CRUD operations #77
public class ListSelectAddRemoveItems extends AbstractTestUIWithLog {
- private ListDataSource<String> dataSource = new ListDataSource<>(
+ private ListDataProvider<String> dataProvider = new ListDataProvider<>(
Collections.emptyList());
private ListSelect<String> listSelect;
@Override
protected void setup(VaadinRequest request) {
- listSelect = new ListSelect<>("ListSelect", dataSource);
+ listSelect = new ListSelect<>("ListSelect", dataProvider);
listSelect.setWidth("100px");
listSelect.setRows(10);
}));
addComponent(new Button("Add first", event -> {
- List<String> list = dataSource.fetch(null)
+ List<String> list = dataProvider.fetch(null)
.collect(Collectors.toList());
list.add(0, "first");
- dataSource = new ListDataSource<>(list);
- listSelect.setDataSource(dataSource);
+ dataProvider = new ListDataProvider<>(list);
+ listSelect.setDataProvider(dataProvider);
logContainer();
}));
addComponent(new Button("Add middle", event -> {
- List<String> list = dataSource.fetch(null)
+ List<String> list = dataProvider.fetch(null)
.collect(Collectors.toList());
list.add(list.size() / 2, "middle");
- dataSource = new ListDataSource<>(list);
- listSelect.setDataSource(dataSource);
+ dataProvider = new ListDataProvider<>(list);
+ listSelect.setDataProvider(dataProvider);
logContainer();
}));
addComponent(new Button("Add last", event -> {
- List<String> list = dataSource.fetch(null)
+ List<String> list = dataProvider.fetch(null)
.collect(Collectors.toList());
list.add("last");
- dataSource = new ListDataSource<>(list);
- listSelect.setDataSource(dataSource);
+ dataProvider = new ListDataProvider<>(list);
+ listSelect.setDataProvider(dataProvider);
logContainer();
}));
addComponent(new Button("Swap", event -> {
- List<String> list = dataSource.fetch(null)
+ List<String> list = dataProvider.fetch(null)
.collect(Collectors.toList());
Collections.swap(list, 0, list.size() - 1);
- dataSource = new ListDataSource<>(list);
- listSelect.setDataSource(dataSource);
+ dataProvider = new ListDataProvider<>(list);
+ listSelect.setDataProvider(dataProvider);
logContainer();
}));
addComponent(new Button("Remove first", event -> {
- List<String> list = dataSource.fetch(null)
+ List<String> list = dataProvider.fetch(null)
.collect(Collectors.toList());
list.remove(0);
- dataSource = new ListDataSource<>(list);
- listSelect.setDataSource(dataSource);
+ dataProvider = new ListDataProvider<>(list);
+ listSelect.setDataProvider(dataProvider);
logContainer();
}));
addComponent(new Button("Remove middle", event -> {
- List<String> list = dataSource.fetch(null)
+ List<String> list = dataProvider.fetch(null)
.collect(Collectors.toList());
list.remove(list.size() / 2);
- dataSource = new ListDataSource<>(list);
- listSelect.setDataSource(dataSource);
+ dataProvider = new ListDataProvider<>(list);
+ listSelect.setDataProvider(dataProvider);
logContainer();
}));
addComponent(new Button("Remove last", event -> {
- List<String> list = dataSource.fetch(null)
+ List<String> list = dataProvider.fetch(null)
.collect(Collectors.toList());
list.remove(list.size() - 1);
- dataSource = new ListDataSource<>(list);
- listSelect.setDataSource(dataSource);
+ dataProvider = new ListDataProvider<>(list);
+ listSelect.setDataProvider(dataProvider);
logContainer();
}));
private void logContainer() {
StringBuilder b = new StringBuilder();
- List<String> list = dataSource.fetch(null).collect(Collectors.toList());
+ List<String> list = dataProvider.fetch(null).collect(Collectors.toList());
for (int i = 0; i < list.size(); i++) {
Object id = list.get(i);
if (i != 0) {
}
public void resetContainer() {
- dataSource = new ListDataSource<>(Arrays.asList("a", "b", "c"));
- listSelect.setDataSource(dataSource);
+ dataProvider = new ListDataProvider<>(Arrays.asList("a", "b", "c"));
+ listSelect.setDataProvider(dataProvider);
}
@Override
} else {
group.setItemIconGenerator(item -> null);
}
- group.getDataSource().refreshAll();
+ group.getDataProvider().refreshAll();
}
private void createItemCaptionGeneratorMenu() {
createSelectAction("Item Caption Generator", "Item Caption Generator",
options, "None", (radioButtonGroup, captionGenerator, data) -> {
radioButtonGroup.setItemCaptionGenerator(captionGenerator);
- radioButtonGroup.getDataSource().refreshAll();
+ radioButtonGroup.getDataProvider().refreshAll();
}, true);
}
@Override
protected String getTestDescription() {
- return "Slider and ProgressBar do not properly pass a value from data source to the client";
+ return "Slider and ProgressBar do not properly pass a value from data provider to the client";
}
@Override
import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
-import com.vaadin.server.data.ListDataSource;
+import com.vaadin.server.data.ListDataProvider;
import com.vaadin.server.data.Query;
import com.vaadin.shared.data.DataCommunicatorConstants;
import com.vaadin.tests.components.AbstractTestUIWithLog;
public class DummyData extends AbstractTestUIWithLog {
/**
- * DataSource that keeps track on how often the data is requested.
+ * DataProvider that keeps track on how often the data is requested.
*/
- private class LoggingDataSource extends ListDataSource<String> {
+ private class LoggingDataProvider extends ListDataProvider<String> {
private int count = 0;
- private LoggingDataSource(Collection<String> collection) {
+ private LoggingDataProvider(Collection<String> collection) {
super(collection);
}
for (int i = 0; i < 300; ++i) {
items.add("Foo " + i);
}
- dummy.setDataSource(new LoggingDataSource(items));
+ dummy.setDataProvider(new LoggingDataProvider(items));
dummy.setValue("Foo 200");
HorizontalLayout controls = new HorizontalLayout();
controls.addComponent(new Button("Select Foo 20", e -> {
dummy.setValue("Foo " + 20);
}));
- controls.addComponent(new Button("Reset data source", e -> {
- dummy.setDataSource(new LoggingDataSource(items));
+ controls.addComponent(new Button("Reset data provider", e -> {
+ dummy.setDataProvider(new LoggingDataProvider(items));
}));
controls.addComponent(new Button("Remove all data", e -> {
- dummy.setDataSource(new LoggingDataSource(Collections.emptyList()));
+ dummy.setDataProvider(new LoggingDataProvider(Collections.emptyList()));
}));
addComponent(dummy);
}
});
componentContainerSelect.setValue(componentContainerSelect
- .getDataSource().fetch(new Query()).iterator().next());
+ .getDataProvider().fetch(new Query()).iterator().next());
Button but1 = new Button("Move in and out of component container",
new Button.ClickListener() {
private Component createMenu(T component) {
MenuBar menu = new MenuBar();
createContainerSizeMenu(menu.addItem("Size", null), component);
- createContainerMenu(menu.addItem("Data source", null), component);
+ createContainerMenu(menu.addItem("Data provider", null), component);
menu.addItem("Create only data",
item -> toggleDataOnly(item, component)).setCheckable(true);
private MenuItem addContainerSizeMenu(int size, MenuItem menu,
T component) {
- MenuItem item = menu.addItem("Set data source size to " + size,
+ MenuItem item = menu.addItem("Set data provider size to " + size,
itm -> setData(itm, size, component, isInMemory));
item.setCheckable(true);
return item;
--- /dev/null
+package com.vaadin.tests.util;
+
+import java.util.stream.IntStream;
+
+import com.vaadin.server.data.BackEndDataProvider;
+
+/**
+ * A data provider for tests that creates "Item n" strings on the fly.
+ *
+ * @author Vaadin Ltd
+ */
+public class ItemDataProvider extends BackEndDataProvider<String> {
+
+ public ItemDataProvider(int size) {
+ super(q -> IntStream
+ .range(q.getOffset(),
+ Math.max(q.getOffset() + q.getLimit() + 1, size))
+ .mapToObj(i -> "Item " + i), q -> size);
+ }
+
+}
+++ /dev/null
-package com.vaadin.tests.util;
-
-import java.util.stream.IntStream;
-
-import com.vaadin.server.data.BackEndDataSource;
-
-/**
- * A data source for tests that creates "Item n" strings on the fly.
- *
- * @author Vaadin Ltd
- */
-public class ItemDataSource extends BackEndDataSource<String> {
-
- public ItemDataSource(int size) {
- super(q -> IntStream
- .range(q.getOffset(),
- Math.max(q.getOffset() + q.getLimit() + 1, size))
- .mapToObj(i -> "Item " + i), q -> size);
- }
-
-}
@Test
public void initialItems_reduceItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data source", "Items", "5");
+ selectMenuPath("Component", "Data provider", "Items", "5");
assertItems(5);
}
@Test
public void initialItems_increaseItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data source", "Items", "100");
+ selectMenuPath("Component", "Data provider", "Items", "100");
assertItems(100);
}
--- /dev/null
+/*
+ * Copyright 2000-2016 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.tests.components.grid.basics;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class RefreshDataProviderTest extends MultiBrowserTest {
+
+ @Test
+ public void updateFirstRow() {
+ openTestURL();
+
+ findElement(By.id("update")).click();
+ WebElement first = findElement(By.tagName("td"));
+ Assert.assertEquals(
+ "UI component is not refreshed after update in data",
+ "Updated coordinates", first.getText());
+ }
+
+ @Test
+ public void addFirstRow() {
+ openTestURL();
+
+ findElement(By.id("add")).click();
+ WebElement first = findElement(By.tagName("td"));
+
+ Assert.assertEquals("UI component is not refreshed after add new data",
+ "Added", first.getText());
+ }
+
+ @Test
+ public void removeFirstRow() {
+ openTestURL();
+
+ WebElement first = findElement(By.tagName("td"));
+ String old = first.getText();
+ first = findElement(By.id("remove"));
+ Assert.assertNotEquals("UI component is not refreshed after removal",
+ old, first.getText());
+ }
+
+}
+++ /dev/null
-/*
- * Copyright 2000-2016 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.tests.components.grid.basics;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebElement;
-
-import com.vaadin.tests.tb3.MultiBrowserTest;
-
-/**
- * @author Vaadin Ltd
- *
- */
-public class RefreshDataSourceTest extends MultiBrowserTest {
-
- @Test
- public void updateFirstRow() {
- openTestURL();
-
- findElement(By.id("update")).click();
- WebElement first = findElement(By.tagName("td"));
- Assert.assertEquals(
- "UI component is not refreshed after update in data",
- "Updated coordinates", first.getText());
- }
-
- @Test
- public void addFirstRow() {
- openTestURL();
-
- findElement(By.id("add")).click();
- WebElement first = findElement(By.tagName("td"));
-
- Assert.assertEquals("UI component is not refreshed after add new data",
- "Added", first.getText());
- }
-
- @Test
- public void removeFirstRow() {
- openTestURL();
-
- WebElement first = findElement(By.tagName("td"));
- String old = first.getText();
- first = findElement(By.id("remove"));
- Assert.assertNotEquals("UI component is not refreshed after removal",
- old, first.getText());
- }
-
-}
\ No newline at end of file
@Test
public void initialItems_reduceItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data source", "Items", "5");
+ selectMenuPath("Component", "Data provider", "Items", "5");
assertItems(5);
}
@Test
public void initialItems_increaseItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data source", "Items", "100");
+ selectMenuPath("Component", "Data provider", "Items", "100");
assertItems(100);
}
@Test
public void initialItems_reduceItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data source", "Items", "5");
+ selectMenuPath("Component", "Data provider", "Items", "5");
assertItems(5);
}
@Test
public void initialItems_increaseItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data source", "Items", "100");
+ selectMenuPath("Component", "Data provider", "Items", "100");
assertItems(100);
}
@Test
public void initialItems_reduceItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data source", "Items", "5");
+ selectMenuPath("Component", "Data provider", "Items", "5");
assertItems(5);
}
@Test
public void initialItems_increaseItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data source", "Items", "100");
+ selectMenuPath("Component", "Data provider", "Items", "100");
assertItems(100);
}
@Test
public void initialItems_reduceItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data source", "Items", "5");
+ selectMenuPath("Component", "Data provider", "Items", "5");
assertItems(5);
}
@Test
public void initialItems_increaseItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data source", "Items", "100");
+ selectMenuPath("Component", "Data provider", "Items", "100");
assertItems(100);
}
@Test
public void itemsMovedFromLeftToRight() {
- selectMenuPath("Component", "Data source", "Items", "5");
+ selectMenuPath("Component", "Data provider", "Items", "5");
assertItems(5);
selectItems("Item 1", "Item 2", "Item 4");
}
@Test
- public void testDataSourceChangeOnlyOneRequest() {
- // Change to a new logging data source
+ public void testDataProviderChangeOnlyOneRequest() {
+ // Change to a new logging data provider
$(ButtonElement.class).get(1).click();
- assertEquals("DataSource change should only cause 1 request",
+ assertEquals("DataProvider change should only cause 1 request",
"3. Backend request #0", getLogRow(0));
}
assertEquals("Unexpected amount of content on init.", 300,
$(DummyElement.class).first()
.findElements(By.className("v-label")).size());
- // Change to an empty data source
+ // Change to an empty data provider
$(ButtonElement.class).get(2).click();
- assertEquals("Empty data source did not work as expected.", 0,
+ assertEquals("Empty data provider did not work as expected.", 0,
$(DummyElement.class).first()
.findElements(By.className("v-label")).size());
- // Change back to logging data source
+ // Change back to logging data provider
$(ButtonElement.class).get(1).click();
assertEquals("Data was not correctly restored.", 300,
$(DummyElement.class).first()