KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > groovy > lang > ObjectRange


1 /*
2  $Id: ObjectRange.java,v 1.12 2004/12/27 10:31:24 spullara 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 org.codehaus.groovy.runtime.InvokerHelper;
49 import org.codehaus.groovy.runtime.IteratorClosureAdapter;
50
51 import java.util.AbstractList JavaDoc;
52 import java.util.Iterator JavaDoc;
53 import java.util.List JavaDoc;
54
55 /**
56  * Represents an inclusive list of objects from a value to a value using
57  * comparators
58  *
59  * @author <a HREF="mailto:james@coredevelopers.net">James Strachan</a>
60  * @version $Revision: 1.12 $
61  */

62 public class ObjectRange extends AbstractList JavaDoc implements Range {
63
64     private Comparable JavaDoc from;
65     private Comparable JavaDoc to;
66     private int size = -1;
67     private final boolean reverse;
68
69     public ObjectRange(Comparable JavaDoc from, Comparable JavaDoc 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 JavaDoc from, Comparable JavaDoc to, boolean reverse) {
79         constructorHelper(from, to);
80
81         this.reverse = reverse;
82     }
83
84     private void constructorHelper(Comparable JavaDoc from, Comparable JavaDoc to) {
85         if (from == null) {
86             throw new IllegalArgumentException JavaDoc("Must specify a non-null value for the 'from' index in a Range");
87         }
88         if (to == null) {
89             throw new IllegalArgumentException JavaDoc("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         /** @todo should code this the Josh Bloch way */
102         return from.hashCode() ^ to.hashCode() + (reverse ? 1 : 0);
103     }
104
105     public boolean equals(Object JavaDoc that) {
106         if (that instanceof ObjectRange) {
107             return equals((ObjectRange) that);
108         } else if (that instanceof List JavaDoc) {
109             return equals((List JavaDoc) 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 JavaDoc 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 JavaDoc getFrom() {
134         return from;
135     }
136
137     public Comparable JavaDoc getTo() {
138         return to;
139     }
140
141     public boolean isReverse() {
142         return reverse;
143     }
144
145     public Object JavaDoc get(int index) {
146         if (index < 0) {
147             throw new IndexOutOfBoundsException JavaDoc("Index: " + index + " should not be negative");
148         }
149         if (index >= size()) {
150             throw new IndexOutOfBoundsException JavaDoc("Index: " + index + " is too big for range: " + this);
151         }
152         Object JavaDoc 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 JavaDoc iterator() {
169         return new Iterator JavaDoc() {
170             int index = 0;
171             Object JavaDoc value = (reverse) ? to : from;
172
173             public boolean hasNext() {
174                 return index < size();
175             }
176
177             public Object JavaDoc 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             // lets lazily calculate the size
201
size = 0;
202             Object JavaDoc value = from;
203             while (to.compareTo(value) >= 0) {
204                 value = increment(value);
205                 size++;
206             }
207         }
208         return size;
209     }
210
211     public List JavaDoc subList(int fromIndex, int toIndex) {
212         if (fromIndex < 0) {
213             throw new IndexOutOfBoundsException JavaDoc("fromIndex = " + fromIndex);
214         }
215         int size = size();
216         if (toIndex > size) {
217             throw new IndexOutOfBoundsException JavaDoc("toIndex = " + toIndex);
218         }
219         if (fromIndex > toIndex) {
220             throw new IllegalArgumentException JavaDoc("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
221         }
222         if (--toIndex >= size) {
223             return new ObjectRange((Comparable JavaDoc) get(fromIndex), getTo(), reverse);
224         } else {
225             return new ObjectRange((Comparable JavaDoc) get(fromIndex), (Comparable JavaDoc) get(toIndex), reverse);
226         }
227     }
228
229     public String JavaDoc toString() {
230         return (reverse) ? "" + to + ".." + from : "" + from + ".." + to;
231     }
232
233     public String JavaDoc inspect() {
234         String JavaDoc toText = InvokerHelper.inspect(to);
235         String JavaDoc fromText = InvokerHelper.inspect(from);
236         return (reverse) ? "" + toText + ".." + fromText : "" + fromText + ".." + toText;
237     }
238
239     public boolean contains(Comparable JavaDoc 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 JavaDoc value = from;
253             while (value.compareTo(to) <= 0) {
254                 closure.call(value);
255                 for (int i = 0; i < step; i++) {
256                     value = (Comparable JavaDoc) increment(value);
257                 }
258             }
259         } else {
260             step = -step;
261             Comparable JavaDoc value = to;
262             while (value.compareTo(from) >= 0) {
263                 closure.call(value);
264                 for (int i = 0; i < step; i++) {
265                     value = (Comparable JavaDoc) decrement(value);
266                 }
267             }
268         }
269     }
270
271     public List JavaDoc step(int step) {
272         IteratorClosureAdapter adapter = new IteratorClosureAdapter(this);
273         step(step, adapter);
274         return adapter.asList();
275     }
276
277     protected Object JavaDoc increment(Object JavaDoc value) {
278         return InvokerHelper.invokeMethod(value, "next", null);
279     }
280
281     protected Object JavaDoc decrement(Object JavaDoc value) {
282         return InvokerHelper.invokeMethod(value, "previous", null);
283     }
284
285     private static Comparable JavaDoc normaliseType(final Comparable JavaDoc operand) {
286         if (operand instanceof Character JavaDoc) {
287             return new Integer JavaDoc(((Character JavaDoc) operand).charValue());
288         } else if (operand instanceof String JavaDoc) {
289             final String JavaDoc string = (String JavaDoc) operand;
290
291             if (string.length() == 1)
292                 return new Integer JavaDoc(string.charAt(0));
293             else
294                 return string;
295         } else {
296             return operand;
297         }
298     }
299 }
300
Popular Tags