diff options
author | Leif Åstrand <legioth@gmail.com> | 2017-05-18 16:11:58 +0300 |
---|---|---|
committer | Pekka Hyvönen <pekka@vaadin.com> | 2017-05-18 16:11:58 +0300 |
commit | 23d65678faf5b0ae59b380d7dbc86e0f9db858cf (patch) | |
tree | 3f8e2a39ed0e24e1569f04bbba15c59b8ef43ea2 | |
parent | 88429109c2f8e77fb3a9ef7b5ab51d51e7dcaa58 (diff) | |
download | vaadin-framework-23d65678faf5b0ae59b380d7dbc86e0f9db858cf.tar.gz vaadin-framework-23d65678faf5b0ae59b380d7dbc86e0f9db858cf.zip |
Add stream variants for the child item provider shorthands (#9375)
3 files changed, 86 insertions, 4 deletions
diff --git a/server/src/main/java/com/vaadin/data/HasHierarchicalDataProvider.java b/server/src/main/java/com/vaadin/data/HasHierarchicalDataProvider.java index e43b9d6b77..52ea205663 100644 --- a/server/src/main/java/com/vaadin/data/HasHierarchicalDataProvider.java +++ b/server/src/main/java/com/vaadin/data/HasHierarchicalDataProvider.java @@ -100,6 +100,50 @@ public interface HasHierarchicalDataProvider<T> extends HasDataProvider<T> { } /** + * Sets the root data items of this component provided as a stream and + * recursively populates them with child items with the given value + * provider. + * <p> + * The provided items are wrapped into a {@link TreeDataProvider} backed by + * a flat {@link TreeData} structure. The data provider instance is used as + * a parameter for the {@link #setDataProvider(DataProvider)} method. It + * means that the items collection can be accessed later on via + * {@link #getTreeData()}: + * + * <pre> + * <code> + * Stream<Person> grandParents = getGrandParents(); + * HasHierarchicalDataProvider<Person> treeGrid = new TreeGrid<>(); + * treeGrid.setItems(grandParents, Person::getChildren); + * ... + * + * TreeData<Person> data = treeGrid.getTreeData(); + * </code> + * </pre> + * <p> + * The returned {@link TreeData} instance may be used as-is to add, remove + * or modify items in the hierarchy. These modifications to the object are + * not automatically reflected back to the TreeGrid. Items modified should + * be refreshed with {@link HierarchicalDataProvider#refreshItem(Object)} + * and when adding or removing items + * {@link HierarchicalDataProvider#refreshAll()} should be called. + * + * @param rootItems + * the root items to display, not {@code null} + * @param childItemProvider + * the value provider used to recursively populate the given root + * items with child items, not {@code null} + */ + public default void setItems(Stream<T> rootItems, + ValueProvider<T, Stream<T>> childItemProvider) { + Objects.requireNonNull(rootItems, "Given root items may not be null"); + Objects.requireNonNull(childItemProvider, + "Given child item provider may not be null"); + setDataProvider(new TreeDataProvider<>( + new TreeData<T>().addItems(rootItems, childItemProvider))); + } + + /** * Sets the data items of this component provided as a collection. * <p> * The provided items are wrapped into a {@link TreeDataProvider} backed by diff --git a/server/src/main/java/com/vaadin/data/TreeData.java b/server/src/main/java/com/vaadin/data/TreeData.java index f5f9709462..2311a71984 100644 --- a/server/src/main/java/com/vaadin/data/TreeData.java +++ b/server/src/main/java/com/vaadin/data/TreeData.java @@ -23,6 +23,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; import java.util.stream.Stream; import com.vaadin.data.provider.TreeDataProvider; @@ -227,6 +228,25 @@ public class TreeData<T> implements Serializable { } /** + * Adds the given items as root items and uses the given value provider to + * recursively populate children of the root items. + * + * @param rootItems + * the root items to add + * @param childItemProvider + * the value provider used to recursively populate this TreeData + * from the given root items + * @return this + */ + public TreeData<T> addItems(Stream<T> rootItems, + ValueProvider<T, Stream<T>> childItemProvider) { + // Must collect to lists since the algorithm iterates multiple times + return addItems(rootItems.collect(Collectors.toList()), + item -> childItemProvider.apply(item) + .collect(Collectors.toList())); + } + + /** * Remove a given item from this structure. Additionally, this will * recursively remove any descendants of the item. * diff --git a/server/src/test/java/com/vaadin/data/provider/TreeDataProviderTest.java b/server/src/test/java/com/vaadin/data/provider/TreeDataProviderTest.java index 3f9f1f6e94..f0b2d5f81f 100644 --- a/server/src/test/java/com/vaadin/data/provider/TreeDataProviderTest.java +++ b/server/src/test/java/com/vaadin/data/provider/TreeDataProviderTest.java @@ -5,6 +5,7 @@ import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.junit.Assert; import org.junit.Test; @@ -12,8 +13,8 @@ import org.junit.Test; import com.vaadin.data.TreeData; import com.vaadin.server.SerializablePredicate; -public class TreeDataProviderTest extends - DataProviderTestBase<TreeDataProvider<StrBean>> { +public class TreeDataProviderTest + extends DataProviderTestBase<TreeDataProvider<StrBean>> { private TreeData<StrBean> data; private List<StrBean> flattenedData; @@ -46,8 +47,7 @@ public class TreeDataProviderTest extends @Test(expected = IllegalArgumentException.class) public void treeData_add_item_parent_not_in_hierarchy_throws() { - new TreeData<>().addItem(new StrBean("", 0, 0), - new StrBean("", 0, 0)); + new TreeData<>().addItem(new StrBean("", 0, 0), new StrBean("", 0, 0)); } @Test(expected = NullPointerException.class) @@ -99,6 +99,24 @@ public class TreeDataProviderTest extends } @Test + public void populate_treeData_with_stream_child_item_provider() { + TreeData<String> stringData = new TreeData<>(); + Stream<String> rootItems = Stream.of("a", "b", "c"); + stringData.addItems(rootItems, item -> { + if (item.length() >= 3 || item.startsWith("c")) { + return Stream.empty(); + } + return Stream.of(item + "/a", item + "/b", item + "/c"); + }); + Assert.assertEquals(stringData.getChildren("a"), + Arrays.asList("a/a", "a/b", "a/c")); + Assert.assertEquals(stringData.getChildren("b"), + Arrays.asList("b/a", "b/b", "b/c")); + Assert.assertEquals(stringData.getChildren("c"), Arrays.asList()); + Assert.assertEquals(stringData.getChildren("a/b"), Arrays.asList()); + } + + @Test public void setFilter() { getDataProvider().setFilter(item -> item.getValue().equals("Xyz") || item.getValue().equals("Baz")); |