View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.compare;
18  
19  import java.util.function.Predicate;
20  
21  import org.apache.commons.lang3.ObjectUtils;
22  
23  /**
24   * Utility library to provide helper methods for translating {@link Comparable#compareTo} result into a boolean.
25   *
26   * <p>Example: {@code boolean x = is(myComparable).lessThanOrEqualTo(otherComparable)}</p>
27   *
28   * <p>#ThreadSafe#</p>
29   *
30   * @since 3.10
31   */
32  public class ComparableUtils {
33  
34      /**
35       * Provides access to the available methods
36       *
37       * @param <A> the type of objects that this object may be compared against.
38       */
39      public static class ComparableCheckBuilder<A extends Comparable<A>> {
40  
41          private final A a;
42  
43          private ComparableCheckBuilder(final A a) {
44              this.a = a;
45          }
46  
47          /**
48           * Checks if {@code [b <= a <= c]} or {@code [b >= a >= c]} where the {@code a} is object passed to {@link #is}.
49           *
50           * @param b the object to compare to the base object
51           * @param c the object to compare to the base object
52           * @return true if the base object is between b and c
53           */
54          public boolean between(final A b, final A c) {
55              return betweenOrdered(b, c) || betweenOrdered(c, b);
56          }
57  
58          /**
59           * Checks if {@code (b < a < c)} or {@code (b > a > c)} where the {@code a} is object passed to {@link #is}.
60           *
61           * @param b the object to compare to the base object
62           * @param c the object to compare to the base object
63           * @return true if the base object is between b and c and not equal to those
64           */
65          public boolean betweenExclusive(final A b, final A c) {
66              return betweenOrderedExclusive(b, c) || betweenOrderedExclusive(c, b);
67          }
68  
69          private boolean betweenOrdered(final A b, final A c) {
70              return greaterThanOrEqualTo(b) && lessThanOrEqualTo(c);
71          }
72  
73          private boolean betweenOrderedExclusive(final A b, final A c) {
74              return greaterThan(b) && lessThan(c);
75          }
76  
77          /**
78           * Checks if the object passed to {@link #is} is equal to {@code b}
79           *
80           * @param b the object to compare to the base object
81           * @return true if the value returned by {@link Comparable#compareTo} is equal to {@code 0}
82           */
83          public boolean equalTo(final A b) {
84              return a.compareTo(b) == 0;
85          }
86  
87          /**
88           * Checks if the object passed to {@link #is} is greater than {@code b}
89           *
90           * @param b the object to compare to the base object
91           * @return true if the value returned by {@link Comparable#compareTo} is greater than {@code 0}
92           */
93          public boolean greaterThan(final A b) {
94              return a.compareTo(b) > 0;
95          }
96  
97          /**
98           * Checks if the object passed to {@link #is} is greater than or equal to {@code b}
99           *
100          * @param b the object to compare to the base object
101          * @return true if the value returned by {@link Comparable#compareTo} is greater than or equal to {@code 0}
102          */
103         public boolean greaterThanOrEqualTo(final A b) {
104             return a.compareTo(b) >= 0;
105         }
106 
107         /**
108          * Checks if the object passed to {@link #is} is less than {@code b}
109          *
110          * @param b the object to compare to the base object
111          * @return true if the value returned by {@link Comparable#compareTo} is less than {@code 0}
112          */
113         public boolean lessThan(final A b) {
114             return a.compareTo(b) < 0;
115         }
116 
117         /**
118          * Checks if the object passed to {@link #is} is less than or equal to {@code b}
119          *
120          * @param b the object to compare to the base object
121          * @return true if the value returned by {@link Comparable#compareTo} is less than or equal to {@code 0}
122          */
123         public boolean lessThanOrEqualTo(final A b) {
124             return a.compareTo(b) <= 0;
125         }
126     }
127 
128     /**
129      * Checks if {@code [b <= a <= c]} or {@code [b >= a >= c]} where the {@code a} is the tested object.
130      *
131      * @param b the object to compare to the tested object
132      * @param c the object to compare to the tested object
133      * @param <A> type of the test object
134      * @return a predicate for true if the tested object is between b and c
135      */
136     public static <A extends Comparable<A>> Predicate<A> between(final A b, final A c) {
137         return a -> is(a).between(b, c);
138     }
139 
140     /**
141      * Checks if {@code (b < a < c)} or {@code (b > a > c)} where the {@code a} is the tested object.
142      *
143      * @param b the object to compare to the tested object
144      * @param c the object to compare to the tested object
145      * @param <A> type of the test object
146      * @return a predicate for true if the tested object is between b and c and not equal to those
147      */
148     public static <A extends Comparable<A>> Predicate<A> betweenExclusive(final A b, final A c) {
149         return a -> is(a).betweenExclusive(b, c);
150     }
151 
152     /**
153      * Checks if the tested object is greater than or equal to {@code b}
154      *
155      * @param b the object to compare to the tested object
156      * @param <A> type of the test object
157      * @return a predicate for true if the value returned by {@link Comparable#compareTo}
158      * is greater than or equal to {@code 0}
159      */
160     public static <A extends Comparable<A>> Predicate<A> ge(final A b) {
161         return a -> is(a).greaterThanOrEqualTo(b);
162     }
163 
164     /**
165      * Checks if the tested object is greater than {@code b}
166      *
167      * @param b the object to compare to the tested object
168      * @param <A> type of the test object
169      * @return a predicate for true if the value returned by {@link Comparable#compareTo} is greater than {@code 0}
170      */
171     public static <A extends Comparable<A>> Predicate<A> gt(final A b) {
172         return a -> is(a).greaterThan(b);
173     }
174 
175     /**
176      * Provides access to the available methods
177      *
178      * @param a base object in the further comparison
179      * @param <A> type of the base object
180      * @return a builder object with further methods
181      */
182     public static <A extends Comparable<A>> ComparableCheckBuilder<A> is(final A a) {
183         return new ComparableCheckBuilder<>(a);
184     }
185 
186     /**
187      * Checks if the tested object is less than or equal to {@code b}
188      *
189      * @param b the object to compare to the tested object
190      * @param <A> type of the test object
191      * @return a predicate for true if the value returned by {@link Comparable#compareTo}
192      * is less than or equal to {@code 0}
193      */
194     public static <A extends Comparable<A>> Predicate<A> le(final A b) {
195         return a -> is(a).lessThanOrEqualTo(b);
196     }
197 
198     /**
199      * Checks if the tested object is less than {@code b}
200      *
201      * @param b the object to compare to the tested object
202      * @param <A> type of the test object
203      * @return a predicate for true if the value returned by {@link Comparable#compareTo} is less than {@code 0}
204      */
205     public static <A extends Comparable<A>> Predicate<A> lt(final A b) {
206         return a -> is(a).lessThan(b);
207     }
208 
209     /**
210      * Returns the greater of two {@link Comparable} values, ignoring null.
211      * <p>
212      * For three or more values, use {@link ObjectUtils#max(Comparable...)}.
213      * </p>
214      *
215      * @param <A> Type of what we are comparing.
216      * @param comparable1 the first comparable, may be null.
217      * @param comparable2 the second comparable, may be null.
218      * @return the largest of {@code comparable1} and {@code comparable2}.
219      * @see ObjectUtils#max(Comparable...)
220      * @since 3.13.0
221      */
222     public static <A extends Comparable<A>> A max(final A comparable1, final A comparable2) {
223         return ObjectUtils.compare(comparable1, comparable2, false) > 0 ? comparable1 : comparable2;
224     }
225 
226     /**
227      * Returns the lesser of two {@link Comparable} values, ignoring null.
228      * <p>
229      * For three or more values, use {@link ObjectUtils#min(Comparable...)}.
230      * </p>
231      *
232      * @param <A> Type of what we are comparing.
233      * @param comparable1 the first comparable, may be null.
234      * @param comparable2 the second comparable, may be null.
235      * @return the smallest of {@code comparable1} and {@code comparable2}.
236      * @see ObjectUtils#min(Comparable...)
237      * @since 3.13.0
238      */
239     public static <A extends Comparable<A>> A min(final A comparable1, final A comparable2) {
240         return ObjectUtils.compare(comparable1, comparable2, true) < 0 ? comparable1 : comparable2;
241     }
242 
243     private ComparableUtils() {}
244 }