Index: /Users/edwin/workspace/groovy/src/main/groovy/lang/IntRange.java =================================================================== --- /Users/edwin/workspace/groovy/src/main/groovy/lang/IntRange.java (revision 4080) +++ /Users/edwin/workspace/groovy/src/main/groovy/lang/IntRange.java (working copy) @@ -46,25 +46,110 @@ package groovy.lang; import java.util.AbstractList; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import javax.naming.OperationNotSupportedException; + +import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.groovy.runtime.InvokerHelper; import org.codehaus.groovy.runtime.IteratorClosureAdapter; /** - * Represents a list of Integer objects from a specified int up to and including - * a given and to. + * Represents a list of Integer objects from a specified int up (or down) to and including + * a given to.
*
+ * This class is a copy of {@link ObjectRange} optimized for int. If you make any
+ * changes to this class, you might consider making parallel changes to {@link ObjectRange}.
+ *
* @author James Strachan
* @version $Revision$
*/
public class IntRange extends AbstractList implements Range {
+ /**
+ * Iterates through each number in an IntRange.
+ */
+ private class IntRangeIterator implements Iterator {
+ /**
+ * Counts from 0 up to size - 1.
+ */
+ int index = 0;
+
+ /**
+ * The number of values in the range.
+ */
+ int size = size();
+
+ /**
+ * The next value to return.
+ */
+ int value = (reverse) ? to : from;
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasNext() {
+ return index < size;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object next() {
+ if (index++ > 0) {
+ if (index > size) {
+ return null;
+ }
+ else {
+ if (reverse) {
+ --value;
+ }
+ else {
+ ++value;
+ }
+ }
+ }
+ return new Integer(value);
+ }
+
+ /**
+ * Not supported.
+ *
+ * @throws OperationNotSupportedException always
+ */
+ public void remove() {
+ IntRange.this.remove(index);
+ }
+ }
+
+ /**
+ * The first number in the range. from is always less than or equal to to.
+ */
private int from;
+
+ /**
+ * The last number in the range. to is always greater than or eqaul to from.
+ */
private int to;
+
+ /**
+ * If false, counts up from from to to. Otherwise, counts down
+ * from to to from.
+ */
private boolean reverse;
+ /**
+ * Creates a new IntRange. If from is greater
+ * than to, a reverse range is created with
+ * from and to swapped.
+ *
+ * @param from
+ * the first number in the range.
+ * @param to
+ * the last number in the range.
+ */
public IntRange(int from, int to) {
if (from > to) {
this.from = to;
@@ -77,25 +162,77 @@
}
}
- protected IntRange(int from, int to, boolean reverse) {
+ /**
+ * Creates a new IntRange.
+ *
+ * @param from
+ * the first value in the range.
+ * @param to
+ * the last value in the range.
+ * @param reverse
+ * true if the range should count from
+ * to to from.
+ *
+ * @throws IllegalArgumentException
+ * if from is greater than to.
+ */
+ protected IntRange(int from, int to, boolean reverse) {
+ if (from > to) {
+ throw new IllegalArgumentException("'from' must be less than or equal to 'to'");
+ }
+
this.from = from;
this.to = to;
this.reverse = reverse;
}
+ /**
+ * Determines if this object is equal to another object. Delegates to
+ * {@link AbstractList#equals(Object)} if that is anthing
+ * other than an {@link IntRange}.
+ *
+ *
+ * It is not necessary to override hashCode, as
+ * {@link AbstractList#hashCode()} provides a suitable hash code.
+ *
+ * Note that equals is generally handled by {@link DefaultGroovyMethods#equals(List, List)} instead of this
+ * method.
+ *
+ * @param that
+ * the object to compare
+ *
+ * @return true if the objects are equal
+ */
public boolean equals(Object that) {
if (that instanceof IntRange) {
return equals((IntRange) that);
}
- else if (that instanceof List) {
+ if (that instanceof List) {
return equals((List) that);
}
return false;
}
+ /**
+ * Compares an IntRange to another IntRange.
+ *
+ * @return true if the ranges are equal
+ */
+ public boolean equals(IntRange that) {
+ return that != null && this.reverse == that.reverse && this.from == that.from && this.to == that.to;
+ }
+
+ /**
+ * Compares this range to a {@link List}.
+ *
+ * @param that
+ * the {@link List} to which to compare.
+ *
+ * @return true if the objects are equal.
+ */
public boolean equals(List that) {
int size = size();
- if (that.size() == size) {
+ if (that != null && that.size() == size) {
for (int i = 0; i < size; i++) {
if (!InvokerHelper.compareEqual(get(i), that.get(i))) {
return false;
@@ -106,30 +243,54 @@
return false;
}
- public boolean equals(IntRange that) {
- return this.reverse == that.reverse && this.from == that.from && this.to == that.to;
- }
-
+ /**
+ * Gets the 'from' value.
+ *
+ * @return the 'from' value.
+ */
public Comparable getFrom() {
return new Integer(from);
}
+ /**
+ * Gets the 'to' value.
+ *
+ * @return the 'to' value.
+ */
public Comparable getTo() {
return new Integer(to);
}
+ /**
+ * Gets the 'from' value as an integer.
+ *
+ * @return the 'from' value as an integer.
+ */
public int getFromInt() {
return from;
}
+ /**
+ * Gets the 'to' value as an integer.
+ *
+ * @return the 'to' value as an integer.
+ */
public int getToInt() {
return to;
}
+ /**
+ * Indicates whether this range counts down or up.
+ *
+ * @return true if this range counts down and false otherwise.
+ */
public boolean isReverse() {
return reverse;
}
+ /**
+ * {@inheritDoc}
+ */
public Object get(int index) {
if (index < 0) {
throw new IndexOutOfBoundsException("Index: " + index + " should not be negative");
@@ -141,47 +302,30 @@
return new Integer(value);
}
+ /**
+ * {@inheritDoc}
+ */
public int size() {
return to - from + 1;
}
- public int hashCode() {
- return from ^ to + (reverse ? 1 : 0);
- }
+ /**
+ * {@inheritDoc}
+ */
+// public int hashCode() {
+// return from ^ to + (reverse ? 1 : 0);
+// }
+ /**
+ * {@inheritDoc}
+ */
public Iterator iterator() {
- return new Iterator() {
- int index = 0;
- int size = size();
- int value = (reverse) ? to : from;
-
- public boolean hasNext() {
- return index < size;
- }
-
- public Object next() {
- if (index++ > 0) {
- if (index > size) {
- return null;
- }
- else {
- if (reverse) {
- --value;
- }
- else {
- ++value;
- }
- }
- }
- return new Integer(value);
- }
-
- public void remove() {
- IntRange.this.remove(index);
- }
- };
+ return new IntRangeIterator();
}
+ /**
+ * {@inheritDoc}
+ */
public List subList(int fromIndex, int toIndex) {
if (fromIndex < 0) {
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
@@ -192,29 +336,53 @@
if (fromIndex > toIndex) {
throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
}
+
+ if (fromIndex == toIndex) {
+ return new ArrayList();
+ }
+
return new IntRange(fromIndex + this.from, toIndex + this.from - 1, reverse);
}
+ /**
+ * {@inheritDoc}
+ */
public String toString() {
return (reverse) ? "" + to + ".." + from : "" + from + ".." + to;
}
+ /**
+ * {@inheritDoc}
+ */
public String inspect() {
return toString();
}
+ /**
+ * {@inheritDoc}
+ */
public boolean contains(Object value) {
if (value instanceof Integer) {
Integer integer = (Integer) value;
int i = integer.intValue();
return i >= from && i <= to;
- } else if (value instanceof IntRange) {
+ }
+ else if (value instanceof IntRange) {
IntRange range = (IntRange) value;
- return from<=range.from && range.to<=to;
+ return from <= range.from && range.to <= to;
}
return false;
}
+ /**
+ * Steps through the range, calling a closure for each number.
+ *
+ * @param step
+ * the amount by which to step. If negative, steps through the
+ * range backwards.
+ * @param closure
+ * the closure to call
+ */
public void step(int step, Closure closure) {
if (reverse) {
step = -step;
@@ -235,6 +403,16 @@
}
}
+ /**
+ * Forms a list by stepping through the range by the indicated interval.
+ *
+ * @param step
+ * the amount by which to step. If negative, steps through the
+ * range backwards.
+ *
+ * @return the list formed by stepping through the range by the indicated
+ * interval.
+ */
public List step(int step) {
IteratorClosureAdapter adapter = new IteratorClosureAdapter(this);
step(step, adapter);