Started incorporating Edwin's patch for COLLECTIONS-253, in preparation for COLLECTIONS-290.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/branches/collections_jdk5_branch@641231 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stephen Kestle 2008-03-26 09:58:51 +00:00
parent 63b2ac8cbd
commit 88aae2856c
11 changed files with 561 additions and 42 deletions

View File

@ -16,6 +16,9 @@
*/
package org.apache.commons.collections;
import static org.apache.commons.collections.functors.AllPredicate.allPredicate;
import static org.apache.commons.collections.functors.TruePredicate.truePredicate;
import java.util.Collection;
import org.apache.commons.collections.functors.AllPredicate;
@ -103,8 +106,8 @@ public class PredicateUtils {
*
* @return the predicate
*/
public static Predicate truePredicate() {
return TruePredicate.INSTANCE;
public static <T> Predicate<T> truePredicate() {
return truePredicate();
}
/**
@ -274,8 +277,8 @@ public class PredicateUtils {
* @throws IllegalArgumentException if the predicates array is null
* @throws IllegalArgumentException if any predicate in the array is null
*/
public static Predicate allPredicate(Predicate[] predicates) {
return AllPredicate.getInstance(predicates);
public static <T> Predicate<T> allPredicate(Predicate<? super T>[] predicates) {
return allPredicate(predicates);
}
/**
@ -290,8 +293,8 @@ public class PredicateUtils {
* @throws IllegalArgumentException if the predicates collection is null
* @throws IllegalArgumentException if any predicate in the collection is null
*/
public static Predicate allPredicate(Collection predicates) {
return AllPredicate.getInstance(predicates);
public static <T> Predicate<T> allPredicate(Collection<Predicate<? super T>> predicates) {
return allPredicate(predicates);
}
/**

View File

@ -16,6 +16,10 @@
*/
package org.apache.commons.collections.functors;
import static org.apache.commons.collections.functors.FunctorUtils.coerce;
import static org.apache.commons.collections.functors.FunctorUtils.validate;
import static org.apache.commons.collections.functors.TruePredicate.truePredicate;
import java.io.Serializable;
import java.util.Collection;
@ -34,14 +38,15 @@ import org.apache.commons.collections.Predicate;
*
* @author Stephen Colebourne
* @author Matt Benson
* @author Stephen Kestle
*/
public final class AllPredicate implements Predicate, PredicateDecorator, Serializable {
public final class AllPredicate<T> implements Predicate<T>, PredicateDecorator<T>, Serializable {
/** Serial version UID */
private static final long serialVersionUID = -3094696765038308799L;
/** The array of predicates to call */
private final Predicate[] iPredicates;
private final Predicate<? super T>[] iPredicates;
/**
* Factory to create the predicate.
@ -53,17 +58,49 @@ public final class AllPredicate implements Predicate, PredicateDecorator, Serial
* @return the <code>all</code> predicate
* @throws IllegalArgumentException if the predicates array is null
* @throws IllegalArgumentException if any predicate in the array is null
* @deprecated Use {@link #allPredicate(Predicate<? super T>...)} instead
*/
public static Predicate getInstance(Predicate[] predicates) {
public static <T> Predicate<T> getInstance(Predicate<? super T> ... predicates) {
return allPredicate(predicates);
}
/**
* Factory to create the predicate.
* <p>
* If the array is size zero, the predicate always returns true.
* If the array is size one, then that predicate is returned.
*
* @param predicates the predicates to check, cloned, not null
* @return the <code>all</code> predicate
* @throws IllegalArgumentException if the predicates array is null
* @throws IllegalArgumentException if any predicate in the array is null
*/
public static <T> Predicate<T> allPredicate(Predicate<? super T> ... predicates) {
FunctorUtils.validate(predicates);
if (predicates.length == 0) {
return TruePredicate.INSTANCE;
return truePredicate();
}
if (predicates.length == 1) {
return predicates[0];
return coerce(predicates[0]);
}
predicates = FunctorUtils.copy(predicates);
return new AllPredicate(predicates);
return new AllPredicate<T>(FunctorUtils.copy(predicates));
}
/**
* Factory to create the predicate.
* <p>
* If the collection is size zero, the predicate always returns true.
* If the collection is size one, then that predicate is returned.
*
* @param predicates the predicates to check, cloned, not null
* @return the <code>all</code> predicate
* @throws IllegalArgumentException if the predicates array is null
* @throws IllegalArgumentException if any predicate in the array is null
* @deprecated Use {@link #allPredicate(Collection<Predicate<? super T>>)} instead
*/
public static <T> Predicate<T> getInstance(Collection<Predicate<? super T>> predicates) {
return allPredicate(predicates);
}
/**
@ -77,24 +114,24 @@ public final class AllPredicate implements Predicate, PredicateDecorator, Serial
* @throws IllegalArgumentException if the predicates array is null
* @throws IllegalArgumentException if any predicate in the array is null
*/
public static Predicate getInstance(Collection predicates) {
Predicate[] preds = FunctorUtils.validate(predicates);
public static <T> Predicate<T> allPredicate(Collection<Predicate<? super T>> predicates) {
final Predicate<? super T>[] preds = validate(predicates);
if (preds.length == 0) {
return TruePredicate.INSTANCE;
return truePredicate();
}
if (preds.length == 1) {
return preds[0];
return coerce(preds[0]);
}
return new AllPredicate(preds);
return new AllPredicate<T>(preds);
}
/**
* Constructor that performs no validation.
* Use <code>getInstance</code> if you want that.
*
*
* @param predicates the predicates to check, not cloned, not null
*/
public AllPredicate(Predicate[] predicates) {
public AllPredicate(Predicate<? super T> ... predicates) {
super();
iPredicates = predicates;
}
@ -105,9 +142,9 @@ public final class AllPredicate implements Predicate, PredicateDecorator, Serial
* @param object the input object
* @return true if all decorated predicates return true
*/
public boolean evaluate(Object object) {
for (int i = 0; i < iPredicates.length; i++) {
if (iPredicates[i].evaluate(object) == false) {
public boolean evaluate(T object) {
for (Predicate<? super T> iPredicate : iPredicates) {
if (!iPredicate.evaluate(object)) {
return false;
}
}
@ -120,7 +157,7 @@ public final class AllPredicate implements Predicate, PredicateDecorator, Serial
* @return the predicates
* @since Commons Collections 3.1
*/
public Predicate[] getPredicates() {
public Predicate<? super T>[] getPredicates() {
return iPredicates;
}

View File

@ -17,7 +17,6 @@
package org.apache.commons.collections.functors;
import java.util.Collection;
import java.util.Iterator;
import org.apache.commons.collections.Closure;
import org.apache.commons.collections.Predicate;
@ -43,15 +42,35 @@ class FunctorUtils {
/**
* Clone the predicates to ensure that the internal reference can't be messed with.
* Due to the {@link Predicate#evaluate(T)} method, Predicate<? super T> is
* able to be coerced to Predicate<T> without casting issues.
*
* @param predicates the predicates to copy
* @return the cloned predicates
*/
static Predicate[] copy(Predicate[] predicates) {
@SuppressWarnings("unchecked")
static <T> Predicate<? super T>[] copy(Predicate<? super T>[] predicates) {
if (predicates == null) {
return null;
}
return (Predicate[]) predicates.clone();
return predicates.clone();
}
/**
* A very simple method that coerces Predicate<? super T> to Predicate<T>.
* Due to the {@link Predicate#evaluate(T)} method, Predicate<? super T> is
* able to be coerced to Predicate<T> without casting issues.
* <p>This method exists
* simply as centralised documentation and atomic unchecked warning
* suppression.
*
* @param <T> the type of object the returned predicate should "accept"
* @param predicate the predicate to coerce.
* @return the coerced predicate.
*/
@SuppressWarnings("unchecked")
static <T> Predicate<T> coerce(Predicate<? super T> predicate){
return (Predicate<T>) predicate;
}
/**
@ -59,7 +78,7 @@ class FunctorUtils {
*
* @param predicates the predicates to validate
*/
static void validate(Predicate[] predicates) {
static void validate(Predicate<?>[] predicates) {
if (predicates == null) {
throw new IllegalArgumentException("The predicate array must not be null");
}
@ -76,15 +95,16 @@ class FunctorUtils {
* @param predicates the predicates to validate
* @return predicate array
*/
static Predicate[] validate(Collection predicates) {
@SuppressWarnings("unchecked")
static <T> Predicate<? super T>[] validate(Collection<Predicate<? super T>> predicates) {
if (predicates == null) {
throw new IllegalArgumentException("The predicate collection must not be null");
}
// convert to array like this to guarantee iterator() ordering
Predicate[] preds = new Predicate[predicates.size()];
Predicate<? super T>[] preds = new Predicate[predicates.size()];
int i = 0;
for (Iterator it = predicates.iterator(); it.hasNext();) {
preds[i] = (Predicate) it.next();
for (Predicate<? super T> predicate : predicates) {
preds[i] = predicate;
if (preds[i] == null) {
throw new IllegalArgumentException("The predicate collection must not contain a null predicate, index " + i + " was null");
}

View File

@ -27,8 +27,9 @@ import org.apache.commons.collections.Predicate;
* @version $Revision$ $Date$
*
* @author Stephen Colebourne
* @author Stephen Kestle
*/
public interface PredicateDecorator extends Predicate {
public interface PredicateDecorator<T> extends Predicate<T> {
/**
* Gets the predicates being decorated as an array.
@ -38,6 +39,6 @@ public interface PredicateDecorator extends Predicate {
*
* @return the predicates being decorated
*/
Predicate[] getPredicates();
Predicate<? super T>[] getPredicates();
}

View File

@ -27,14 +27,27 @@ import org.apache.commons.collections.Predicate;
* @version $Revision$ $Date$
*
* @author Stephen Colebourne
* @author Stephen Kestle
*/
public final class TruePredicate implements Predicate, Serializable {
public final class TruePredicate<T> implements Predicate<T>, Serializable {
/** Serial version UID */
private static final long serialVersionUID = 3374767158756189740L;
/** Singleton predicate instance */
public static final Predicate INSTANCE = new TruePredicate();
public static final Predicate<?> INSTANCE = new TruePredicate<Object>();
/**
* Factory returning the singleton instance.
*
* @return the singleton instance
* @since Commons Collections 3.1
* @deprecated
*/
@Deprecated
public static <T> Predicate<T> getInstance() {
return truePredicate();
}
/**
* Factory returning the singleton instance.
@ -42,8 +55,9 @@ public final class TruePredicate implements Predicate, Serializable {
* @return the singleton instance
* @since Commons Collections 3.1
*/
public static Predicate getInstance() {
return INSTANCE;
@SuppressWarnings("unchecked")
public static <T> Predicate<T> truePredicate() {
return (Predicate<T>) INSTANCE;
}
/**
@ -59,8 +73,7 @@ public final class TruePredicate implements Predicate, Serializable {
* @param object the input object
* @return true always
*/
public boolean evaluate(Object object) {
public boolean evaluate(T object) {
return true;
}
}

View File

@ -0,0 +1,89 @@
package org.apache.commons.collections.functors;
import static org.easymock.EasyMock.verify;
import static org.easymock.EasyMock.replay;
import org.junit.Before;
import org.junit.After;
import org.apache.commons.collections.Predicate;
import org.easymock.EasyMock;
import java.util.ArrayList;
import java.util.List;
/**
* Base class for tests of predicates which delegate to other predicates when evaluating an object. This class
* provides methods to create and verify mock predicates to which to delegate.
*
* @since Commons Collections 3.0
* @version $Revision: 468603 $ $Date: 2006-10-27 17:52:37 -0700 (Fri, 27 Oct 2006) $
*
* @author Edwin Tellman
*/
public abstract class PredicateTestBase<T> {
/**
* Mock predicates created by a single test case which need to be verified after the test completes.
*/
private List<Predicate<? super T>> mockPredicatesToVerify;
/**
* The value to pass to mocks.
*/
private final T testValue;
/**
* Creates a new <code>PredicateTestBase</code>.
*
* @param testValue the value to pass to mock predicates.
*/
protected PredicateTestBase(final T testValue) {
this.testValue = testValue;
}
/**
* Creates the list of predicates to verify.
*/
@Before
public final void createVerifyList()
{
mockPredicatesToVerify = new ArrayList<Predicate<? super T>>();
}
/**
* Verifies all the mock predicates created for the test.
*/
@After
public final void verifyPredicates()
{
for (Predicate<? super T> predicate : mockPredicatesToVerify) {
verify(predicate);
}
}
/**
* Gets the value which will be passed to the mock predicates.
*
* @return the test value.
*/
protected final T getTestValue() {
return testValue;
}
/**
* Creates a single mock predicate.
*
* @param returnValue the return value for the mock predicate, or null if the mock is not expected to be called.
*
* @return a single mock predicate.
*/
@SuppressWarnings({"unchecked"})
protected final Predicate<T> createMockPredicate(final Boolean returnValue) {
final Predicate<T> mockPredicate = EasyMock.createMock(Predicate.class);
if (returnValue != null) {
EasyMock.expect(mockPredicate.evaluate(testValue)).andReturn(returnValue);
}
replay(mockPredicate);
mockPredicatesToVerify.add(mockPredicate);
return mockPredicate;
}
}

View File

@ -0,0 +1,19 @@
package org.apache.commons.collections.functors;
import junit.framework.TestCase;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
/**
* Entry point for all Functors package tests.
*
* @version $Revision: 471163 $ $Date: 2006-11-04 02:56:39 -0800 (Sat, 04 Nov 2006) $
*
* @author Edwin Tellman
*/
@RunWith(Suite.class)
@SuiteClasses({TestAllPredicate.class})
public class TestAll extends TestCase {
}

View File

@ -0,0 +1,134 @@
package org.apache.commons.collections.functors;
import junit.framework.JUnit4TestAdapter;
import org.apache.commons.collections.Predicate;
import static org.apache.commons.collections.functors.AllPredicate.allPredicate;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import java.util.Collection;
import java.util.Collections;
/**
* Tests the org.apache.commons.collections.functors.AllPredicate class.
*
* @since Commons Collections 3.0
* @version $Revision: 468603 $ $Date: 2006-10-27 17:52:37 -0700 (Fri, 27 Oct 2006) $
*
* @author Edwin Tellman
*/
public class TestAllPredicate extends TestAnyAllOnePredicate<Integer> {
/**
* Creates a JUnit3 test suite.
*
* @return a JUnit3 test suite
*/
public static junit.framework.Test suite() {
return new JUnit4TestAdapter(TestAllPredicate.class);
}
/**
* Creates a new <code>TestAllPredicate</code>.
*/
public TestAllPredicate() {
super(42);
}
/**
* {@inheritDoc}
*/
@Override
protected final Predicate<Integer> getPredicateInstance(final Predicate<? super Integer> ... predicates) {
return AllPredicate.allPredicate(predicates);
}
/**
* {@inheritDoc}
*/
@Override
protected final Predicate<Integer> getPredicateInstance(final Collection<Predicate<? super Integer>> predicates) {
return AllPredicate.allPredicate(predicates);
}
/**
* Verifies that providing an empty predicate array evaluates to true.
*/
@SuppressWarnings({"unchecked"})
@Test
public void emptyArrayToGetInstance()
{
assertTrue("empty array not true", getPredicateInstance(new Predicate[] {}).evaluate(null));
}
/**
* Verifies that providing an empty predicate collection evaluates to true.
*/
@Test
public void emptyCollectionToGetInstance()
{
final Predicate<Integer> allPredicate = getPredicateInstance(
Collections.<Predicate<? super Integer>>emptyList());
assertTrue("empty collection not true", allPredicate.evaluate(getTestValue()));
}
/**
* Tests whether a single true predicate evaluates to true.
*/
@Test
public void oneTruePredicate()
{
// use the constructor directly, as getInstance() returns the original predicate when passed
// an array of size one.
final Predicate<Integer> predicate = createMockPredicate(true);
assertTrue("single true predicate evaluated to false",
allPredicate(predicate).evaluate(getTestValue()));
}
/**
* Tests whether a single false predicate evaluates to true.
*/
@Test
public void oneFalsePredicate()
{
// use the constructor directly, as getInstance() returns the original predicate when passed
// an array of size one.
final Predicate<Integer> predicate = createMockPredicate(false);
assertFalse("single false predicate evaluated to true",
allPredicate(predicate).evaluate(getTestValue()));
}
/**
* Tests whether multiple true predicates evaluates to true.
*/
@Test
public void allTrue()
{
assertTrue("multiple true predicates evaluated to false",
getPredicateInstance(true, true).evaluate(getTestValue()));
assertTrue("multiple true predicates evaluated to false",
getPredicateInstance(true, true, true).evaluate(getTestValue()));
}
/**
* Tests whether combining some true and one false evalutes to false. Also verifies that only the first
* false predicate is actually evaluated
*/
@Test
public void trueAndFalseCombined()
{
assertFalse("false predicate evaluated to true",
getPredicateInstance(false, null).evaluate(getTestValue()));
assertFalse("false predicate evaluated to true",
getPredicateInstance(false, null, null).evaluate(getTestValue()));
assertFalse("false predicate evaluated to true",
getPredicateInstance(true, false, null).evaluate(getTestValue()));
assertFalse("false predicate evaluated to true",
getPredicateInstance(true, true, false).evaluate(getTestValue()));
assertFalse("false predicate evaluated to true",
getPredicateInstance(true, true, false, null).evaluate(getTestValue()));
}
}

View File

@ -0,0 +1,66 @@
package org.apache.commons.collections.functors;
import org.apache.commons.collections.Predicate;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import java.util.Collections;
/**
* Base class for tests of AnyPredicate, AllPredicate, and OnePredicate.
*
* @since Commons Collections 3.0
* @version $Revision: 468603 $ $Date: 2006-10-27 17:52:37 -0700 (Fri, 27 Oct 2006) $
*
* @author Edwin Tellman
*/
public abstract class TestAnyAllOnePredicate<T> extends TestCompositePredicate<T> {
/**
* Creates a new <code>TestCompositePredicate</code>.
*
* @param testValue the value which the mock predicates should expect to see (may be null).
*/
protected TestAnyAllOnePredicate(final T testValue) {
super(testValue);
}
/**
* Tests whether <code>getInstance</code> with a one element array returns the first element in the array.
*/
@Test
public final void singleElementArrayToGetInstance()
{
final Predicate<T> predicate = createMockPredicate(null);
final Predicate<T> allPredicate = getPredicateInstance(predicate);
assertSame("expected argument to be returned by getInstance()", predicate, allPredicate);
}
/**
* Tests that passing a singleton collection to <code>getInstance</code> returns the single element in the
* collection.
*/
@Test
public final void singletonCollectionToGetInstance()
{
final Predicate<T> predicate = createMockPredicate(null);
final Predicate<T> allPredicate = getPredicateInstance(
Collections.<Predicate<? super T>>singleton(predicate));
assertSame("expected singleton collection member to be returned by getInstance()",
predicate, allPredicate);
}
/**
* Tests creating composite predicate instances with single predicates and verifies that the composite returns
* the same value as the single predicate does.
*/
public final void singleValues()
{
assertTrue(getPredicateInstance(true).evaluate(null));
assertFalse(getPredicateInstance(false).evaluate(null));
}
}

View File

@ -0,0 +1,135 @@
package org.apache.commons.collections.functors;
import org.apache.commons.collections.Predicate;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Base class for tests of composite predicates.
*
* @since Commons Collections 3.0
* @version $Revision: 468603 $ $Date: 2006-10-27 17:52:37 -0700 (Fri, 27 Oct 2006) $
*
* @author Edwin Tellman
*/
public abstract class TestCompositePredicate<T> extends PredicateTestBase<T> {
/**
* Creates a new <code>TestCompositePredicate</code>.
*
* @param testValue the value which the mock predicates should expect to see (may be null).
*/
protected TestCompositePredicate(final T testValue) {
super(testValue);
}
/**
* Creates an instance of the predicate to test.
*
* @param predicates the arguments to <code>getInstance</code>.
*
* @return a predicate to test.
*/
protected abstract Predicate<T> getPredicateInstance(final Predicate<? super T> ... predicates);
/**
* Creates an instance of the predicate to test.
*
* @param predicates the argument to <code>getInstance</code>.
*
* @return a predicate to test.
*/
protected abstract Predicate<T> getPredicateInstance(final Collection<Predicate<? super T>> predicates);
/**
* Creates an instance of the predicate to test.
*
* @param mockReturnValues the return values for the mock predicates, or null if that mock is not expected
* to be called
*
* @return a predicate to test.
*/
protected final Predicate<T> getPredicateInstance(final Boolean ... mockReturnValues)
{
final List<Predicate<? super T>> predicates = new ArrayList<Predicate<? super T>>();
for (Boolean returnValue : mockReturnValues) {
predicates.add(createMockPredicate(returnValue));
}
return getPredicateInstance(predicates);
}
/**
* Tests whether <code>getInstance</code> with a one element array returns the first element in the array.
*/
public void singleElementArrayToGetInstance()
{
final Predicate<T> predicate = createMockPredicate(null);
final Predicate<T> allPredicate = getPredicateInstance(predicate);
Assert.assertSame("expected argument to be returned by getInstance()", predicate, allPredicate);
}
/**
* Tests that passing a singleton collection to <code>getInstance</code> returns the single element in the
* collection.
*/
public void singletonCollectionToGetInstance()
{
final Predicate<T> predicate = createMockPredicate(null);
final Predicate<T> allPredicate = getPredicateInstance(
Collections.<Predicate<? super T>>singleton(predicate));
Assert.assertSame("expected argument to be returned by getInstance()", predicate, allPredicate);
}
/**
* Tests <code>getInstance</code> with a null predicate array.
*/
@SuppressWarnings({"unchecked"})
@Test(expected = IllegalArgumentException.class)
public final void nullArrayToGetInstance() {
getPredicateInstance((Predicate<T>[]) null);
}
/**
* Tests <code>getInstance</code> with a single null element in the predicate array.
*/
@SuppressWarnings({"unchecked"})
@Test(expected = IllegalArgumentException.class)
public final void nullElementInArrayToGetInstance() {
getPredicateInstance(new Predicate[] { null });
}
/**
* Tests <code>getInstance</code> with two null elements in the predicate array.
*/
@SuppressWarnings({"unchecked"})
@Test(expected = IllegalArgumentException.class)
public final void nullElementsInArrayToGetInstance() {
getPredicateInstance(new Predicate[] { null, null });
}
/**
* Tests <code>getInstance</code> with a null predicate collection
*/
@Test(expected = IllegalArgumentException.class)
public final void nullCollectionToGetInstance() {
getPredicateInstance((Collection<Predicate<? super T>>) null);
}
/**
* Tests <code>getInstance</code> with a predicate collection that contains null elements
*/
@Test(expected = IllegalArgumentException.class)
public final void nullElementsInCollectionToGetInstance() {
final Collection<Predicate<? super T>> coll = new ArrayList<Predicate<? super T>>();
coll.add(null);
coll.add(null);
getPredicateInstance(coll);
}
}

View File

@ -16,6 +16,8 @@
*/
package org.apache.commons.collections.iterators;
import static org.apache.commons.collections.functors.TruePredicate.truePredicate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -125,7 +127,7 @@ public class TestFilterIterator extends AbstractTestIterator {
Iterator iter2 = Collections.EMPTY_LIST.iterator();
FilterIterator filterIterator = new FilterIterator(iter1);
filterIterator.setPredicate(TruePredicate.getInstance());
filterIterator.setPredicate(truePredicate());
// this iterator has elements
assertEquals(true, filterIterator.hasNext());
@ -142,7 +144,7 @@ public class TestFilterIterator extends AbstractTestIterator {
Iterator iter = Collections.singleton(null).iterator();
FilterIterator filterIterator = new FilterIterator(iter);
filterIterator.setPredicate(TruePredicate.getInstance());
filterIterator.setPredicate(truePredicate());
// this predicate matches
assertEquals(true, filterIterator.hasNext());