1 46 package groovy.lang; 47 48 import org.codehaus.groovy.runtime.InvokerHelper; 49 import org.codehaus.groovy.runtime.IteratorClosureAdapter; 50 51 import java.util.AbstractList ; 52 import java.util.Iterator ; 53 import java.util.List ; 54 55 62 public class ObjectRange extends AbstractList implements Range { 63 64 private Comparable from; 65 private Comparable to; 66 private int size = -1; 67 private final boolean reverse; 68 69 public ObjectRange(Comparable from, Comparable to) { 70 this.reverse = InvokerHelper.compareGreaterThan(from, to); 71 if (this.reverse) { 72 constructorHelper(to, from); 73 } else { 74 constructorHelper(from, to); 75 } 76 } 77 78 public ObjectRange(Comparable from, Comparable to, boolean reverse) { 79 constructorHelper(from, to); 80 81 this.reverse = reverse; 82 } 83 84 private void constructorHelper(Comparable from, Comparable to) { 85 if (from == null) { 86 throw new IllegalArgumentException ("Must specify a non-null value for the 'from' index in a Range"); 87 } 88 if (to == null) { 89 throw new IllegalArgumentException ("Must specify a non-null value for the 'to' index in a Range"); 90 } 91 if (from.getClass() == to.getClass()) { 92 this.from = from; 93 this.to = to; 94 } else { 95 this.from = normaliseType(from); 96 this.to = normaliseType(to); 97 } 98 } 99 100 public int hashCode() { 101 102 return from.hashCode() ^ to.hashCode() + (reverse ? 1 : 0); 103 } 104 105 public boolean equals(Object that) { 106 if (that instanceof ObjectRange) { 107 return equals((ObjectRange) that); 108 } else if (that instanceof List ) { 109 return equals((List ) that); 110 } 111 return false; 112 } 113 114 public boolean equals(ObjectRange that) { 115 return this.reverse == that.reverse 116 && InvokerHelper.compareEqual(this.from, that.from) 117 && InvokerHelper.compareEqual(this.to, that.to); 118 } 119 120 public boolean equals(List that) { 121 int size = size(); 122 if (that.size() == size) { 123 for (int i = 0; i < size; i++) { 124 if (!InvokerHelper.compareEqual(get(i), that.get(i))) { 125 return false; 126 } 127 } 128 return true; 129 } 130 return false; 131 } 132 133 public Comparable getFrom() { 134 return from; 135 } 136 137 public Comparable getTo() { 138 return to; 139 } 140 141 public boolean isReverse() { 142 return reverse; 143 } 144 145 public Object get(int index) { 146 if (index < 0) { 147 throw new IndexOutOfBoundsException ("Index: " + index + " should not be negative"); 148 } 149 if (index >= size()) { 150 throw new IndexOutOfBoundsException ("Index: " + index + " is too big for range: " + this); 151 } 152 Object value = null; 153 if (reverse) { 154 value = to; 155 156 for (int i = 0; i < index; i++) { 157 value = decrement(value); 158 } 159 } else { 160 value = from; 161 for (int i = 0; i < index; i++) { 162 value = increment(value); 163 } 164 } 165 return value; 166 } 167 168 public Iterator iterator() { 169 return new Iterator () { 170 int index = 0; 171 Object value = (reverse) ? to : from; 172 173 public boolean hasNext() { 174 return index < size(); 175 } 176 177 public Object next() { 178 if (index++ > 0) { 179 if (index > size()) { 180 value = null; 181 } else { 182 if (reverse) { 183 value = decrement(value); 184 } else { 185 value = increment(value); 186 } 187 } 188 } 189 return value; 190 } 191 192 public void remove() { 193 ObjectRange.this.remove(index); 194 } 195 }; 196 } 197 198 public int size() { 199 if (size == -1) { 200 size = 0; 202 Object value = from; 203 while (to.compareTo(value) >= 0) { 204 value = increment(value); 205 size++; 206 } 207 } 208 return size; 209 } 210 211 public List subList(int fromIndex, int toIndex) { 212 if (fromIndex < 0) { 213 throw new IndexOutOfBoundsException ("fromIndex = " + fromIndex); 214 } 215 int size = size(); 216 if (toIndex > size) { 217 throw new IndexOutOfBoundsException ("toIndex = " + toIndex); 218 } 219 if (fromIndex > toIndex) { 220 throw new IllegalArgumentException ("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); 221 } 222 if (--toIndex >= size) { 223 return new ObjectRange((Comparable ) get(fromIndex), getTo(), reverse); 224 } else { 225 return new ObjectRange((Comparable ) get(fromIndex), (Comparable ) get(toIndex), reverse); 226 } 227 } 228 229 public String toString() { 230 return (reverse) ? "" + to + ".." + from : "" + from + ".." + to; 231 } 232 233 public String inspect() { 234 String toText = InvokerHelper.inspect(to); 235 String fromText = InvokerHelper.inspect(from); 236 return (reverse) ? "" + toText + ".." + fromText : "" + fromText + ".." + toText; 237 } 238 239 public boolean contains(Comparable value) { 240 int result = from.compareTo(value); 241 if (result == 0) { 242 return true; 243 } 244 return result < 0 && to.compareTo(value) >= 0; 245 } 246 247 public void step(int step, Closure closure) { 248 if (reverse) { 249 step = -step; 250 } 251 if (step >= 0) { 252 Comparable value = from; 253 while (value.compareTo(to) <= 0) { 254 closure.call(value); 255 for (int i = 0; i < step; i++) { 256 value = (Comparable ) increment(value); 257 } 258 } 259 } else { 260 step = -step; 261 Comparable value = to; 262 while (value.compareTo(from) >= 0) { 263 closure.call(value); 264 for (int i = 0; i < step; i++) { 265 value = (Comparable ) decrement(value); 266 } 267 } 268 } 269 } 270 271 public List step(int step) { 272 IteratorClosureAdapter adapter = new IteratorClosureAdapter(this); 273 step(step, adapter); 274 return adapter.asList(); 275 } 276 277 protected Object increment(Object value) { 278 return InvokerHelper.invokeMethod(value, "next", null); 279 } 280 281 protected Object decrement(Object value) { 282 return InvokerHelper.invokeMethod(value, "previous", null); 283 } 284 285 private static Comparable normaliseType(final Comparable operand) { 286 if (operand instanceof Character ) { 287 return new Integer (((Character ) operand).charValue()); 288 } else if (operand instanceof String ) { 289 final String string = (String ) operand; 290 291 if (string.length() == 1) 292 return new Integer (string.charAt(0)); 293 else 294 return string; 295 } else { 296 return operand; 297 } 298 } 299 } 300 | Popular Tags |