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()