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    *      https://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   * Helper translating {@link Comparable#compareTo} results to booleans.
25   *
26   * <p>
27   * Example: {@code boolean x = ComparableUtils.is(myComparable).lessThanOrEqualTo(otherComparable)}
28   * </p>
29   *
30   * <p>
31   * #ThreadSafe#
32   * </p>
33   *
34   * @since 3.10
35   */
36  public class ComparableUtils {
37  
38      /**
39       * Compares objects of a given generic type {@code A}.
40       *
41       * @param <A> The type of objects that this object may be compared against.
42       */
43      public static class ComparableCheckBuilder<A extends Comparable<A>> {
44  
45          private final A a;
46  
47          private ComparableCheckBuilder(final A a) {
48              this.a = a;
49          }
50  
51          /**
52           * Tests if {@code [b <= a <= c]} or {@code [b >= a >= c]} where the {@code a} is object passed to {@link #is}.
53           *
54           * @param b The object to compare to the base object
55           * @param c The object to compare to the base object
56           * @return true if the base object is between b and c
57           */
58          public boolean between(final A b, final A c) {
59              return betweenOrdered(b, c) || betweenOrdered(c, b);
60          }
61  
62          /**
63           * Tests if {@code (b < a < c)} or {@code (b > a > c)} where the {@code a} is object passed to {@link #is}.
64           *
65           * @param b The object to compare to the base object
66           * @param c The object to compare to the base object
67           * @return true if the base object is between b and c and not equal to those
68           */
69          public boolean betweenExclusive(final A b, final A c) {
70              return betweenOrderedExclusive(b, c) || betweenOrderedExclusive(c, b);
71          }
72  
73          private boolean betweenOrdered(final A b, final A c) {
74              return greaterThanOrEqualTo(b) && lessThanOrEqualTo(c);
75          }
76  
77          private boolean betweenOrderedExclusive(final A b, final A c) {
78              return greaterThan(b) && lessThan(c);
79          }
80  
81          /**
82           * Tests if the object passed to {@link #is} is equal to {@code b}
83           *
84           * @param b The object to compare to the base object
85           * @return true if the value returned by {@link Comparable#compareTo} is equal to {@code 0}
86           */
87          public boolean equalTo(final A b) {
88              return a != null && a.compareTo(b) == 0;
89          }
90  
91          /**
92           * Tests if the object passed to {@link #is} is greater than {@code b}
93           *
94           * @param b The object to compare to the base object
95           * @return true if the value returned by {@link Comparable#compareTo} is greater than {@code 0}
96           */
97          public boolean greaterThan(final A b) {
98              return a != null && a.compareTo(b) > 0;
99          }
100 
101         /**
102          * Tests if the object passed to {@link #is} is greater than or equal to {@code b}
103          *
104          * @param b The object to compare to the base object
105          * @return true if the value returned by {@link Comparable#compareTo} is greater than or equal to {@code 0}
106          */
107         public boolean greaterThanOrEqualTo(final A b) {
108             return a != null && a.compareTo(b) >= 0;
109         }
110 
111         /**
112          * Tests if the object passed to {@link #is} is less than {@code b}
113          *
114          * @param b The object to compare to the base object
115          * @return true if the value returned by {@link Comparable#compareTo} is less than {@code 0}
116          */
117         public boolean lessThan(final A b) {
118             return a != null && a.compareTo(b) < 0;
119         }
120 
121         /**
122          * Tests if the object passed to {@link #is} is less than or equal to {@code b}
123          *
124          * @param b The object to compare to the base object
125          * @return true if the value returned by {@link Comparable#compareTo} is less than or equal to {@code 0}
126          */
127         public boolean lessThanOrEqualTo(final A b) {
128             return a != null && a.compareTo(b) <= 0;
129         }
130     }
131 
132     /**
133      * Creates a predicate to test if {@code [b <= a <= c]} or {@code [b >= a >= c]} where the {@code a} is the tested object.
134      *
135      * @param b The object to compare to the tested object
136      * @param c The object to compare to the tested object
137      * @param <A> type of the test object
138      * @return A predicate for true if the tested object is between b and c
139      */
140     public static <A extends Comparable<A>> Predicate<A> between(final A b, final A c) {
141         return a -> is(a).between(b, c);
142     }
143 
144     /**
145      * Creates a predicate to test if {@code (b < a < c)} or {@code (b > a > c)} where the {@code a} is the tested object.
146      *
147      * @param b The object to compare to the tested object
148      * @param c The object to compare to the tested object
149      * @param <A> type of the test object
150      * @return A predicate for true if the tested object is between b and c and not equal to those
151      */
152     public static <A extends Comparable<A>> Predicate<A> betweenExclusive(final A b, final A c) {
153         return a -> is(a).betweenExclusive(b, c);
154     }
155 
156     /**
157      * Creates a predicate to test if the tested object is greater than or equal to {@code b}
158      *
159      * @param b The object to compare to the tested object
160      * @param <A> type of the test object
161      * @return A predicate for true if the value returned by {@link Comparable#compareTo}
162      * is greater than or equal to {@code 0}
163      */
164     public static <A extends Comparable<A>> Predicate<A> ge(final A b) {
165         return a -> is(a).greaterThanOrEqualTo(b);
166     }
167 
168     /**
169      * Creates a predicate to test if the tested object is greater than {@code b}
170      *
171      * @param b The object to compare to the tested object
172      * @param <A> type of the test object
173      * @return A predicate for true if the value returned by {@link Comparable#compareTo} is greater than {@code 0}
174      */
175     public static <A extends Comparable<A>> Predicate<A> gt(final A b) {
176         return a -> is(a).greaterThan(b);
177     }
178 
179     /**
180      * Creates a new {@link ComparableCheckBuilder}.
181      *
182      * @param a base object in the further comparison
183      * @param <A> type of the base object
184      * @return A builder object with further methods
185      */
186     public static <A extends Comparable<A>> ComparableCheckBuilder<A> is(final A a) {
187         return new ComparableCheckBuilder<>(a);
188     }
189 
190     /**
191      * Creates a predicate to test if the tested object is less than or equal to {@code b}
192      *
193      * @param b The object to compare to the tested object
194      * @param <A> type of the test object
195      * @return A predicate for true if the value returned by {@link Comparable#compareTo}
196      * is less than or equal to {@code 0}
197      */
198     public static <A extends Comparable<A>> Predicate<A> le(final A b) {
199         return a -> is(a).lessThanOrEqualTo(b);
200     }
201 
202     /**
203      * Creates a predicate to test if the tested object is less than {@code b}
204      *
205      * @param b The object to compare to the tested object
206      * @param <A> type of the test object
207      * @return A predicate for true if the value returned by {@link Comparable#compareTo} is less than {@code 0}
208      */
209     public static <A extends Comparable<A>> Predicate<A> lt(final A b) {
210         return a -> is(a).lessThan(b);
211     }
212 
213     /**
214      * Returns the greater of two {@link Comparable} values, ignoring null.
215      * <p>
216      * For three or more values, use {@link ObjectUtils#max(Comparable...)}.
217      * </p>
218      *
219      * @param <A> Type of what we are comparing.
220      * @param comparable1 The first comparable, may be null.
221      * @param comparable2 The second comparable, may be null.
222      * @return The largest of {@code comparable1} and {@code comparable2}.
223      * @see ObjectUtils#max(Comparable...)
224      * @since 3.13.0
225      */
226     public static <A extends Comparable<A>> A max(final A comparable1, final A comparable2) {
227         return ObjectUtils.compare(comparable1, comparable2, false) > 0 ? comparable1 : comparable2;
228     }
229 
230     /**
231      * Returns the lesser of two {@link Comparable} values, ignoring null.
232      * <p>
233      * For three or more values, use {@link ObjectUtils#min(Comparable...)}.
234      * </p>
235      *
236      * @param <A> Type of what we are comparing.
237      * @param comparable1 The first comparable, may be null.
238      * @param comparable2 The second comparable, may be null.
239      * @return The smallest of {@code comparable1} and {@code comparable2}.
240      * @see ObjectUtils#min(Comparable...)
241      * @since 3.13.0
242      */
243     public static <A extends Comparable<A>> A min(final A comparable1, final A comparable2) {
244         return ObjectUtils.compare(comparable1, comparable2, true) < 0 ? comparable1 : comparable2;
245     }
246 
247     private ComparableUtils() {
248         // empty
249     }
250 }