Copying from Collections to Lang
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1154829 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c409d49153
commit
c405a2bac5
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* 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.HashMap;
|
||||
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(Object, Object) 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 <code>compare</code> 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 3.0
|
||||
* @version $Revision$ $Date$
|
||||
*
|
||||
* @author David Leppik
|
||||
* @author Stephen Colebourne
|
||||
* @author Janek Bogucki
|
||||
*/
|
||||
public class FixedOrderComparator<T> implements Comparator<T> {
|
||||
|
||||
/**
|
||||
* Unknown object behavior enum.
|
||||
* @since Commons Collections 5
|
||||
*/
|
||||
public static enum UnknownObjectBehavior {
|
||||
BEFORE, AFTER, EXCEPTION;
|
||||
}
|
||||
|
||||
/** Internal map of object to position */
|
||||
private final Map<T, Integer> map = new HashMap<T, Integer>();
|
||||
|
||||
/** 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 UnknownObjectBehavior unknownObjectBehavior = UnknownObjectBehavior.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(T[] 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<T> items) {
|
||||
super();
|
||||
if (items == null) {
|
||||
throw new IllegalArgumentException("The list of items must not be null");
|
||||
}
|
||||
for (T t : items) {
|
||||
add(t);
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
*
|
||||
* @return {@link UnknownObjectBehavior}
|
||||
*/
|
||||
public UnknownObjectBehavior getUnknownObjectBehavior() {
|
||||
return unknownObjectBehavior;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the behavior for comparing unknown objects.
|
||||
*
|
||||
* @param unknownObjectBehavior the flag for unknown behaviour -
|
||||
* UNKNOWN_AFTER, UNKNOWN_BEFORE or UNKNOWN_THROW_EXCEPTION
|
||||
* @throws UnsupportedOperationException if a comparison has been performed
|
||||
* @throws IllegalArgumentException if the unknown flag is not valid
|
||||
*/
|
||||
public void setUnknownObjectBehavior(UnknownObjectBehavior unknownObjectBehavior) {
|
||||
checkLocked();
|
||||
if (unknownObjectBehavior == null) {
|
||||
throw new IllegalArgumentException("Unknown object behavior must not be null");
|
||||
}
|
||||
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(T obj) {
|
||||
checkLocked();
|
||||
Integer 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(T existingObj, T newObj) {
|
||||
checkLocked();
|
||||
Integer position = map.get(existingObj);
|
||||
if (position == null) {
|
||||
throw new IllegalArgumentException(existingObj + " not known to " + this);
|
||||
}
|
||||
Integer 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
|
||||
* @return negative if obj1 is less, positive if greater, zero if equal
|
||||
* @throws IllegalArgumentException if obj1 or obj2 are not known
|
||||
* to this Comparator and an alternative behavior has not been set
|
||||
* via {@link #setUnknownObjectBehavior(UnknownObjectBehavior)}.
|
||||
*/
|
||||
public int compare(T obj1, T obj2) {
|
||||
isLocked = true;
|
||||
Integer position1 = map.get(obj1);
|
||||
Integer position2 = map.get(obj2);
|
||||
if (position1 == null || position2 == null) {
|
||||
switch (unknownObjectBehavior) {
|
||||
case BEFORE:
|
||||
return position1 == null ? position2 == null ? 0 : -1 : 1;
|
||||
case AFTER:
|
||||
return position1 == null ? position2 == null ? 0 : 1 : -1;
|
||||
case EXCEPTION:
|
||||
Object unknownObj = (position1 == null) ? obj1 : obj2;
|
||||
throw new IllegalArgumentException("Attempting to compare unknown object "
|
||||
+ unknownObj);
|
||||
default: //could be null
|
||||
throw new UnsupportedOperationException("Unknown unknownObjectBehavior: "
|
||||
+ unknownObjectBehavior);
|
||||
}
|
||||
}
|
||||
return position1.compareTo(position2);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue