+++ /dev/null
-/*
- * 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.util.Objects;
-
-/**
- * Interface for DataProviders that support chaining filters.
- *
- * @author Vaadin Ltd
- * @since 8.0
- *
- * @param <T>
- * the data provider data type
- * @param <F>
- * the data provider filter type
- */
-public interface AppendableFilterDataProvider<T, F> extends DataProvider<T, F> {
-
- /**
- * Applies a filter to the current chain of filters in this data provider.
- *
- * @param filter
- * the applied filter; not {@code null}
- * @return new data provider with the filter applied
- */
- @Override
- public default AppendableFilterDataProvider<T, F> withFilter(F filter) {
- Objects.requireNonNull(filter, "The applied filter can't be null");
- return DataProviderWrapper.chain(this, filter);
- }
-
- /**
- * Combines two filters into one.
- *
- * @param filter1
- * the base filter; not {@code null}
- * @param filter2
- * the filter to merge to the base filter; not {@code null}
- * @return combined filter; not {@code null}
- */
- public F combineFilters(F filter1, F filter2);
-
-}
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import com.vaadin.data.HasDataProvider;
+import com.vaadin.data.HasFilterableDataProvider;
import com.vaadin.server.SerializableFunction;
import com.vaadin.shared.Registration;
*/
Registration addDataProviderListener(DataProviderListener listener);
- /**
- * Returns a new wrapped data provider with given default filter. Default
- * filter will apply to each query and further filtering will not be
- * supported in the wrapped data provider.
- *
- * @param filter
- * the default filter
- * @return wrapped data provider with provided filter
- */
- public default DataProvider<T, ?> withFilter(F filter) {
- Objects.requireNonNull(filter, "Filter can't be null");
- return DataProviderWrapper.filter(this, filter);
- }
-
/**
* Convert the data provider to use a different filter type. It is used for
* adapting this data provider to a filter type provided by a Component such
public abstract class DataProviderWrapper<T, F, M>
implements DataProvider<T, F> {
- /**
- * Variant of data provider wrapper that supports chaining filters.
- *
- * @param <T>
- * the data provider data type
- * @param <F>
- * the data provider filter type
- */
- protected abstract static class AppendableFilterDataProviderWrapper<T, F>
- extends DataProviderWrapper<T, F, F>
- implements AppendableFilterDataProvider<T, F> {
-
- /**
- * Constructs a filtering wrapper for a data provider with filter
- * chaining.
- *
- * @param dataProvider
- * the wrapped data provider
- */
- protected AppendableFilterDataProviderWrapper(
- AppendableFilterDataProvider<T, F> dataProvider) {
- super(dataProvider);
- }
-
- @Override
- public F combineFilters(F filter1, F filter2) {
- return ((AppendableFilterDataProvider<T, F>) dataProvider)
- .combineFilters(filter1, filter2);
- }
- }
-
/**
* The actual data provider behind this wrapper.
*/
*/
protected abstract M getFilter(Query<T, F> query);
- /**
- * Creates a data provider wrapper with a static filter set to each Query.
- * This {@code DataProvider} will deliberately ignore any possible filters
- * from the Query.
- *
- * @see DataProvider#withFilter(Object)
- *
- * @param dataProvider
- * the underlying data provider
- * @param filter
- * the static filter for each query
- *
- * @param <T>
- * data provider data type
- * @param <F>
- * query filter type
- *
- * @return wrapped data provider with static filter
- */
- public static <T, F> DataProvider<T, Void> filter(
- DataProvider<T, F> dataProvider, F filter) {
- return new DataProviderWrapper<T, Void, F>(dataProvider) {
-
- @Override
- protected F getFilter(Query<T, Void> query) {
- assert !query.getFilter()
- .isPresent() : "A filter is provided to a data provider that should be unfilterable";
- return filter;
- }
- };
- }
-
/**
* Creates a data provider wrapper with filter type mapping. The mapper
* function will be applied to a query filter if it is present.
}
};
}
-
- /**
- * Creates a data provider wrapper with a chained filter. The filter will be
- * combined to existing filters using
- * {@link AppendableFilterDataProvider#combineFilters(Object, Object)}.
- *
- * @param dataProvider
- * the underlying data provider
- * @param filter
- * the chained filter
- *
- * @param <T>
- * data provider data type
- * @param <F>
- * query filter type
- * @return wrapped data provider with chained filter
- */
- public static <T, F> AppendableFilterDataProvider<T, F> chain(
- AppendableFilterDataProvider<T, F> dataProvider, F filter) {
- return new AppendableFilterDataProviderWrapper<T, F>(dataProvider) {
-
- @Override
- protected F getFilter(Query<T, F> query) {
- return query.getFilter().map(f -> combineFilters(filter, f))
- .orElse(filter);
- }
- };
- }
}
* data type
*/
public class ListDataProvider<T>
- extends AbstractDataProvider<T, SerializablePredicate<T>>
- implements AppendableFilterDataProvider<T, SerializablePredicate<T>>,
+ extends AbstractDataProvider<T, SerializablePredicate<T>> implements
ConfigurableFilterDataProvider<T, SerializablePredicate<T>, SerializablePredicate<T>> {
private static final SerializableSupplier<Locale> CURRENT_LOCALE_SUPPLIER = () -> {
return item -> Objects.equals(valueProvider.apply(item), requiredValue);
}
- @Override
- public SerializablePredicate<T> combineFilters(
- SerializablePredicate<T> filter1,
- 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.
import org.junit.Test;
import com.vaadin.server.SerializableComparator;
-import com.vaadin.server.SerializablePredicate;
import com.vaadin.shared.data.sort.SortDirection;
public class ListDataProviderTest
return DataProvider.create(data);
}
- @Test
- public void filteringListDataProvider_appliedFilters() {
- Assert.assertEquals("Filtering result differ",
- data.stream().filter(fooFilter).count(),
- dataProvider.withFilter(fooFilter).size(new Query<>()));
-
- Assert.assertEquals("Chained filtering result differ",
- data.stream().filter(fooFilter.and(gt5Filter)).count(),
- dataProvider.withFilter(fooFilter)
- .size(new Query<>(gt5Filter)));
- }
-
- @Test
- public void filteringListDataProvider_chainedFilters() {
- Assert.assertEquals("Chained filtering result differ",
- data.stream().filter(fooFilter.and(gt5Filter)).count(),
- dataProvider.withFilter(fooFilter).withFilter(gt5Filter)
- .size(new Query<>()));
- }
-
- @Test
- public void filteringListDataProvider_chainedFiltersWithOrInsteadOfAnd() {
- ListDataProvider<StrBean> orFilteredDataProvider = new ListDataProvider<StrBean>(
- data) {
-
- @Override
- public SerializablePredicate<StrBean> combineFilters(
- SerializablePredicate<StrBean> filter1,
- SerializablePredicate<StrBean> filter2) {
- return t -> filter1.test(t) || filter2.test(t);
- }
- };
-
- Assert.assertEquals("Chained filtering result differ",
- data.stream().filter(fooFilter.or(gt5Filter)).count(),
- orFilteredDataProvider.withFilter(fooFilter)
- .withFilter(gt5Filter).size(new Query<>()));
- }
-
- @Test
- public void filteringListDataProvider_appliedFilterAndConverter() {
- Assert.assertEquals("Filtering result differ with 'Foo'",
- data.stream().filter(gt5Filter.and(fooFilter)).count(),
- dataProvider.withFilter(gt5Filter).convertFilter(
- text -> strBean -> strBean.getValue().equals(text))
- .size(new Query<>("Foo")));
-
- Assert.assertEquals("Filtering result differ with 'Xyz'", data.stream()
- .filter(gt5Filter.and(s -> s.getValue().equals("Xyz"))).count(),
- dataProvider.withFilter(gt5Filter).convertFilter(
- text -> strBean -> strBean.getValue().equals(text))
- .size(new Query<>("Xyz")));
-
- Assert.assertEquals("No results should've been found", 0,
- dataProvider.withFilter(gt5Filter).convertFilter(
- text -> strBean -> strBean.getValue().equals(text))
- .size(new Query<>("Zyx")));
- }
-
@Test
public void setSortByProperty_ascending() {
ListDataProvider<StrBean> dataProvider = getDataProvider();
// Filters by last name, regardless of the item caption generator
ListDataProvider<Person> ldp = DataProvider.create(getPersonArray());
+ ldp.setFilter(person -> person.getFirstName().contains("nr"));
+
// Same as above, but only showing a subset of the persons
- comboBox.setDataProvider(ldp
- .withFilter(person -> person.getFirstName().contains("nr"))
- .convertFilter(
- text -> person -> person.getLastName().contains(text)));
+ comboBox.setDataProvider(ldp.convertFilter(
+ text -> person -> person.getLastName().contains(text)));
checkFiltering("t", "Engel", 2, 1);
}