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 */
017package org.apache.commons.lang3.compare;
018
019import java.util.function.Predicate;
020
021import org.apache.commons.lang3.ObjectUtils;
022
023/**
024 * Utility library to provide helper methods for translating {@link Comparable#compareTo} result into a boolean.
025 *
026 * <p>Example: {@code boolean x = is(myComparable).lessThanOrEqualTo(otherComparable)}</p>
027 *
028 * <p>#ThreadSafe#</p>
029 *
030 * @since 3.10
031 */
032public class ComparableUtils {
033
034    /**
035     * Provides access to the available methods
036     *
037     * @param <A> the type of objects that this object may be compared against.
038     */
039    public static class ComparableCheckBuilder<A extends Comparable<A>> {
040
041        private final A a;
042
043        private ComparableCheckBuilder(final A a) {
044            this.a = a;
045        }
046
047        /**
048         * Checks if {@code [b <= a <= c]} or {@code [b >= a >= c]} where the {@code a} is object passed to {@link #is}.
049         *
050         * @param b the object to compare to the base object
051         * @param c the object to compare to the base object
052         * @return true if the base object is between b and c
053         */
054        public boolean between(final A b, final A c) {
055            return betweenOrdered(b, c) || betweenOrdered(c, b);
056        }
057
058        /**
059         * Checks if {@code (b < a < c)} or {@code (b > a > c)} where the {@code a} is object passed to {@link #is}.
060         *
061         * @param b the object to compare to the base object
062         * @param c the object to compare to the base object
063         * @return true if the base object is between b and c and not equal to those
064         */
065        public boolean betweenExclusive(final A b, final A c) {
066            return betweenOrderedExclusive(b, c) || betweenOrderedExclusive(c, b);
067        }
068
069        private boolean betweenOrdered(final A b, final A c) {
070            return greaterThanOrEqualTo(b) && lessThanOrEqualTo(c);
071        }
072
073        private boolean betweenOrderedExclusive(final A b, final A c) {
074            return greaterThan(b) && lessThan(c);
075        }
076
077        /**
078         * Checks if the object passed to {@link #is} is equal to {@code b}
079         *
080         * @param b the object to compare to the base object
081         * @return true if the value returned by {@link Comparable#compareTo} is equal to {@code 0}
082         */
083        public boolean equalTo(final A b) {
084            return a.compareTo(b) == 0;
085        }
086
087        /**
088         * Checks if the object passed to {@link #is} is greater than {@code b}
089         *
090         * @param b the object to compare to the base object
091         * @return true if the value returned by {@link Comparable#compareTo} is greater than {@code 0}
092         */
093        public boolean greaterThan(final A b) {
094            return a.compareTo(b) > 0;
095        }
096
097        /**
098         * Checks if the object passed to {@link #is} is greater than or equal to {@code b}
099         *
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}