Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

DataProvider.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright 2000-2016 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.data.provider;
  17. import java.io.Serializable;
  18. import java.util.Arrays;
  19. import java.util.Collection;
  20. import java.util.Objects;
  21. import java.util.stream.Collectors;
  22. import java.util.stream.Stream;
  23. import com.vaadin.data.HasDataProvider;
  24. import com.vaadin.data.HasFilterableDataProvider;
  25. import com.vaadin.data.provider.CallbackDataProvider.CountCallback;
  26. import com.vaadin.data.provider.CallbackDataProvider.FetchCallback;
  27. import com.vaadin.server.SerializableBiFunction;
  28. import com.vaadin.server.SerializableFunction;
  29. import com.vaadin.shared.Registration;
  30. /**
  31. * A common interface for fetching data from a backend. The {@link DataProvider}
  32. * interface is used by listing components implementing {@link HasDataProvider}
  33. * or {@link HasFilterableDataProvider}. The listing component will provide a
  34. * {@link Query} object with request information, and the data provider uses
  35. * this information to return a stream containing requested beans.
  36. * <p>
  37. * Vaadin comes with a ready-made solution for in-memory data, known as
  38. * {@link ListDataProvider} which can be created using static {@code create}
  39. * methods in this interface. For custom backends such as SQL, EntityManager,
  40. * REST APIs or SpringData, use a {@link BackEndDataProvider} or its subclass.
  41. *
  42. * @author Vaadin Ltd.
  43. *
  44. * @param <T>
  45. * data type
  46. * @param <F>
  47. * filter type
  48. *
  49. * @see #ofCollection(Collection)
  50. * @see #ofItems(Object...)
  51. * @see #fromStream(Stream)
  52. * @see #fromCallbacks(FetchCallback, CountCallback)
  53. * @see #fromFilteringCallbacks(FetchCallback, CountCallback)
  54. * @see ListDataProvider
  55. * @see BackEndDataProvider
  56. *
  57. * @since 8.0
  58. */
  59. public interface DataProvider<T, F> extends Serializable {
  60. /**
  61. * Gets whether the DataProvider content all available in memory or does it
  62. * use some external backend.
  63. *
  64. * @return {@code true} if all data is in memory; {@code false} if not
  65. */
  66. boolean isInMemory();
  67. /**
  68. * Gets the amount of data in this DataProvider.
  69. *
  70. * @param query
  71. * query with sorting and filtering
  72. * @return the size of the data provider
  73. */
  74. int size(Query<T, F> query);
  75. /**
  76. * Fetches data from this DataProvider using given {@code query}.
  77. *
  78. * @param query
  79. * given query to request data
  80. * @return the result of the query request: a stream of data objects, not
  81. * {@code null}
  82. */
  83. Stream<T> fetch(Query<T, F> query);
  84. /**
  85. * Refreshes the given item. This method should be used to inform all
  86. * {@link DataProviderListener DataProviderListeners} that an item has been
  87. * updated or replaced with a new instance.
  88. * <p>
  89. * For this to work properly, the item must either implement
  90. * {@link #equals(Object)} and {@link #hashCode()} to consider both the old
  91. * and the new item instances to be equal, or alternatively
  92. * {@link #getId(Object)} should be implemented to return an appropriate
  93. * identifier.
  94. *
  95. * @see #getId(Object)
  96. *
  97. * @param item
  98. * the item to refresh
  99. */
  100. void refreshItem(T item);
  101. /**
  102. * Refreshes all data based on currently available data in the underlying
  103. * provider.
  104. */
  105. void refreshAll();
  106. /**
  107. * Gets an identifier for the given item. This identifier is used by the
  108. * framework to determine equality between two items.
  109. * <p>
  110. * Default is to use item itself as its own identifier. If the item has
  111. * {@link Object#equals(Object)} and {@link Object#hashCode()} implemented
  112. * in a way that it can be compared to other items, no changes are required.
  113. * <p>
  114. * <strong>Note:</strong> This method will be called often by the Framework.
  115. * It should not do any expensive operations.
  116. *
  117. * @param item
  118. * the item to get identifier for; not {@code null}
  119. * @return the identifier for given item; not {@code null}
  120. */
  121. public default Object getId(T item) {
  122. Objects.requireNonNull(item, "Cannot provide an id for a null item.");
  123. return item;
  124. }
  125. /**
  126. * Adds a data provider listener. The listener is called when some piece of
  127. * data is updated.
  128. * <p>
  129. * The {@link #refreshAll()} method fires {@link DataChangeEvent} each time
  130. * when it's called. It allows to update UI components when user changes
  131. * something in the underlying data.
  132. *
  133. * @see #refreshAll()
  134. * @param listener
  135. * the data change listener, not null
  136. * @return a registration for the listener
  137. */
  138. Registration addDataProviderListener(DataProviderListener<T> listener);
  139. /**
  140. * Wraps this data provider to create a data provider that uses a different
  141. * filter type. This can be used for adapting this data provider to a filter
  142. * type provided by a Component such as ComboBox.
  143. * <p>
  144. * For example receiving a String from ComboBox and making a Predicate based
  145. * on it:
  146. *
  147. * <pre>
  148. * DataProvider&lt;Person, Predicate&lt;Person&gt;&gt; dataProvider;
  149. * // ComboBox uses String as the filter type
  150. * DataProvider&lt;Person, String&gt; wrappedProvider = dataProvider
  151. * .withConvertedFilter(filterText -&gt; {
  152. * Predicate&lt;Person&gt; predicate = person -&gt; person.getName()
  153. * .startsWith(filterText);
  154. * return predicate;
  155. * });
  156. * comboBox.setDataProvider(wrappedProvider);
  157. * </pre>
  158. *
  159. * @param filterConverter
  160. * callback that converts the filter in the query of the wrapped
  161. * data provider into a filter supported by this data provider.
  162. * Will only be called if the query contains a filter. Not
  163. * <code>null</code>
  164. *
  165. * @param <C>
  166. * the filter type that the wrapped data provider accepts;
  167. * typically provided by a Component
  168. *
  169. * @return wrapped data provider, not <code>null</code>
  170. */
  171. public default <C> DataProvider<T, C> withConvertedFilter(
  172. SerializableFunction<C, F> filterConverter) {
  173. Objects.requireNonNull(filterConverter,
  174. "Filter converter can't be null");
  175. return new DataProviderWrapper<T, C, F>(this) {
  176. @Override
  177. protected F getFilter(Query<T, C> query) {
  178. return query.getFilter().map(filterConverter).orElse(null);
  179. }
  180. };
  181. }
  182. /**
  183. * Wraps this data provider to create a data provider that supports
  184. * programmatically setting a filter that will be combined with a filter
  185. * provided through the query.
  186. *
  187. * @see #withConfigurableFilter()
  188. * @see ConfigurableFilterDataProvider#setFilter(Object)
  189. *
  190. * @param filterCombiner
  191. * a callback for combining and the configured filter with the
  192. * filter from the query to get a filter to pass to the wrapped
  193. * provider. Either parameter might be <code>null</code>, but the
  194. * callback will not be invoked at all if both would be
  195. * <code>null</code>. Not <code>null</code>.
  196. *
  197. * @return a data provider with a configurable filter, not <code>null</code>
  198. */
  199. public default <Q, C> ConfigurableFilterDataProvider<T, Q, C> withConfigurableFilter(
  200. SerializableBiFunction<Q, C, F> filterCombiner) {
  201. return new ConfigurableFilterDataProviderWrapper<T, Q, C, F>(this) {
  202. @Override
  203. protected F combineFilters(Q queryFilter, C configuredFilter) {
  204. return filterCombiner.apply(queryFilter, configuredFilter);
  205. }
  206. };
  207. }
  208. /**
  209. * Wraps this data provider to create a data provider that supports
  210. * programmatically setting a filter but no filtering through the query.
  211. *
  212. * @see #withConfigurableFilter(SerializableBiFunction)
  213. * @see ConfigurableFilterDataProvider#setFilter(Object)
  214. *
  215. * @return a data provider with a configurable filter, not <code>null</code>
  216. */
  217. public default ConfigurableFilterDataProvider<T, Void, F> withConfigurableFilter() {
  218. return withConfigurableFilter((queryFilter, configuredFilter) -> {
  219. assert queryFilter == null : "Filter from Void query must be null";
  220. return configuredFilter;
  221. });
  222. }
  223. /**
  224. * Creates a new data provider backed by a collection.
  225. * <p>
  226. * The collection is used as-is. Changes in the collection will be visible
  227. * via the created data provider. The caller should copy the collection if
  228. * necessary.
  229. *
  230. * @param <T>
  231. * the data item type
  232. * @param items
  233. * the collection of data, not <code>null</code>
  234. * @return a new list data provider
  235. */
  236. public static <T> ListDataProvider<T> ofCollection(Collection<T> items) {
  237. return new ListDataProvider<>(items);
  238. }
  239. /**
  240. * Creates a new data provider from the given items.
  241. * <p>
  242. * The items are copied into a new backing list, so structural changes to
  243. * the provided array will not be visible via the created data provider.
  244. *
  245. * @param <T>
  246. * the data item type
  247. * @param items
  248. * the data items
  249. * @return a new list data provider
  250. */
  251. @SafeVarargs
  252. public static <T> ListDataProvider<T> ofItems(T... items) {
  253. return new ListDataProvider<>(Arrays.asList(items));
  254. }
  255. /**
  256. * Creates a new data provider from the given stream. <b>All items in the
  257. * stream are eagerly collected to a list.</b>
  258. * <p>
  259. * This is a shorthand for using {@link #ofCollection(Collection)} after
  260. * collecting the items in the stream to a list with e.g.
  261. * {@code stream.collect(Collectors.toList));}.
  262. * <p>
  263. * <strong>Using big streams is not recommended, you should instead use a
  264. * lazy data provider.</strong> See
  265. * {@link #fromCallbacks(FetchCallback, CountCallback)} or
  266. * {@link BackEndDataProvider} for more info.
  267. *
  268. * @param <T>
  269. * the data item type
  270. * @param items
  271. * a stream of data items, not {@code null}
  272. * @return a new list data provider
  273. */
  274. public static <T> ListDataProvider<T> fromStream(Stream<T> items) {
  275. return new ListDataProvider<>(items.collect(Collectors.toList()));
  276. }
  277. /**
  278. * Creates a new data provider that uses filtering callbacks for fetching
  279. * and counting items from any backing store.
  280. * <p>
  281. * The query that is passed to each callback may contain a filter value that
  282. * is provided by the component querying for data.
  283. *
  284. * @param fetchCallback
  285. * function that returns a stream of items from the back end for
  286. * a query
  287. * @param countCallback
  288. * function that returns the number of items in the back end for
  289. * a query
  290. * @return a new callback data provider
  291. */
  292. public static <T, F> CallbackDataProvider<T, F> fromFilteringCallbacks(
  293. FetchCallback<T, F> fetchCallback,
  294. CountCallback<T, F> countCallback) {
  295. return new CallbackDataProvider<>(fetchCallback, countCallback);
  296. }
  297. /**
  298. * Creates a new data provider that uses callbacks for fetching and counting
  299. * items from any backing store.
  300. * <p>
  301. * The query that is passed to each callback will not contain any filter
  302. * values.
  303. *
  304. * @param fetchCallback
  305. * function that returns a stream of items from the back end for
  306. * a query
  307. * @param countCallback
  308. * function that returns the number of items in the back end for
  309. * a query
  310. * @return a new callback data provider
  311. */
  312. public static <T> CallbackDataProvider<T, Void> fromCallbacks(
  313. FetchCallback<T, Void> fetchCallback,
  314. CountCallback<T, Void> countCallback) {
  315. return fromFilteringCallbacks(fetchCallback, countCallback);
  316. }
  317. }