Author: hlship
Date: Mon May 31 17:34:54 2010
New Revision: 949814

URL: http://svn.apache.org/viewvc?rev=949814&view=rev
Log:
Fill in some edge cases and get code coverage to 100%

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/F.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=949814&r1=949813&r2=949814&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:34:54 2010
@@ -43,12 +43,9 @@ abstract class AbstractFlow<T> implement
     {
         List<T> result = new ArrayList<T>();
 
-        Flow<T> current = flow;
-
-        while (!current.isEmpty())
+        for (T value : flow)
         {
-            result.add(current.first());
-            current = current.rest();
+            result.add(value);
         }
 
         return result;
@@ -102,11 +99,11 @@ abstract class AbstractFlow<T> implement
     /** Subclasses may override this for efficiency. */
     public Flow<T> each(Worker<? super T> worker)
     {
-        Flow<T> cursor = this;
-        while (!cursor.isEmpty())
+        Defense.notNull(worker, "worker");
+
+        for (T value : this)
         {
-            worker.work(cursor.first());
-            cursor = cursor.rest();
+            worker.work(value);
         }
 
         return this;
@@ -152,16 +149,25 @@ abstract class AbstractFlow<T> implement
 
     public Flow<T> reverse()
     {
+        if (isEmpty())
+            return F.emptyFlow();
+
         return new ArrayFlow<T>(this).reverse();
     }
 
     public Flow<T> sort()
     {
+        if (isEmpty())
+            return F.emptyFlow();
+
         return new ArrayFlow<T>(this).sort();
     }
 
     public Flow<T> sort(Comparator<? super T> comparator)
     {
+        if (isEmpty())
+            return F.emptyFlow();
+
         return new ArrayFlow<T>(this).sort(comparator);
     }
 

Modified: 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/F.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/F.java?rev=949814&r1=949813&r2=949814&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/F.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/func/F.java
 Mon May 31 17:34:54 2010
@@ -24,7 +24,8 @@ import java.util.Collection;
  */
 public class F
 {
-    private final static Flow<?> EMPTY_FLOW = new EmptyFlow();
+    @SuppressWarnings("unchecked")
+    final static Flow<?> EMPTY_FLOW = new EmptyFlow();
 
     @SuppressWarnings("unchecked")
     static <T> Flow<T> emptyFlow()

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=949814&r1=949813&r2=949814&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:34:54 2010
@@ -35,6 +35,9 @@ class MappedFlow<T, X> extends AbstractF
     // Guarded by this
     private Flow<X> rest;
 
+    // Guarded by this
+    private boolean empty;
+
     public MappedFlow(Mapper<T, X> mapper, Flow<T> mappedFlow)
     {
         this.mapper = mapper;
@@ -48,9 +51,11 @@ class MappedFlow<T, X> extends AbstractF
         return first;
     }
 
-    public boolean isEmpty()
+    public synchronized boolean isEmpty()
     {
-        return false;
+        resolve();
+
+        return empty;
     }
 
     public synchronized Flow<X> rest()
@@ -65,16 +70,17 @@ class MappedFlow<T, X> extends AbstractF
         if (resolved)
             return;
 
-        // The mappedFlow should never be empty
-
-        first = mapper.map(mappedFlow.first());
-
-        Flow<T> mappedRest = mappedFlow.rest();
-
-        if (mappedRest.isEmpty())
+        if (mappedFlow.isEmpty())
+        {
+            empty = true;
             rest = F.emptyFlow();
+        }
         else
-            rest = new MappedFlow<T, X>(mapper, mappedRest);
+        {
+            first = mapper.map(mappedFlow.first());
+
+            rest = new MappedFlow<T, X>(mapper, mappedFlow.rest());
+        }
 
         mappedFlow = null;
 

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=949814&r1=949813&r2=949814&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:34:54 2010
@@ -17,6 +17,7 @@ package org.apache.tapestry5.func;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 
@@ -26,6 +27,7 @@ import org.testng.annotations.Test;
 
 public class FuncTest extends TestUtils
 {
+
     private Mapper<String, Integer> stringToLength = new Mapper<String, 
Integer>()
     {
         public Integer map(String input)
@@ -50,6 +52,8 @@ public class FuncTest extends TestUtils
         };
     };
 
+    private Flow<Integer> filteredEmpty = F.flow(1, 3, 5, 7).filter(evenp);
+
     @Test
     public void map()
     {
@@ -116,6 +120,35 @@ public class FuncTest extends TestUtils
     }
 
     @Test
+    public void each_on_non_array_flow()
+    {
+        List<String> source = Arrays.asList("Mary", "had", "a", "little", 
"lamb");
+
+        final StringBuffer buffer = new StringBuffer();
+
+        Worker<String> worker = new Worker<String>()
+        {
+            public void work(String value)
+            {
+                if (buffer.length() > 0)
+                    buffer.append(" ");
+
+                buffer.append(value);
+            }
+        };
+
+        F.flow(source).filter(new Predicate<String>()
+        {
+            public boolean accept(String object)
+            {
+                return object.contains("a");
+            }
+        }).each(worker);
+
+        assertEquals(buffer.toString(), "Mary had a lamb");
+    }
+
+    @Test
     public void flow_each()
     {
         Flow<String> flow = F.flow("Mary", "had", "a", "little", "lamb");
@@ -431,4 +464,128 @@ public class FuncTest extends TestUtils
     {
         assertTrue(F.flow().rest().isEmpty());
     }
+
+    @Test
+    public void list_of_empty_flow_is_empty()
+    {
+        assertTrue(filteredEmpty.isEmpty());
+        assertSame(filteredEmpty.toList(), Collections.EMPTY_LIST);
+    }
+
+    @Test
+    public void operations_on_empty_list_yield_empty()
+    {
+        assertSame(filteredEmpty.reverse(), F.EMPTY_FLOW);
+        assertSame(filteredEmpty.sort(), F.EMPTY_FLOW);
+        assertSame(filteredEmpty.sort(new Comparator<Integer>()
+        {
+            public int compare(Integer o1, Integer o2)
+            {
+                unreachable();
+
+                return 0;
+            }
+        }), F.EMPTY_FLOW);
+    }
+
+    @Test
+    public void sort_non_array_flow()
+    {
+        assertListsEquals(filteredEmpty.append(7, 3, 9).sort().toList(), 3, 7, 
9);
+    }
+
+    @Test
+    public void reverse_non_array_flow()
+    {
+        assertListsEquals(filteredEmpty.append(1, 2, 3).reverse().toList(), 3, 
2, 1);
+    }
+
+    @Test(expectedExceptions = UnsupportedOperationException.class)
+    public void remove_on_flow_iterator_is_not_supported()
+    {
+        Flow<Integer> flow = F.flow(1, 2, 3).filter(evenp);
+
+        Iterator<Integer> it = flow.iterator();
+
+        assertTrue(it.hasNext());
+        assertEquals(it.next(), new Integer(2));
+
+        it.remove();
+    }
+
+    @Test
+    public void sort_with_comparator_on_non_array_flow()
+    {
+        Flow<String> flow = F.flow("Mary", "had", "a", "little", "lamb");
+
+        List<String> result = flow.filter(new Predicate<String>()
+        {
+            public boolean accept(String object)
+            {
+                return object.contains("a");
+            }
+        }).sort(new Comparator<String>()
+        {
+            public int compare(String o1, String o2)
+            {
+                return o1.length() - o2.length();
+
+            };
+        }).toList();
+
+        assertListsEquals(result, "a", "had", "Mary", "lamb");
+    }
+
+    @Test
+    public void map_of_filtered_empty_is_empty()
+    {
+        assertTrue(filteredEmpty.map(new Mapper<Integer, Integer>()
+        {
+            public Integer map(Integer value)
+            {
+                unreachable();
+
+                return value;
+            }
+        }).isEmpty());
+    }
+
+    @Test
+    public void each_on_empty_flow()
+    {
+        Flow<Integer> flow = F.emptyFlow();
+
+        assertSame(flow.each(new Worker<Integer>()
+        {
+            public void work(Integer value)
+            {
+                unreachable();
+            }
+        }), flow);
+    }
+
+    @Test
+    public void remove_on_empty_flow()
+    {
+        Flow<Integer> flow = F.emptyFlow();
+
+        assertSame(flow.remove(evenp), flow);
+    }
+
+    @Test
+    public void reduce_on_empty_flow()
+    {
+        Flow<Integer> flow = F.emptyFlow();
+        Integer initial = 99;
+
+        assertSame(flow.reduce(new Reducer<Integer, Integer>()
+        {
+            public Integer reduce(Integer accumulator, Integer value)
+            {
+                unreachable();
+
+                return null;
+            }
+        }, initial), initial);
+    }
 }


Reply via email to