All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.mmm.base.range.Range Maven / Gradle / Ivy

/* Copyright (c) The m-m-m Team, Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0 */
package io.github.mmm.base.range;

import java.util.Comparator;

/**
 * This class represents a range from {@link #getMin() minimum} to {@link #getMax() maximum}. Implementations shall
 * validate at construction so a given {@link Range} should always be valid. 
* ATTENTION:
* The {@link #getMin() minimum} and {@link #getMax() maximum} may be {@code null} for {@link #unbounded() unbounded * ranges}. It is still recommended to use fixed bounds such as {@link Long#MAX_VALUE}. However, for types such as * {@link java.math.BigDecimal} this is not possible. * * @param type of the contained values. * @since 1.0.0 */ public interface Range> { /** Char indicating start with inclusive minimum. */ char BOUND_START_INCLUSIVE = '['; /** Char indicating start with exclusive minimum. */ char BOUND_START_EXCLUSIVE = '('; /** Char indicating end with inclusive maximum. */ char BOUND_END_INCLUSIVE = ']'; /** Char indicating end with exclusive maximum. */ char BOUND_END_EXCLUSIVE = ')'; /** * Char to separate minimum and maximum. Mathematical convention would be to use a comma (','), but this causes * problems when parsing {@link Object#toString() string representations} as a comma may also occur in the minimum or * maximum value. */ char BOUND_SEPARATOR = '\uFF0C'; /** The unbound minimum. */ String MIN_UNBOUND = "\u2212\u221E"; /** The unbound maximum. */ String MAX_UNBOUND = "+\u221E"; /** Property name of {@link #getMin()}. */ String PROPERTY_MIN = "min"; /** Property name of {@link #getMax()}. */ String PROPERTY_MAX = "max"; /** * @return the lower bound of this range or {@code null} if no lower bound is defined. Has to be less than * {@link #getMax() max} if both boundaries are not {@code null}. */ V getMin(); /** * @return the upper bound of this range or {@code null} if no upper bound is defined. Has to be greater than * {@link #getMin() min} if both boundaries are not {@code null}. */ V getMax(); /** * @return the {@link Comparator} used to {@link Comparator#compare(Object, Object) compare} values of this * {@link Range}. The default implementation assumes that the value type implements {@link Comparable}. If you * want to use other value types you need to override this method. */ @SuppressWarnings({ "unchecked", "rawtypes" }) default Comparator getComparator() { return (Comparator) Comparator.naturalOrder(); } /** * This method determines if the given {@code value} is within this {@link Range} from {@link #getMin() minimum} to * {@link #getMax() maximum}. * * @param value is the vale to check. * @return {@code true} if contained ({@link #getMin() minimum} {@literal <=} {@code value} {@literal >=} * {@link #getMax() maximum}), {@code false} otherwise. If the given value is {@code null}, {@code false} will * be returned. */ default boolean contains(V value) { if (value == null) { return false; } return value == clip(value); } /** * This method clips the given {@code value} so the result is {@link #contains(Comparable) contained} in this * {@link Range} unless the given {@code value} is {@code null}. * * @param value is the vale to clip. May be {@code null}. * @return the given {@code value} clipped to this range. If the given {@code value} is less than the {@link #getMin() * minimum}, that {@link #getMin() minimum} will be returned. If the given {@code value} is greater than the * {@link #getMax() maximum}, that {@link #getMax() maximum} will be returned. Otherwise the given * {@code value} is returned. */ default V clip(V value) { if (value == null) { return null; } Comparator comparator = getComparator(); int delta; V min = getMin(); if (min != null) { delta = comparator.compare(value, min); if (delta < 0) { // value < min return min; } } V max = getMax(); if (max != null) { delta = comparator.compare(value, max); if (delta > 0) { // value > max return max; } } return value; } /** * @param minimum the new {@link #getMin() minimum}. * @param maximum the new {@link #getMax() maximum}. * @return a new {@link Range} with the given boundaries. */ Range with(V minimum, V maximum); /** * @param minimum the new {@link #getMin() minimum}. * @return a new {@link Range} where the {@link #getMin() minimum} is set to the given {@code minimum} value. */ default Range withMin(V minimum) { return with(minimum, getMax()); } /** * @param maximum the new {@link #getMax() maximum}. * @return a new {@link Range} where the {@link #getMax() maximum} is set to the given {@code maximum} value. */ default Range withMax(V maximum) { return with(getMin(), maximum); } /** * @param range the {@link Range} to build the intersection with. * @return the intersection of this {@link Range} with the given {@link Range} that is a {@link Range} with the * highest {@link #getMin() minimum} and the lowest {@link #getMax() maximum} of the two ranges to intersect. * In case the {@link Range}s the intersection of */ Range intersection(Range range); /** * @return true if this {@link Range} is {@link #unbounded() unbounded}. */ default boolean isUnbounded() { return ((getMin() == null) && (getMax() == null)); } /** * @param type of the {@link #contains(Comparable) contained value}. * @param min the {@link #getMin() minimum}. * @param max the {@link #getMax() maximum}. * @return the specified {@link Range}. */ static > Range of(T min, T max) { return RangeType.of(min, max); } /** * @param type of the {@link #contains(Comparable) contained value}. * @return the unbounded {@link Range} instance {@link #contains(Comparable) containing} all values (with * {@link #getMin()} and {@link #getMax()} being {@code null}). */ static > Range unbounded() { return RangeType.UNBOUNDED; } /** * @param type of the {@link #contains(Comparable) contained value}. * @return the invalid {@link Range} instance {@link #contains(Comparable) containing} no values at all (with * {@link #getMin()} and {@link #getMax()} being {@code null}). */ static > Range invalid() { return RangeType.INVALID; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy