123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- /*
- * 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.data.provider;
-
- import java.io.Serializable;
- import java.util.Arrays;
- import java.util.Collection;
- import java.util.Objects;
- import java.util.stream.Collectors;
- import java.util.stream.Stream;
-
- import com.vaadin.data.HasDataProvider;
- import com.vaadin.data.HasFilterableDataProvider;
- import com.vaadin.data.provider.CallbackDataProvider.CountCallback;
- import com.vaadin.data.provider.CallbackDataProvider.FetchCallback;
- import com.vaadin.server.SerializableBiFunction;
- import com.vaadin.server.SerializableFunction;
- import com.vaadin.shared.Registration;
-
- /**
- * A common interface for fetching data from a backend. The {@link DataProvider}
- * interface is used by listing components implementing {@link HasDataProvider}
- * or {@link HasFilterableDataProvider}. The listing component will provide a
- * {@link Query} object with request information, and the data provider uses
- * this information to return a stream containing requested beans.
- * <p>
- * Vaadin comes with a ready-made solution for in-memory data, known as
- * {@link ListDataProvider} which can be created using static {@code create}
- * methods in this interface. For custom backends such as SQL, EntityManager,
- * REST APIs or SpringData, use a {@link BackEndDataProvider} or its subclass.
- *
- * @author Vaadin Ltd.
- *
- * @param <T>
- * data type
- * @param <F>
- * filter type
- *
- * @see #ofCollection(Collection)
- * @see #ofItems(Object...)
- * @see #fromStream(Stream)
- * @see #fromCallbacks(FetchCallback, CountCallback)
- * @see #fromFilteringCallbacks(FetchCallback, CountCallback)
- * @see ListDataProvider
- * @see BackEndDataProvider
- *
- * @since 8.0
- */
- public interface DataProvider<T, F> 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 query
- * query with sorting and filtering
- * @return the size of the data provider
- */
- int size(Query<T, F> query);
-
- /**
- * 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<T, F> query);
-
- /**
- * Refreshes the given item. This method should be used to inform all
- * {@link DataProviderListener DataProviderListeners} that an item has been
- * updated or replaced with a new instance.
- * <p>
- * For this to work properly, the item must either implement
- * {@link #equals(Object)} and {@link #hashCode()} to consider both the old
- * and the new item instances to be equal, or alternatively
- * {@link #getId(Object)} should be implemented to return an appropriate
- * identifier.
- *
- * @see #getId(Object)
- *
- * @param item
- * the item to refresh
- */
- void refreshItem(T item);
-
- /**
- * Refreshes all data based on currently available data in the underlying
- * provider.
- */
- void refreshAll();
-
- /**
- * Gets an identifier for the given item. This identifier is used by the
- * framework to determine equality between two items.
- * <p>
- * Default is to use item itself as its own identifier. If the item has
- * {@link Object#equals(Object)} and {@link Object#hashCode()} implemented
- * in a way that it can be compared to other items, no changes are required.
- * <p>
- * <strong>Note:</strong> This method will be called often by the Framework.
- * It should not do any expensive operations.
- *
- * @param item
- * the item to get identifier for; not {@code null}
- * @return the identifier for given item; not {@code null}
- */
- public default Object getId(T item) {
- Objects.requireNonNull(item, "Cannot provide an id for a null item.");
- return item;
- }
-
- /**
- * 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<T> listener);
-
- /**
- * Wraps this data provider to create a data provider that uses a different
- * filter type. This can be used for adapting this data provider to a filter
- * type provided by a Component such as ComboBox.
- * <p>
- * For example receiving a String from ComboBox and making a Predicate based
- * on it:
- *
- * <pre>
- * DataProvider<Person, Predicate<Person>> dataProvider;
- * // ComboBox uses String as the filter type
- * DataProvider<Person, String> wrappedProvider = dataProvider
- * .withConvertedFilter(filterText -> {
- * Predicate<Person> predicate = person -> person.getName()
- * .startsWith(filterText);
- * return predicate;
- * });
- * comboBox.setDataProvider(wrappedProvider);
- * </pre>
- *
- * @param filterConverter
- * callback that converts the filter in the query of the wrapped
- * data provider into a filter supported by this data provider.
- * Will only be called if the query contains a filter. Not
- * <code>null</code>
- *
- * @param <C>
- * the filter type that the wrapped data provider accepts;
- * typically provided by a Component
- *
- * @return wrapped data provider, not <code>null</code>
- */
- public default <C> DataProvider<T, C> withConvertedFilter(
- SerializableFunction<C, F> filterConverter) {
- Objects.requireNonNull(filterConverter,
- "Filter converter can't be null");
- return new DataProviderWrapper<T, C, F>(this) {
- @Override
- protected F getFilter(Query<T, C> query) {
- return query.getFilter().map(filterConverter).orElse(null);
- }
- };
- }
-
- /**
- * Wraps this data provider to create a data provider that supports
- * programmatically setting a filter that will be combined with a filter
- * provided through the query.
- *
- * @see #withConfigurableFilter()
- * @see ConfigurableFilterDataProvider#setFilter(Object)
- *
- * @param filterCombiner
- * a callback for combining and the configured filter with the
- * filter from the query to get a filter to pass to the wrapped
- * provider. Either parameter might be <code>null</code>, but the
- * callback will not be invoked at all if both would be
- * <code>null</code>. Not <code>null</code>.
- *
- * @return a data provider with a configurable filter, not <code>null</code>
- */
- public default <Q, C> ConfigurableFilterDataProvider<T, Q, C> withConfigurableFilter(
- SerializableBiFunction<Q, C, F> filterCombiner) {
- return new ConfigurableFilterDataProviderWrapper<T, Q, C, F>(this) {
- @Override
- protected F combineFilters(Q queryFilter, C configuredFilter) {
- return filterCombiner.apply(queryFilter, configuredFilter);
- }
- };
- }
-
- /**
- * Wraps this data provider to create a data provider that supports
- * programmatically setting a filter but no filtering through the query.
- *
- * @see #withConfigurableFilter(SerializableBiFunction)
- * @see ConfigurableFilterDataProvider#setFilter(Object)
- *
- * @return a data provider with a configurable filter, not <code>null</code>
- */
- public default ConfigurableFilterDataProvider<T, Void, F> withConfigurableFilter() {
- return withConfigurableFilter((queryFilter, configuredFilter) -> {
- assert queryFilter == null : "Filter from Void query must be null";
-
- return configuredFilter;
- });
- }
-
- /**
- * Creates a new data provider backed by a collection.
- * <p>
- * The collection is used as-is. Changes in the collection will be visible
- * via the created data provider. The caller should copy the collection if
- * necessary.
- *
- * @param <T>
- * the data item type
- * @param items
- * the collection of data, not <code>null</code>
- * @return a new list data provider
- */
- public static <T> ListDataProvider<T> ofCollection(Collection<T> items) {
- return new ListDataProvider<>(items);
- }
-
- /**
- * Creates a new data provider from the given items.
- * <p>
- * The items are copied into a new backing list, so structural changes to
- * the provided array will not be visible via the created data provider.
- *
- * @param <T>
- * the data item type
- * @param items
- * the data items
- * @return a new list data provider
- */
- @SafeVarargs
- public static <T> ListDataProvider<T> ofItems(T... items) {
- return new ListDataProvider<>(Arrays.asList(items));
- }
-
- /**
- * Creates a new data provider from the given stream. <b>All items in the
- * stream are eagerly collected to a list.</b>
- * <p>
- * This is a shorthand for using {@link #ofCollection(Collection)} after
- * collecting the items in the stream to a list with e.g.
- * {@code stream.collect(Collectors.toList));}.
- * <p>
- * <strong>Using big streams is not recommended, you should instead use a
- * lazy data provider.</strong> See
- * {@link #fromCallbacks(FetchCallback, CountCallback)} or
- * {@link BackEndDataProvider} for more info.
- *
- * @param <T>
- * the data item type
- * @param items
- * a stream of data items, not {@code null}
- * @return a new list data provider
- */
- public static <T> ListDataProvider<T> fromStream(Stream<T> items) {
- return new ListDataProvider<>(items.collect(Collectors.toList()));
- }
-
- /**
- * Creates a new data provider that uses filtering callbacks for fetching
- * and counting items from any backing store.
- * <p>
- * The query that is passed to each callback may contain a filter value that
- * is provided by the component querying for data.
- *
- * @param fetchCallback
- * function that returns a stream of items from the back end for
- * a query
- * @param countCallback
- * function that returns the number of items in the back end for
- * a query
- * @return a new callback data provider
- */
- public static <T, F> CallbackDataProvider<T, F> fromFilteringCallbacks(
- FetchCallback<T, F> fetchCallback,
- CountCallback<T, F> countCallback) {
- return new CallbackDataProvider<>(fetchCallback, countCallback);
- }
-
- /**
- * Creates a new data provider that uses callbacks for fetching and counting
- * items from any backing store.
- * <p>
- * The query that is passed to each callback will not contain any filter
- * values.
- *
- * @param fetchCallback
- * function that returns a stream of items from the back end for
- * a query
- * @param countCallback
- * function that returns the number of items in the back end for
- * a query
- * @return a new callback data provider
- */
- public static <T> CallbackDataProvider<T, Void> fromCallbacks(
- FetchCallback<T, Void> fetchCallback,
- CountCallback<T, Void> countCallback) {
- return fromFilteringCallbacks(fetchCallback, countCallback);
- }
- }
|