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 }