Add new FixedOrderComparator that allows the order to be easily specified
from David Leppik, bug ref 16823 git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@131005 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
37b4ba1135
commit
54a2013989
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/comparators/FixedOrderComparator.java,v 1.1 2003/04/13 17:37:26 scolebourne Exp $
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution, if
|
||||
* any, must include the following acknowlegement:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowlegement may appear in the software itself,
|
||||
* if and wherever such third-party acknowlegements normally appear.
|
||||
*
|
||||
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
|
||||
* Foundation" must not be used to endorse or promote products derived
|
||||
* from this software without prior written permission. For written
|
||||
* permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Group.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.commons.collections.comparators;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A Comparator which imposes a specific order on a specific set of Objects.
|
||||
* Objects are presented to the FixedOrderComparator in a specified order and
|
||||
* subsequent calls to {@link #compare} yield that order.
|
||||
* For example:
|
||||
* <pre>
|
||||
* String[] planets = {"Mercury", "Venus", "Earth", "Mars"};
|
||||
* FixedOrderComparator distanceFromSun = new FixedOrderComparator(planets);
|
||||
* Arrays.sort(planets); // Sort to alphabetical order
|
||||
* Arrays.sort(planets, distanceFromSun); // Back to original order
|
||||
* </pre>
|
||||
* <p>
|
||||
* Once {@link #compare} has been called, the FixedOrderComparator is locked and
|
||||
* attempts to modify it yield an UnsupportedOperationException.
|
||||
* <p>
|
||||
* 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.
|
||||
*
|
||||
* @since Commons Collections 2.2
|
||||
* @version $Revision: 1.1 $ $Date: 2003/04/13 17:37:26 $
|
||||
*
|
||||
* @author David Leppik
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public class FixedOrderComparator implements Comparator {
|
||||
|
||||
/**
|
||||
* Behavior when comparing unknown Objects:
|
||||
* unknown objects compare as before known Objects.
|
||||
*/
|
||||
public static final int UNKNOWN_BEFORE = 0;
|
||||
|
||||
/**
|
||||
* Behavior when comparing unknown Objects:
|
||||
* unknown objects compare as before known Objects.
|
||||
*/
|
||||
public static final int UNKNOWN_AFTER = 1;
|
||||
|
||||
/**
|
||||
* Behavior when comparing unknown Objects:
|
||||
* unknown objects cause a IllegalArgumentException to be thrown.
|
||||
* This is the default behavior.
|
||||
*/
|
||||
public static final int UNKNOWN_THROW_EXCEPTION = 2;
|
||||
|
||||
/** Internal map of object to position */
|
||||
private final Map map = new HashMap();
|
||||
/** Counter used in determining the position in the map */
|
||||
private int counter = 0;
|
||||
/** Is the comparator locked against further change */
|
||||
private boolean isLocked = false;
|
||||
/** The behaviour in the case of an unknown object */
|
||||
private int unknownObjectBehavior = UNKNOWN_THROW_EXCEPTION;
|
||||
|
||||
// Constructors
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Constructs an empty FixedOrderComparator.
|
||||
*/
|
||||
public FixedOrderComparator() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a FixedOrderComparator which uses the order of the given array
|
||||
* to compare the objects.
|
||||
* <p>
|
||||
* The array is copied, so later changes will not affect the comparator.
|
||||
*
|
||||
* @param items the items that the comparator can compare in order
|
||||
* @throws IllegalArgumentException if the array is null
|
||||
*/
|
||||
public FixedOrderComparator(Object[] items) {
|
||||
super();
|
||||
if (items == null) {
|
||||
throw new IllegalArgumentException("The list of items must not be null");
|
||||
}
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
add(items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a FixedOrderComparator which uses the order of the given list
|
||||
* to compare the objects.
|
||||
* <p>
|
||||
* The list is copied, so later changes will not affect the comparator.
|
||||
*
|
||||
* @param items the items that the comparator can compare in order
|
||||
* @throws IllegalArgumentException if the list is null
|
||||
*/
|
||||
public FixedOrderComparator(List items) {
|
||||
super();
|
||||
if (items == null) {
|
||||
throw new IllegalArgumentException("The list of items must not be null");
|
||||
}
|
||||
for (Iterator it = items.iterator(); it.hasNext();) {
|
||||
add(it.next());
|
||||
}
|
||||
}
|
||||
|
||||
// Bean methods / state querying methods
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns true if modifications cannot be made to the FixedOrderComparator.
|
||||
* FixedOrderComparators cannot be modified once they have performed a comparison.
|
||||
*
|
||||
* @return true if attempts to change the FixedOrderComparator yield an
|
||||
* UnsupportedOperationException, false if it can be changed.
|
||||
*/
|
||||
public boolean isLocked() {
|
||||
return isLocked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see whether the comparator is now locked against further changes.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the comparator is locked
|
||||
*/
|
||||
protected void checkLocked() {
|
||||
if (isLocked()) {
|
||||
throw new UnsupportedOperationException("Cannot modify a FixedOrderComparator after a comparison");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the behavior for comparing unknown objects.
|
||||
*/
|
||||
public int getUnkownObjectBehavior() {
|
||||
return unknownObjectBehavior;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the behavior for comparing unknown objects.
|
||||
*
|
||||
* @throws UnsupportedOperationException if a comparison has been performed
|
||||
* @throws IllegalArgumentException if the unknown flag is not valid
|
||||
*/
|
||||
public void setUnknownObjectBehavior(int unknownObjectBehavior) {
|
||||
checkLocked();
|
||||
if (unknownObjectBehavior != UNKNOWN_AFTER
|
||||
&& unknownObjectBehavior != UNKNOWN_BEFORE
|
||||
&& unknownObjectBehavior != UNKNOWN_THROW_EXCEPTION) {
|
||||
throw new IllegalArgumentException("Unrecognised value for unkown behaviour flag");
|
||||
}
|
||||
this.unknownObjectBehavior = unknownObjectBehavior;
|
||||
}
|
||||
|
||||
// Methods for adding items
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Adds an item, which compares as after all items known to the Comparator.
|
||||
* If the item is already known to the Comparator, its old position is
|
||||
* replaced with the new position.
|
||||
*
|
||||
* @param obj the item to be added to the Comparator.
|
||||
* @return true if obj has been added for the first time, false if
|
||||
* it was already known to the Comparator.
|
||||
* @throws UnsupportedOperationException if a comparison has already been made
|
||||
*/
|
||||
public boolean add(Object obj) {
|
||||
checkLocked();
|
||||
Object position = map.put(obj, new Integer(counter++));
|
||||
return (position == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new item, which compares as equal to the given existing item.
|
||||
*
|
||||
* @param existingObj an item already in the Comparator's set of
|
||||
* known objects
|
||||
* @param newObj an item to be added to the Comparator's set of
|
||||
* known objects
|
||||
* @return true if newObj has been added for the first time, false if
|
||||
* it was already known to the Comparator.
|
||||
* @throws IllegalArgumentException if existingObject is not in the
|
||||
* Comparator's set of known objects.
|
||||
* @throws UnsupportedOperationException if a comparison has already been made
|
||||
*/
|
||||
public boolean addAsEqual(Object existingObj, Object newObj) {
|
||||
checkLocked();
|
||||
Integer position = (Integer) map.get(existingObj);
|
||||
if (position == null) {
|
||||
throw new IllegalArgumentException(existingObj + " not known to " + this);
|
||||
}
|
||||
Object result = map.put(newObj, position);
|
||||
return (result == null);
|
||||
}
|
||||
|
||||
// Comparator methods
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Compares two objects according to the order of this Comparator.
|
||||
* <p>
|
||||
* It is important to note that this class will throw an IllegalArgumentException
|
||||
* in the case of an unrecognised object. This is not specified in the
|
||||
* Comparator interface, but is the most appropriate exception.
|
||||
*
|
||||
* @param obj1 the first object to compare
|
||||
* @param obj2 the second object to compare
|
||||
* @throws IllegalArgumentException if o1 or o2 are not known
|
||||
* to this Comparator and an alternative behavior has not been set
|
||||
* via {@link #setUnknownObjectBehavior(int)}.
|
||||
*/
|
||||
public int compare(Object obj1, Object obj2) {
|
||||
isLocked = true;
|
||||
Integer position1 = (Integer) map.get(obj1);
|
||||
Integer position2 = (Integer) map.get(obj2);
|
||||
if (position1 == null || position2 == null) {
|
||||
switch (unknownObjectBehavior) {
|
||||
case UNKNOWN_BEFORE :
|
||||
if (position1 == null) {
|
||||
return (position2 == null) ? 0 : -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
case UNKNOWN_AFTER :
|
||||
if (position1 == null) {
|
||||
return (position2 == null) ? 0 : 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
case UNKNOWN_THROW_EXCEPTION :
|
||||
Object unknownObj = (position1 == null) ? obj1 : obj2;
|
||||
throw new IllegalArgumentException("Attempting to compare unknown object " + unknownObj);
|
||||
default :
|
||||
throw new UnsupportedOperationException("Unknown unknownObjectBehavior: " + unknownObjectBehavior);
|
||||
}
|
||||
} else {
|
||||
return position1.compareTo(position2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/comparators/TestAll.java,v 1.2 2003/01/10 00:21:08 rwaldhoff Exp $
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/comparators/TestAll.java,v 1.3 2003/04/13 17:37:26 scolebourne Exp $
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
|
@ -55,16 +55,17 @@
|
|||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.commons.collections.comparators;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
/**
|
||||
* Entry point for all Comparator Collections tests.
|
||||
*
|
||||
* @author Stephen Colebourne
|
||||
* @version $Revision: 1.2 $ $Date: 2003/01/10 00:21:08 $
|
||||
* @version $Revision: 1.3 $ $Date: 2003/04/13 17:37:26 $
|
||||
*/
|
||||
public class TestAll extends TestCase {
|
||||
public TestAll(String testName) {
|
||||
|
@ -76,6 +77,7 @@ public class TestAll extends TestCase {
|
|||
suite.addTest(TestBooleanComparator.suite());
|
||||
suite.addTest(TestComparableComparator.suite());
|
||||
suite.addTest(TestComparatorChain.suite());
|
||||
suite.addTest(TestFixedOrderComparator.suite());
|
||||
suite.addTest(TestNullComparator.suite());
|
||||
suite.addTest(TestReverseComparator.suite());
|
||||
return suite;
|
||||
|
@ -85,4 +87,5 @@ public class TestAll extends TestCase {
|
|||
String[] testCaseName = { TestAll.class.getName() };
|
||||
junit.textui.TestRunner.main(testCaseName);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/comparators/TestFixedOrderComparator.java,v 1.1 2003/04/13 17:37:26 scolebourne Exp $
|
||||
* $Revision: 1.1 $
|
||||
* $Date: 2003/04/13 17:37:26 $
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 1999-2001 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution, if
|
||||
* any, must include the following acknowlegement:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowlegement may appear in the software itself,
|
||||
* if and wherever such third-party acknowlegements normally appear.
|
||||
*
|
||||
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
|
||||
* Foundation" must not be used to endorse or promote products derived
|
||||
* from this software without prior written permission. For written
|
||||
* permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Group.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.commons.collections.comparators;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
/**
|
||||
* Test class for FixedOrderComparator.
|
||||
*
|
||||
* @author David Leppik
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public class TestFixedOrderComparator extends TestCase {
|
||||
|
||||
|
||||
/**
|
||||
* Top cities of the world, by population including metro areas.
|
||||
*/
|
||||
public static final String topCities[] = new String[] {
|
||||
"Tokyo",
|
||||
"Mexico City",
|
||||
"Mumbai",
|
||||
"Sao Paulo",
|
||||
"New York",
|
||||
"Shanghai",
|
||||
"Lagos",
|
||||
"Los Angeles",
|
||||
"Calcutta",
|
||||
"Buenos Aires"
|
||||
};
|
||||
|
||||
//
|
||||
// Initialization and busywork
|
||||
//
|
||||
|
||||
public TestFixedOrderComparator(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return new TestSuite(TestFixedOrderComparator.class);
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
junit.textui.TestRunner.run(suite());
|
||||
}
|
||||
|
||||
//
|
||||
// Set up and tear down
|
||||
//
|
||||
|
||||
|
||||
|
||||
//
|
||||
// The tests
|
||||
//
|
||||
|
||||
/**
|
||||
* Tests that the constructor plus add method compares items properly.
|
||||
*/
|
||||
public void testConstructorPlusAdd() {
|
||||
FixedOrderComparator comparator = new FixedOrderComparator();
|
||||
for (int i = 0; i < topCities.length; i++) {
|
||||
comparator.add(topCities[i]);
|
||||
}
|
||||
String[] keys = (String[]) topCities.clone();
|
||||
assertComparatorYieldsOrder(keys, comparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the array constructor compares items properly.
|
||||
*/
|
||||
public void testArrayConstructor() {
|
||||
String[] keys = (String[]) topCities.clone();
|
||||
String[] topCitiesForTest = (String[]) topCities.clone();
|
||||
FixedOrderComparator comparator = new FixedOrderComparator(topCitiesForTest);
|
||||
assertComparatorYieldsOrder(keys, comparator);
|
||||
// test that changing input after constructor has no effect
|
||||
topCitiesForTest[0] = "Brighton";
|
||||
assertComparatorYieldsOrder(keys, comparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the list constructor.
|
||||
*/
|
||||
public void testListConstructor() {
|
||||
String[] keys = (String[]) topCities.clone();
|
||||
List topCitiesForTest = new LinkedList(Arrays.asList(topCities));
|
||||
FixedOrderComparator comparator = new FixedOrderComparator(topCitiesForTest);
|
||||
assertComparatorYieldsOrder(keys, comparator);
|
||||
// test that changing input after constructor has no effect
|
||||
topCitiesForTest.set(0, "Brighton");
|
||||
assertComparatorYieldsOrder(keys, comparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests addAsEqual method.
|
||||
*/
|
||||
public void testAddAsEqual() {
|
||||
FixedOrderComparator comparator = new FixedOrderComparator(topCities);
|
||||
comparator.addAsEqual("New York", "Minneapolis");
|
||||
assertEquals(0, comparator.compare("New York", "Minneapolis"));
|
||||
assertEquals(-1, comparator.compare("Tokyo", "Minneapolis"));
|
||||
assertEquals(1, comparator.compare("Shanghai", "Minneapolis"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether or not updates are disabled after a comparison is made.
|
||||
*/
|
||||
public void testLock() {
|
||||
FixedOrderComparator comparator = new FixedOrderComparator(topCities);
|
||||
assertEquals(false, comparator.isLocked());
|
||||
comparator.compare("New York", "Tokyo");
|
||||
assertEquals(true, comparator.isLocked());
|
||||
try {
|
||||
comparator.add("Minneapolis");
|
||||
fail("Should have thrown an UnsupportedOperationException");
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// success -- ignore
|
||||
}
|
||||
|
||||
try {
|
||||
comparator.addAsEqual("New York", "Minneapolis");
|
||||
fail("Should have thrown an UnsupportedOperationException");
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// success -- ignore
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnknownObjectBehavior() {
|
||||
FixedOrderComparator comparator = new FixedOrderComparator(topCities);
|
||||
try {
|
||||
comparator.compare("New York", "Minneapolis");
|
||||
fail("Should have thrown a IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// success-- ignore
|
||||
}
|
||||
try {
|
||||
comparator.compare("Minneapolis", "New York");
|
||||
fail("Should have thrown a IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// success-- ignore
|
||||
}
|
||||
assertEquals(FixedOrderComparator.UNKNOWN_THROW_EXCEPTION, comparator.getUnkownObjectBehavior());
|
||||
|
||||
comparator = new FixedOrderComparator(topCities);
|
||||
comparator.setUnknownObjectBehavior(FixedOrderComparator.UNKNOWN_BEFORE);
|
||||
assertEquals(FixedOrderComparator.UNKNOWN_BEFORE, comparator.getUnkownObjectBehavior());
|
||||
LinkedList keys = new LinkedList(Arrays.asList(topCities));
|
||||
keys.addFirst("Minneapolis");
|
||||
assertComparatorYieldsOrder(keys.toArray(new String[0]), comparator);
|
||||
|
||||
assertEquals(-1, comparator.compare("Minneapolis", "New York"));
|
||||
assertEquals( 1, comparator.compare("New York", "Minneapolis"));
|
||||
assertEquals( 0, comparator.compare("Minneapolis", "St Paul"));
|
||||
|
||||
comparator = new FixedOrderComparator(topCities);
|
||||
comparator.setUnknownObjectBehavior(FixedOrderComparator.UNKNOWN_AFTER);
|
||||
keys = new LinkedList(Arrays.asList(topCities));
|
||||
keys.add("Minneapolis");
|
||||
assertComparatorYieldsOrder(keys.toArray(new String[0]), comparator);
|
||||
|
||||
assertEquals( 1, comparator.compare("Minneapolis", "New York"));
|
||||
assertEquals(-1, comparator.compare("New York", "Minneapolis"));
|
||||
assertEquals( 0, comparator.compare("Minneapolis", "St Paul"));
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Helper methods
|
||||
//
|
||||
|
||||
/** Shuffles the keys and asserts that the comparator sorts them back to
|
||||
* their original order.
|
||||
*/
|
||||
private void assertComparatorYieldsOrder(Object[] orderedObjects,
|
||||
Comparator comparator) {
|
||||
Object[] keys = (Object[]) orderedObjects.clone();
|
||||
|
||||
// shuffle until the order changes. It's extremely rare that
|
||||
// this requires more than one shuffle.
|
||||
|
||||
boolean isInNewOrder = false;
|
||||
while (keys.length > 1 && isInNewOrder == false) {
|
||||
shuffle: {
|
||||
Random rand = new Random();
|
||||
for (int i = keys.length-1; i > 0; i--) {
|
||||
Object swap = keys[i];
|
||||
int j = rand.nextInt(i+1);
|
||||
keys[i] = keys[j];
|
||||
keys[j] = swap;
|
||||
}
|
||||
}
|
||||
|
||||
testShuffle: {
|
||||
for (int i = 0; i < keys.length && !isInNewOrder; i++) {
|
||||
if( !orderedObjects[i].equals(keys[i])) {
|
||||
isInNewOrder = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The real test: sort and make sure they come out right.
|
||||
|
||||
Arrays.sort(keys, comparator);
|
||||
|
||||
for (int i = 0; i < orderedObjects.length; i++) {
|
||||
assertEquals(orderedObjects[i], keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue