Author: brentworden Date: Fri Oct 15 20:44:33 2010 New Revision: 1023105 URL: http://svn.apache.org/viewvc?rev=1023105&view=rev Log: [COLLECTIONS-8] added comparator based predicate.
Added: commons/proper/collections/trunk/src/java/org/apache/commons/collections/functors/ComparatorPredicate.java commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestComparatorPredicate.java Modified: commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestAll.java Added: commons/proper/collections/trunk/src/java/org/apache/commons/collections/functors/ComparatorPredicate.java URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/java/org/apache/commons/collections/functors/ComparatorPredicate.java?rev=1023105&view=auto ============================================================================== --- commons/proper/collections/trunk/src/java/org/apache/commons/collections/functors/ComparatorPredicate.java (added) +++ commons/proper/collections/trunk/src/java/org/apache/commons/collections/functors/ComparatorPredicate.java Fri Oct 15 20:44:33 2010 @@ -0,0 +1,188 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.commons.collections.functors; + +import java.io.Serializable; +import java.util.Comparator; + +import org.apache.commons.collections.Predicate; + +/** + * Predicate that compares the input object with the one stored in the predicate using a comparator. + * In addition, the comparator result can be evaluated in accordance to a supplied criterion value. + * + * In order to demonstrate the use of the predicate, the following variables are declared: + * + * <pre> + * Integer ONE = new Integer(1); + * Integer TWO = new Integer(2); + * + * Comparator comparator = new Comparator() { + * + * public int compare(Object first, Object second) { + * return ((Integer) second) - ((Integer) first); + * } + * + * }; + * </pre> + * + * Using the declared variables, the <code>ComparatorPredicate</code> can be used used in the + * following way: + * + * <pre> + * ComparatorPredicate.getInstance(ONE, comparator).evaluate(TWO); + * </pre> + * + * The input variable <code>TWO</code> in compared to the stored variable <code>ONE</code> using + * the supplied <code>comparator</code>. This is the default usage of the predicate and will return + * <code>true</code> if the underlying comparator returns <code>0</code>. In addition to the default + * usage of the predicate, it is possible to evaluate the comparator's result in several ways. The + * following {...@link Criterion} enumeration values are provided by the predicate: + * </p> + * + * <ul> + * <li>EQUAL</li> + * <li>GREATER</li> + * <li>GREATER_OR_EQUAL</li> + * <li>LESS</li> + * <li>LESS_OR_EQUAL</li> + * </ul> + * + * The following examples demonstrates how these constants can be used in order to manipulate the + * evaluation of a comparator result. + * + * <pre> + * ComparatorPredicate.getInstance(ONE, comparator, <b>ComparatorPredicate.Criterion.GREATER</b>).evaluate(TWO); + * </pre> + * + * The input variable TWO is compared to the stored variable ONE using the supplied <code>comparator</code> + * using the <code>GREATER</code> evaluation criterion constant. This instructs the predicate to + * return <code>true</code> if the comparator returns a value greater than <code>0</code>. + * + * @since Commons Collections 4.0 + * @version $Revision: $ $Date: $ + * + * @author Rune Peter Bjørnstad. + */ +public class ComparatorPredicate<T> implements Predicate<T>, Serializable { + + public enum Criterion { + EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL, + }; + + private static final long serialVersionUID = 1L; + + // Instance variables: + + /** The internal object to compare with */ + private final T object; + + /** The comparator to use for comparison */ + private final Comparator<T> comparator; + + /** The comparison evaluation criterion to use */ + private final Criterion criterion; + + /** + * Factory to create the comparator predicate + * + * @param object the object to compare to + * @param comparator the comparator to use for comparison + * @return the predicate + * @throws IllegalArgumentException if comparator is null + */ + public static <T> Predicate<T> getInstance(T object, Comparator<T> comparator) { + return getInstance(object, comparator, Criterion.EQUAL); + } + + /** + * Factory to create the comparator predicate + * + * @param object the object to compare to + * @param comparator the comparator to use for comparison + * @param criterion the criterion to use to evaluate comparison + * @return the predicate + * @throws IllegalArgumentexception if comparator is null of criterion is invalid + */ + public static <T> Predicate<T> getInstance(T object, Comparator<T> comparator, Criterion criterion) { + if (comparator == null) { + throw new IllegalArgumentException("Comparator must not be null."); + } + if (criterion == null) { + throw new IllegalArgumentException("Criterion must not be null."); + } + return new ComparatorPredicate<T>(object, comparator, criterion); + } + + /** + * Constructor that performs no validation. + * Use <code>getInstance</code> if you want. + * + * @param object the object to compare to + * @param comparator the comparator to use for comparison + * @param criterion the criterion to use to evaluate comparison + */ + public ComparatorPredicate(T object, Comparator<T> comparator, Criterion criterion) { + super(); + this.object = object; + this.comparator = comparator; + this.criterion = criterion; + } + + /** + * Evaluates the predicate. The predicate evaluates to <code>true</code> in the following cases: + * + * <ul> + * <li><code>comparator.compare(object, input) == 0 && criterion == EQUAL</code></li> + * <li><code>comparator.compare(object, input) < 0 && criterion == LESS</code></li> + * <li><code>comparator.compare(object, input) > 0 && criterion == GREATER</code></li> + * <li><code>comparator.compare(object, input) >= 0 && criterion == GREATER_OR_EQUAL</code></li> + * <li><code>comparator.compare(object, input) <= 0 && criterion == LESS_OR_EQUAL</code></li> + * </ul> + * + * @see org.apache.commons.collections.Predicate#evaluate(java.lang.Object) + * @see java.util.Comparator.compare(java.lang.Object first, java.lang.Object second) + * + * @throws IllegalStateException if the criterion is invalid (really not possible) + */ + public boolean evaluate(T target) { + + boolean result = false; + int comparison = comparator.compare(object, target); + switch (criterion) { + case EQUAL: + result = (comparison == 0); + break; + case GREATER: + result = (comparison > 0); + break; + case LESS: + result = (comparison < 0); + break; + case GREATER_OR_EQUAL: + result = (comparison >= 0); + break; + case LESS_OR_EQUAL: + result = (comparison <= 0); + break; + default: + throw new IllegalStateException("The current criterion '" + criterion + "' is invalid."); + } + + return result; + } +} Modified: commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestAll.java URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestAll.java?rev=1023105&r1=1023104&r2=1023105&view=diff ============================================================================== --- commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestAll.java (original) +++ commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestAll.java Fri Oct 15 20:44:33 2010 @@ -31,6 +31,7 @@ import org.junit.runners.Suite.SuiteClas */ @RunWith(Suite.class) @SuiteClasses({TestAllPredicate.class, + TestComparatorPredicate.class, TestEqualPredicate.class, TestNullPredicate.class}) public class TestAll extends TestCase { Added: commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestComparatorPredicate.java URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestComparatorPredicate.java?rev=1023105&view=auto ============================================================================== --- commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestComparatorPredicate.java (added) +++ commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestComparatorPredicate.java Fri Oct 15 20:44:33 2010 @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.commons.collections.functors; + +import static org.apache.commons.collections.functors.ComparatorPredicate.*; +import static org.junit.Assert.assertSame; + +import java.util.Comparator; + +import org.apache.commons.collections.Predicate; +import org.junit.Test; + + +public class TestComparatorPredicate extends BasicPredicateTestBase { + private class TestComparator<T extends Comparable<T>> implements Comparator<T> { + public int compare(T first, T second) { + return first.compareTo(second); + } + } + + @Test + public void compareEquals() { + Integer value = Integer.valueOf(10); + Predicate<Integer> p = getInstance(value, new TestComparator<Integer>()); + assertFalse(p, Integer.valueOf(value.intValue() - 1)); + assertTrue(p, Integer.valueOf(value.intValue())); + assertFalse(p, Integer.valueOf(value.intValue() + 1)); + } + + @Test + public void compareGreater() { + Integer value = Integer.valueOf(10); + Predicate<Integer> p = getInstance(value, new TestComparator<Integer>(), Criterion.GREATER); + assertTrue(p, Integer.valueOf(value.intValue() - 1)); + assertFalse(p, Integer.valueOf(value.intValue())); + assertFalse(p, Integer.valueOf(value.intValue() + 1)); + } + + @Test + public void compareLess() { + Integer value = Integer.valueOf(10); + Predicate<Integer> p = getInstance(value, new TestComparator<Integer>(), Criterion.LESS); + assertFalse(p, Integer.valueOf(value.intValue() - 1)); + assertFalse(p, Integer.valueOf(value.intValue())); + assertTrue(p, Integer.valueOf(value.intValue() + 1)); + } + + @Test + public void compareGreaterOrEqual() { + Integer value = Integer.valueOf(10); + Predicate<Integer> p = getInstance(value, new TestComparator<Integer>(), Criterion.GREATER_OR_EQUAL); + assertTrue(p, Integer.valueOf(value.intValue() - 1)); + assertTrue(p, Integer.valueOf(value.intValue())); + assertFalse(p, Integer.valueOf(value.intValue() + 1)); + } + + @Test + public void compareLessOrEqual() { + Integer value = Integer.valueOf(10); + Predicate<Integer> p = getInstance(value, new TestComparator<Integer>(), Criterion.LESS_OR_EQUAL); + assertFalse(p, Integer.valueOf(value.intValue() - 1)); + assertTrue(p, Integer.valueOf(value.intValue())); + assertTrue(p, Integer.valueOf(value.intValue() + 1)); + } + + @Override + protected Predicate<?> generatePredicate() { + return getInstance(Integer.valueOf(10), new TestComparator<Integer>()); + } +}