]> source.dussan.org Git - vaadin-framework.git/commitdiff
Allow distinct configurable filter and wrapped filter types (#8322)
authorLeif Åstrand <legioth@gmail.com>
Wed, 25 Jan 2017 07:23:09 +0000 (09:23 +0200)
committerDenis <denis@vaadin.com>
Wed, 25 Jan 2017 07:23:09 +0000 (09:23 +0200)
* Allow distinct configurable filter and wrapped filter types

This enables implementing the use case that was already described
towards the end of datamodel-providers.asciidoc.

Also swaps the order of the callback type parameters to make all three
match the order of the ConfigurableFilterDataProvider type parameters.

documentation/datamodel/datamodel-providers.asciidoc
server/src/main/java/com/vaadin/data/provider/ConfigurableFilterDataProviderWrapper.java
server/src/main/java/com/vaadin/data/provider/DataProvider.java
server/src/test/java/com/vaadin/data/provider/ConfigurableFilterDataProviderWrapperTest.java

index 35d47db4f9e1a4799b0e9fa33ed3de0f0bbd3960..6b5fea2275ada876c42e8ea6db63b9bf160870be 100644 (file)
@@ -402,7 +402,7 @@ DataProvider<Person, Set<String>> personProvider = getPersonProvider();
 
 ConfigurableFilterDataProvider<Person, String, Set<String>> wrapper =
   personProvider.withConfigurableFilter(
-    (Set<String> configuredFilters, String queryFilter) -> {
+    (String queryFilter, Set<String> configuredFilters) -> {
       Set<String> combinedFilters = new HashSet<>();
       combinedFilters.addAll(configuredFilters);
       combinedFilters.add(queryFilter);
@@ -529,7 +529,8 @@ everythingConfigurable.setFilter(
 // For use with ComboBox and separate department filtering
 ConfigurableDataProvider<Person, String, Department> mixed =
   dataProvider.withConfigurableFilter(
-    (department, filterText) -> {
+    // Can be shortened as PersonFilter::new
+    (filterText, department) -> {
       return new PersonFilter(filterText, department);
     }
   );
index c6256787ce97453e0a20c6dce274b34cbee43530..b83fc98013cdbc5e9c8468254404a65ce9c92a12 100644 (file)
@@ -28,9 +28,11 @@ package com.vaadin.data.provider;
  *            the query filter type
  * @param <C>
  *            the configurable filter type
+ * @param <F>
+ *            the filter type of the wrapped data provider
  */
-public abstract class ConfigurableFilterDataProviderWrapper<T, Q, C>
-        extends DataProviderWrapper<T, Q, C>
+public abstract class ConfigurableFilterDataProviderWrapper<T, Q, C, F>
+        extends DataProviderWrapper<T, Q, F>
         implements ConfigurableFilterDataProvider<T, Q, C> {
 
     private C configuredFilter;
@@ -43,33 +45,36 @@ public abstract class ConfigurableFilterDataProviderWrapper<T, Q, C>
      *            the data provider to wrap, not <code>null</code>
      */
     public ConfigurableFilterDataProviderWrapper(
-            DataProvider<T, C> dataProvider) {
+            DataProvider<T, F> dataProvider) {
         super(dataProvider);
     }
 
     @Override
-    protected C getFilter(Query<T, Q> query) {
-        return query.getFilter().map(
-                queryFilter -> combineFilters(configuredFilter, queryFilter))
-                .orElse(configuredFilter);
+    protected F getFilter(Query<T, Q> query) {
+        Q queryFilter = query.getFilter().orElse(null);
+        if (configuredFilter == null && queryFilter == null) {
+            return null;
+        }
+        return combineFilters(queryFilter, configuredFilter);
     }
 
     /**
      * Combines the configured filter and the filter from the query into one
-     * filter instance that can be passed to the wrapped data provider. This
-     * method is called only if there is a query filter, otherwise the
-     * configured filter will be directly passed to the query.
-     *
+     * filter instance that can be passed to the wrapped data provider. Will not
+     * be called if the configured filter is <code>null</code> and the query has
+     * no filter.
+     * 
+     * @param queryFilter
+     *            the filter received through the query, or <code>null</code> if
+     *            no filter was provided in the query
      * @param configuredFilter
      *            the filter that this data provider is configured to use, or
      *            <code>null</code> if no filter has been configured
-     * @param queryFilter
-     *            the filter received through the query, not <code>null</code>
      * @return a filter that combines the two provided queries, or
      *         <code>null</code> to not pass any filter to the wrapped data
      *         provider
      */
-    protected abstract C combineFilters(C configuredFilter, Q queryFilter);
+    protected abstract F combineFilters(Q queryFilter, C configuredFilter);
 
     @Override
     public void setFilter(C filter) {
index e641f0d05766222f2e33ca7c244f331be42e7d16..380a1f48097deed836daa44151823ccf039e1456 100644 (file)
@@ -163,17 +163,18 @@ public interface DataProvider<T, F> extends Serializable {
      * @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. Will only be called if the query contains a filter.
-     *            Not <code>null</code>
+     *            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 <C> ConfigurableFilterDataProvider<T, C, F> withConfigurableFilter(
-            SerializableBiFunction<F, C, F> filterCombiner) {
-        return new ConfigurableFilterDataProviderWrapper<T, C, F>(this) {
+    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(F configuredFilter, C queryFilter) {
-                return filterCombiner.apply(configuredFilter, queryFilter);
+            protected F combineFilters(Q queryFilter, C configuredFilter) {
+                return filterCombiner.apply(queryFilter, configuredFilter);
             }
         };
     }
@@ -188,7 +189,7 @@ public interface DataProvider<T, F> extends Serializable {
      * @return a data provider with a configurable filter, not <code>null</code>
      */
     public default ConfigurableFilterDataProvider<T, Void, F> withConfigurableFilter() {
-        return withConfigurableFilter((configuredFilter, queryFilter) -> {
+        return withConfigurableFilter((queryFilter, configuredFilter) -> {
             assert queryFilter == null : "Filter from Void query must be null";
 
             return configuredFilter;
index 115e4fd6bd99e0ac20efc42e0615293f991561a6..b2be27bd8d9cc2ace32bb8190c14bcfd50274821 100644 (file)
@@ -29,13 +29,19 @@ public class ConfigurableFilterDataProviderWrapperTest {
             StrBean.generateRandomBeans(100));
     private ConfigurableFilterDataProvider<StrBean, Void, SerializablePredicate<StrBean>> configurableVoid = backEndProvider
             .withConfigurableFilter();
-    private ConfigurableFilterDataProvider<StrBean, SerializablePredicate<StrBean>, SerializablePredicate<StrBean>> configurablePredicate = backEndProvider
-            .withConfigurableFilter((configuredFilter, queryFilter) -> item -> {
-                if (configuredFilter != null && !configuredFilter.test(item)) {
+    private ConfigurableFilterDataProvider<StrBean, String, Integer> configurablePredicate = backEndProvider
+            .withConfigurableFilter((queryFilter, configuredFilter) -> item -> {
+                if (queryFilter != null
+                        && !item.getValue().equals(queryFilter)) {
                     return false;
                 }
 
-                return queryFilter.test(item);
+                if (configuredFilter != null
+                        && item.getId() < configuredFilter.intValue()) {
+                    return false;
+                }
+
+                return true;
             });
 
     @Test
@@ -60,9 +66,9 @@ public class ConfigurableFilterDataProviderWrapperTest {
 
     @Test
     public void predicate_setFilter() {
-        configurablePredicate.setFilter(xyzFilter);
+        configurablePredicate.setFilter(Integer.valueOf(50));
 
-        Assert.assertEquals("Set filter should be used", 1,
+        Assert.assertEquals("Set filter should be used", 49,
                 configurablePredicate.size(new Query<>()));
 
         configurablePredicate.setFilter(null);
@@ -74,7 +80,7 @@ public class ConfigurableFilterDataProviderWrapperTest {
     @Test
     public void predicate_queryFilter() {
         Assert.assertEquals("Query filter should be used", 1,
-                configurablePredicate.size(new Query<>(xyzFilter)));
+                configurablePredicate.size(new Query<>("Xyz")));
 
         Assert.assertEquals("null query filter should return all items", 100,
                 configurablePredicate.size(new Query<>()));
@@ -82,15 +88,15 @@ public class ConfigurableFilterDataProviderWrapperTest {
 
     @Test
     public void predicate_combinedFilters() {
-        configurablePredicate.setFilter(item -> item.getValue().equals("Foo"));
+        configurablePredicate.setFilter(Integer.valueOf(50));
 
         Assert.assertEquals("Both filters should be used", 0,
-                configurablePredicate.size(new Query<>(xyzFilter)));
+                configurablePredicate.size(new Query<>("Xyz")));
 
         configurablePredicate.setFilter(null);
 
         Assert.assertEquals("Only zyz filter should be used", 1,
-                configurablePredicate.size(new Query<>(xyzFilter)));
+                configurablePredicate.size(new Query<>("Xyz")));
     }
 
 }