[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;
import java.io.Serializable;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@ -39,11 +40,16 @@ import java.util.Map;
* Instances of FixedOrderComparator are not synchronized. The class is not
* thread-safe at construction time, but it is thread-safe to perform
* multiple comparisons after all the setup operations are complete.
* <p>
* This class is Serializable from Commons Collections 4.0.
*
* @since 3.0
* @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.
@ -240,4 +246,53 @@ public class FixedOrderComparator<T> implements Comparator<T> {
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;
import java.io.Serializable;
import java.util.Comparator;
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
* return value from the transform operation will be passed to the decorated
* {@link Comparator#compare(Object,Object) compare} method.
* <p>
* This class is Serializable from Commons Collections 4.0.
*
* @since 2.1
* @version $Id$
@ -32,7 +35,10 @@ import org.apache.commons.collections.Transformer;
* @see org.apache.commons.collections.Transformer
* @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. */
protected final Comparator<E> decorated;
@ -76,5 +82,48 @@ public class TransformingComparator<E> implements Comparator<E> {
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 org.apache.commons.collections.AbstractTestObject;
import org.junit.Test;
/**
* Abstract test class for testing the Comparator interface.
* <p>
* Concrete subclasses declare the comparator to be tested.
* 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.
*
* @param testName the test class name
*/
public AbstractTestComparator(String testName) {
public AbstractComparatorTest(String testName) {
super(testName);
}
@ -114,6 +113,7 @@ public abstract class AbstractTestComparator<T> extends AbstractTestObject {
/**
* Test sorting an empty list
*/
@Test
public void testEmptyListSort() {
List<T> list = new LinkedList<T>();
sortObjects(list, makeObject());
@ -126,6 +126,7 @@ public abstract class AbstractTestComparator<T> extends AbstractTestObject {
/**
* Test sorting a reversed list.
*/
@Test
public void testReverseListSort() {
Comparator<T> comparator = makeObject();
@ -142,6 +143,7 @@ public abstract class AbstractTestComparator<T> extends AbstractTestObject {
/**
* Test sorting a random list.
*/
@Test
public void testRandomListSort() {
Comparator<T> comparator = makeObject();
@ -166,6 +168,7 @@ public abstract class AbstractTestComparator<T> extends AbstractTestObject {
/**
* Nearly all Comparators should be Serializable.
*/
@Test
public void testComparatorIsSerializable() {
Comparator<T> comparator = makeObject();
assertTrue("This comparator should be Serializable.",
@ -189,6 +192,7 @@ public abstract class AbstractTestComparator<T> extends AbstractTestObject {
* against the canonical version in SVN.
*/
@SuppressWarnings("unchecked")
@Test
public void testComparatorCompatibility() throws IOException, ClassNotFoundException {
if (!skipSerializedCanonicalTests()) {
Comparator<T> comparator = null;
@ -201,7 +205,7 @@ public abstract class AbstractTestComparator<T> extends AbstractTestObject {
boolean autoCreateSerialized = false;
if (autoCreateSerialized) {
comparator = makeObject();
comparator = makeObject();
String fileName = getCanonicalComparatorName(comparator);
writeExternalFormToDisk((Serializable) comparator, fileName);
fail("Serialized form could not be found. A serialized version "

View File

@ -26,18 +26,16 @@ import junit.framework.TestSuite;
/**
* Test the NullComparator.
*
* @version $Revision$
*
* @author Michael A. Smith
* @version $Id$
*/
public abstract class AbstractTestNullComparator extends AbstractTestComparator<Integer> {
public abstract class AbstractNullComparatorTest extends AbstractComparatorTest<Integer> {
public AbstractTestNullComparator(String testName) {
public AbstractNullComparatorTest(String testName) {
super(testName);
}
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(TestNullComparator2.class));
return suite;
@ -46,7 +44,7 @@ public abstract class AbstractTestNullComparator extends AbstractTestComparator<
/**
* 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) {
super(testName);
@ -78,7 +76,7 @@ public abstract class AbstractTestNullComparator extends AbstractTestComparator<
/**
* 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) {
super(testName);

View File

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

View File

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

View File

@ -21,16 +21,16 @@ import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
/**
* Tests for ComparatorChain.
*
* @version $Revision$
*
* @author Unknown
* @version $Id$
*/
public class TestComparatorChain extends AbstractTestComparator<TestComparatorChain.PseudoRow> {
public class ComparatorChainTest extends AbstractComparatorTest<ComparatorChainTest.PseudoRow> {
public TestComparatorChain(String testName) {
public ComparatorChainTest(String testName) {
super(testName);
}
@ -42,6 +42,7 @@ public class TestComparatorChain extends AbstractTestComparator<TestComparatorCh
return chain;
}
@Test
public void testNoopComparatorChain() {
ComparatorChain<Integer> chain = new ComparatorChain<Integer>();
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);
}
@Test
public void testBadNoopComparatorChain() {
ComparatorChain<Integer> chain = new ComparatorChain<Integer>();
Integer i1 = new Integer(4);
@ -63,6 +65,7 @@ public class TestComparatorChain extends AbstractTestComparator<TestComparatorCh
}
}
@Test
public void testListComparatorChain() {
List<Comparator<Integer>> list = new LinkedList<Comparator<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);
}
@Test
public void testBadListComparatorChain() {
List<Comparator<Integer>> list = new LinkedList<Comparator<Integer>>();
ComparatorChain<Integer> chain = new ComparatorChain<Integer>(list);
@ -86,6 +90,7 @@ public class TestComparatorChain extends AbstractTestComparator<TestComparatorCh
}
}
@Test
public void testComparatorChainOnMinvaluedCompatator() {
// -1 * Integer.MIN_VALUE is less than 0,
// 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.Random;
import junit.framework.TestCase;
import org.junit.Test;
/**
* Test class for FixedOrderComparator.
*
* @version $Revision$
*
* @author David Leppik
* @author Stephen Colebourne
* @version $Id$
*/
public class TestFixedOrderComparator extends TestCase {
public class FixedOrderComparatorTest extends AbstractComparatorTest<String> {
/**
* Top cities of the world, by population including metro areas.
@ -54,7 +51,7 @@ public class TestFixedOrderComparator extends TestCase {
// Initialization and busywork
//
public TestFixedOrderComparator(String name) {
public FixedOrderComparatorTest(String name) {
super(name);
}
@ -62,7 +59,21 @@ public class TestFixedOrderComparator extends TestCase {
// 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
@ -71,6 +82,7 @@ public class TestFixedOrderComparator extends TestCase {
/**
* Tests that the constructor plus add method compares items properly.
*/
@Test
public void testConstructorPlusAdd() {
FixedOrderComparator<String> comparator = new FixedOrderComparator<String>();
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.
*/
@Test
public void testArrayConstructor() {
String[] keys = topCities.clone();
String[] topCitiesForTest = topCities.clone();
@ -96,6 +109,7 @@ public class TestFixedOrderComparator extends TestCase {
/**
* Tests the list constructor.
*/
@Test
public void testListConstructor() {
String[] keys = topCities.clone();
List<String> topCitiesForTest = new LinkedList<String>(Arrays.asList(topCities));
@ -109,6 +123,7 @@ public class TestFixedOrderComparator extends TestCase {
/**
* Tests addAsEqual method.
*/
@Test
public void testAddAsEqual() {
FixedOrderComparator<String> comparator = new FixedOrderComparator<String>(topCities);
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.
*/
@Test
public void testLock() {
FixedOrderComparator<String> comparator = new FixedOrderComparator<String>(topCities);
assertEquals(false, comparator.isLocked());
@ -140,6 +156,7 @@ public class TestFixedOrderComparator extends TestCase {
}
}
@Test
public void testUnknownObjectBehavior() {
FixedOrderComparator<String> comparator = new FixedOrderComparator<String>(topCities);
try {
@ -186,7 +203,6 @@ public class TestFixedOrderComparator extends TestCase {
/** Shuffles the keys and asserts that the comparator sorts them back to
* their original order.
*/
@SuppressWarnings("unused")
private void assertComparatorYieldsOrder(String[] orderedObjects,
Comparator<String> comparator) {
String[] keys = orderedObjects.clone();

View File

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