    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 *      https://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 * Helper translating {@link Comparable#compareTo} results to booleans.
    025 *
    026 * <p>Example: {@code boolean x = ComparableUtils.is(myComparable).lessThanOrEqualTo(otherComparable)}</p>
    027 *
    028 * <p>#ThreadSafe#</p>
    029 *
    030 * @since 3.10
    031 */
    032public class ComparableUtils {
    033
    034    /**
    035     * Compares objects of a given generic type {@code A}.
    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         * Tests 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         * Tests 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         * Tests 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 != null && a.compareTo(b) == 0;
    085        }
    086
    087        /**
    088         * Tests 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 != null && a.compareTo(b) > 0;
    095        }
    096
    097        /**
    098         * Tests 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 != 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}