/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.command.util;
/**
* An immutable representation of a sequential number range.
*
* A number range uses two number of values to denote points of
* positive and negative infinity. By default, these values are
* Integer.MAX_VALUE and Integer.MIN_VALUE respectively. If start
* or end are equal to or beyond the infinity values, then the
* range is considered to be infinite in that direction.
*
* It is worth noting that the Comparable interface is sensitive
* to the points of positive and negative infinity. Two number ranges
* can have different start and end points and be considered equal if
* both ranges are also infinite in that direction.
*
* @author chris boertien
*/
public final class NumberRange implements Comparable<NumberRange> {
private final int start;
private final int end;
private final int negativeInfinity;
private final int positiveInfinity;
/**
* Creates a number range.
*
* This number range uses posInf and negInf to denote positive and negative
* infinity respectively.
*
* @param start the start of the range
* @param end the end of the range
* @param posInf the point of positive infinity
* @param negInf the point of negative infinity
* @throws IllegalArgumentException if start > end or negInf >= posInf
*/
public NumberRange(int start, int end, int negInf, int posInf) {
if (start > end) {
throw new IllegalArgumentException("start > end");
}
if (negInf >= posInf) {
throw new IllegalArgumentException("negInf >= posInf");
}
this.start = start;
this.end = end;
this.negativeInfinity = negInf;
this.positiveInfinity = posInf;
}
/**
* Creates a number range.
*
* This number range uses Integer.MAX_VALUE and Integer.MIN_VALUE to denote
* positive and negative infinity respectively.
*
* @param start the start of the range
* @param end the end of the range
* @throws IllegalArgumentException if start > end
*/
public NumberRange(int start, int end) {
this(start, end, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
/**
* Compares this NumberRange to another NumberRange for order.
*
* NumberRanges are ordered first by their start position, and second
* by their end position.
*
* A NumberRange that is negatively infinite is considered less than one that
* is not negatively infinite. Also a NumberRange that is not positively infinite
* is considered less than one that is positively infinite.
*
* @param that the NumberRange to compare this one to
* @return -1 if this comes before that, 1 if that comes before this, 0 if they are equal.
*/
public int compareTo(NumberRange that) {
if (equals(that)) {
return 0;
}
boolean a1 = isStartInfinite();
boolean a2 = isEndInfinite();
boolean b1 = that.isStartInfinite();
boolean b2 = that.isEndInfinite();
if (a1 ^ b1) {
return a1 ? -1 : 1;
}
if ((a1 && b1) || (start == that.start)) {
if (a2 ^ b2) {
return a2 ? -1 : 1;
}
return end - that.end;
}
return start - that.start;
}
/**
* Tests this NumberRange for equivalence to that NumberRange.
*
* Two NumberRanges are considered equal if:
* <ul>
* <li>if both are negatively infinite AND both are positively infinite
* <li>if both are negatively infinite AND neither are positively infinite AND both have the same end point.
* <li>if neither are negatively infinite AND both have the same start point AND both are positvely infinite
* <li>if neither are negatively infinite AND both have the same start point AND
* neither are positively infinite AND both have the same end point.
* </ul>
*
* @param that the NumberRage to compare with
* @return true if the NumberRanges are equal
*/
public boolean equals(NumberRange that) {
boolean a1 = isStartInfinite();
boolean a2 = isEndInfinite();
boolean b1 = that.isStartInfinite();
boolean b2 = that.isEndInfinite();
return ((a1 && b1) || (!(a1 ^ b1) && (start == that.start)))
&& ((a2 && b2) || (!(a2 ^ b2) && (end == that.end)));
}
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (!(that instanceof NumberRange)) {
return false;
}
return equals((NumberRange) that);
}
@Override
public String toString() {
return start + "-" + end;
}
/**
* The starting position of this number range.
*
* Even if the start value is beyond the negative infinity point
* this will still return the value of the start position.
*
* @return the start
*/
public int start() {
return start;
}
/**
* The ending position of this number range.
*
* Even if the end value is beyond the positive infinity point
* this will still return the value of the start position.
*
* @return the end
*/
public int end() {
return end;
}
/**
* Does this NumberRange represent a range that is positively infinite.
*
* @return true if the end position is >= positive infinity.
*/
public boolean isEndInfinite() {
return end >= positiveInfinity;
}
/**
* Does this NumberRange represent a range that is negatively infinite.
*
* @return true if the start position is <= negative infinity
*/
public boolean isStartInfinite() {
return start <= negativeInfinity;
}
}