summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <teemusa@vaadin.com>2016-11-25 16:06:22 +0200
committerIlia Motornyi <elmot@vaadin.com>2016-11-28 15:18:00 +0000
commit8310ada79e04d47e2118394b3c00a4fc90bd2fe4 (patch)
tree4473d1cd7503132fff8cae9ad57600f3a4100510 /server
parent302f870e302e9d8324e7cc6e8a5b6db41038db0a (diff)
downloadvaadin-framework-8310ada79e04d47e2118394b3c00a4fc90bd2fe4.tar.gz
vaadin-framework-8310ada79e04d47e2118394b3c00a4fc90bd2fe4.zip
Add ComboBox custom filtering methods and tests
Change-Id: I640c6a7b3b8b89eff4b007d1cb70a25bbe28167e
Diffstat (limited to 'server')
-rw-r--r--server/src/main/java/com/vaadin/server/SerializableBiPredicate.java34
-rw-r--r--server/src/main/java/com/vaadin/ui/ComboBox.java45
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxFilteringTest.java181
3 files changed, 260 insertions, 0 deletions
diff --git a/server/src/main/java/com/vaadin/server/SerializableBiPredicate.java b/server/src/main/java/com/vaadin/server/SerializableBiPredicate.java
new file mode 100644
index 0000000000..dd0635ca9d
--- /dev/null
+++ b/server/src/main/java/com/vaadin/server/SerializableBiPredicate.java
@@ -0,0 +1,34 @@
+/*
+ * 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.server;
+
+import java.io.Serializable;
+import java.util.function.BiPredicate;
+
+/**
+ * A {@link BiPredicate} that is also {@link Serializable}.
+ *
+ * @author Vaadin Ltd
+ * @since 8.0
+ * @param <T>
+ * the type of the first input to the predicate
+ * @param <U>
+ * the type of the second input to the predicate
+ */
+public interface SerializableBiPredicate<T, U>
+ extends BiPredicate<T, U>, Serializable {
+ // Only method inherited from Function
+}
diff --git a/server/src/main/java/com/vaadin/ui/ComboBox.java b/server/src/main/java/com/vaadin/ui/ComboBox.java
index 2b91236843..9399e1b129 100644
--- a/server/src/main/java/com/vaadin/ui/ComboBox.java
+++ b/server/src/main/java/com/vaadin/ui/ComboBox.java
@@ -39,6 +39,7 @@ import com.vaadin.event.FieldEvents.FocusListener;
import com.vaadin.server.KeyMapper;
import com.vaadin.server.Resource;
import com.vaadin.server.ResourceReference;
+import com.vaadin.server.SerializableBiPredicate;
import com.vaadin.server.data.DataCommunicator;
import com.vaadin.server.data.DataKeyMapper;
import com.vaadin.server.data.DataProvider;
@@ -255,6 +256,50 @@ public class ComboBox<T> extends AbstractSingleSelect<T>
}
/**
+ * Sets the data items of this listing and a simple string filter with which
+ * the item string and the text the user has input are compared.
+ * <p>
+ * Note that unlike {@link #setItems(Collection)}, no automatic case
+ * conversion is performed before the comparison.
+ *
+ * @param filterPredicate
+ * predicate for comparing the item string (first parameter) and
+ * the filter string (second parameter)
+ * @param items
+ * the data items to display
+ */
+ public void setItems(
+ SerializableBiPredicate<String, String> filterPredicate,
+ Collection<T> items) {
+ DataProvider<T, String> provider = DataProvider.create(items)
+ .convertFilter(filterText -> item -> filterPredicate.test(
+ getItemCaptionGenerator().apply(item), filterText));
+ setDataProvider(provider);
+ }
+
+ /**
+ * Sets the data items of this listing and a simple string filter with which
+ * the item string and the text the user has input are compared.
+ * <p>
+ * Note that unlike {@link #setItems(Collection)}, no automatic case
+ * conversion is performed before the comparison.
+ *
+ * @param filterPredicate
+ * predicate for comparing the item string (first parameter) and
+ * the filter string (second parameter)
+ * @param items
+ * the data items to display
+ */
+ public void setItems(
+ SerializableBiPredicate<String, String> filterPredicate,
+ @SuppressWarnings("unchecked") T... items) {
+ DataProvider<T, String> provider = DataProvider.create(items)
+ .convertFilter(filterText -> item -> filterPredicate.test(
+ getItemCaptionGenerator().apply(item), filterText));
+ setDataProvider(provider);
+ }
+
+ /**
* Gets the current placeholder text shown when the combo box would be
* empty.
*
diff --git a/server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxFilteringTest.java b/server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxFilteringTest.java
new file mode 100644
index 0000000000..54ea367fca
--- /dev/null
+++ b/server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxFilteringTest.java
@@ -0,0 +1,181 @@
+/*
+ * 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.tests.server.component.combobox;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.server.data.DataProvider;
+import com.vaadin.server.data.ListDataProvider;
+import com.vaadin.server.data.Query;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.tests.data.bean.Sex;
+import com.vaadin.ui.ComboBox;
+
+/**
+ * Test for ComboBox data providers and filtering.
+ *
+ * @author Vaadin Ltd
+ */
+public class ComboBoxFilteringTest {
+ private static final String[] PERSON_NAMES = new String[] {
+ "Enrique Iglesias", "Henry Dunant", "Erwin Engelbrecht" };
+
+ private ComboBox<Person> comboBox;
+
+ @Before
+ public void setup() {
+ comboBox = new ComboBox<>();
+ comboBox.setLocale(Locale.US);
+ }
+
+ @Test
+ public void setItems_array_defaultFiltering() {
+ comboBox.setItemCaptionGenerator(Person::getFirstName);
+
+ // Result: typing "en" into the search field finds "Enrique Iglesias"
+ // and "Henry Dunant", but not "Erwin Engelbrecht"
+ comboBox.setItems(getPersonArray());
+
+ checkFiltering("en", "ennen", 3, 2);
+ }
+
+ @Test
+ public void setItems_array_setItemCaptionAfterItems() {
+ // Result: typing "en" into the search field finds "Enrique Iglesias"
+ // and "Henry Dunant", but not "Erwin Engelbrecht"
+ comboBox.setItems(getPersonArray());
+
+ // It shouldn't matter if this is done before or after setItems
+ comboBox.setItemCaptionGenerator(Person::getFirstName);
+
+ checkFiltering("en", "ennen", 3, 2);
+ }
+
+ @Test
+ public void setItems_collection_defaultFiltering() {
+ comboBox.setItemCaptionGenerator(Person::getFirstName);
+
+ // Result: typing "en" into the search field finds "Enrique Iglesias"
+ // and "Henry Dunant", but not "Erwin Engelbrecht"
+ comboBox.setItems(getPersonCollection());
+
+ checkFiltering("en", "ennen", 3, 2);
+ }
+
+ @Test
+ public void setItems_collection_setItemCaptionAfterItems() {
+ // Result: typing "en" into the search field finds "Enrique Iglesias"
+ // and "Henry Dunant", but not "Erwin Engelbrecht"
+ comboBox.setItems(getPersonCollection());
+
+ // It shouldn't matter if this is done before or after setItems
+ comboBox.setItemCaptionGenerator(Person::getFirstName);
+
+ checkFiltering("en", "ennen", 3, 2);
+ }
+
+ @Test
+ public void setItems_array_customFiltering() {
+ comboBox.setItemCaptionGenerator(Person::getFirstName);
+
+ // Result: typing "en" into the search field finds "Enrique Iglesias"
+ // and "Henry Dunant", but not "Erwin Engelbrecht"
+ comboBox.setItems(String::startsWith, getPersonArray());
+
+ checkFiltering("Er", "er", 3, 1);
+ }
+
+ @Test
+ public void setItems_collection_customFiltering() {
+ comboBox.setItemCaptionGenerator(Person::getFirstName);
+
+ // Result: typing "en" into the search field finds "Enrique Iglesias"
+ // and "Henry Dunant", but not "Erwin Engelbrecht"
+ comboBox.setItems(String::startsWith, getPersonCollection());
+
+ checkFiltering("Er", "er", 3, 1);
+ }
+
+ public void invalid_dataProvider_compile_error() {
+ // uncommenting this causes a compile time error
+ ListDataProvider<Person> ldp = DataProvider.create(getPersonArray());
+ // Compile error, because of invalid data provider filter type
+ // comboBox.setDataProvider(ldp);
+ }
+
+ @Test
+ public void customDataProvider_filterByLastName() {
+ comboBox.setItemCaptionGenerator(Person::getFirstName);
+
+ // Filters by last name, regardless of the item caption generator
+ ListDataProvider<Person> ldp = DataProvider.create(getPersonArray());
+ comboBox.setDataProvider(ldp.convertFilter(
+ text -> person -> person.getLastName().contains(text)));
+
+ checkFiltering("u", "ab", 3, 1);
+ }
+
+ @Test
+ public void customDataProvider_filterByLastNameWithAccessRestriction() {
+ comboBox.setItemCaptionGenerator(Person::getFirstName);
+
+ // Filters by last name, regardless of the item caption generator
+ ListDataProvider<Person> ldp = DataProvider.create(getPersonArray());
+ // Same as above, but only showing a subset of the persons
+ comboBox.setDataProvider(ldp
+ .applyFilter(person -> person.getFirstName().contains("nr"))
+ .convertFilter(
+ text -> person -> person.getLastName().contains(text)));
+
+ checkFiltering("t", "Engel", 2, 1);
+ }
+
+ private void checkFiltering(String filterText, String nonMatchingFilterText,
+ int totalMatches, int matchingResults) {
+ DataProvider<Person, String> dataProvider = comboBox.getDataProvider();
+
+ Assert.assertEquals(
+ "ComboBox filtered out results with no filter applied",
+ totalMatches, dataProvider.size(new Query<String>()));
+ Assert.assertEquals(
+ "ComboBox filtered out results with empty filter string",
+ totalMatches, dataProvider.size(new Query<String>("")));
+ Assert.assertEquals("ComboBox filtered out wrong number of results",
+ matchingResults,
+ dataProvider.size(new Query<String>(filterText)));
+ Assert.assertEquals(
+ "ComboBox should have no results with a non-matching filter", 0,
+ dataProvider.size(new Query<String>(nonMatchingFilterText)));
+ }
+
+ private List<Person> getPersonCollection() {
+ return Stream
+ .of(PERSON_NAMES).map(name -> new Person(name.split(" ")[0],
+ name.split(" ")[1], null, 0, Sex.MALE, null))
+ .collect(Collectors.toList());
+ }
+
+ private Person[] getPersonArray() {
+ return getPersonCollection().toArray(new Person[PERSON_NAMES.length]);
+ }
+}