]> source.dussan.org Git - vaadin-framework.git/commitdiff
Add stream variants for the child item provider shorthands (#9375)
authorLeif Åstrand <legioth@gmail.com>
Thu, 18 May 2017 13:11:58 +0000 (16:11 +0300)
committerPekka Hyvönen <pekka@vaadin.com>
Thu, 18 May 2017 13:11:58 +0000 (16:11 +0300)
server/src/main/java/com/vaadin/data/HasHierarchicalDataProvider.java
server/src/main/java/com/vaadin/data/TreeData.java
server/src/test/java/com/vaadin/data/provider/TreeDataProviderTest.java

index e43b9d6b77f6ddabfa9e4a69e8d7f52b07228454..52ea205663a08363722a0809d1bc999df796fd92 100644 (file)
@@ -99,6 +99,50 @@ public interface HasHierarchicalDataProvider<T> extends HasDataProvider<T> {
                 new TreeData<T>().addItems(rootItems, childItemProvider)));
     }
 
+    /**
+     * 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>
index f5f970946219242b6b878c2dd2f41e4fd64b90b0..2311a71984f1c915be9b5ad5013293c6672a032b 100644 (file)
@@ -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;
@@ -226,6 +227,25 @@ public class TreeData<T> implements Serializable {
         return this;
     }
 
+    /**
+     * 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.
index 3f9f1f6e949c6fcb549a5cf8728d2ac10f6f64b7..f0b2d5f81f0adff261327e35d6866b59ee4a5bd2 100644 (file)
@@ -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)
@@ -98,6 +98,24 @@ public class TreeDataProviderTest extends
         Assert.assertEquals(stringData.getChildren("a/b"), Arrays.asList());
     }
 
+    @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")