aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/main/java/com/vaadin/data
diff options
context:
space:
mode:
authorLeif Åstrand <legioth@gmail.com>2017-01-22 21:50:46 +0200
committerGitHub <noreply@github.com>2017-01-22 21:50:46 +0200
commit5447e7e05392483455f7df4bf2af5d5d74e5a2ae (patch)
tree5028592fea2d9f1dda0c23d1448b92b8a35dc6fd /server/src/main/java/com/vaadin/data
parent19427ba7c7a51d3af61c170a7ba54137eb629ac8 (diff)
downloadvaadin-framework-5447e7e05392483455f7df4bf2af5d5d74e5a2ae.tar.gz
vaadin-framework-5447e7e05392483455f7df4bf2af5d5d74e5a2ae.zip
Add ListDataProvider shorthands for filter conversion (#8279)
Also updates ComboBox.setItems to use these new shorthands This is one of many steps towards #8245
Diffstat (limited to 'server/src/main/java/com/vaadin/data')
-rw-r--r--server/src/main/java/com/vaadin/data/provider/ListDataProvider.java195
1 files changed, 195 insertions, 0 deletions
diff --git a/server/src/main/java/com/vaadin/data/provider/ListDataProvider.java b/server/src/main/java/com/vaadin/data/provider/ListDataProvider.java
index 470339bc2a..4269ddbeff 100644
--- a/server/src/main/java/com/vaadin/data/provider/ListDataProvider.java
+++ b/server/src/main/java/com/vaadin/data/provider/ListDataProvider.java
@@ -17,14 +17,18 @@ package com.vaadin.data.provider;
import java.util.Collection;
import java.util.Comparator;
+import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import com.vaadin.data.ValueProvider;
+import com.vaadin.server.SerializableBiPredicate;
import com.vaadin.server.SerializableComparator;
import com.vaadin.server.SerializablePredicate;
+import com.vaadin.server.SerializableSupplier;
import com.vaadin.shared.data.sort.SortDirection;
+import com.vaadin.ui.UI;
/**
* {@link DataProvider} wrapper for {@link Collection}s. This class does not
@@ -38,6 +42,15 @@ public class ListDataProvider<T>
implements AppendableFilterDataProvider<T, SerializablePredicate<T>>,
ConfigurableFilterDataProvider<T, SerializablePredicate<T>, SerializablePredicate<T>> {
+ private static final SerializableSupplier<Locale> CURRENT_LOCALE_SUPPLIER = () -> {
+ UI currentUi = UI.getCurrent();
+ if (currentUi != null) {
+ return currentUi.getLocale();
+ } else {
+ return Locale.getDefault();
+ }
+ };
+
private SerializableComparator<T> sortOrder = null;
private SerializablePredicate<T> filter;
@@ -376,4 +389,186 @@ public class ListDataProvider<T>
SerializablePredicate<T> filter2) {
return t -> filter1.test(t) && filter2.test(t);
}
+
+ /**
+ * Wraps this data provider to create a new data provider that is filtered
+ * by comparing an item to the filter value provided in the query.
+ * <p>
+ * The predicate receives the item as the first parameter and the query
+ * filter value as the second parameter, and should return <code>true</code>
+ * if the corresponding item should be included. The query filter value is
+ * never <code>null</code> – all items are included without running the
+ * predicate if the query doesn't define any filter.
+ *
+ * @param predicate
+ * a predicate to use for comparing the item to the query filter,
+ * not <code>null</code>
+ *
+ * @return a data provider that filters accordingly, not <code>null</code>
+ */
+ public <Q> DataProvider<T, Q> filteringBy(
+ SerializableBiPredicate<T, Q> predicate) {
+ Objects.requireNonNull(predicate, "Predicate cannot be null");
+
+ return convertFilter(
+ filterValue -> item -> predicate.test(item, filterValue));
+ }
+
+ /**
+ * Wraps this data provider to create a new data provider that is filtered
+ * by comparing an item property value to the filter value provided in the
+ * query.
+ * <p>
+ * The predicate receives the property value as the first parameter and the
+ * query filter value as the second parameter, and should return
+ * <code>true</code> if the corresponding item should be included. The query
+ * filter value is never <code>null</code> – all items are included without
+ * running either callback if the query doesn't define any filter.
+ *
+ * @param valueProvider
+ * a value provider that gets the property value, not
+ * <code>null</code>
+ * @param predicate
+ * a predicate to use for comparing the property value to the
+ * query filter, not <code>null</code>
+ *
+ * @return a data provider that filters accordingly, not <code>null</code>
+ */
+ public <V, Q> DataProvider<T, Q> filteringBy(
+ ValueProvider<T, V> valueProvider,
+ SerializableBiPredicate<V, Q> predicate) {
+ Objects.requireNonNull(valueProvider, "Value provider cannot be null");
+ Objects.requireNonNull(predicate, "Predicate cannot be null");
+
+ return filteringBy((item, filterValue) -> predicate
+ .test(valueProvider.apply(item), filterValue));
+ }
+
+ /**
+ * Wraps this data provider to create a new data provider that is filtered
+ * by testing whether the value of a property is equals to the filter value
+ * provided in the query. Equality is tested using
+ * {@link Objects#equals(Object, Object)}.
+ *
+ * @param valueProvider
+ * a value provider that gets the property value, not
+ * <code>null</code>
+ *
+ * @return a data provider that filters accordingly, not <code>null</code>
+ */
+ public <V> DataProvider<T, V> filteringByEquals(
+ ValueProvider<T, V> valueProvider) {
+ return filteringBy(valueProvider, Objects::equals);
+ }
+
+ private <V, Q> DataProvider<T, Q> filteringByIgnoreNull(
+ ValueProvider<T, V> valueProvider,
+ SerializableBiPredicate<V, Q> predicate) {
+ Objects.requireNonNull(predicate, "Predicate cannot be null");
+
+ return filteringBy(valueProvider,
+ (itemValue, queryFilter) -> itemValue != null
+ && predicate.test(itemValue, queryFilter));
+ }
+
+ /**
+ * Wraps this data provider to create a new data provider that is filtered
+ * by a string by checking whether the lower case representation of the
+ * filter value provided in the query is a substring of the lower case
+ * representation of an item property value. The filter never passes if the
+ * item property value is <code>null</code>.
+ *
+ * @param valueProvider
+ * a value provider that gets the string property value, not
+ * <code>null</code>
+ * @param locale
+ * the locale to use for converting the strings to lower case,
+ * not <code>null</code>
+ * @return a data provider that filters accordingly, not <code>null</code>
+ */
+ public DataProvider<T, String> filteringBySubstring(
+ ValueProvider<T, String> valueProvider, Locale locale) {
+ Objects.requireNonNull(locale, "Locale cannot be null");
+ return filteringByCaseInsensitiveString(valueProvider, String::contains,
+ () -> locale);
+ }
+
+ /**
+ * Wraps this data provider to create a new data provider that is filtered
+ * by a string by checking whether the lower case representation of the
+ * filter value provided in the query is a substring of the lower case
+ * representation of an item property value. Conversion to lower case is
+ * done using the locale of the {@link UI#getCurrent() current UI} if
+ * available, or otherwise {@link Locale#getDefault() the default locale}.
+ * The filter never passes if the item property value is <code>null</code>.
+ *
+ * @param valueProvider
+ * a value provider that gets the string property value, not
+ * <code>null</code>
+ * @return a data provider that filters accordingly, not <code>null</code>
+ */
+ public DataProvider<T, String> filteringBySubstring(
+ ValueProvider<T, String> valueProvider) {
+ return filteringByCaseInsensitiveString(valueProvider, String::contains,
+ CURRENT_LOCALE_SUPPLIER);
+ }
+
+ /**
+ * Wraps this data provider to create a new data provider that is filtered
+ * by a string by checking whether the lower case representation of an item
+ * property value starts with the lower case representation of the filter
+ * value provided in the query. The filter never passes if the item property
+ * value is <code>null</code>.
+ *
+ * @param valueProvider
+ * a value provider that gets the string property value, not
+ * <code>null</code>
+ * @param locale
+ * the locale to use for converting the strings to lower case,
+ * not <code>null</code>
+ * @return a data provider that filters accordingly, not <code>null</code>
+ */
+ public DataProvider<T, String> filteringByPrefix(
+ ValueProvider<T, String> valueProvider, Locale locale) {
+ return filteringByCaseInsensitiveString(valueProvider,
+ String::startsWith, () -> locale);
+ }
+
+ /**
+ * Wraps this data provider to create a new data provider that is filtered
+ * by a string by checking whether the lower case representation of an item
+ * property value starts with the lower case representation of the filter
+ * value provided in the query. Conversion to lower case is done using the
+ * locale of the {@link UI#getCurrent() current UI} if available, or
+ * otherwise {@link Locale#getDefault() the default locale}. The filter
+ * never passes if the item property value is <code>null</code>.
+ *
+ * @param valueProvider
+ * a value provider that gets the string property value, not
+ * <code>null</code>
+ * @return a data provider that filters accordingly, not <code>null</code>
+ */
+ public DataProvider<T, String> filteringByPrefix(
+ ValueProvider<T, String> valueProvider) {
+ return filteringByCaseInsensitiveString(valueProvider,
+ String::startsWith, CURRENT_LOCALE_SUPPLIER);
+ }
+
+ private DataProvider<T, String> filteringByCaseInsensitiveString(
+ ValueProvider<T, String> valueProvider,
+ SerializableBiPredicate<String, String> predicate,
+ SerializableSupplier<Locale> localeSupplier) {
+ // Only assert since these are only passed from our own code
+ assert predicate != null;
+ assert localeSupplier != null;
+
+ return filteringByIgnoreNull(valueProvider,
+ (itemString, filterString) -> {
+ Locale locale = localeSupplier.get();
+ assert locale != null;
+
+ return predicate.test(itemString.toLowerCase(locale),
+ filterString.toLowerCase(locale));
+ });
+ }
}