cdc.applic.expressions.content.AbstractRange Maven / Gradle / Ivy
Show all versions of cdc-applic-expressions Show documentation
package cdc.applic.expressions.content;
import java.util.Comparator;
import java.util.Objects;
import cdc.applic.expressions.IllegalOperationException;
import cdc.util.lang.Checks;
/**
* Base range implementation.
*
* The minimum value can be greater than the maximum one. In that case, the range is empty.
* Two empty ranges are considered as equal, whatever the bounds are.
*
* Warning: The comparison algorithm is intended for internal use.
*
* @author Damien Carbonne
*
* @param The value type.
* @param The range type.
*/
public abstract class AbstractRange,
R extends AbstractRange>
implements Range, Comparable {
private final V min;
private final V max;
protected AbstractRange(V min,
V max) {
this.min = min;
this.max = max;
}
protected AbstractRange(V value) {
this.min = value;
this.max = value;
}
private static IllegalArgumentException nonCompliantRange(Range range) {
return new IllegalArgumentException("Non compliant range: " + range);
}
protected abstract R self();
public abstract Domain getDomain();
/**
* Creates a Comparator based on min values.
*
* @param The value type.
* @param The range type.
* @return A new Comparator based on min values.
*/
public static , R extends AbstractRange> Comparator minComparator() {
return Comparator.comparing(R::getMin);
}
/**
* Creates a Comparator based on max values.
*
* @param The value type.
* @param The range type.
* @return A new Comparator based on max values.
*/
public static , R extends AbstractRange> Comparator maxComparator() {
return Comparator.comparing(R::getMax);
}
/**
* Creates a Comparator based on min, then max values.
*
* @param The value type.
* @param The range type.
* @return A new Comparator based on min, then max values.
*/
public static , R extends AbstractRange> Comparator minMaxComparator() {
return Comparator.comparing(R::getMin)
.thenComparing(R::getMax);
}
@Override
public final V getMin() {
return min;
}
@Override
public final V getMax() {
return max;
}
@Override
public final boolean isEmpty() {
return min.compareTo(max) > 0;
}
@Override
public final boolean isSingleton() {
return min.equals(max);
}
@Override
public V getSingletonValue() {
if (!isSingleton()) {
throw new IllegalOperationException("This range is not a singleton " + this);
}
return min;
}
public final boolean containsValue(V v) {
return min.compareTo(v) <= 0 && max.compareTo(v) >= 0;
}
@Override
public final boolean contains(Value value) {
if (getDomain().getValueClass().isInstance(value)) {
return containsValue(getDomain().getValueClass().cast(value));
} else {
throw new IllegalArgumentException("Non compliant value: " + value);
}
}
public final boolean containsRange(R r) {
return (min.compareTo(r.getMin()) <= 0 && max.compareTo(r.getMax()) >= 0) || r.isEmpty();
}
@Override
public final boolean contains(Range range) {
if (getDomain().getRangeClass().isInstance(range)) {
return containsRange(getDomain().getRangeClass().cast(range));
} else {
throw nonCompliantRange(range);
}
}
public final boolean intersectsRange(R r) {
return RangeUtils.intersected(self(), r);
}
@Override
public final boolean intersects(Range range) {
if (getDomain().getRangeClass().isInstance(range)) {
return intersectsRange(getDomain().getRangeClass().cast(range));
} else {
throw nonCompliantRange(range);
}
}
public final R intersectionWith(R range) {
return RangeUtils.intersection(getDomain(), self(), range);
}
@Override
public final R intersectionWith(Range range) {
if (getDomain().getRangeClass().isInstance(range)) {
return intersectionWith(getDomain().getRangeClass().cast(range));
} else {
throw nonCompliantRange(range);
}
}
@Override
public final String getNonEscapedLiteral() {
if (getMin().equals(getMax())) {
return getMin().toString();
} else {
final StringBuilder builder = new StringBuilder();
builder.append(getMin());
builder.append(BOUNDS_SEPARATOR);
builder.append(getMax());
return builder.toString();
}
}
@Override
public final String getProtectedLiteral() {
return getNonEscapedLiteral();
}
@Override
public int compareTo(R o) {
Checks.isFalse(isEmpty(), "Can not compare empty range");
Checks.isFalse(o.isEmpty(), "Can not compare empty range");
if (ComparableUtils.lessThan(max, o.getMin())) {
return -1;
} else if (ComparableUtils.greaterThan(min, o.getMax())) {
return 1;
} else {
return 0;
}
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!(object instanceof AbstractRange)) {
return false;
}
final AbstractRange, ?> other = (AbstractRange, ?>) object;
return min.equals(other.min) && max.equals(other.max)
|| isEmpty() && other.isEmpty();
}
@Override
public int hashCode() {
return isEmpty() ? 0 : Objects.hash(min, max);
}
@Override
public String toString() {
return getProtectedLiteral();
}
}