[COLLECTIONS-272] Added support for serialization to FixedOrderComparator and TransformingComparator, added missing equals/hashCode, renamed tests.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1367748 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas Neidhart 2012-07-31 20:23:29 +00:00
parent 61fe60ef9d
commit ab32bf1d78
13 changed files with 245 additions and 41 deletions

View File

@ -16,6 +16,7 @@
*/ */
package org.apache.commons.collections.comparators; package org.apache.commons.collections.comparators;
import java.io.Serializable;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -39,11 +40,16 @@ import java.util.Map;
* Instances of FixedOrderComparator are not synchronized. The class is not * Instances of FixedOrderComparator are not synchronized. The class is not
* thread-safe at construction time, but it is thread-safe to perform * thread-safe at construction time, but it is thread-safe to perform
* multiple comparisons after all the setup operations are complete. * multiple comparisons after all the setup operations are complete.
* <p>
* This class is Serializable from Commons Collections 4.0.
* *
* @since 3.0 * @since 3.0
* @version $Id$ * @version $Id$
*/ */
public class FixedOrderComparator<T> implements Comparator<T> { public class FixedOrderComparator<T> implements Comparator<T>, Serializable {
/** Serialization version from Collections 4.0. */
private static final long serialVersionUID = 82794675842863201L;
/** /**
* Unknown object behavior enum. * Unknown object behavior enum.
@ -240,4 +246,53 @@ public class FixedOrderComparator<T> implements Comparator<T> {
return position1.compareTo(position2); return position1.compareTo(position2);
} }
//-----------------------------------------------------------------------
/**
* Implement a hash code for this comparator that is consistent with
* {@link #equals(Object) equals}.
*
* @return a hash code for this comparator.
*/
@Override
public int hashCode() {
int total = 17;
total = total*37 + (map == null ? 0 : map.hashCode());
total = total*37 + (unknownObjectBehavior == null ? 0 : unknownObjectBehavior.hashCode());
total = total*37 + counter;
total = total*37 + (isLocked ? 0 : 1);
return total;
}
/**
* Returns <code>true</code> iff <i>that</i> Object is
* is a {@link Comparator} whose ordering is known to be
* equivalent to mine.
* <p>
* This implementation returns <code>true</code>
* iff <code><i>that</i></code> is a {@link FixedOrderComparator}
* whose attributes are equal to mine.
*
* @param object the object to compare to
* @return true if equal
*/
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (null == object) {
return false;
}
if (object.getClass().equals(this.getClass())) {
FixedOrderComparator<?> comp = (FixedOrderComparator<?>) object;
return (null == map ? null == comp.map : map.equals(comp.map) &&
null == unknownObjectBehavior ? null == comp.unknownObjectBehavior :
unknownObjectBehavior == comp.unknownObjectBehavior &&
counter == comp.counter &&
isLocked == comp.isLocked &&
unknownObjectBehavior == comp.unknownObjectBehavior);
}
return false;
}
} }

View File

@ -16,6 +16,7 @@
*/ */
package org.apache.commons.collections.comparators; package org.apache.commons.collections.comparators;
import java.io.Serializable;
import java.util.Comparator; import java.util.Comparator;
import org.apache.commons.collections.ComparatorUtils; import org.apache.commons.collections.ComparatorUtils;
@ -25,6 +26,8 @@ import org.apache.commons.collections.Transformer;
* Decorates another Comparator with transformation behavior. That is, the * Decorates another Comparator with transformation behavior. That is, the
* return value from the transform operation will be passed to the decorated * return value from the transform operation will be passed to the decorated
* {@link Comparator#compare(Object,Object) compare} method. * {@link Comparator#compare(Object,Object) compare} method.
* <p>
* This class is Serializable from Commons Collections 4.0.
* *
* @since 2.1 * @since 2.1
* @version $Id$ * @version $Id$
@ -32,7 +35,10 @@ import org.apache.commons.collections.Transformer;
* @see org.apache.commons.collections.Transformer * @see org.apache.commons.collections.Transformer
* @see org.apache.commons.collections.comparators.ComparableComparator * @see org.apache.commons.collections.comparators.ComparableComparator
*/ */
public class TransformingComparator<E> implements Comparator<E> { public class TransformingComparator<E> implements Comparator<E>, Serializable {
/** Serialization version from Collections 4.0. */
private static final long serialVersionUID = 3456940356043606220L;
/** The decorated comparator. */ /** The decorated comparator. */
protected final Comparator<E> decorated; protected final Comparator<E> decorated;
@ -76,5 +82,48 @@ public class TransformingComparator<E> implements Comparator<E> {
return this.decorated.compare(value1, value2); return this.decorated.compare(value1, value2);
} }
//-----------------------------------------------------------------------
/**
* Implement a hash code for this comparator that is consistent with
* {@link #equals(Object) equals}.
*
* @return a hash code for this comparator.
*/
@Override
public int hashCode() {
int total = 17;
total = total*37 + (decorated == null ? 0 : decorated.hashCode());
total = total*37 + (transformer == null ? 0 : transformer.hashCode());
return total;
}
/**
* Returns <code>true</code> iff <i>that</i> Object is
* is a {@link Comparator} whose ordering is known to be
* equivalent to mine.
* <p>
* This implementation returns <code>true</code>
* iff <code><i>that</i></code> is a {@link TransformingComparator}
* whose attributes are equal to mine.
*
* @param object the object to compare to
* @return true if equal
*/
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (null == object) {
return false;
}
if (object.getClass().equals(this.getClass())) {
TransformingComparator<?> comp = (TransformingComparator<?>) object;
return (null == decorated ? null == comp.decorated : decorated.equals(comp.decorated) &&
null == transformer ? null == comp.transformer : transformer.equals(comp.transformer));
}
return false;
}
} }

View File

@ -25,23 +25,22 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.apache.commons.collections.AbstractTestObject; import org.apache.commons.collections.AbstractTestObject;
import org.junit.Test;
/** /**
* Abstract test class for testing the Comparator interface. * Abstract test class for testing the Comparator interface.
* <p> * <p>
* Concrete subclasses declare the comparator to be tested. * Concrete subclasses declare the comparator to be tested.
* They also declare certain aspects of the tests. * They also declare certain aspects of the tests.
*
* @author Stephen Colebourne
*/ */
public abstract class AbstractTestComparator<T> extends AbstractTestObject { public abstract class AbstractComparatorTest<T> extends AbstractTestObject {
/** /**
* JUnit constructor. * JUnit constructor.
* *
* @param testName the test class name * @param testName the test class name
*/ */
public AbstractTestComparator(String testName) { public AbstractComparatorTest(String testName) {
super(testName); super(testName);
} }
@ -114,6 +113,7 @@ public abstract class AbstractTestComparator<T> extends AbstractTestObject {
/** /**
* Test sorting an empty list * Test sorting an empty list
*/ */
@Test
public void testEmptyListSort() { public void testEmptyListSort() {
List<T> list = new LinkedList<T>(); List<T> list = new LinkedList<T>();
sortObjects(list, makeObject()); sortObjects(list, makeObject());
@ -126,6 +126,7 @@ public abstract class AbstractTestComparator<T> extends AbstractTestObject {
/** /**
* Test sorting a reversed list. * Test sorting a reversed list.
*/ */
@Test
public void testReverseListSort() { public void testReverseListSort() {
Comparator<T> comparator = makeObject(); Comparator<T> comparator = makeObject();
@ -142,6 +143,7 @@ public abstract class AbstractTestComparator<T> extends AbstractTestObject {
/** /**
* Test sorting a random list. * Test sorting a random list.
*/ */
@Test
public void testRandomListSort() { public void testRandomListSort() {
Comparator<T> comparator = makeObject(); Comparator<T> comparator = makeObject();
@ -166,6 +168,7 @@ public abstract class AbstractTestComparator<T> extends AbstractTestObject {
/** /**
* Nearly all Comparators should be Serializable. * Nearly all Comparators should be Serializable.
*/ */
@Test
public void testComparatorIsSerializable() { public void testComparatorIsSerializable() {
Comparator<T> comparator = makeObject(); Comparator<T> comparator = makeObject();
assertTrue("This comparator should be Serializable.", assertTrue("This comparator should be Serializable.",
@ -189,6 +192,7 @@ public abstract class AbstractTestComparator<T> extends AbstractTestObject {
* against the canonical version in SVN. * against the canonical version in SVN.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Test
public void testComparatorCompatibility() throws IOException, ClassNotFoundException { public void testComparatorCompatibility() throws IOException, ClassNotFoundException {
if (!skipSerializedCanonicalTests()) { if (!skipSerializedCanonicalTests()) {
Comparator<T> comparator = null; Comparator<T> comparator = null;

View File

@ -26,18 +26,16 @@ import junit.framework.TestSuite;
/** /**
* Test the NullComparator. * Test the NullComparator.
* *
* @version $Revision$ * @version $Id$
*
* @author Michael A. Smith
*/ */
public abstract class AbstractTestNullComparator extends AbstractTestComparator<Integer> { public abstract class AbstractNullComparatorTest extends AbstractComparatorTest<Integer> {
public AbstractTestNullComparator(String testName) { public AbstractNullComparatorTest(String testName) {
super(testName); super(testName);
} }
public static Test suite() { public static Test suite() {
TestSuite suite = new TestSuite(AbstractTestNullComparator.class.getName()); TestSuite suite = new TestSuite(AbstractNullComparatorTest.class.getName());
suite.addTest(new TestSuite(TestNullComparator1.class)); suite.addTest(new TestSuite(TestNullComparator1.class));
suite.addTest(new TestSuite(TestNullComparator2.class)); suite.addTest(new TestSuite(TestNullComparator2.class));
return suite; return suite;
@ -46,7 +44,7 @@ public abstract class AbstractTestNullComparator extends AbstractTestComparator<
/** /**
* Test the NullComparator with nulls high, using comparable comparator * Test the NullComparator with nulls high, using comparable comparator
**/ **/
public static class TestNullComparator1 extends AbstractTestNullComparator { public static class TestNullComparator1 extends AbstractNullComparatorTest {
public TestNullComparator1(String testName) { public TestNullComparator1(String testName) {
super(testName); super(testName);
@ -78,7 +76,7 @@ public abstract class AbstractTestNullComparator extends AbstractTestComparator<
/** /**
* Test the NullComparator with nulls low using the comparable comparator * Test the NullComparator with nulls low using the comparable comparator
**/ **/
public static class TestNullComparator2 extends AbstractTestNullComparator { public static class TestNullComparator2 extends AbstractNullComparatorTest {
public TestNullComparator2(String testName) { public TestNullComparator2(String testName) {
super(testName); super(testName);

View File

@ -20,20 +20,20 @@ import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import org.junit.Test;
/** /**
* Tests for {@link BooleanComparator}. * Tests for {@link BooleanComparator}.
* *
* @version $Revision$ * @version $Id$
*
* @author Rodney Waldhoff
*/ */
@SuppressWarnings("boxing") @SuppressWarnings("boxing")
public class TestBooleanComparator extends AbstractTestComparator<Boolean> { public class BooleanComparatorTest extends AbstractComparatorTest<Boolean> {
// conventional // conventional
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
public TestBooleanComparator(String testName) { public BooleanComparatorTest(String testName) {
super(testName); super(testName);
} }
@ -65,12 +65,15 @@ public class TestBooleanComparator extends AbstractTestComparator<Boolean> {
// tests // tests
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@Test
public void testConstructors() { public void testConstructors() {
allTests(false,new BooleanComparator()); allTests(false,new BooleanComparator());
allTests(false,new BooleanComparator(false)); allTests(false,new BooleanComparator(false));
allTests(true,new BooleanComparator(true)); allTests(true,new BooleanComparator(true));
} }
@Test
public void testStaticFactoryMethods() { public void testStaticFactoryMethods() {
allTests(false,BooleanComparator.getFalseFirstComparator()); allTests(false,BooleanComparator.getFalseFirstComparator());
allTests(false,BooleanComparator.booleanComparator(false)); allTests(false,BooleanComparator.booleanComparator(false));
@ -78,6 +81,7 @@ public class TestBooleanComparator extends AbstractTestComparator<Boolean> {
allTests(true,BooleanComparator.booleanComparator(true)); allTests(true,BooleanComparator.booleanComparator(true));
} }
@Test
public void testEqualsCompatibleInstance() { public void testEqualsCompatibleInstance() {
assertEquals(new BooleanComparator(),new BooleanComparator(false)); assertEquals(new BooleanComparator(),new BooleanComparator(false));
assertEquals(new BooleanComparator(false),new BooleanComparator(false)); assertEquals(new BooleanComparator(false),new BooleanComparator(false));

View File

@ -23,13 +23,13 @@ import java.util.List;
/** /**
* Tests for ComparableComparator. * Tests for ComparableComparator.
* *
* @version $Revision$ * @version $Id$
* *
*/ */
@SuppressWarnings("boxing") @SuppressWarnings("boxing")
public class TestComparableComparator extends AbstractTestComparator<Integer> { public class ComparableComparatorTest extends AbstractComparatorTest<Integer> {
public TestComparableComparator(String testName) { public ComparableComparatorTest(String testName) {
super(testName); super(testName);
} }

View File

@ -21,16 +21,16 @@ import java.util.Comparator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.junit.Test;
/** /**
* Tests for ComparatorChain. * Tests for ComparatorChain.
* *
* @version $Revision$ * @version $Id$
*
* @author Unknown
*/ */
public class TestComparatorChain extends AbstractTestComparator<TestComparatorChain.PseudoRow> { public class ComparatorChainTest extends AbstractComparatorTest<ComparatorChainTest.PseudoRow> {
public TestComparatorChain(String testName) { public ComparatorChainTest(String testName) {
super(testName); super(testName);
} }
@ -42,6 +42,7 @@ public class TestComparatorChain extends AbstractTestComparator<TestComparatorCh
return chain; return chain;
} }
@Test
public void testNoopComparatorChain() { public void testNoopComparatorChain() {
ComparatorChain<Integer> chain = new ComparatorChain<Integer>(); ComparatorChain<Integer> chain = new ComparatorChain<Integer>();
Integer i1 = new Integer(4); Integer i1 = new Integer(4);
@ -52,6 +53,7 @@ public class TestComparatorChain extends AbstractTestComparator<TestComparatorCh
assertTrue("Comparison returns the right order", chain.compare(i1, i2) == correctValue); assertTrue("Comparison returns the right order", chain.compare(i1, i2) == correctValue);
} }
@Test
public void testBadNoopComparatorChain() { public void testBadNoopComparatorChain() {
ComparatorChain<Integer> chain = new ComparatorChain<Integer>(); ComparatorChain<Integer> chain = new ComparatorChain<Integer>();
Integer i1 = new Integer(4); Integer i1 = new Integer(4);
@ -63,6 +65,7 @@ public class TestComparatorChain extends AbstractTestComparator<TestComparatorCh
} }
} }
@Test
public void testListComparatorChain() { public void testListComparatorChain() {
List<Comparator<Integer>> list = new LinkedList<Comparator<Integer>>(); List<Comparator<Integer>> list = new LinkedList<Comparator<Integer>>();
list.add(new ComparableComparator<Integer>()); list.add(new ComparableComparator<Integer>());
@ -74,6 +77,7 @@ public class TestComparatorChain extends AbstractTestComparator<TestComparatorCh
assertTrue("Comparison returns the right order", chain.compare(i1, i2) == correctValue); assertTrue("Comparison returns the right order", chain.compare(i1, i2) == correctValue);
} }
@Test
public void testBadListComparatorChain() { public void testBadListComparatorChain() {
List<Comparator<Integer>> list = new LinkedList<Comparator<Integer>>(); List<Comparator<Integer>> list = new LinkedList<Comparator<Integer>>();
ComparatorChain<Integer> chain = new ComparatorChain<Integer>(list); ComparatorChain<Integer> chain = new ComparatorChain<Integer>(list);
@ -86,6 +90,7 @@ public class TestComparatorChain extends AbstractTestComparator<TestComparatorCh
} }
} }
@Test
public void testComparatorChainOnMinvaluedCompatator() { public void testComparatorChainOnMinvaluedCompatator() {
// -1 * Integer.MIN_VALUE is less than 0, // -1 * Integer.MIN_VALUE is less than 0,
// test that ComparatorChain handles this edge case correctly // test that ComparatorChain handles this edge case correctly

View File

@ -22,17 +22,14 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import junit.framework.TestCase; import org.junit.Test;
/** /**
* Test class for FixedOrderComparator. * Test class for FixedOrderComparator.
* *
* @version $Revision$ * @version $Id$
*
* @author David Leppik
* @author Stephen Colebourne
*/ */
public class TestFixedOrderComparator extends TestCase { public class FixedOrderComparatorTest extends AbstractComparatorTest<String> {
/** /**
* Top cities of the world, by population including metro areas. * Top cities of the world, by population including metro areas.
@ -54,7 +51,7 @@ public class TestFixedOrderComparator extends TestCase {
// Initialization and busywork // Initialization and busywork
// //
public TestFixedOrderComparator(String name) { public FixedOrderComparatorTest(String name) {
super(name); super(name);
} }
@ -62,7 +59,21 @@ public class TestFixedOrderComparator extends TestCase {
// Set up and tear down // Set up and tear down
// //
@Override
public Comparator<String> makeObject() {
FixedOrderComparator<String> comparator = new FixedOrderComparator<String>(topCities);
return comparator;
}
@Override
public List<String> getComparableObjectsOrdered() {
return Arrays.asList(topCities);
}
@Override
public String getCompatibilityVersion() {
return "4";
}
// //
// The tests // The tests
@ -71,6 +82,7 @@ public class TestFixedOrderComparator extends TestCase {
/** /**
* Tests that the constructor plus add method compares items properly. * Tests that the constructor plus add method compares items properly.
*/ */
@Test
public void testConstructorPlusAdd() { public void testConstructorPlusAdd() {
FixedOrderComparator<String> comparator = new FixedOrderComparator<String>(); FixedOrderComparator<String> comparator = new FixedOrderComparator<String>();
for (int i = 0; i < topCities.length; i++) { for (int i = 0; i < topCities.length; i++) {
@ -83,6 +95,7 @@ public class TestFixedOrderComparator extends TestCase {
/** /**
* Tests that the array constructor compares items properly. * Tests that the array constructor compares items properly.
*/ */
@Test
public void testArrayConstructor() { public void testArrayConstructor() {
String[] keys = topCities.clone(); String[] keys = topCities.clone();
String[] topCitiesForTest = topCities.clone(); String[] topCitiesForTest = topCities.clone();
@ -96,6 +109,7 @@ public class TestFixedOrderComparator extends TestCase {
/** /**
* Tests the list constructor. * Tests the list constructor.
*/ */
@Test
public void testListConstructor() { public void testListConstructor() {
String[] keys = topCities.clone(); String[] keys = topCities.clone();
List<String> topCitiesForTest = new LinkedList<String>(Arrays.asList(topCities)); List<String> topCitiesForTest = new LinkedList<String>(Arrays.asList(topCities));
@ -109,6 +123,7 @@ public class TestFixedOrderComparator extends TestCase {
/** /**
* Tests addAsEqual method. * Tests addAsEqual method.
*/ */
@Test
public void testAddAsEqual() { public void testAddAsEqual() {
FixedOrderComparator<String> comparator = new FixedOrderComparator<String>(topCities); FixedOrderComparator<String> comparator = new FixedOrderComparator<String>(topCities);
comparator.addAsEqual("New York", "Minneapolis"); comparator.addAsEqual("New York", "Minneapolis");
@ -120,6 +135,7 @@ public class TestFixedOrderComparator extends TestCase {
/** /**
* Tests whether or not updates are disabled after a comparison is made. * Tests whether or not updates are disabled after a comparison is made.
*/ */
@Test
public void testLock() { public void testLock() {
FixedOrderComparator<String> comparator = new FixedOrderComparator<String>(topCities); FixedOrderComparator<String> comparator = new FixedOrderComparator<String>(topCities);
assertEquals(false, comparator.isLocked()); assertEquals(false, comparator.isLocked());
@ -140,6 +156,7 @@ public class TestFixedOrderComparator extends TestCase {
} }
} }
@Test
public void testUnknownObjectBehavior() { public void testUnknownObjectBehavior() {
FixedOrderComparator<String> comparator = new FixedOrderComparator<String>(topCities); FixedOrderComparator<String> comparator = new FixedOrderComparator<String>(topCities);
try { try {
@ -186,7 +203,6 @@ public class TestFixedOrderComparator extends TestCase {
/** Shuffles the keys and asserts that the comparator sorts them back to /** Shuffles the keys and asserts that the comparator sorts them back to
* their original order. * their original order.
*/ */
@SuppressWarnings("unused")
private void assertComparatorYieldsOrder(String[] orderedObjects, private void assertComparatorYieldsOrder(String[] orderedObjects,
Comparator<String> comparator) { Comparator<String> comparator) {
String[] keys = orderedObjects.clone(); String[] keys = orderedObjects.clone();

View File

@ -25,16 +25,16 @@ import java.util.Comparator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.junit.Test;
/** /**
* Tests for ReverseComparator. * Tests for ReverseComparator.
* *
* @version $Revision$ * @version $Id$
*
* @author Unknown
*/ */
public class TestReverseComparator extends AbstractTestComparator<Integer> { public class ReverseComparatorTest extends AbstractComparatorTest<Integer> {
public TestReverseComparator(String testName) { public ReverseComparatorTest(String testName) {
super(testName); super(testName);
} }
@ -71,6 +71,7 @@ public class TestReverseComparator extends AbstractTestComparator<Integer> {
*/ */
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Test
public void testSerializeDeserializeThenCompare() throws Exception { public void testSerializeDeserializeThenCompare() throws Exception {
Comparator comp = new ReverseComparator(new ComparableComparator()); Comparator comp = new ReverseComparator(new ComparableComparator());

View File

@ -0,0 +1,72 @@
/*
* 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.comparators;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.collections.TransformerUtils;
/**
* Test class for TransformingComparator.
*
* @version $Id$
*/
public class TransformingComparatorTest extends AbstractComparatorTest<Integer> {
//
// Initialization and busywork
//
public TransformingComparatorTest(String name) {
super(name);
}
//
// Set up and tear down
//
@Override
public Comparator<Integer> makeObject() {
Comparator<Integer> decorated = new ComparableComparator<Integer>();
TransformingComparator<Integer> comparator =
new TransformingComparator<Integer>(TransformerUtils.<Integer>nopTransformer(), decorated);
return comparator;
}
@Override
public List<Integer> getComparableObjectsOrdered() {
List<Integer> list = new LinkedList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
return list;
}
@Override
public String getCompatibilityVersion() {
return "4";
}
//
// The tests
//
}