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 2011/01/04 23:39:11 UTC

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

Author: hlship
Date: Tue Jan  4 22:39:10 2011
New Revision: 1055223

URL: http://svn.apache.org/viewvc?rev=1055223&view=rev
Log:
TAP5-1390: Add predicate factories for matching String prefixes and suffixes
Make it easy to filter a ZippedFlow using a Predicate that applies to its first or second tuple values

Added:
    tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/StringPredicateTests.java
Modified:
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/F.java
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/ZippedFlow.java
    tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/ZippedFlowImpl.java
    tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/ZippedFlowTests.java

Modified: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/F.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/F.java?rev=1055223&r1=1055222&r2=1055223&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/F.java (original)
+++ tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/F.java Tue Jan  4 22:39:10 2011
@@ -26,9 +26,9 @@ import java.util.Iterator;
  * created
  * using {@link #flow(Collection)} and {@link #flow(Object...)}.
  * <p>
- * F will be used a bit, thus it has a short name (for those who don't like static imports). It
- * provides a base set of Predicate, Mapper and Reducer factories. A good development pattern for
- * applications is to provide a similar, application-specific, set of such factories.
+ * F will be used a bit, thus it has a short name (for those who don't like static imports). It provides a base set of
+ * Predicate, Mapper and Reducer factories. A good development pattern for applications is to provide a similar,
+ * application-specific, set of such factories.
  * 
  * @since 5.2.0
  */
@@ -159,8 +159,7 @@ public class F
     }
 
     /**
-     * A Mapper factory that gets the string value of the flow value using
-     * {@link String#valueOf(Object)}.
+     * A Mapper factory that gets the string value of the flow value using {@link String#valueOf(Object)}.
      */
     public static <T> Mapper<T, String> stringValueOf()
     {
@@ -314,8 +313,8 @@ public class F
 
     /**
      * Creates a lazy Flow from the {@link Iterator} obtained from the iterable. The Flow
-     * will be threadsafe as long as the iterable yields a new Iterator on each invocation
-     * <em>and</em> the underlying iterable object is not modified while the Flow is evaluating.
+     * will be threadsafe as long as the iterable yields a new Iterator on each invocation <em>and</em> the underlying
+     * iterable object is not modified while the Flow is evaluating.
      * In other words, not extremely threadsafe.
      */
     public static <T> Flow<T> flow(Iterable<T> iterable)
@@ -400,4 +399,72 @@ public class F
             }
         };
     }
+
+    /**
+     * A Predicate factory for matching String elements with a given prefix.
+     * 
+     * @since 5.3.0
+     */
+    public static Predicate<String> startsWith(String prefix)
+    {
+        return startsWith(prefix, false);
+    }
+
+    /**
+     * As {@link #startsWith(String)}, but ignores case.
+     * 
+     * @since 5.3.0
+     */
+    public static Predicate<String> startsWithIgnoringCase(String prefix)
+    {
+        return startsWith(prefix, true);
+    }
+
+    /** @since 5.3.0 */
+    private static Predicate<String> startsWith(final String prefix, final boolean ignoreCase)
+    {
+        return new Predicate<String>()
+        {
+            @Override
+            public boolean accept(String element)
+            {
+                return element.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
+            }
+        };
+    }
+
+    /**
+     * A Predicate factory for matching String elements with a given suffix.
+     * 
+     * @since 5.3.0
+     */
+    public static Predicate<String> endsWith(String suffix)
+    {
+        return endsWith(suffix, false);
+    }
+
+    /**
+     * As with {@link #endsWith(String)} but ignores case.
+     * 
+     * @since 5.3.0
+     */
+    public static Predicate<String> endsWithIgnoringCase(String suffix)
+    {
+        return endsWith(suffix, true);
+    }
+
+    /** @since 5.3.0 */
+    private static Predicate<String> endsWith(final String suffix, final boolean ignoreCase)
+    {
+        return new Predicate<String>()
+        {
+            @Override
+            public boolean accept(String element)
+            {
+                return element
+                        .regionMatches(ignoreCase, element.length() - suffix.length(), suffix, 0, suffix.length());
+            }
+        };
+    }
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/ZippedFlow.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/ZippedFlow.java?rev=1055223&r1=1055222&r2=1055223&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/ZippedFlow.java (original)
+++ tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/ZippedFlow.java Tue Jan  4 22:39:10 2011
@@ -16,8 +16,7 @@ package org.apache.tapestry5.func;
 
 /**
  * The result of the {@link Flow#zipWith(Flow)} method, a Flow of combined {@link Tuple} values
- * (that can be deconstructed, eventually, using {@link #unzip()}). Each operation of {@link Flow}
- * has a corresponding implementation here, on the Tuple values.
+ * (that can be deconstructed, eventually, using {@link #unzip()}).
  * 
  * @param <A>
  * @param <B>
@@ -51,4 +50,28 @@ public interface ZippedFlow<A, B> extend
      * operation.
      */
     Flow<B> seconds();
+
+    /**
+     * Filters the tuples in the zipped flow by applying a predicate to the first value in each tuple.
+     * This is a lazy operation.
+     */
+    ZippedFlow<A, B> filterOnFirst(Predicate<? super A> predicate);
+
+    /**
+     * Filters the tuples in the zipped flow by applying a predicate to the second value in each tuple. This
+     * is a lazy operations.
+     */
+    ZippedFlow<A, B> filterOnSecond(Predicate<? super B> predicate);
+
+    /**
+     * Removes tuples from the zipped flow by applying a predicate to the first value in each tuple.
+     * This is a lazy operation.
+     */
+    ZippedFlow<A, B> removeOnFirst(Predicate<? super A> predicate);
+
+    /**
+     * Removes tuples from the zipped flow by applying a predicate to the second value in each tuple. This
+     * is a lazy operations.
+     */
+    ZippedFlow<A, B> removeOnSecond(Predicate<? super B> predicate);
 }

Modified: tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/ZippedFlowImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/ZippedFlowImpl.java?rev=1055223&r1=1055222&r2=1055223&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/ZippedFlowImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-func/src/main/java/org/apache/tapestry5/func/ZippedFlowImpl.java Tue Jan  4 22:39:10 2011
@@ -20,8 +20,8 @@ import java.util.List;
 import java.util.Set;
 
 /**
- * The single implementation of {@link ZippedFlow}, that operates by wrapping around an ordinary
- * {@link Flow} of the {@link Tuples} of the zipped flow. In the future, we may create an
+ * The single implementation of {@link ZippedFlow}, that operates by wrapping around an ordinary {@link Flow} of the
+ * {@link Tuples} of the zipped flow. In the future, we may create an
  * EmptyZippedFlow implementation as well.
  * 
  * @param <A>
@@ -141,7 +141,6 @@ class ZippedFlowImpl<A, B> implements Zi
     {
         return tupleFlow.map(new Mapper<Tuple<A, B>, A>()
         {
-
             @Override
             public A map(Tuple<A, B> value)
             {
@@ -159,7 +158,6 @@ class ZippedFlowImpl<A, B> implements Zi
     {
         return tupleFlow.map(new Mapper<Tuple<A, B>, B>()
         {
-
             @Override
             public B map(Tuple<A, B> value)
             {
@@ -168,4 +166,46 @@ class ZippedFlowImpl<A, B> implements Zi
         });
     }
 
+    public ZippedFlow<A, B> filterOnFirst(final Predicate<? super A> predicate)
+    {
+        assert predicate != null;
+
+        return filter(new Predicate<Tuple<A, B>>()
+        {
+            @Override
+            public boolean accept(Tuple<A, B> element)
+            {
+                return predicate.accept(element.first);
+            }
+        });
+    }
+
+    public ZippedFlow<A, B> filterOnSecond(final Predicate<? super B> predicate)
+    {
+        assert predicate != null;
+
+        return filter(new Predicate<Tuple<A, B>>()
+        {
+            @Override
+            public boolean accept(Tuple<A, B> element)
+            {
+                return predicate.accept(element.second);
+            }
+        });
+    }
+
+    public ZippedFlow<A, B> removeOnFirst(Predicate<? super A> predicate)
+    {
+        assert predicate != null;
+
+        return filterOnFirst(predicate.invert());
+    }
+
+    public ZippedFlow<A, B> removeOnSecond(Predicate<? super B> predicate)
+    {
+        assert predicate != null;
+
+        return filterOnSecond(predicate.invert());
+    }
+
 }

Added: tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/StringPredicateTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/StringPredicateTests.java?rev=1055223&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/StringPredicateTests.java (added)
+++ tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/StringPredicateTests.java Tue Jan  4 22:39:10 2011
@@ -0,0 +1,51 @@
+// Copyright 2011 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;
+
+import org.testng.annotations.Test;
+
+public class StringPredicateTests extends BaseFuncTest
+{
+    @Test
+    public void prefix_predicate()
+    {
+        Flow<String> names = F.flow("Howard", "Henry", "Anna", "Hubert");
+
+        assertFlowValues(names.remove(F.startsWith("H")), "Anna");
+    }
+
+    @Test
+    public void case_insensitive_prefix_predicate()
+    {
+        Flow<String> names = F.flow("Howard", "Henry", "Anna", "Hubert");
+
+        assertFlowValues(names.filter(F.startsWithIgnoringCase("h")), "Howard", "Henry", "Hubert");
+    }
+
+    @Test
+    public void suffix_predicate()
+    {
+        Flow<String> names = F.flow("Ted", "Charly", "Fred", "Anna");
+
+        assertFlowValues(names.filter(F.endsWith("red")), "Fred");
+    }
+
+    @Test
+    public void case_insensitive_suffix_precicate()
+    {
+        Flow<String> names = F.flow("Ted", "Charly", "Fred", "Anna");
+
+        assertFlowValues(names.filter(F.endsWithIgnoringCase("RED")), "Fred");
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/ZippedFlowTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/ZippedFlowTests.java?rev=1055223&r1=1055222&r2=1055223&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/ZippedFlowTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-func/src/test/java/org/apache/tapestry5/func/ZippedFlowTests.java Tue Jan  4 22:39:10 2011
@@ -29,6 +29,30 @@ public class ZippedFlowTests extends Bas
 
     ZippedFlow<Integer, String> zipped = numbers.zipWith(names);
 
+    @Test
+    public void filter_on_first()
+    {
+        assertFlowValues(zipped.filterOnFirst(F.eql(3)).seconds(), "wilma");
+    }
+
+    @Test
+    public void remove_on_first()
+    {
+        assertFlowValues(zipped.removeOnFirst(F.neq(2)).seconds(), "barney");
+    }
+
+    @Test
+    public void filter_on_second()
+    {
+        assertFlowValues(zipped.filterOnSecond(F.startsWith("b")).seconds(), "barney");
+    }
+
+    @Test
+    public void remove_on_second()
+    {
+        assertFlowValues(zipped.removeOnSecond(F.startsWith("b")).seconds(), "fred", "wilma");
+    }
+
     @SuppressWarnings("unchecked")
     @Test
     public void zip_flows_together()