001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.commons.collections;
018    
019    import java.util.Collection;
020    import java.util.Comparator;
021    
022    import org.apache.commons.collections.comparators.BooleanComparator;
023    import org.apache.commons.collections.comparators.ComparableComparator;
024    import org.apache.commons.collections.comparators.ComparatorChain;
025    import org.apache.commons.collections.comparators.NullComparator;
026    import org.apache.commons.collections.comparators.ReverseComparator;
027    import org.apache.commons.collections.comparators.TransformingComparator;
028    
029    /**
030     * Provides convenient static utility methods for <Code>Comparator</Code>
031     * objects.
032     * <p>
033     * Most of the functionality in this class can also be found in the 
034     * <code>comparators</code> package. This class merely provides a 
035     * convenient central place if you have use for more than one class
036     * in the <code>comparators</code> subpackage.
037     *
038     * @since Commons Collections 2.1
039     * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
040     * 
041     * @author Paul Jack
042     * @author Stephen Colebourne
043     */
044    public class ComparatorUtils {
045    
046        /**
047         * ComparatorUtils should not normally be instantiated.
048         */
049        public ComparatorUtils() {
050        }
051    
052        /**
053         * Comparator for natural sort order.
054         *
055         * @see ComparableComparator#getInstance
056         */
057        public static final Comparator NATURAL_COMPARATOR = ComparableComparator.getInstance();
058    
059        /**
060         * Gets a comparator that uses the natural order of the objects.
061         *
062         * @return  a comparator which uses natural order
063         */
064        public static Comparator naturalComparator() {
065            return NATURAL_COMPARATOR;
066        }
067    
068        /**
069         * Gets a comparator that compares using two {@link Comparator}s.
070         * <p>
071         * The second comparator is used if the first comparator returns equal.
072         *
073         * @param comparator1  the first comparator to use, not null
074         * @param comparator2  the first comparator to use, not null
075         * @return a {@link ComparatorChain} formed from the two comparators
076         * @throws NullPointerException if either comparator is null
077         * @see ComparatorChain
078         */
079        public static Comparator chainedComparator(Comparator comparator1, Comparator comparator2) {
080            return chainedComparator(new Comparator[] {comparator1, comparator2});
081        }
082    
083        /**
084         * Gets a comparator that compares using an array of {@link Comparator}s, applied
085         * in sequence until one returns not equal or the array is exhausted.
086         *
087         * @param comparators  the comparators to use, not null or empty or containing nulls
088         * @return a {@link ComparatorChain} formed from the input comparators
089         * @throws NullPointerException if comparators array is null or contains a null
090         * @see ComparatorChain
091         */
092        public static Comparator chainedComparator(Comparator[] comparators) {
093            ComparatorChain chain = new ComparatorChain();
094            for (int i = 0; i < comparators.length; i++) {
095                if (comparators[i] == null) {
096                    throw new NullPointerException("Comparator cannot be null");
097                }
098                chain.addComparator(comparators[i]);
099            }
100            return chain;
101        }
102    
103        /**
104         * Gets a comparator that compares using a collection of {@link Comparator}s,
105         * applied in (default iterator) sequence until one returns not equal or the 
106         * collection is exhausted.
107         *
108         * @param comparators  the comparators to use, not null or empty or containing nulls
109         * @return a {@link ComparatorChain} formed from the input comparators
110         * @throws NullPointerException if comparators collection is null or contains a null
111         * @throws ClassCastException if the comparators collection contains the wrong object type
112         * @see ComparatorChain
113         */
114        public static Comparator chainedComparator(Collection comparators) {
115            return chainedComparator(
116                (Comparator[]) comparators.toArray(new Comparator[comparators.size()])
117            );
118        }
119    
120        /**
121         * Gets a comparator that reverses the order of the given comparator.
122         *
123         * @param comparator  the comparator to reverse
124         * @return  a comparator that reverses the order of the input comparator
125         * @see ReverseComparator
126         */
127        public static Comparator reversedComparator(Comparator comparator) {
128            if (comparator == null) {
129                comparator = NATURAL_COMPARATOR;
130            }
131            return new ReverseComparator(comparator);
132        }
133    
134        /**
135         * Gets a Comparator that can sort Boolean objects.
136         * <p>
137         * The parameter specifies whether true or false is sorted first.
138         * <p>
139         * The comparator throws NullPointerException if a null value is compared.
140         * 
141         * @param trueFirst  when <code>true</code>, sort 
142         *        <code>true</code> {@link Boolean}s before
143         *        <code>false</code> {@link Boolean}s.
144         * @return  a comparator that sorts booleans
145         */
146        public static Comparator booleanComparator(boolean trueFirst) {
147            return BooleanComparator.getBooleanComparator(trueFirst);
148        }
149        
150        /**
151         * Gets a Comparator that controls the comparison of <code>null</code> values.
152         * <p>
153         * The returned comparator will consider a null value to be less than
154         * any nonnull value, and equal to any other null value.  Two nonnull
155         * values will be evaluated with the given comparator.
156         *
157         * @param comparator the comparator that wants to allow nulls
158         * @return  a version of that comparator that allows nulls
159         * @see NullComparator
160         */
161        public static Comparator nullLowComparator(Comparator comparator) {
162            if (comparator == null) {
163                comparator = NATURAL_COMPARATOR;
164            }
165            return new NullComparator(comparator, false);
166        }
167    
168        /**
169         * Gets a Comparator that controls the comparison of <code>null</code> values.
170         * <p>
171         * The returned comparator will consider a null value to be greater than
172         * any nonnull value, and equal to any other null value.  Two nonnull
173         * values will be evaluated with the given comparator.
174         *
175         * @param comparator the comparator that wants to allow nulls
176         * @return  a version of that comparator that allows nulls
177         * @see NullComparator
178         */
179        public static Comparator nullHighComparator(Comparator comparator) {
180            if (comparator == null) {
181                comparator = NATURAL_COMPARATOR;
182            }
183            return new NullComparator(comparator, true);
184        }
185    
186        /**
187         * Gets a Comparator that passes transformed objects to the given comparator.
188         * <p>
189         * Objects passed to the returned comparator will first be transformed
190         * by the given transformer before they are compared by the given
191         * comparator.
192         *
193         * @param comparator  the sort order to use
194         * @param transformer  the transformer to use
195         * @return  a comparator that transforms its input objects before comparing them
196         * @see  TransformingComparator
197         */
198        public static Comparator transformedComparator(Comparator comparator, Transformer transformer) {
199            if (comparator == null) {
200                comparator = NATURAL_COMPARATOR;
201            }
202            return new TransformingComparator(transformer, comparator);
203        }
204    
205        /**
206         *  Returns the smaller of the given objects according to the given 
207         *  comparator, returning the second object if the comparator
208         *  returns equal.
209         * 
210         *  @param o1  the first object to compare
211         *  @param o2  the second object to compare
212         *  @param comparator  the sort order to use
213         *  @return  the smaller of the two objects
214         */
215        public static Object min(Object o1, Object o2, Comparator comparator) {
216            if (comparator == null) {
217                comparator = NATURAL_COMPARATOR;
218            }
219            int c = comparator.compare(o1, o2);
220            return (c < 0) ? o1 : o2;
221        }
222    
223        /**
224         *  Returns the larger of the given objects according to the given 
225         *  comparator, returning the second object if the comparator 
226         *  returns equal.
227         * 
228         *  @param o1  the first object to compare
229         *  @param o2  the second object to compare
230         *  @param comparator  the sort order to use
231         *  @return  the larger of the two objects
232         */
233        public static Object max(Object o1, Object o2, Comparator comparator) {
234            if (comparator == null) {
235                comparator = NATURAL_COMPARATOR;
236            }
237            int c = comparator.compare(o1, o2);
238            return (c > 0) ? o1 : o2;
239        }
240        
241    }