View Javadoc

1   /*
2    $Id: IntRange.java,v 1.10 2004/01/25 16:21:37 jstrachan Exp $
3   
4    Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5   
6    Redistribution and use of this software and associated documentation
7    ("Software"), with or without modification, are permitted provided
8    that the following conditions are met:
9   
10   1. Redistributions of source code must retain copyright
11      statements and notices.  Redistributions must also contain a
12      copy of this document.
13  
14   2. Redistributions in binary form must reproduce the
15      above copyright notice, this list of conditions and the
16      following disclaimer in the documentation and/or other
17      materials provided with the distribution.
18  
19   3. The name "groovy" must not be used to endorse or promote
20      products derived from this Software without prior written
21      permission of The Codehaus.  For written permission,
22      please contact info@codehaus.org.
23  
24   4. Products derived from this Software may not be called "groovy"
25      nor may "groovy" appear in their names without prior written
26      permission of The Codehaus. "groovy" is a registered
27      trademark of The Codehaus.
28  
29   5. Due credit should be given to The Codehaus -
30      http://groovy.codehaus.org/
31  
32   THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
33   ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
34   NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
36   THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43   OF THE POSSIBILITY OF SUCH DAMAGE.
44  
45   */
46  package groovy.lang;
47  
48  import java.util.AbstractList;
49  import java.util.Iterator;
50  import java.util.List;
51  
52  import org.codehaus.groovy.runtime.InvokerHelper;
53  import org.codehaus.groovy.runtime.IteratorClosureAdapter;
54  
55  /***
56   * Represents a list of Integer objects from a specified int up to and including
57   * a given and to.
58   * 
59   * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
60   * @version $Revision: 1.10 $
61   */
62  public class IntRange extends AbstractList implements Range {
63  
64      private int from;
65      private int to;
66      private boolean reverse;
67  
68      public IntRange(int from, int to) {
69          if (from > to) {
70              this.from = to;
71              this.to = from;
72              this.reverse = true;
73          }
74          else {
75              this.from = from;
76              this.to = to;
77          }
78      }
79  
80      protected IntRange(int from, int to, boolean reverse) {
81          this.from = from;
82          this.to = to;
83          this.reverse = reverse;
84      }
85  
86      public boolean equals(Object that) {
87          if (that instanceof IntRange) {
88              return equals((IntRange) that);
89          }
90          else if (that instanceof List) {
91              return equals((List) that);
92          }
93          return false;
94      }
95  
96      public boolean equals(List that) {
97          int size = size();
98          if (that.size() == size) {
99              for (int i = 0; i < size; i++) {
100                 if (!InvokerHelper.compareEqual(get(i), that.get(i))) {
101                     return false;
102                 }
103             }
104             return true;
105         }
106         return false;
107     }
108 
109     public boolean equals(IntRange that) {
110         return this.reverse == that.reverse && this.from == that.from && this.to == that.to;
111     }
112 
113     public Comparable getFrom() {
114         return new Integer(from);
115     }
116 
117     public Comparable getTo() {
118         return new Integer(to);
119     }
120 
121     public int getFromInt() {
122         return from;
123     }
124 
125     public int getToInt() {
126         return to;
127     }
128 
129     public boolean isReverse() {
130         return reverse;
131     }
132 
133     public Object get(int index) {
134         if (index < 0) {
135             throw new IndexOutOfBoundsException("Index: " + index + " should not be negative");
136         }
137         if (index >= size()) {
138             throw new IndexOutOfBoundsException("Index: " + index + " too big for range: " + this);
139         }
140         int value = (reverse) ? to - index : index + from;
141         return new Integer(value);
142     }
143 
144     public int size() {
145         return to - from + 1;
146     }
147 
148     public int hashCode() {
149         return from ^ to + (reverse ? 1 : 0);
150     }
151 
152     public Iterator iterator() {
153         return new Iterator() {
154             int index = 0;
155             int size = size();
156             int value = (reverse) ? to : from;
157 
158             public boolean hasNext() {
159                 return index < size;
160             }
161 
162             public Object next() {
163                 if (index++ > 0) {
164                     if (index > size) {
165                         return null;
166                     }
167                     else {
168                         if (reverse) {
169                             --value;
170                         }
171                         else {
172                             ++value;
173                         }
174                     }
175                 }
176                 return new Integer(value);
177             }
178 
179             public void remove() {
180                 IntRange.this.remove(index);
181             }
182         };
183     }
184 
185     public List subList(int fromIndex, int toIndex) {
186         if (fromIndex < 0) {
187             throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
188         }
189         if (toIndex > size()) {
190             throw new IndexOutOfBoundsException("toIndex = " + toIndex);
191         }
192         if (fromIndex > toIndex) {
193             throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
194         }
195         return new IntRange(fromIndex + this.from, toIndex + this.from - 1, reverse);
196     }
197 
198     public String toString() {
199         return (reverse) ? "" + to + ".." + from : "" + from + ".." + to;
200     }
201     
202     public String inspect() {
203         return toString();
204     }
205     
206     public boolean contains(Object value) {
207         if (value instanceof Integer) {
208             Integer integer = (Integer) value;
209             int i = integer.intValue();
210             return i >= from && i <= to;
211         }
212         return false;
213     }
214 
215     public void step(int step, Closure closure) {
216         if (reverse) {
217             step = -step;
218         }
219         if (step >= 0) {
220             int value = from;
221             while (value <= to) {
222                 closure.call(new Integer(value));
223                 value = value + step;
224             }
225         }
226         else {
227             int value = to;
228             while (value >= from) {
229                 closure.call(new Integer(value));
230                 value = value + step;
231             }
232         }
233     }
234 
235     public List step(int step) {
236         IteratorClosureAdapter adapter = new IteratorClosureAdapter(this);
237         step(step, adapter);
238         return adapter.asList();
239     }
240 }