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>Example: {@code boolean x = ComparableUtils.is(myComparable).lessThanOrEqualTo(otherComparable)}</p>
27 *
28 * <p>#ThreadSafe#</p>
29 *
30 * @since 3.10
31 */
32 public class ComparableUtils {
33
34 /**
35 * Compares objects of a given generic type {@code A}.
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 * Tests 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 * Tests 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 * Tests 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 != null && a.compareTo(b) == 0;
85 }
86
87 /**
88 * Tests 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 != null && a.compareTo(b) > 0;
95 }
96
97 /**
98 * Tests 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 != null && a.compareTo(b) >= 0;
105 }
106
107 /**
108 * Tests 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 != null && a.compareTo(b) < 0;
115 }
116
117 /**
118 * Tests 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 != null && a.compareTo(b) <= 0;
125 }
126 }
127
128 /**
129 * Creates a predicate to test 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 * Creates a predicate to test 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 * Creates a predicate to test 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 * Creates a predicate to test 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 * Creates a new {@link ComparableCheckBuilder}.
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 * Creates a predicate to test 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 * Creates a predicate to test 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 // empty
245 }
246 }