You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ListDataProvider.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  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.util.Collection;
  18. import java.util.Comparator;
  19. import java.util.Locale;
  20. import java.util.Objects;
  21. import java.util.Optional;
  22. import java.util.stream.Stream;
  23. import com.vaadin.data.ValueProvider;
  24. import com.vaadin.server.SerializableBiPredicate;
  25. import com.vaadin.server.SerializableComparator;
  26. import com.vaadin.server.SerializablePredicate;
  27. import com.vaadin.server.SerializableSupplier;
  28. import com.vaadin.shared.data.sort.SortDirection;
  29. import com.vaadin.ui.UI;
  30. /**
  31. * {@link DataProvider} wrapper for {@link Collection}s. This class does not
  32. * actually handle the {@link Query} parameters.
  33. *
  34. * @param <T>
  35. * data type
  36. */
  37. public class ListDataProvider<T>
  38. extends AbstractDataProvider<T, SerializablePredicate<T>> implements
  39. ConfigurableFilterDataProvider<T, SerializablePredicate<T>, SerializablePredicate<T>> {
  40. private static final SerializableSupplier<Locale> CURRENT_LOCALE_SUPPLIER = () -> {
  41. UI currentUi = UI.getCurrent();
  42. if (currentUi != null) {
  43. return currentUi.getLocale();
  44. } else {
  45. return Locale.getDefault();
  46. }
  47. };
  48. private SerializableComparator<T> sortOrder = null;
  49. private SerializablePredicate<T> filter;
  50. private final Collection<T> backend;
  51. /**
  52. * Constructs a new ListDataProvider.
  53. * <p>
  54. * No protective copy is made of the list, and changes in the provided
  55. * backing Collection will be visible via this data provider. The caller
  56. * should copy the list if necessary.
  57. *
  58. * @param items
  59. * the initial data, not null
  60. */
  61. public ListDataProvider(Collection<T> items) {
  62. Objects.requireNonNull(items, "items cannot be null");
  63. backend = items;
  64. sortOrder = null;
  65. }
  66. /**
  67. * Returns the underlying data items.
  68. *
  69. * @return the underlying data items
  70. */
  71. public Collection<T> getItems() {
  72. return backend;
  73. }
  74. @Override
  75. public Stream<T> fetch(Query<T, SerializablePredicate<T>> query) {
  76. Stream<T> stream = getFilteredStream(query);
  77. Optional<Comparator<T>> comparing = Stream
  78. .of(query.getInMemorySorting(), sortOrder)
  79. .filter(c -> c != null)
  80. .reduce((c1, c2) -> c1.thenComparing(c2));
  81. if (comparing.isPresent()) {
  82. stream = stream.sorted(comparing.get());
  83. }
  84. return stream.skip(query.getOffset()).limit(query.getLimit());
  85. }
  86. @Override
  87. public boolean isInMemory() {
  88. return true;
  89. }
  90. @Override
  91. public int size(Query<T, SerializablePredicate<T>> query) {
  92. return (int) getFilteredStream(query).count();
  93. }
  94. private Stream<T> getFilteredStream(
  95. Query<T, SerializablePredicate<T>> query) {
  96. Stream<T> stream = backend.stream();
  97. // Apply our own filters first so that query filters never see the items
  98. // that would already have been filtered out
  99. if (filter != null) {
  100. stream = stream.filter(filter);
  101. }
  102. stream = query.getFilter().map(stream::filter).orElse(stream);
  103. return stream;
  104. }
  105. /**
  106. * Sets the comparator to use as the default sorting for this data provider.
  107. * This overrides the sorting set by any other method that manipulates the
  108. * default sorting of this data provider.
  109. * <p>
  110. * The default sorting is used if the query defines no sorting. The default
  111. * sorting is also used to determine the ordering of items that are
  112. * considered equal by the sorting defined in the query.
  113. *
  114. * @see #setSortOrder(ValueProvider, SortDirection)
  115. * @see #addSortComparator(SerializableComparator)
  116. *
  117. * @param comparator
  118. * a comparator to use, or <code>null</code> to clear any
  119. * previously set sort order
  120. */
  121. public void setSortComparator(SerializableComparator<T> comparator) {
  122. this.sortOrder = comparator;
  123. refreshAll();
  124. }
  125. /**
  126. * Sets the property and direction to use as the default sorting for this
  127. * data provider. This overrides the sorting set by any other method that
  128. * manipulates the default sorting of this data provider.
  129. * <p>
  130. * The default sorting is used if the query defines no sorting. The default
  131. * sorting is also used to determine the ordering of items that are
  132. * considered equal by the sorting defined in the query.
  133. *
  134. * @see #setSortComparator(SerializableComparator)
  135. * @see #addSortOrder(ValueProvider, SortDirection)
  136. *
  137. * @param valueProvider
  138. * the value provider that defines the property do sort by, not
  139. * <code>null</code>
  140. * @param sortDirection
  141. * the sort direction to use, not <code>null</code>
  142. */
  143. public <V extends Comparable<? super V>> void setSortOrder(
  144. ValueProvider<T, V> valueProvider, SortDirection sortDirection) {
  145. setSortComparator(propertyComparator(valueProvider, sortDirection));
  146. }
  147. /**
  148. * Adds a comparator to the default sorting for this data provider. If no
  149. * default sorting has been defined, then the provided comparator will be
  150. * used as the default sorting. If a default sorting has been defined, then
  151. * the provided comparator will be used to determine the ordering of items
  152. * that are considered equal by the previously defined default sorting.
  153. * <p>
  154. * The default sorting is used if the query defines no sorting. The default
  155. * sorting is also used to determine the ordering of items that are
  156. * considered equal by the sorting defined in the query.
  157. *
  158. * @see #setSortComparator(SerializableComparator)
  159. * @see #addSortOrder(ValueProvider, SortDirection)
  160. *
  161. * @param comparator
  162. * a comparator to add, not <code>null</code>
  163. */
  164. public void addSortComparator(SerializableComparator<T> comparator) {
  165. Objects.requireNonNull(comparator, "Sort order to add cannot be null");
  166. SerializableComparator<T> originalComparator = this.sortOrder;
  167. if (originalComparator == null) {
  168. setSortComparator(comparator);
  169. } else {
  170. setSortComparator((a, b) -> {
  171. int result = originalComparator.compare(a, b);
  172. if (result == 0) {
  173. result = comparator.compare(a, b);
  174. }
  175. return result;
  176. });
  177. }
  178. }
  179. /**
  180. * Adds a property and direction to the default sorting for this data
  181. * provider. If no default sorting has been defined, then the provided sort
  182. * order will be used as the default sorting. If a default sorting has been
  183. * defined, then the provided sort order will be used to determine the
  184. * ordering of items that are considered equal by the previously defined
  185. * default sorting.
  186. * <p>
  187. * The default sorting is used if the query defines no sorting. The default
  188. * sorting is also used to determine the ordering of items that are
  189. * considered equal by the sorting defined in the query.
  190. *
  191. * @see #setSortOrder(ValueProvider, SortDirection)
  192. * @see #addSortComparator(SerializableComparator)
  193. *
  194. * @param valueProvider
  195. * the value provider that defines the property do sort by, not
  196. * <code>null</code>
  197. * @param sortDirection
  198. * the sort direction to use, not <code>null</code>
  199. */
  200. public <V extends Comparable<? super V>> void addSortOrder(
  201. ValueProvider<T, V> valueProvider, SortDirection sortDirection) {
  202. addSortComparator(propertyComparator(valueProvider, sortDirection));
  203. }
  204. private static <V extends Comparable<? super V>, T> SerializableComparator<T> propertyComparator(
  205. ValueProvider<T, V> valueProvider, SortDirection sortDirection) {
  206. Objects.requireNonNull(valueProvider, "Value provider cannot be null");
  207. Objects.requireNonNull(sortDirection, "Sort direction cannot be null");
  208. Comparator<V> comparator = getNaturalSortComparator(sortDirection);
  209. return (a, b) -> comparator.compare(valueProvider.apply(a),
  210. valueProvider.apply(b));
  211. }
  212. private static <V extends Comparable<? super V>> Comparator<V> getNaturalSortComparator(
  213. SortDirection sortDirection) {
  214. Comparator<V> comparator = Comparator.naturalOrder();
  215. if (sortDirection == SortDirection.DESCENDING) {
  216. comparator = comparator.reversed();
  217. }
  218. return comparator;
  219. }
  220. /**
  221. * Sets a filter to be applied to all queries. The filter replaces any
  222. * filter that has been set or added previously.
  223. *
  224. * @see #setFilter(ValueProvider, SerializablePredicate)
  225. * @see #setFilterByValue(ValueProvider, Object)
  226. * @see #addFilter(SerializablePredicate)
  227. *
  228. * @param filter
  229. * the filter to set, or <code>null</code> to remove any set
  230. * filters
  231. */
  232. @Override
  233. public void setFilter(SerializablePredicate<T> filter) {
  234. this.filter = filter;
  235. refreshAll();
  236. }
  237. /**
  238. * Adds a filter to be applied to all queries. The filter will be used in
  239. * addition to any filter that has been set or added previously.
  240. *
  241. * @see #addFilter(ValueProvider, SerializablePredicate)
  242. * @see #addFilterByValue(ValueProvider, Object)
  243. * @see #setFilter(SerializablePredicate)
  244. *
  245. * @param filter
  246. * the filter to add, not <code>null</code>
  247. */
  248. public void addFilter(SerializablePredicate<T> filter) {
  249. Objects.requireNonNull(filter, "Filter cannot be null");
  250. if (this.filter == null) {
  251. setFilter(filter);
  252. } else {
  253. SerializablePredicate<T> oldFilter = this.filter;
  254. setFilter(item -> oldFilter.test(item) && filter.test(item));
  255. }
  256. }
  257. /**
  258. * Removes any filter that has been set or added previously.
  259. *
  260. * @see #setFilter(SerializablePredicate)
  261. */
  262. public void clearFilters() {
  263. setFilter(null);
  264. }
  265. /**
  266. * Sets a filter for an item property. The filter replaces any filter that
  267. * has been set or added previously.
  268. *
  269. * @see #setFilter(SerializablePredicate)
  270. * @see #setFilterByValue(ValueProvider, Object)
  271. * @see #addFilter(ValueProvider, SerializablePredicate)
  272. *
  273. * @param valueProvider
  274. * value provider that gets the property value, not
  275. * <code>null</code>
  276. * @param valueFilter
  277. * filter for testing the property value, not <code>null</code>
  278. */
  279. public <V> void setFilter(ValueProvider<T, V> valueProvider,
  280. SerializablePredicate<V> valueFilter) {
  281. setFilter(createValueProviderFilter(valueProvider, valueFilter));
  282. }
  283. /**
  284. * Adds a filter for an item property. The filter will be used in addition
  285. * to any filter that has been set or added previously.
  286. *
  287. * @see #addFilter(SerializablePredicate)
  288. * @see #addFilterByValue(ValueProvider, Object)
  289. * @see #setFilter(ValueProvider, SerializablePredicate)
  290. *
  291. * @param valueProvider
  292. * value provider that gets the property value, not
  293. * <code>null</code>
  294. * @param valueFilter
  295. * filter for testing the property value, not <code>null</code>
  296. */
  297. public <V> void addFilter(ValueProvider<T, V> valueProvider,
  298. SerializablePredicate<V> valueFilter) {
  299. Objects.requireNonNull(valueProvider, "Value provider cannot be null");
  300. Objects.requireNonNull(valueFilter, "Value filter cannot be null");
  301. addFilter(createValueProviderFilter(valueProvider, valueFilter));
  302. }
  303. private static <T, V> SerializablePredicate<T> createValueProviderFilter(
  304. ValueProvider<T, V> valueProvider,
  305. SerializablePredicate<V> valueFilter) {
  306. return item -> valueFilter.test(valueProvider.apply(item));
  307. }
  308. /**
  309. * Sets a filter that requires an item property to have a specific value.
  310. * The property value and the provided value are compared using
  311. * {@link Object#equals(Object)}. The filter replaces any filter that has
  312. * been set or added previously.
  313. *
  314. * @see #setFilter(SerializablePredicate)
  315. * @see #setFilter(ValueProvider, SerializablePredicate)
  316. * @see #addFilterByValue(ValueProvider, Object)
  317. *
  318. * @param valueProvider
  319. * value provider that gets the property value, not
  320. * <code>null</code>
  321. * @param requiredValue
  322. * the value that the property must have for the filter to pass
  323. */
  324. public <V> void setFilterByValue(ValueProvider<T, V> valueProvider,
  325. V requiredValue) {
  326. setFilter(createEqualsFilter(valueProvider, requiredValue));
  327. }
  328. /**
  329. * Adds a filter that requires an item property to have a specific value.
  330. * The property value and the provided value are compared using
  331. * {@link Object#equals(Object)}.The filter will be used in addition to any
  332. * filter that has been set or added previously.
  333. *
  334. * @see #setFilterByValue(ValueProvider, Object)
  335. * @see #addFilter(SerializablePredicate)
  336. * @see #addFilter(ValueProvider, SerializablePredicate)
  337. *
  338. * @param valueProvider
  339. * value provider that gets the property value, not
  340. * <code>null</code>
  341. * @param requiredValue
  342. * the value that the property must have for the filter to pass
  343. */
  344. public <V> void addFilterByValue(ValueProvider<T, V> valueProvider,
  345. V requiredValue) {
  346. addFilter(createEqualsFilter(valueProvider, requiredValue));
  347. }
  348. private static <T, V> SerializablePredicate<T> createEqualsFilter(
  349. ValueProvider<T, V> valueProvider, V requiredValue) {
  350. Objects.requireNonNull(valueProvider, "Value provider cannot be null");
  351. return item -> Objects.equals(valueProvider.apply(item), requiredValue);
  352. }
  353. /**
  354. * Wraps this data provider to create a new data provider that is filtered
  355. * by comparing an item to the filter value provided in the query.
  356. * <p>
  357. * The predicate receives the item as the first parameter and the query
  358. * filter value as the second parameter, and should return <code>true</code>
  359. * if the corresponding item should be included. The query filter value is
  360. * never <code>null</code> – all items are included without running the
  361. * predicate if the query doesn't define any filter.
  362. *
  363. * @param predicate
  364. * a predicate to use for comparing the item to the query filter,
  365. * not <code>null</code>
  366. *
  367. * @return a data provider that filters accordingly, not <code>null</code>
  368. */
  369. public <Q> DataProvider<T, Q> filteringBy(
  370. SerializableBiPredicate<T, Q> predicate) {
  371. Objects.requireNonNull(predicate, "Predicate cannot be null");
  372. return withConvertedFilter(
  373. filterValue -> item -> predicate.test(item, filterValue));
  374. }
  375. /**
  376. * Wraps this data provider to create a new data provider that is filtered
  377. * by comparing an item property value to the filter value provided in the
  378. * query.
  379. * <p>
  380. * The predicate receives the property value as the first parameter and the
  381. * query filter value as the second parameter, and should return
  382. * <code>true</code> if the corresponding item should be included. The query
  383. * filter value is never <code>null</code> – all items are included without
  384. * running either callback if the query doesn't define any filter.
  385. *
  386. * @param valueProvider
  387. * a value provider that gets the property value, not
  388. * <code>null</code>
  389. * @param predicate
  390. * a predicate to use for comparing the property value to the
  391. * query filter, not <code>null</code>
  392. *
  393. * @return a data provider that filters accordingly, not <code>null</code>
  394. */
  395. public <V, Q> DataProvider<T, Q> filteringBy(
  396. ValueProvider<T, V> valueProvider,
  397. SerializableBiPredicate<V, Q> predicate) {
  398. Objects.requireNonNull(valueProvider, "Value provider cannot be null");
  399. Objects.requireNonNull(predicate, "Predicate cannot be null");
  400. return filteringBy((item, filterValue) -> predicate
  401. .test(valueProvider.apply(item), filterValue));
  402. }
  403. /**
  404. * Wraps this data provider to create a new data provider that is filtered
  405. * by testing whether the value of a property is equals to the filter value
  406. * provided in the query. Equality is tested using
  407. * {@link Objects#equals(Object, Object)}.
  408. *
  409. * @param valueProvider
  410. * a value provider that gets the property value, not
  411. * <code>null</code>
  412. *
  413. * @return a data provider that filters accordingly, not <code>null</code>
  414. */
  415. public <V> DataProvider<T, V> filteringByEquals(
  416. ValueProvider<T, V> valueProvider) {
  417. return filteringBy(valueProvider, Objects::equals);
  418. }
  419. private <V, Q> DataProvider<T, Q> filteringByIgnoreNull(
  420. ValueProvider<T, V> valueProvider,
  421. SerializableBiPredicate<V, Q> predicate) {
  422. Objects.requireNonNull(predicate, "Predicate cannot be null");
  423. return filteringBy(valueProvider,
  424. (itemValue, queryFilter) -> itemValue != null
  425. && predicate.test(itemValue, queryFilter));
  426. }
  427. /**
  428. * Wraps this data provider to create a new data provider that is filtered
  429. * by a string by checking whether the lower case representation of the
  430. * filter value provided in the query is a substring of the lower case
  431. * representation of an item property value. The filter never passes if the
  432. * item property value is <code>null</code>.
  433. *
  434. * @param valueProvider
  435. * a value provider that gets the string property value, not
  436. * <code>null</code>
  437. * @param locale
  438. * the locale to use for converting the strings to lower case,
  439. * not <code>null</code>
  440. * @return a data provider that filters accordingly, not <code>null</code>
  441. */
  442. public DataProvider<T, String> filteringBySubstring(
  443. ValueProvider<T, String> valueProvider, Locale locale) {
  444. Objects.requireNonNull(locale, "Locale cannot be null");
  445. return filteringByCaseInsensitiveString(valueProvider, String::contains,
  446. () -> locale);
  447. }
  448. /**
  449. * Wraps this data provider to create a new data provider that is filtered
  450. * by a string by checking whether the lower case representation of the
  451. * filter value provided in the query is a substring of the lower case
  452. * representation of an item property value. Conversion to lower case is
  453. * done using the locale of the {@link UI#getCurrent() current UI} if
  454. * available, or otherwise {@link Locale#getDefault() the default locale}.
  455. * The filter never passes if the item property value is <code>null</code>.
  456. *
  457. * @param valueProvider
  458. * a value provider that gets the string property value, not
  459. * <code>null</code>
  460. * @return a data provider that filters accordingly, not <code>null</code>
  461. */
  462. public DataProvider<T, String> filteringBySubstring(
  463. ValueProvider<T, String> valueProvider) {
  464. return filteringByCaseInsensitiveString(valueProvider, String::contains,
  465. CURRENT_LOCALE_SUPPLIER);
  466. }
  467. /**
  468. * Wraps this data provider to create a new data provider that is filtered
  469. * by a string by checking whether the lower case representation of an item
  470. * property value starts with the lower case representation of the filter
  471. * value provided in the query. The filter never passes if the item property
  472. * value is <code>null</code>.
  473. *
  474. * @param valueProvider
  475. * a value provider that gets the string property value, not
  476. * <code>null</code>
  477. * @param locale
  478. * the locale to use for converting the strings to lower case,
  479. * not <code>null</code>
  480. * @return a data provider that filters accordingly, not <code>null</code>
  481. */
  482. public DataProvider<T, String> filteringByPrefix(
  483. ValueProvider<T, String> valueProvider, Locale locale) {
  484. return filteringByCaseInsensitiveString(valueProvider,
  485. String::startsWith, () -> locale);
  486. }
  487. /**
  488. * Wraps this data provider to create a new data provider that is filtered
  489. * by a string by checking whether the lower case representation of an item
  490. * property value starts with the lower case representation of the filter
  491. * value provided in the query. Conversion to lower case is done using the
  492. * locale of the {@link UI#getCurrent() current UI} if available, or
  493. * otherwise {@link Locale#getDefault() the default locale}. The filter
  494. * never passes if the item property value is <code>null</code>.
  495. *
  496. * @param valueProvider
  497. * a value provider that gets the string property value, not
  498. * <code>null</code>
  499. * @return a data provider that filters accordingly, not <code>null</code>
  500. */
  501. public DataProvider<T, String> filteringByPrefix(
  502. ValueProvider<T, String> valueProvider) {
  503. return filteringByCaseInsensitiveString(valueProvider,
  504. String::startsWith, CURRENT_LOCALE_SUPPLIER);
  505. }
  506. private DataProvider<T, String> filteringByCaseInsensitiveString(
  507. ValueProvider<T, String> valueProvider,
  508. SerializableBiPredicate<String, String> predicate,
  509. SerializableSupplier<Locale> localeSupplier) {
  510. // Only assert since these are only passed from our own code
  511. assert predicate != null;
  512. assert localeSupplier != null;
  513. return filteringByIgnoreNull(valueProvider,
  514. (itemString, filterString) -> {
  515. Locale locale = localeSupplier.get();
  516. assert locale != null;
  517. return predicate.test(itemString.toLowerCase(locale),
  518. filterString.toLowerCase(locale));
  519. });
  520. }
  521. }