KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > comparators > FixedOrderComparator


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.collections.comparators;
17
18 import java.util.Comparator JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23
24 /**
25  * A Comparator which imposes a specific order on a specific set of Objects.
26  * Objects are presented to the FixedOrderComparator in a specified order and
27  * subsequent calls to {@link #compare(Object, Object) compare} yield that order.
28  * For example:
29  * <pre>
30  * String[] planets = {"Mercury", "Venus", "Earth", "Mars"};
31  * FixedOrderComparator distanceFromSun = new FixedOrderComparator(planets);
32  * Arrays.sort(planets); // Sort to alphabetical order
33  * Arrays.sort(planets, distanceFromSun); // Back to original order
34  * </pre>
35  * <p>
36  * Once <code>compare</code> has been called, the FixedOrderComparator is locked
37  * and attempts to modify it yield an UnsupportedOperationException.
38  * <p>
39  * Instances of FixedOrderComparator are not synchronized. The class is not
40  * thread-safe at construction time, but it is thread-safe to perform
41  * multiple comparisons after all the setup operations are complete.
42  *
43  * @since Commons Collections 3.0
44  * @version $Revision: 1.10 $ $Date: 2004/05/15 13:24:11 $
45  *
46  * @author David Leppik
47  * @author Stephen Colebourne
48  * @author Janek Bogucki
49  */

50 public class FixedOrderComparator implements Comparator JavaDoc {
51
52     /**
53      * Behavior when comparing unknown Objects:
54      * unknown objects compare as before known Objects.
55      */

56     public static final int UNKNOWN_BEFORE = 0;
57
58     /**
59      * Behavior when comparing unknown Objects:
60      * unknown objects compare as after known Objects.
61      */

62     public static final int UNKNOWN_AFTER = 1;
63
64     /**
65      * Behavior when comparing unknown Objects:
66      * unknown objects cause a IllegalArgumentException to be thrown.
67      * This is the default behavior.
68      */

69     public static final int UNKNOWN_THROW_EXCEPTION = 2;
70
71     /** Internal map of object to position */
72     private final Map JavaDoc map = new HashMap JavaDoc();
73     /** Counter used in determining the position in the map */
74     private int counter = 0;
75     /** Is the comparator locked against further change */
76     private boolean isLocked = false;
77     /** The behaviour in the case of an unknown object */
78     private int unknownObjectBehavior = UNKNOWN_THROW_EXCEPTION;
79
80     // Constructors
81
//-----------------------------------------------------------------------
82
/**
83      * Constructs an empty FixedOrderComparator.
84      */

85     public FixedOrderComparator() {
86         super();
87     }
88
89     /**
90      * Constructs a FixedOrderComparator which uses the order of the given array
91      * to compare the objects.
92      * <p>
93      * The array is copied, so later changes will not affect the comparator.
94      *
95      * @param items the items that the comparator can compare in order
96      * @throws IllegalArgumentException if the array is null
97      */

98     public FixedOrderComparator(Object JavaDoc[] items) {
99         super();
100         if (items == null) {
101             throw new IllegalArgumentException JavaDoc("The list of items must not be null");
102         }
103         for (int i = 0; i < items.length; i++) {
104             add(items[i]);
105         }
106     }
107
108     /**
109      * Constructs a FixedOrderComparator which uses the order of the given list
110      * to compare the objects.
111      * <p>
112      * The list is copied, so later changes will not affect the comparator.
113      *
114      * @param items the items that the comparator can compare in order
115      * @throws IllegalArgumentException if the list is null
116      */

117     public FixedOrderComparator(List JavaDoc items) {
118         super();
119         if (items == null) {
120             throw new IllegalArgumentException JavaDoc("The list of items must not be null");
121         }
122         for (Iterator JavaDoc it = items.iterator(); it.hasNext();) {
123             add(it.next());
124         }
125     }
126
127     // Bean methods / state querying methods
128
//-----------------------------------------------------------------------
129
/**
130      * Returns true if modifications cannot be made to the FixedOrderComparator.
131      * FixedOrderComparators cannot be modified once they have performed a comparison.
132      *
133      * @return true if attempts to change the FixedOrderComparator yield an
134      * UnsupportedOperationException, false if it can be changed.
135      */

136     public boolean isLocked() {
137         return isLocked;
138     }
139
140     /**
141      * Checks to see whether the comparator is now locked against further changes.
142      *
143      * @throws UnsupportedOperationException if the comparator is locked
144      */

145     protected void checkLocked() {
146         if (isLocked()) {
147             throw new UnsupportedOperationException JavaDoc("Cannot modify a FixedOrderComparator after a comparison");
148         }
149     }
150
151     /**
152      * Gets the behavior for comparing unknown objects.
153      *
154      * @return the flag for unknown behaviour - UNKNOWN_AFTER,
155      * UNKNOWN_BEFORE or UNKNOWN_THROW_EXCEPTION
156      */

157     public int getUnknownObjectBehavior() {
158         return unknownObjectBehavior;
159     }
160
161     /**
162      * Sets the behavior for comparing unknown objects.
163      *
164      * @param unknownObjectBehavior the flag for unknown behaviour -
165      * UNKNOWN_AFTER, UNKNOWN_BEFORE or UNKNOWN_THROW_EXCEPTION
166      * @throws UnsupportedOperationException if a comparison has been performed
167      * @throws IllegalArgumentException if the unknown flag is not valid
168      */

169     public void setUnknownObjectBehavior(int unknownObjectBehavior) {
170         checkLocked();
171         if (unknownObjectBehavior != UNKNOWN_AFTER
172             && unknownObjectBehavior != UNKNOWN_BEFORE
173             && unknownObjectBehavior != UNKNOWN_THROW_EXCEPTION) {
174             throw new IllegalArgumentException JavaDoc("Unrecognised value for unknown behaviour flag");
175         }
176         this.unknownObjectBehavior = unknownObjectBehavior;
177     }
178
179     // Methods for adding items
180
//-----------------------------------------------------------------------
181
/**
182      * Adds an item, which compares as after all items known to the Comparator.
183      * If the item is already known to the Comparator, its old position is
184      * replaced with the new position.
185      *
186      * @param obj the item to be added to the Comparator.
187      * @return true if obj has been added for the first time, false if
188      * it was already known to the Comparator.
189      * @throws UnsupportedOperationException if a comparison has already been made
190      */

191     public boolean add(Object JavaDoc obj) {
192         checkLocked();
193         Object JavaDoc position = map.put(obj, new Integer JavaDoc(counter++));
194         return (position == null);
195     }
196
197     /**
198      * Adds a new item, which compares as equal to the given existing item.
199      *
200      * @param existingObj an item already in the Comparator's set of
201      * known objects
202      * @param newObj an item to be added to the Comparator's set of
203      * known objects
204      * @return true if newObj has been added for the first time, false if
205      * it was already known to the Comparator.
206      * @throws IllegalArgumentException if existingObject is not in the
207      * Comparator's set of known objects.
208      * @throws UnsupportedOperationException if a comparison has already been made
209      */

210     public boolean addAsEqual(Object JavaDoc existingObj, Object JavaDoc newObj) {
211         checkLocked();
212         Integer JavaDoc position = (Integer JavaDoc) map.get(existingObj);
213         if (position == null) {
214             throw new IllegalArgumentException JavaDoc(existingObj + " not known to " + this);
215         }
216         Object JavaDoc result = map.put(newObj, position);
217         return (result == null);
218     }
219
220     // Comparator methods
221
//-----------------------------------------------------------------------
222
/**
223      * Compares two objects according to the order of this Comparator.
224      * <p>
225      * It is important to note that this class will throw an IllegalArgumentException
226      * in the case of an unrecognised object. This is not specified in the
227      * Comparator interface, but is the most appropriate exception.
228      *
229      * @param obj1 the first object to compare
230      * @param obj2 the second object to compare
231      * @return negative if obj1 is less, positive if greater, zero if equal
232      * @throws IllegalArgumentException if obj1 or obj2 are not known
233      * to this Comparator and an alternative behavior has not been set
234      * via {@link #setUnknownObjectBehavior(int)}.
235      */

236     public int compare(Object JavaDoc obj1, Object JavaDoc obj2) {
237         isLocked = true;
238         Integer JavaDoc position1 = (Integer JavaDoc) map.get(obj1);
239         Integer JavaDoc position2 = (Integer JavaDoc) map.get(obj2);
240         if (position1 == null || position2 == null) {
241             switch (unknownObjectBehavior) {
242                 case UNKNOWN_BEFORE :
243                     if (position1 == null) {
244                         return (position2 == null) ? 0 : -1;
245                     } else {
246                         return 1;
247                     }
248                 case UNKNOWN_AFTER :
249                     if (position1 == null) {
250                         return (position2 == null) ? 0 : 1;
251                     } else {
252                         return -1;
253                     }
254                 case UNKNOWN_THROW_EXCEPTION :
255                     Object JavaDoc unknownObj = (position1 == null) ? obj1 : obj2;
256                     throw new IllegalArgumentException JavaDoc("Attempting to compare unknown object " + unknownObj);
257                 default :
258                     throw new UnsupportedOperationException JavaDoc("Unknown unknownObjectBehavior: " + unknownObjectBehavior);
259             }
260         } else {
261             return position1.compareTo(position2);
262         }
263     }
264
265 }
266
Popular Tags