You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by ad...@apache.org on 2015/12/01 12:51:23 UTC

[4/4] wicket git commit: Introduced MarkupContainer#childrenStream to leverage Java 8 Stream when accessing children components

Introduced MarkupContainer#childrenStream to leverage Java 8 Stream when accessing children components


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/73ac8c7e
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/73ac8c7e
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/73ac8c7e

Branch: refs/heads/lambdas
Commit: 73ac8c7e6da3ff9dd0244ad66c63944ba3d64c78
Parents: c70c0a2
Author: Andrea Del Bene <ad...@apache.org>
Authored: Tue Dec 1 12:49:22 2015 +0100
Committer: Andrea Del Bene <ad...@apache.org>
Committed: Tue Dec 1 12:49:49 2015 +0100

----------------------------------------------------------------------
 .../java/org/apache/wicket/MarkupContainer.java | 17 +++++
 .../org/apache/wicket/MarkupContainerTest.java  | 39 ++++++++++-
 .../org/apache/wicket/util/NestedIterator.java  | 70 ++++++++++++++++++++
 3 files changed, 125 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/73ac8c7e/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
index 916b994..fb2cf1f 100644
--- a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
+++ b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
@@ -24,6 +24,8 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 import org.apache.commons.collections4.map.LinkedMap;
 import org.apache.wicket.core.util.string.ComponentStrings;
@@ -43,6 +45,7 @@ import org.apache.wicket.model.IComponentInheritedModel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.IWrapModel;
 import org.apache.wicket.settings.DebugSettings;
+import org.apache.wicket.util.NestedIterator;
 import org.apache.wicket.util.lang.Args;
 import org.apache.wicket.util.lang.Classes;
 import org.apache.wicket.util.lang.Generics;
@@ -2191,4 +2194,18 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp
 	{
 		add(component);
 	}
+	
+	/**
+	 * Creates a {@code java.util.stream.Stream} returning all the children (included nested ones)
+	 * of the this container.
+	 * 
+	 * @return a stream returning children.
+	 */
+	public Stream<Component> childrenStream()
+	{
+		NestedIterator<Component> nestedIterator = new NestedIterator<>(this);
+		Iterable<Component> iterable = () -> nestedIterator;
+		
+		return StreamSupport.stream(iterable.spliterator(), false);
+	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/73ac8c7e/wicket-core/src/test/java/org/apache/wicket/MarkupContainerTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/MarkupContainerTest.java b/wicket-core/src/test/java/org/apache/wicket/MarkupContainerTest.java
index aba2148..1bea201 100644
--- a/wicket-core/src/test/java/org/apache/wicket/MarkupContainerTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/MarkupContainerTest.java
@@ -29,6 +29,7 @@ import java.util.ConcurrentModificationException;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Random;
+import java.util.stream.Stream;
 
 import org.apache.commons.collections4.map.LinkedMap;
 import org.apache.wicket.core.util.lang.WicketObjects;
@@ -37,6 +38,7 @@ import org.apache.wicket.markup.html.WebComponent;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.panel.EmptyPanel;
 import org.apache.wicket.util.resource.IResourceStream;
 import org.apache.wicket.util.resource.StringResourceStream;
@@ -1208,7 +1210,42 @@ public class MarkupContainerTest extends WicketTestCase
 		assertThat(iterator1.hasNext(), is(false));
 		assertThat(iterator2.hasNext(), is(false));
 	}
-
+	
+	@Test
+	public void testStreamOfChildren() throws Exception
+	{
+		WebMarkupContainer wmc = new WebMarkupContainer("id");
+		WebMarkupContainer container = new WebMarkupContainer("container");
+		addNChildren(wmc, 10);
+		
+		wmc.add(container);
+		container.add(new Form<>("form"));
+		
+		long wmcNumber = filterChildrenStreamByClass(wmc, WebMarkupContainer.class).count();
+		assertEquals(2l, wmcNumber);
+		
+		long formNumber = filterChildrenStreamByClass(wmc, Form.class).count();
+		assertEquals(1l, formNumber);
+		
+		long labelNumber = filterChildrenStreamByClass(wmc, Label.class).count();
+		assertEquals(10l, labelNumber);
+	}
+	
+	/**
+	 * Returns a stream containg only children components who are instance of 
+	 * <code>filterClass</code>.
+	 * 
+	 * @param container
+	 * 			the parent markup container
+	 * @param filterClass
+	 * 			the component class to use as filter
+	 * @return a stream containg only children who are instance of param <code>filterClass</code>
+	 */
+	private Stream<Component> filterChildrenStreamByClass(MarkupContainer container, Class<? extends Component> filterClass)
+	{
+		return container.childrenStream().filter(filterClass::isInstance);
+	}
+	
 	/**
 	 * Asserts that the children property of the {@code wmc} is of a particular {@code type}.
 	 * 

http://git-wip-us.apache.org/repos/asf/wicket/blob/73ac8c7e/wicket-util/src/main/java/org/apache/wicket/util/NestedIterator.java
----------------------------------------------------------------------
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/NestedIterator.java b/wicket-util/src/main/java/org/apache/wicket/util/NestedIterator.java
new file mode 100644
index 0000000..f2526db
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/NestedIterator.java
@@ -0,0 +1,70 @@
+package org.apache.wicket.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Iterator;
+
+/**
+ * Wrapper class for {@link java.util.Iterator} meant to recursively
+ * iterate over its elements if they are iterable.
+ * 
+ * @author Andrea Del Bene
+ */
+public class NestedIterator<E> implements Iterator<E>
+{
+	private Iterator<E> currentIterator;
+	private Deque<Iterator<E>> iteratorStack = new ArrayDeque<>();
+	
+	public NestedIterator(Iterator<E> currentIterator)
+	{
+		this.currentIterator = currentIterator;
+	}
+	
+	public NestedIterator(Iterable<E> iterable)
+	{
+		this(iterable.iterator());
+	}
+
+	@Override
+	public boolean hasNext()
+	{
+		if (!currentIterator.hasNext() && !iteratorStack.isEmpty())
+		{
+			currentIterator = iteratorStack.pop();
+		}
+		
+		return currentIterator.hasNext();
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public E next()
+	{
+		E nextElement = currentIterator.next();
+		
+		if (nextElement instanceof Iterable)
+		{
+			iteratorStack.push(currentIterator);
+			currentIterator = ((Iterable<E>)nextElement).iterator();
+		}
+		
+		return nextElement;
+	}
+
+}