You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2010/06/03 08:43:58 UTC

svn commit: r950886 - in /tapestry/tapestry5/trunk/tapestry-func/src: main/java/org/apache/tapestry5/func/ test/java/org/apache/tapestry5/func/

Author: hlship
Date: Thu Jun  3 06:43:58 2010
New Revision: 950886

URL: http://svn.apache.org/viewvc?rev=950886&view=rev
Log:
Replace most subclasses of AbstractFlow with a new LazyFlow combined with a LazyFunction (thus isolating virtually all synchronization to a single class, LazyFlow)

Added:
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyConcat.java   (with props)
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyContinuation.java   (with props)
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFilter.java   (with props)
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFlow.java   (contents, props changed)
      - copied, changed from r950828, tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/MappedFlow.java
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFunction.java   (with props)
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyIterate.java   (with props)
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyMapper.java   (with props)
Removed:
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/ConcatFlow.java
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/FilteredFlow.java
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/MappedFlow.java
Modified:
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/AbstractFlow.java
    tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/FuncTest.java

Modified: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/AbstractFlow.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/AbstractFlow.java?rev=950886&r1=950885&r2=950886&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/AbstractFlow.java (original)
+++ tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/AbstractFlow.java Thu Jun  3 06:43:58 2010
@@ -89,9 +89,7 @@ abstract class AbstractFlow<T> implement
 
     public Flow<T> concat(Flow<? extends T> other)
     {
-        // Possible optimization is to check for EmptyFlow here (but not isEmpty(),
-        // so as not to prematurely realize values in the Flow).
-        return new ConcatFlow<T>(this, other);
+        return lazy(new LazyConcat<T>(this, other));
     }
 
     /** Subclasses may override this for efficiency. */
@@ -111,14 +109,19 @@ abstract class AbstractFlow<T> implement
     {
         assert predicate != null;
 
-        return new FilteredFlow<T>(predicate, this);
+        return lazy(new LazyFilter<T>(predicate, this));
+    }
+
+    private static <Y> Flow<Y> lazy(LazyFunction<Y> function)
+    {
+        return new LazyFlow<Y>(function);
     }
 
     public <X> Flow<X> map(Mapper<T, X> mapper)
     {
         assert mapper != null;
 
-        return new MappedFlow<T, X>(mapper, this);
+        return lazy(new LazyMapper<T, X>(mapper, this));
     }
 
     public <A> A reduce(Reducer<A, T> reducer, A initial)

Added: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyConcat.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyConcat.java?rev=950886&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyConcat.java (added)
+++ tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyConcat.java Thu Jun  3 06:43:58 2010
@@ -0,0 +1,41 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.func;
+
+@SuppressWarnings("unchecked")
+class LazyConcat<T> implements LazyFunction<T>
+{
+    private final Flow<T> first, second;
+
+    public LazyConcat(Flow<T> first, Flow<? extends T> second)
+    {
+        this.first = first;
+        this.second = (Flow<T>) second;
+    }
+
+    public LazyContinuation<T> next()
+    {
+        if (first.isEmpty())
+        {
+            if (second.isEmpty())
+                return null;
+
+            return new LazyContinuation<T>(second.first(), new LazyIterate<T>(second.rest()));
+        }
+
+        return new LazyContinuation<T>(first.first(), new LazyConcat<T>(first.rest(), second));
+    }
+
+}

Propchange: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyConcat.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyContinuation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyContinuation.java?rev=950886&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyContinuation.java (added)
+++ tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyContinuation.java Thu Jun  3 06:43:58 2010
@@ -0,0 +1,46 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.func;
+
+/**
+ * The result of the evaluation of a {@link LazyFunction}.
+ * 
+ * @since 5.2.0
+ */
+public class LazyContinuation<T>
+{
+    private final T nextValue;
+
+    private final LazyFunction<T> nextFunction;
+
+    public LazyContinuation(T next, LazyFunction<T> nextFunction)
+    {
+        this.nextValue = next;
+        this.nextFunction = nextFunction;
+    }
+
+    /** Returns the next value computed by the lazy function. */
+    public T nextValue()
+    {
+        return nextValue;
+    }
+
+    /** Returns a new lazy function that will return the next continuation. */
+    public LazyFunction<T> nextFunction()
+    {
+        return nextFunction;
+    }
+
+}

Propchange: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyContinuation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFilter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFilter.java?rev=950886&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFilter.java (added)
+++ tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFilter.java Thu Jun  3 06:43:58 2010
@@ -0,0 +1,45 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.func;
+
+class LazyFilter<T> implements LazyFunction<T>
+{
+    private final Predicate<? super T> predicate;
+
+    private final Flow<T> flow;
+
+    public LazyFilter(Predicate<? super T> predicate, Flow<T> flow)
+    {
+        this.predicate = predicate;
+        this.flow = flow;
+    }
+
+    public LazyContinuation<T> next()
+    {
+        Flow<T> cursor = flow;
+
+        while (!cursor.isEmpty())
+        {
+            T potential = cursor.first();
+
+            if (predicate.accept(potential))
+                return new LazyContinuation<T>(potential, new LazyFilter<T>(predicate, cursor.rest()));
+            
+            cursor = cursor.rest();
+        }
+
+        return null;
+    }
+}

Propchange: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFlow.java (from r950828, tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/MappedFlow.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFlow.java?p2=tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFlow.java&p1=tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/MappedFlow.java&r1=950828&r2=950886&rev=950886&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/MappedFlow.java (original)
+++ tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFlow.java Thu Jun  3 06:43:58 2010
@@ -14,38 +14,26 @@
 
 package org.apache.tapestry5.func;
 
-/**
- * Flow that wraps around another Flow, transforming it value by value into a new Flow.
- * 
- * @since 5.2.0
- */
-class MappedFlow<T, X> extends AbstractFlow<X>
+class LazyFlow<T> extends AbstractFlow<T>
 {
-    private final Mapper<T, X> mapper;
+    // All instance variables guarded by this
 
-    // Used to determine first, rest
-    // Guarded by this
-    private Flow<T> mappedFlow;
-
-    // Guarded by this
     private boolean resolved;
 
-    // Guarded by this
-    private X first;
+    private boolean empty;
 
-    // Guarded by this
-    private Flow<X> rest;
+    private T first;
 
-    // Guarded by this
-    private boolean empty;
+    private Flow<T> rest;
 
-    public MappedFlow(Mapper<T, X> mapper, Flow<T> mappedFlow)
+    private LazyFunction<T> lazyFunction;
+
+    public LazyFlow(LazyFunction<T> lazyFunction)
     {
-        this.mapper = mapper;
-        this.mappedFlow = mappedFlow;
+        this.lazyFunction = lazyFunction;
     }
 
-    public synchronized X first()
+    public synchronized T first()
     {
         resolve();
 
@@ -59,43 +47,34 @@ class MappedFlow<T, X> extends AbstractF
         return empty;
     }
 
-    public synchronized Flow<X> rest()
+    public synchronized Flow<T> rest()
     {
         resolve();
 
         return rest;
     }
 
-    private void resolve()
+    private synchronized void resolve()
     {
         if (resolved)
             return;
 
-        if (mappedFlow.isEmpty())
+        LazyContinuation<T> continuation = lazyFunction.next();
+
+        if (continuation == null)
         {
             empty = true;
             rest = F.emptyFlow();
         }
         else
         {
-            first = mapper.map(mappedFlow.first());
+            first = continuation.nextValue();
 
-            rest = new MappedFlow<T, X>(mapper, mappedFlow.rest());
+            rest = new LazyFlow<T>(continuation.nextFunction());
         }
 
-        mappedFlow = null;
-
         resolved = true;
+        
+        lazyFunction = null;
     }
-
-    public synchronized int count()
-    {
-        if (resolved) { 
-            return empty ? 0 : 1 + rest.count(); }
-
-        // Not yet resolved, so mappedFlow is still valid. Mapping never changes the count, thus:
-
-        return mappedFlow.count();
-    }
-
 }

Propchange: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFlow.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFunction.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFunction.java?rev=950886&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFunction.java (added)
+++ tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFunction.java Thu Jun  3 06:43:58 2010
@@ -0,0 +1,33 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.func;
+
+/**
+ * A lazy function is used to populate a {@link Flow} incrementally. Lazy functions allow calculations to be
+ * deferred. They also support infinitely large Flows, where successive values are computed just as needed.
+ * 
+ * @since 5.2.0
+ */
+public interface LazyFunction<T>
+{
+    /**
+     * Calculates the next value for the function. The return value is tricky: it combines the next value in the
+     * {@link Flow} with a function to compute the value after that as a {@link LazyContinuation}. Alternately, a
+     * LazyFunction can return null to indicate that it has returned all the values it can.
+     * 
+     * @return continuation containing next value and next function, or null when no more values can be produced
+     */
+    LazyContinuation<T> next();
+}

Propchange: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyFunction.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyIterate.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyIterate.java?rev=950886&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyIterate.java (added)
+++ tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyIterate.java Thu Jun  3 06:43:58 2010
@@ -0,0 +1,36 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.func;
+
+/**
+ * Used by {@link LazyConcat} to iterate the second flow.
+ */
+class LazyIterate<T> implements LazyFunction<T>
+{
+    private final Flow<T> flow;
+
+    public LazyIterate(Flow<T> flow)
+    {
+        this.flow = flow;
+    }
+
+    public LazyContinuation<T> next()
+    {
+        if (flow.isEmpty())
+            return null;
+
+        return new LazyContinuation<T>(flow.first(), new LazyIterate<T>(flow.rest()));
+    }
+}

Propchange: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyIterate.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyMapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyMapper.java?rev=950886&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyMapper.java (added)
+++ tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyMapper.java Thu Jun  3 06:43:58 2010
@@ -0,0 +1,39 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.func;
+
+class LazyMapper<T, X> implements LazyFunction<X>
+{
+    private final Mapper<T, X> mapper;
+
+    private final Flow<T> flow;
+
+    public LazyMapper(Mapper<T, X> mapper, Flow<T> flow)
+    {
+        this.mapper = mapper;
+        this.flow = flow;
+    }
+
+    public LazyContinuation<X> next()
+    {
+        if (flow.isEmpty())
+            return null;
+
+        X mapped = mapper.map(flow.first());
+
+        return new LazyContinuation<X>(mapped, new LazyMapper<T, X>(mapper, flow.rest()));
+    }
+
+}

Propchange: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/LazyMapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/FuncTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/FuncTest.java?rev=950886&r1=950885&r2=950886&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/FuncTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/FuncTest.java Thu Jun  3 06:43:58 2010
@@ -641,18 +641,6 @@ public class FuncTest extends Assert
     }
 
     @Test
-    public void count_of_a_mapped_flow_before_and_after_realization()
-    {
-        Flow<Integer> flow = F.flow("Mary", "had", "a", "little", "lamb").map(stringToLength);
-
-        assertEquals(flow.count(), 5);
-
-        assertEquals(flow.first(), (Integer) 4);
-
-        assertEquals(flow.count(), 5);
-    }
-
-    @Test
     public void count_of_a_filtered_flow()
     {
         Flow<String> flow = F.flow("Mary", "had", "a", "little", "lamb");
@@ -678,4 +666,12 @@ public class FuncTest extends Assert
         assertListsEquals(flow.map(F.<Integer> stringValueOf()).toList(), "1", "2", "3");
     }
 
+    @Test
+    public void concat_empty_list()
+    {
+        Flow<Integer> flow = F.flow(1, 3);
+
+        assertListsEquals(flow.concat(flow.filter(evenp)).toList(), 1, 3);
+    }
+
 }