/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.measure;

import java.util.Objects;
import java.util.Formatter;
import java.util.Formattable;
import java.util.FormattableFlags;
import java.io.Serializable;
import javax.measure.Unit;
import org.apache.sis.internal.util.Strings;
import org.apache.sis.util.collection.CheckedContainer;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.Emptiable;
import org.apache.sis.util.Numbers;


/**
 * A set of minimum and maximum values of a certain class, allowing
 * a user to determine if a value of the same class is contained inside the range.
 * The minimum and maximum values do not have to be included in the range, and
 * can be null.  If the minimum or maximum values are null, the range is said to
 * be unbounded on that endpoint. If both the minimum and maximum are null,
 * the range is completely unbounded and all values of that class are contained
 * within the range. Null values are always considered <em>exclusive</em>,
 * since iterations over the values will never reach the infinite endpoint.
 *
 * <p>The minimal and maximal values (the <cite>endpoints</cite>) may be inclusive or exclusive.
 * Numeric ranges where both endpoints are inclusive are called <cite>closed intervals</cite>
 * and are represented by square brackets, for example "{@code [0 … 255]}".
 * Numeric ranges where both endpoints are exclusive are called <cite>open intervals</cite>
 * and are represented by parenthesis, for example "{@code (0 … 256)}".</p>
 *
 * <h2>Type and value of range elements</h2>
 * To be a member of a {@code Range}, the {@code <E>} type defining the range must implement the
 * {@link Comparable} interface. All argument values given to the methods of this class shall be
 * or contain instances of that {@code <E>} type. The type is enforced by parameterized type,
 * but some subclasses may put additional constraints. For example {@link MeasurementRange} will
 * additionally checks the units of measurement. Consequently every methods defined in this class
 * may throw an {@link IllegalArgumentException} if a given argument does not met some constraint
 * beyond the type.
 *
 * <h2>Relationship with ISO 19123 definition of range</h2>
 * The ISO 19123 standard (<cite>Coverage geometry and functions</cite>) defines the range as the set
 * (either finite or transfinite) of feature attribute
 * values associated by a function (the coverage) with the
 * elements of the coverage domain. In other words, if we see a coverage as a function, then a range
 * is the set of possible return values.
 *
 * <p>The characteristics of the spatial domain are defined by the ISO 19123 standard whereas the
 * characteristics of the attribute range are not part of that standard. In Apache SIS, those
 * characteristics are described by the {@code SampleDimension} class,
 * which may contain one or many {@code Range} instances. Consequently this {@code Range} class
 * is closely related, but not identical, to the ISO 19123 definition or range.</p>
 *
 * <p>Ranges are not necessarily numeric. Numeric and non-numeric ranges can be associated to
 * discrete coverages, while typically only
 * numeric ranges can be associated to continuous coverages.</p>
 *
 * <h2>Immutability and thread safety</h2>
 * This class and the {@link NumberRange} / {@link MeasurementRange} subclasses are immutable,
 * and thus inherently thread-safe. Other subclasses may or may not be immutable, at implementation choice.
 * But implementers are encouraged to make sure that all subclasses remain immutable for more predictable behavior.
 *
 * @author  Joe White
 * @author  Martin Desruisseaux (Geomatys)
 * @author  Jody Garnett (for parameterized type inspiration)
 * @version 1.0
 *
 * @param <E>  the type of range elements, typically a {@link Number} subclass or {@link java.util.Date}.
 *
 * @see RangeFormat
 * @see org.apache.sis.util.collection.RangeSet
 *
 * @since 0.3
 * @module
 */
public class Range<E extends Comparable<? super E>> implements CheckedContainer<E>, Formattable, Emptiable, Serializable {
    /**
     * For cross-version compatibility.
     */
    private static final long serialVersionUID = 603508245068333284L;

    /**
     * The base type of elements in this range.
     *
     * @see #getElementType()
     */
    final Class<E> elementType;

    /**
     * The minimal and maximal values.
     */
    final E minValue, maxValue;

    /**
     * Whether the minimal or maximum value is included.
     */
    final boolean isMinIncluded, isMaxIncluded;

    /**
     * Constructs a range with the same type and the same values than the specified range.
     * This is a copy constructor.
     *
     * @param  range  the range to copy.
     */
    public Range(final Range<E> range) {
        elementType   = range.elementType;
        minValue      = range.minValue;
        isMinIncluded = range.isMinIncluded;
        maxValue      = range.maxValue;
        isMaxIncluded = range.isMaxIncluded;
        assert validate() : elementType;
    }

    /**
     * Creates a new range bounded by the given endpoint values.
     * If the given minimum value is greater than the maximum value, then the range {@linkplain #isEmpty() is empty}.
     *
     * <div class="note"><b>Assertion:</b>
     * This constructor verifies the {@code minValue} and {@code maxValue} arguments type if Java assertions
     * are enabled. This verification is not performed in normal execution because theoretically unnecessary
     * unless Java generic types have been tricked.</div>
     *
     * @param  elementType    the base type of the range elements.
     * @param  minValue       the minimal value, or {@code null} if none.
     * @param  isMinIncluded  {@code true} if the minimal value is inclusive, or {@code false} if exclusive.
     * @param  maxValue       the maximal value, or {@code null} if none.
     * @param  isMaxIncluded  {@code true} if the maximal value is inclusive, or {@code false} if exclusive.
     */
    public Range(final Class<E> elementType,
            final E minValue, final boolean isMinIncluded,
            final E maxValue, final boolean isMaxIncluded)
    {
        ArgumentChecks.ensureNonNull("elementType", elementType);
        /*
         * The 'isMin/Maxincluded' flags must be forced to 'false' if 'minValue' or 'maxValue'
         * are null. This is required for proper working of algorithms implemented in this class.
         */
        this.elementType   = elementType;
        this.minValue      = minValue;
        this.isMinIncluded = isMinIncluded && (minValue != null);
        this.maxValue      = maxValue;
        this.isMaxIncluded = isMaxIncluded && (maxValue != null);
        assert validate() : elementType;
    }

    /**
     * Creates a new range using the same element type than this range. This method will
     * be overridden by subclasses in order to create a range of a more specific type.
     *
     * <div class="note"><b>API note:</b>
     * This method is invoked by all operations (union, intersection, <i>etc.</i>) that may create a new range.
     * But despite this fact, the return type of those methods are nailed down to {@code Range} (i.e. subclasses
     * shall not override the above-cited operations with covariant return type) because those operations may return
     * the given argument directly, and we have no guarantees on the type of those arguments.</div>
     */
    Range<E> create(final E minValue, final boolean isMinIncluded,
                    final E maxValue, final boolean isMaxIncluded)
    {
        return new Range<>(elementType, minValue, isMinIncluded, maxValue, isMaxIncluded);
    }

    /**
     * Returns an initially empty array of {@code getClass()} type and of the given length.
     * This method is overridden by subclasses in order to create arrays of more specific type.
     * This method is invoked by the {@link #subtract(Range)} method. It is okay to use the new
     * array only if the ranges to store in that array are only {@code this} or new ranges created
     * by the {@link #create(Comparable, boolean, Comparable, boolean)} method - otherwise we may
     * get an {@link ArrayStoreException}.
     */
    @SuppressWarnings({"unchecked","rawtypes"})                     // Generic array creation.
    Range<E>[] newArray(final int length) {
        return new Range[length];
    }

    /**
     * To be overridden by {@link MeasurementRange} only.
     *
     * @return the unit of measurement, or {@code null}.
     */
    Unit<?> unit() {
        return null;
    }

    /**
     * Invoked by the constructors in order to ensure that the argument are of valid types.
     * This check is performed only when assertions are enabled. This test is not needed in
     * normal execution if the users do not bypass the checks performed by generic types.
     */
    private boolean validate() {
        ArgumentChecks.ensureCanCast("minValue", elementType, minValue);
        ArgumentChecks.ensureCanCast("maxValue", elementType, maxValue);
        return Comparable.class.isAssignableFrom(elementType);
    }

    /**
     * Returns the base type of elements in this range.
     * This is the type specified at construction time.
     */
    @Override
    public Class<E> getElementType() {
        return elementType;
    }

    /**
     * Returns the minimal value, or {@code null} if this range has no lower limit.
     * If non-null, the returned value is either inclusive or exclusive depending on
     * the boolean returned by {@link #isMinIncluded()}.
     *
     * @return the minimal value, or {@code null} if this range is unbounded on the lower side.
     */
    public E getMinValue() {
        return minValue;
    }

    /**
     * Returns {@code true} if the {@linkplain #getMinValue() minimal value} is inclusive,
     * or {@code false} if exclusive. Note that {@code null} values are always considered
     * exclusive.
     *
     * @return {@code true} if the minimal value is inclusive, or {@code false} if exclusive.
     */
    public boolean isMinIncluded() {
        return isMinIncluded;
    }

    /**
     * Returns the maximal value, or {@code null} if this range has no upper limit.
     * If non-null, the returned value is either inclusive or exclusive depending on
     * the boolean returned by {@link #isMaxIncluded()}.
     *
     * @return the maximal value, or {@code null} if this range is unbounded on the upper side.
     */
    public E getMaxValue() {
        return maxValue;
    }

    /**
     * Returns {@code true} if the {@linkplain #getMaxValue() maximal value} is inclusive,
     * or {@code false} if exclusive. Note that {@code null} values are always considered
     * exclusive.
     *
     * @return {@code true} if the maximal value is inclusive, or {@code false} if exclusive.
     */
    public boolean isMaxIncluded() {
        return isMaxIncluded;
    }

    /**
     * Returns {@code true} if this range is empty. A range is empty if the
     * {@linkplain #getMinValue() minimum value} is greater than the
     * {@linkplain #getMaxValue() maximum value}, or if they are equal while
     * at least one of them is exclusive.
     *
     * <div class="note"><b>API note:</b>
     * This method is final because often used by the internal implementation.
     * Making the method final ensures that the other methods behave consistently.</div>
     *
     * @return {@code true} if this range is empty.
     */
    @Override
    public final boolean isEmpty() {
        if (minValue == null || maxValue == null) {
            return false;                               // Unbounded: can not be empty.
        }
        final int c = minValue.compareTo(maxValue);
        if (c < 0) {
            return false;                               // Minimum is smaller than maximum.
        }
        // If min and max are equal, then the range is empty if at least one of them is exclusive.
        return (c != 0) || !isMinIncluded || !isMaxIncluded;
    }

    /**
     * Returns {@code true} if this range is both left-bounded and right-bounded.
     * A {@code true} return value guarantees that:
     *
     * <ol>
     *   <li>both {@link #getMinValue()} and {@link #getMaxValue()} will return non-null values;</li>
     *   <li>if minimum and maximum values are numbers, then those numbers are finite.</li>
     * </ol>
     *
     * @return whether this range is left- and right-bounded.
     *
     * @since 1.0
     */
    public boolean isBounded() {
        return minValue != null && maxValue != null;
    }

    /**
     * Returns {@code true} if this range contains the given value. A range never contains the
     * {@code null} value. This is consistent with the <a href="#skip-navbar_top">class javadoc</a>
     * stating that null {@linkplain #getMinValue() minimum} or {@linkplain #getMaxValue() maximum}
     * values are exclusive.
     *
     * @param  value  the value to check for inclusion in this range.
     * @return {@code true} if the given value is included in this range.
     */
    public boolean contains(final E value) {
        if (value == null) {
            return false;
        }
        /*
         * Implementation note: when testing for inclusion or intersection in a range
         * (or in a rectangle, cube, etc.), it is often easier to test when we do not
         * have inclusion than to test for inclusion. So we test when to return false
         * and if no such test pass, we can return true.
         *
         * We consistently use min/maxValue.compareTo(value) in this class rather than
         * the opposite argument order (namely value.compareTo(min/maxValue)) in the
         * hope to reduce the risk of inconsistent behavior if usera pass different
         * sub-classes for the 'value' argument with different implementations of the
         * 'compareTo' method. Intead than using those user implementations, we always
         * use the implementations provided by min/maxValue.
         */
        if (minValue != null) {
            final int c = minValue.compareTo(value);
            if (isMinIncluded ? (c > 0) : (c >= 0)) {
                return false;
            }
        }
        if (maxValue != null) {
            final int c = maxValue.compareTo(value);
            if (isMaxIncluded ? (c < 0) : (c <= 0)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns {@code true} if the supplied range is fully contained within this range.
     *
     * @param  range  the range to check for inclusion in this range.
     * @return {@code true} if the given range is included in this range.
     * @throws IllegalArgumentException if the given range is incompatible,
     *         for example because of incommensurable units of measurement.
     */
    public boolean contains(final Range<? extends E> range) {
        /*
         * We could implement this method as below:
         *
         *     return contains(range.minValue) && contains(range.maxValue);
         *
         * However the above code performs more comparisons than necessary,
         * since it implicitly performs the following redundant checks:
         *
         *     (range.minValue < maxValue) redundant with (range.maxValue < maxValue)
         *     (range.maxValue > minValue) redundant with (range.minValue > minValue)
         *
         * We can implement this method with less comparisons as below:
         *
         *     return minValue.compareTo(range.minValue) <= 0 &&
         *            maxValue.compareTo(range.maxValue) >= 0;
         *
         * However we still have a little bit of additional checks to perform for the
         * inclusion status of both ranges.  Since the same checks will be needed for
         * intersection methods,  we factor out the comparisons in 'compareMinTo' and
         * 'compareMaxTo' methods.
         */
        return (compareMinTo(range.minValue, range.isMinIncluded ? 0 : -1) <= 0) &&
               (compareMaxTo(range.maxValue, range.isMaxIncluded ? 0 : +1) >= 0);
    }

    /**
     * Returns {@code true} if this range intersects the given range.
     *
     * @param  range  the range to check for intersection with this range.
     * @return {@code true} if the given range intersects this range.
     * @throws IllegalArgumentException if the given range is incompatible,
     *         for example because of incommensurable units of measurement.
     */
    public boolean intersects(final Range<? extends E> range) {
        return (compareMinTo(range.maxValue, range.isMaxIncluded ? 0 : +1) <= 0) &&
               (compareMaxTo(range.minValue, range.isMinIncluded ? 0 : -1) >= 0);
    }

    /**
     * Returns the intersection between this range and the given range.
     *
     * @param  range  the range to intersect.
     * @return the intersection of this range with the given range.
     * @throws IllegalArgumentException if the given range is incompatible,
     *         for example because of incommensurable units of measurement.
     */
    public Range<E> intersect(final Range<E> range) {
        if (range.isEmpty()) return range;
        if (this .isEmpty()) return this;
        /*
         * For two ranges [L₁ … H₁] and [L₂ … H₂], the intersection is given by
         * ([max(L₁, L₂) … min(H₁, H₂)]). Only two comparisons is needed.
         *
         * There is a small complication since we shall also handle the inclusive states.
         * so instead of extracting the minimal and maximal values directly, we will
         * find which range contains the highest minimal value, and which range contains
         * the smallest maximal value. If we find the same range in both case (which can
         * be either 'this' or 'range), return that range. Otherwise we need to create a
         * new one.
         */
        final Range<E> intersect, min, max;
        min = compareMinTo(range.minValue, range.isMinIncluded ? 0 : -1) < 0 ? range : this;
        max = compareMaxTo(range.maxValue, range.isMaxIncluded ? 0 : +1) > 0 ? range : this;
        if (min == max) {
            intersect = min;
        } else {
            intersect = create(min.minValue, min.isMinIncluded, max.maxValue, max.isMaxIncluded);
        }
        assert intersect.isEmpty() == !intersects(range) : intersect;
        return intersect;
    }

    /**
     * Returns the union of this range with the given range.
     *
     * @param  range  the range to add to this range.
     * @return the union of this range with the given range.
     * @throws IllegalArgumentException if the given range is incompatible,
     *         for example because of incommensurable units of measurement.
     */
    public Range<E> union(final Range<E> range) {
        if (range.isEmpty()) return this;
        if (this .isEmpty()) return range;

        final Range<E> union, min, max;
        min = compareMinTo(range.minValue, range.isMinIncluded ? 0 : -1) > 0 ? range : this;
        max = compareMaxTo(range.maxValue, range.isMaxIncluded ? 0 : +1) < 0 ? range : this;
        if (min == max) {
            union = min;
        } else {
            union = create(min.minValue, min.isMinIncluded, max.maxValue, max.isMaxIncluded);
        }
        assert union.contains(min) : min;
        assert union.contains(max) : max;
        return union;
    }

    /**
     * Returns the range of values that are in this range but not in the given range.
     * This method returns an array of length 0, 1 or 2:
     *
     * <ul>
     *   <li>If the given range contains fully this range, returns an array of length 0.</li>
     *   <li>If the given range is in the middle of this range, then the subtraction results in
     *       two disjoint ranges which will be returned as two elements in the array.</li>
     *   <li>Otherwise returns an array of length 1.</li>
     * </ul>
     *
     * @param  range  the range to subtract.
     * @return this range without the given range, as an array of length 0, 1 or 2.
     * @throws IllegalArgumentException if the given range is incompatible,
     *         for example because of incommensurable units of measurement.
     */
    public Range<E>[] subtract(final Range<E> range) {
        /*
         * Implementation note: never store the 'range' argument value in the array
         * returned by 'newArray(int)', otherwise we may get an ArrayStoreException.
         */
        final Range<E> subtract;
        if (!intersects(range)) {
            subtract = this;
        } else {
            final boolean clipMin = compareMinTo(range.minValue, range.isMinIncluded ? 0 : -1) >= 0;
            final boolean clipMax = compareMaxTo(range.maxValue, range.isMaxIncluded ? 0 : +1) <= 0;
            if (clipMin) {
                if (clipMax) {
                    // The given range contains fully this range.
                    assert range.contains(this) : range;
                    return newArray(0);
                }
                subtract = create(range.maxValue, !range.isMaxIncluded, maxValue, isMaxIncluded);
            } else {
                if (!clipMax) {
                    final Range<E>[] array = newArray(2);
                    array[0] = create(minValue, isMinIncluded, range.minValue, !range.isMinIncluded);
                    array[1] = create(range.maxValue, !range.isMaxIncluded, maxValue, isMaxIncluded);
                    return array;
                }
                subtract = create(minValue, isMinIncluded, range.minValue, !range.isMinIncluded);
            }
        }
        assert contains(subtract) : subtract;
        assert !subtract.intersects(range) : subtract;
        final Range<E>[] array = newArray(1);
        array[0] = subtract;
        return array;
    }

    /**
     * Compares the {@linkplain #getMinValue() minimum value} of this range with the given endpoint of
     * another range. Since the given value is either the minimal or maximal value of another range,
     * it may be inclusive or exclusive. The latter is specified by {@code position} as below:
     *
     * <ul>
     *   <li> 0 if {@code value} is inclusive.</li>
     *   <li>-1 if {@code value} is exclusive and lower than the inclusive values of the other range.</li>
     *   <li>+1 if {@code value} is exclusive and higher than the inclusive values of the other range.</li>
     * </ul>
     *
     * Note that the non-zero position shall be exactly -1 or +1, not arbitrary negative or positive.
     *
     * @param  value     an endpoint value of the other range to be compared to the minimal value of this range.
     * @param  position  the position of {@code value} relative to the inclusive values of the other range.
     * @return position (-, + or 0) of the inclusive values of this range compared to the other range.
     *
     * @see #contains(Range)
     */
    private int compareMinTo(final E value, int position) {
        /*
         * Check for infinite values.  If the given value is infinite, it can be either positive or
         * negative infinity, which we can infer from the 'position' argument. Note that 'position'
         * can not be 0 in such case, since infinities are always exclusive in this class.
         */
        if (minValue == null) {
            return (value == null) ? 0 : -1;
        }
        if (value == null) {
            return -position;
        }
        /*
         * Compare the two finite values. If they are not equal, we are done regardless the
         * inclusion states, because the difference between included and excluded values is
         * considered smaller than any quantity we can represent.
         */
        final int c = minValue.compareTo(value);
        if (c != 0) {
            return c;
        }
        /*
         * The two values are equal. If the 'minValue' of this range is inclusive, then the given
         * 'value' is directly at the "right" place (the beginning of the interior of this range),
         * so the 'position' argument gives directly the position of the "true minValue" relative
         * to the interior of the other range.
         *
         * But if 'minValue' is exclusive, then the "true minValue" of this range is one position
         * to the right  (where "position" is a counter for an infinitely small quantity, similar
         * to 'dx' in calculus). The effect is to return 0 if the given 'value' is also exclusive
         * and lower than the interior of the other range (position == -1),  and a positive value
         * in all other cases.
         */
        if (!isMinIncluded) {
            position++;
        }
        return position;
    }

    /**
     * Compares the {@linkplain #getMaxValue() maximum value} of this range with the given endpoint
     * of another range. See the comment in {@link #compareMinTo(Comparable, int)} for more details.
     */
    private int compareMaxTo(final E value, int position) {
        if (maxValue == null) {
            return (value == null) ? 0 : +1;
        }
        if (value == null) {
            return -position;
        }
        final int c = maxValue.compareTo(value);
        if (c != 0) {
            return c;
        }
        if (!isMaxIncluded) {
            position--;
        }
        return position;
    }

    /**
     * Compares this range with the given object for equality.
     * Two ranges are considered equal if they met the following conditions:
     *
     * <ul>
     *   <li>They are of the same {@linkplain #getClass() class}.</li>
     *   <li>They have the same {@linkplain #getElementType() element type}.</li>
     *   <li>Both ranges {@linkplain #isEmpty() are empty}, <strong>or</strong> (if at least one range is non-empty):
     *     <ul>
     *       <li>They have equal {@linkplain #getMinValue() minimum} value in the sense of {@link Object#equals(Object)}.</li>
     *       <li>They have equal {@linkplain #getMaxValue() maximum} value in the sense of {@link Object#equals(Object)}.</li>
     *       <li>They have equal {@linkplain #isMinIncluded() inclusive minimum} flag.</li>
     *       <li>They have equal {@linkplain #isMaxIncluded() inclusive maximum} flag.</li>
     *     </ul>
     *   <li>Any other requirement added by subclasses.
     *       In particular {@link MeasurementRange} compares also the units of measurement.</li>
     * </ul>
     *
     * Note that this method may return {@code true} even if the bounds are not strictly identical.
     * In particular this method returns {@code true} if the ranges are empty regardless their minimum and maximum values,
     * and also returns {@code true} if the bounds are wrappers for some {@link Float#NaN} or {@link Double#NaN} values
     * even if their {@linkplain Double#doubleToRawLongBits(double) raw bits pattern} are not the same.
     * The latter is because {@link Float#equals(Object)} and {@link Double#equals(Object)} consider all NaN values as equal.
     *
     * @param  object  the object to compare with this range for equality.
     * @return {@code true} if the given object is equal to this range.
     */
    @Override
    public boolean equals(final Object object) {
        if (object == this) {
            return true;
        }
        if (object != null && object.getClass() == getClass()) {
            final Range<?> other = (Range<?>) object;
            if (Objects.equals(elementType, other.elementType)) {
                if (isEmpty()) {
                    return other.isEmpty();
                }
                return Objects.equals(minValue, other.minValue) &&
                       Objects.equals(maxValue, other.maxValue) &&
                       isMinIncluded == other.isMinIncluded &&
                       isMaxIncluded == other.isMaxIncluded;
            }
        }
        return false;
    }

    /**
     * Returns a hash code value for this range.
     */
    @Override
    public int hashCode() {
        int hash = elementType.hashCode();
        if (!isEmpty()) {
            hash = 13 * hash + Objects.hashCode(minValue);
            hash = 13 * hash + Objects.hashCode(maxValue);
            hash += isMinIncluded ?   17 :   37;
            hash += isMaxIncluded ? 1231 : 1237;
        }
        return hash ^ (int) serialVersionUID;
    }

    /**
     * Returns {@code true} if the given number is formatted with only one character.
     * We will use less space if the minimum and maximum values are formatted using
     * only one digit. This method assumes that we have verified that the element type
     * is an integer type before to invoke this method.
     */
    private static boolean isCompact(final Comparable<?> value, final boolean ifNull) {
        if (value == null) {
            return ifNull;
        }
        final long n = ((Number) value).longValue();
        return n >= 0 && n < 10;
    }

    /**
     * Returns a unlocalized string representation of this range. This method complies to the format
     * described in the <a href="https://en.wikipedia.org/wiki/ISO_31-11">ISO 31-11</a> standard,
     * except that the minimal and maximal values are separated by the "{@code …}" character
     * instead of coma. More specifically, the string representation is defined as below:
     *
     * <ul>
     *   <li>If the range {@linkplain #isEmpty() is empty}, then this method returns "{@code {}}".</li>
     *   <li>Otherwise if the minimal value is equal to the maximal value, then the string
     *       representation of that value is returned inside braces as in "{@code {value}}".</li>
     *   <li>Otherwise the string representation of the minimal and maximal values are formatted
     *       like "{@code [min … max]}" for inclusive endpoints or "{@code (min … max)}" for exclusive
     *       endpoints, or a mix of both styles. The "{@code ∞}" symbol is used in place of
     *       {@code min} or {@code max} for unbounded ranges.</li>
     * </ul>
     *
     * If this range is a {@link MeasurementRange}, then the {@linkplain Unit unit of measurement}
     * is appended to the above string representation except for empty ranges.
     *
     * @see RangeFormat
     * @see <a href="https://en.wikipedia.org/wiki/ISO_31-11">Wikipedia: ISO 31-11</a>
     */
    @Override
    public String toString() {
        if (isEmpty()) {
            return "{}";
        }
        final StringBuilder buffer = new StringBuilder(20);
        if (minValue != null && minValue.equals(maxValue)) {
            buffer.append('{').append(minValue).append('}');
        } else {
            buffer.append(isMinIncluded ? '[' : '(');
            if (minValue == null) {
                buffer.append("−∞");
            } else {
                buffer.append(minValue);
            }
            // Compact representation for integers, more space for real numbers.
            if (Numbers.isInteger(elementType) && isCompact(minValue, false) && isCompact(maxValue, true)) {
                buffer.append('…');
            } else {
                buffer.append(" … ");
            }
            if (maxValue == null) {
                buffer.append('∞');
            } else {
                buffer.append(maxValue);
            }
            buffer.append(isMaxIncluded ? ']' : ')');
        }
        final Unit<?> unit = unit();
        if (unit != null) {
            final String symbol = unit.toString();
            if (symbol != null && !symbol.isEmpty()) {
                if (Character.isLetterOrDigit(symbol.codePointAt(0))) {
                    buffer.append(' ');
                }
                buffer.append(symbol);
            }
        }
        return buffer.toString();
    }

    /**
     * Formats this range using the provided formatter. This method is invoked when a
     * {@code Range} object is formatted using the {@code "%s"} conversion specifier of
     * {@link Formatter}. Users don't need to invoke this method explicitly.
     *
     * <p>If the alternate flags is present (as in {@code "%#s"}), then the range will
     * be formatted using the {@linkplain RangeFormat#isAlternateForm() alternate form}
     * for exclusive bounds.</p>
     *
     * @param  formatter  the formatter in which to format this range.
     * @param  flags      {@link FormattableFlags#LEFT_JUSTIFY} for left alignment, or 0 for right alignment.
     * @param  width      minimal number of characters to write, padding with {@code ' '} if necessary.
     * @param  precision  maximal number of characters to write, or -1 if no limit.
     */
    @Override
    public void formatTo(final Formatter formatter, final int flags, final int width, int precision) {
        final String value;
        if (precision == 0) {
            value = "";
        } else {
            final RangeFormat format = new RangeFormat(formatter.locale(), elementType);
            format.setAlternateForm((flags & FormattableFlags.ALTERNATE) != 0);
            value = format.format(this, new StringBuffer(), null).toString();
        }
        Strings.formatTo(formatter, flags, width, precision, value);
    }
}
