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.comparators;
018    
019    import java.io.Serializable;
020    import java.util.Comparator;
021    
022    /**
023     * A {@link Comparator} for {@link Boolean} objects that can sort either
024     * true or false first.
025     * <p>
026     * @see #getTrueFirstComparator()
027     * @see #getFalseFirstComparator()
028     * @see #getBooleanComparator(boolean)
029     * 
030     * @since Commons Collections 3.0
031     * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
032     * 
033     * @author Rodney Waldhoff
034     */
035    public final class BooleanComparator implements Comparator, Serializable {
036    
037        /** Serialization version. */
038        private static final long serialVersionUID = 1830042991606340609L;
039    
040        /** Constant "true first" reference. */
041        private static final BooleanComparator TRUE_FIRST = new BooleanComparator(true);
042    
043        /** Constant "false first" reference. */
044        private static final BooleanComparator FALSE_FIRST = new BooleanComparator(false);
045    
046        /** <code>true</code> iff <code>true</code> values sort before <code>false</code> values. */
047        private boolean trueFirst = false;
048    
049        //-----------------------------------------------------------------------
050        /**
051         * Returns a BooleanComparator instance that sorts 
052         * <code>true</code> values before <code>false</code> values.
053         * <p />
054         * Clients are encouraged to use the value returned from 
055         * this method instead of constructing a new instance 
056         * to reduce allocation and garbage collection overhead when
057         * multiple BooleanComparators may be used in the same 
058         * virtual machine.
059         * 
060         * @return the true first singleton BooleanComparator
061         */
062        public static BooleanComparator getTrueFirstComparator() {
063            return TRUE_FIRST;
064        }
065        
066        /**
067         * Returns a BooleanComparator instance that sorts 
068         * <code>false</code> values before <code>true</code> values.
069         * <p />
070         * Clients are encouraged to use the value returned from 
071         * this method instead of constructing a new instance 
072         * to reduce allocation and garbage collection overhead when
073         * multiple BooleanComparators may be used in the same 
074         * virtual machine.
075         * 
076         * @return the false first singleton BooleanComparator
077         */
078        public static BooleanComparator getFalseFirstComparator() {
079            return FALSE_FIRST;
080        }
081            
082        /**
083         * Returns a BooleanComparator instance that sorts 
084         * <code><i>trueFirst</i></code> values before 
085         * <code>&#x21;<i>trueFirst</i></code> values.
086         * <p />
087         * Clients are encouraged to use the value returned from 
088         * this method instead of constructing a new instance 
089         * to reduce allocation and garbage collection overhead when
090         * multiple BooleanComparators may be used in the same 
091         * virtual machine.
092         * 
093         * @param trueFirst when <code>true</code>, sort 
094         * <code>true</code> <code>Boolean</code>s before <code>false</code>
095         * @return a singleton BooleanComparator instance
096         */
097        public static BooleanComparator getBooleanComparator(boolean trueFirst) {
098            return trueFirst ? TRUE_FIRST : FALSE_FIRST;
099        }
100    
101        //-----------------------------------------------------------------------
102        /**
103         * Creates a <code>BooleanComparator</code> that sorts
104         * <code>false</code> values before <code>true</code> values.
105         * <p>
106         * Equivalent to {@link #BooleanComparator(boolean) BooleanComparator(false)}.
107         * <p>
108         * Please use the static factory instead whenever possible.
109         */
110        public BooleanComparator() {
111            this(false);
112        }
113    
114        /**
115         * Creates a <code>BooleanComparator</code> that sorts
116         * <code><i>trueFirst</i></code> values before 
117         * <code>&#x21;<i>trueFirst</i></code> values.
118         * <p>
119         * Please use the static factories instead whenever possible.
120         * 
121         * @param trueFirst when <code>true</code>, sort 
122         *  <code>true</code> boolean values before <code>false</code>
123         */
124        public BooleanComparator(boolean trueFirst) {
125            this.trueFirst = trueFirst;
126        }
127    
128        //-----------------------------------------------------------------------
129        /**
130         * Compares two arbitrary Objects.
131         * When both arguments are <code>Boolean</code>, this method is equivalent to 
132         * {@link #compare(Boolean,Boolean) compare((Boolean)<i>obj1</i>,(Boolean)<i>obj2</i>)}.
133         * When either argument is not a <code>Boolean</code>, this methods throws
134         * a {@link ClassCastException}.
135         * 
136         * @param obj1  the first object to compare
137         * @param obj2  the second object to compare
138         * @return negative if obj1 is less, positive if greater, zero if equal
139         * @throws ClassCastException when either argument is not <code>Boolean</code>
140         */
141        public int compare(Object obj1, Object obj2) {
142            return compare((Boolean)obj1, (Boolean)obj2);
143        }
144        
145        /**
146         * Compares two non-<code>null</code> <code>Boolean</code> objects
147         * according to the value of {@link #sortsTrueFirst()}.
148         * 
149         * @param b1  the first boolean to compare
150         * @param b2  the second boolean to compare
151         * @return negative if obj1 is less, positive if greater, zero if equal
152         * @throws NullPointerException when either argument <code>null</code>
153         */
154        public int compare(Boolean b1, Boolean b2) {
155            boolean v1 = b1.booleanValue();
156            boolean v2 = b2.booleanValue();
157    
158            return (v1 ^ v2) ? ( (v1 ^ trueFirst) ? 1 : -1 ) : 0;
159        }
160    
161        //-----------------------------------------------------------------------
162        /**
163         * Implement a hash code for this comparator that is consistent with
164         * {@link #equals(Object) equals}.
165         *
166         * @return a hash code for this comparator.
167         */
168        public int hashCode() {
169            int hash = "BooleanComparator".hashCode();
170            return trueFirst ? -1 * hash : hash;
171        }
172    
173        /**
174         * Returns <code>true</code> iff <i>that</i> Object is 
175         * is a {@link Comparator} whose ordering is known to be 
176         * equivalent to mine.
177         * <p>
178         * This implementation returns <code>true</code>
179         * iff <code><i>that</i></code> is a {@link BooleanComparator} 
180         * whose value of {@link #sortsTrueFirst()} is equal to mine.
181         * 
182         * @param object  the object to compare to
183         * @return true if equal
184         */
185        public boolean equals(Object object) {
186            return (this == object) || 
187                   ((object instanceof BooleanComparator) && 
188                    (this.trueFirst == ((BooleanComparator)object).trueFirst));
189        }
190    
191        //-----------------------------------------------------------------------
192        /**
193         * Returns <code>true</code> iff
194         * I sort <code>true</code> values before 
195         * <code>false</code> values.  In other words,
196         * returns <code>true</code> iff
197         * {@link #compare(Boolean,Boolean) compare(Boolean.FALSE,Boolean.TRUE)}
198         * returns a positive value.
199         * 
200         * @return the trueFirst flag
201         */
202        public boolean sortsTrueFirst() {
203            return trueFirst;
204        }
205    
206    }