    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
    021/**
    022 * <p>Utility library to provide helper methods for translating {@link Comparable#compareTo} result into a boolean.</p>
    023 *
    024 * <p>Example: {@code boolean x = is(myComparable).lessThanOrEqualTo(otherComparable)}</p>
    025 *
    026 * <p>#ThreadSafe#</p>
    027 *
    028 * @since 3.10
    029 */
    030public class ComparableUtils {
    031
    032    /**
    033     * Provides access to the available methods
    034     *
    035     * @param <A> the type of objects that this object may be compared against.
    036     */
    037    public static class ComparableCheckBuilder<A extends Comparable<A>> {
    038
    039        private final A a;
    040
    041        private ComparableCheckBuilder(final A a) {
    042            this.a = a;
    043        }
    044
    045        /**
    046         * Checks if {@code [b <= a <= c]} or {@code [b >= a >= c]} where the {@code a} is object passed to {@link #is}.
    047         *
    048         * @param b the object to compare to the base object
    049         * @param c the object to compare to the base object
    050         * @return true if the base object is between b and c
    051         */
    052        public boolean between(final A b, final A c) {
    053            return betweenOrdered(b, c) || betweenOrdered(c, b);
    054        }
    055
    056        /**
    057         * Checks if {@code (b < a < c)} or {@code (b > a > c)} where the {@code a} is object passed to {@link #is}.
    058         *
    059         * @param b the object to compare to the base object
    060         * @param c the object to compare to the base object
    061         * @return true if the base object is between b and c and not equal to those
    062         */
    063        public boolean betweenExclusive(final A b, final A c) {
    064            return betweenOrderedExclusive(b, c) || betweenOrderedExclusive(c, b);
    065        }
    066
    067        private boolean betweenOrdered(final A b, final A c) {
    068            return greaterThanOrEqualTo(b) && lessThanOrEqualTo(c);
    069        }
    070
    071        private boolean betweenOrderedExclusive(final A b, final A c) {
    072            return greaterThan(b) && lessThan(c);
    073        }
    074
    075        /**
    076         * Checks if the object passed to {@link #is} is equal to {@code b}
    077         *
    078         * @param b the object to compare to the base object
    079         * @return true if the value returned by {@link Comparable#compareTo} is equal to {@code 0}
    080         */
    081        public boolean equalTo(final A b) {
    082            return a.compareTo(b) == 0;
    083        }
    084
    085        /**
    086         * Checks if the object passed to {@link #is} is greater than {@code b}
    087         *
    088         * @param b the object to compare to the base object
    089         * @return true if the value returned by {@link Comparable#compareTo} is greater than {@code 0}
    090         */
    091        public boolean greaterThan(final A b) {
    092            return a.compareTo(b) > 0;
    093        }
    094
    095        /**
    096         * Checks if the object passed to {@link #is} is greater than or equal to {@code b}
    097         *
    098         * @param b the object to compare to the base object
    099         * @return true if the value returned by {@link Comparable#compareTo} is greater than or equal to {@code 0}
    100         */
    101        public boolean greaterThanOrEqualTo(final A b) {
    102            return a.compareTo(b) >= 0;
    103        }
    104
    105        /**
    106         * Checks if the object passed to {@link #is} is less than {@code b}
    107         *
    108         * @param b the object to compare to the base object
    109         * @return true if the value returned by {@link Comparable#compareTo} is less than {@code 0}
    110         */
    111        public boolean lessThan(final A b) {
    112            return a.compareTo(b) < 0;
    113        }
    114
    115        /**
    116         * Checks if the object passed to {@link #is} is less than or equal to {@code b}
    117         *
    118         * @param b the object to compare to the base object
    119         * @return true if the value returned by {@link Comparable#compareTo} is less than or equal to {@code 0}
    120         */
    121        public boolean lessThanOrEqualTo(final A b) {
    122            return a.compareTo(b) <= 0;
    123        }
    124    }
    125
    126    /**
    127     * Checks if {@code [b <= a <= c]} or {@code [b >= a >= c]} where the {@code a} is the tested object.
    128     *
    129     * @param b the object to compare to the tested object
    130     * @param c the object to compare to the tested object
    131     * @param <A> type of the test object
    132     * @return a predicate for true if the tested object is between b and c
    133     */
    134    public static <A extends Comparable<A>> Predicate<A> between(final A b, final A c) {
    135        return a -> is(a).between(b, c);
    136    }
    137
    138    /**
    139     * Checks if {@code (b < a < c)} or {@code (b > a > c)} where the {@code a} is the tested object.
    140     *
    141     * @param b the object to compare to the tested object
    142     * @param c the object to compare to the tested object
    143     * @param <A> type of the test object
    144     * @return a predicate for true if the tested object is between b and c and not equal to those
    145     */
    146    public static <A extends Comparable<A>> Predicate<A> betweenExclusive(final A b, final A c) {
    147        return a -> is(a).betweenExclusive(b, c);
    148    }
    149
    150    /**
    151     * Checks if the tested object is greater than or equal to {@code b}
    152     *
    153     * @param b the object to compare to the tested object
    154     * @param <A> type of the test object
    155     * @return a predicate for true if the value returned by {@link Comparable#compareTo}
    156     * is greater than or equal to {@code 0}
    157     */
    158    public static <A extends Comparable<A>> Predicate<A> ge(final A b) {
    159        return a -> is(a).greaterThanOrEqualTo(b);
    160    }
    161
    162    /**
    163     * Checks if the tested object is greater than {@code b}
    164     *
    165     * @param b the object to compare to the tested object
    166     * @param <A> type of the test object
    167     * @return a predicate for true if the value returned by {@link Comparable#compareTo} is greater than {@code 0}
    168     */
    169    public static <A extends Comparable<A>> Predicate<A> gt(final A b) {
    170        return a -> is(a).greaterThan(b);
    171    }
    172
    173    /**
    174     * Provides access to the available methods
    175     *
    176     * @param a base object in the further comparison
    177     * @param <A> type of the base object
    178     * @return a builder object with further methods
    179     */
    180    public static <A extends Comparable<A>> ComparableCheckBuilder<A> is(final A a) {
    181        return new ComparableCheckBuilder<>(a);
    182    }
    183
    184    /**
    185     * Checks if the tested object is less than or equal to {@code b}
    186     *
    187     * @param b the object to compare to the tested object
    188     * @param <A> type of the test object
    189     * @return a predicate for true if the value returned by {@link Comparable#compareTo}
    190     * is less than or equal to {@code 0}
    191     */
    192    public static <A extends Comparable<A>> Predicate<A> le(final A b) {
    193        return a -> is(a).lessThanOrEqualTo(b);
    194    }
    195
    196    /**
    197     * Checks if the tested object is less than {@code b}
    198     *
    199     * @param b the object to compare to the tested object
    200     * @param <A> type of the test object
    201     * @return a predicate for true if the value returned by {@link Comparable#compareTo} is less than {@code 0}
    202     */
    203    public static <A extends Comparable<A>> Predicate<A> lt(final A b) {
    204        return a -> is(a).lessThan(b);
    205    }
    206
    207    private ComparableUtils() {}
    208}