Author: hlship
Date: Mon May 31 17:55:51 2010
New Revision: 949821
URL: http://svn.apache.org/viewvc?rev=949821&view=rev
Log:
Add method mapcat() to the Flow interface
Modified:
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/AbstractFlow.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/ConcatFlow.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/EmptyFlow.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/Flow.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/MappedFlow.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/func/FuncTest.java
Modified:
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/AbstractFlow.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/AbstractFlow.java?rev=949821&r1=949820&r2=949821&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/AbstractFlow.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/AbstractFlow.java
Mon May 31 17:55:51 2010
@@ -140,6 +140,22 @@ abstract class AbstractFlow<T> implement
return accumulator;
}
+ public <X> Flow<X> mapcat(Mapper<T, Flow<X>> mapper)
+ {
+ Flow<Flow<X>> flows = map(mapper);
+
+ if (flows.isEmpty())
+ return F.emptyFlow();
+
+ return flows.rest().reduce(new Reducer<Flow<X>, Flow<X>>()
+ {
+ public Flow<X> reduce(Flow<X> accumulator, Flow<X> value)
+ {
+ return accumulator.concat(value);
+ }
+ }, flows.first());
+ }
+
public Flow<T> remove(Predicate<? super T> predicate)
{
Defense.notNull(predicate, "predicate");
Modified:
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/ConcatFlow.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/ConcatFlow.java?rev=949821&r1=949820&r2=949821&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/ConcatFlow.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/ConcatFlow.java
Mon May 31 17:55:51 2010
@@ -22,6 +22,7 @@ package org.apache.tapestry5.func;
*/
class ConcatFlow<T> extends AbstractFlow<T>
{
+ // All instance variables are guarded by this
private Flow<T> firstFlow;
private Flow<T> secondFlow;
Modified:
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/EmptyFlow.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/EmptyFlow.java?rev=949821&r1=949820&r2=949821&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/EmptyFlow.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/EmptyFlow.java
Mon May 31 17:55:51 2010
@@ -59,10 +59,9 @@ class EmptyFlow<T> extends AbstractFlow<
}
/** Does nothing; returns this empty list (as a Flow<X>). */
- @SuppressWarnings("unchecked")
public <X> Flow<X> map(Mapper<T, X> mapper)
{
- return (Flow<X>) this;
+ return F.emptyFlow();
}
/** Does nothing; returns the initial value. */
@@ -102,4 +101,9 @@ class EmptyFlow<T> extends AbstractFlow<
return (Flow<T>) other;
}
+ public <X> Flow<X> mapcat(Mapper<T, Flow<X>> mapper)
+ {
+ return F.emptyFlow();
+ }
+
}
Modified:
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/Flow.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/Flow.java?rev=949821&r1=949820&r2=949821&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/Flow.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/Flow.java
Mon May 31 17:55:51 2010
@@ -36,6 +36,12 @@ public interface Flow<T> extends Iterabl
<X> Flow<X> map(Mapper<T, X> mapper);
/**
+ * Given a {...@link Mapper} that maps a T to a Flow<X>, this method will
lazily concatenate
+ * all the output flows into a single Flow<X>.
+ */
+ <X> Flow<X> mapcat(Mapper<T, Flow<X>> mapper);
+
+ /**
* Filters values, keeping only values where the predicate is true,
returning a new Flow with just
* the retained values.
*/
Modified:
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/MappedFlow.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/MappedFlow.java?rev=949821&r1=949820&r2=949821&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/MappedFlow.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/MappedFlow.java
Mon May 31 17:55:51 2010
@@ -24,6 +24,7 @@ class MappedFlow<T, X> extends AbstractF
private final Mapper<T, X> mapper;
// Used to determine first, rest
+ // Guarded by this
private Flow<T> mappedFlow;
// Guarded by this
Modified:
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/func/FuncTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/func/FuncTest.java?rev=949821&r1=949820&r2=949821&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/func/FuncTest.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/func/FuncTest.java
Mon May 31 17:55:51 2010
@@ -588,4 +588,36 @@ public class FuncTest extends TestUtils
}
}, initial), initial);
}
+
+ private Mapper<Integer, Flow<Integer>> sequencer = new Mapper<Integer,
Flow<Integer>>()
+ {
+
+ public Flow<Integer> map(Integer value)
+ {
+ Flow<Integer> flow = F.flow();
+
+ for (int i = 0; i < value; i++)
+ flow = flow.append(value);
+
+ return flow;
+ }
+ };
+
+ @Test
+ public void mapcat_on_empty_flow_is_empty()
+ {
+ Flow<Integer> flow = F.flow();
+
+ assertSame(flow.mapcat(sequencer), flow);
+
+ assertTrue(filteredEmpty.mapcat(sequencer).isEmpty());
+ }
+
+ @Test
+ public void mapcat()
+ {
+ Flow<Integer> flow = F.flow(3, 1, 2);
+
+ assertListsEquals(flow.mapcat(sequencer).toList(), 3, 3, 3, 1, 2, 2);
+ }
}