KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > betwixt > expression > IteratorExpression


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.commons.betwixt.expression;
18
19 import java.lang.reflect.Array JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.Enumeration JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.NoSuchElementException JavaDoc;
26
27
28 /** <p><code>IteratorExpression</code> returns an iterator over the current context.</p>
29   *
30   * @author <a HREF="mailto:jstrachan@apache.org">James Strachan</a>
31   * @version $Revision: 1.8.4.1 $
32   */

33 public class IteratorExpression implements Expression {
34     
35     /** Use this <code>Expression</code> to perform initial evaluation*/
36     private Expression expression;
37     
38     /**
39      * Construct <code>IteratorExpression</code> using given expression for initial evaluation.
40      * @param expression this expression will be evaluated and the result converted to an
41      * iterator.
42      */

43     public IteratorExpression(Expression expression) {
44         this.expression = expression;
45     }
46     
47     /**
48      * Returns an interator over the current context
49      * @see org.apache.commons.betwixt.expression.Expression
50      */

51     public Object JavaDoc evaluate(Context context) {
52         // evaluate wrapped expression against context
53
Object JavaDoc value = expression.evaluate( context );
54         
55         // based on the class of the result,
56
// return an appropriate iterator
57
if ( value instanceof Iterator JavaDoc ) {
58             // if the value is an iterator, we're done
59
return (Iterator JavaDoc) value;
60             
61         } else if ( value instanceof Collection JavaDoc ) {
62             // if it's a collection, return an iterator for that collection
63
Collection JavaDoc collection = (Collection JavaDoc) value;
64             return collection.iterator();
65             
66         } else if ( value instanceof Map JavaDoc ) {
67             // if it's a map, return an iterator for the map entries
68
Map JavaDoc map = (Map JavaDoc) value;
69             return map.entrySet().iterator();
70             
71         } else if ( value instanceof Enumeration JavaDoc ) {
72             // if it's an enumeration, wrap it in an EnumerationIterator
73
return new EnumerationIterator( (Enumeration JavaDoc) value );
74             
75         } else if ( value != null ) {
76             // if we have an array return an ArrayIterator
77
Class JavaDoc type = value.getClass();
78             if ( type.isArray() ) {
79                 return new ArrayIterator( value );
80             }
81         }
82         
83         // we've got something we can't deal with
84
// so return an empty iterator
85
return Collections.EMPTY_LIST.iterator();
86     }
87
88     /**
89      * Do nothing
90      * @see org.apache.commons.betwixt.expression.Expression
91      */

92     public void update(Context context, String JavaDoc newValue) {
93         // do nothing
94
}
95     
96     /**
97      * Returns something useful for logging
98      * @return string useful for logging
99      */

100     public String JavaDoc toString() {
101         return "IteratorExpression [expression=" + expression + "]";
102     }
103     
104
105         /**
106          * <code>ArrayIterator</code> originated in commons-collections. Added
107          * as a private inner class to break dependency.
108          *
109          * @author James Strachan
110          * @author Mauricio S. Moura
111          * @author Michael A. Smith
112          * @author Neil O'Toole
113          * @author Stephen Colebourne
114          */

115     private static final class ArrayIterator implements Iterator JavaDoc {
116
117         /** The array to iterate over */
118         protected Object JavaDoc array;
119
120         /** The start index to loop from */
121         protected int startIndex = 0;
122
123         /** The end index to loop to */
124         protected int endIndex = 0;
125
126         /** The current iterator index */
127         protected int index = 0;
128
129         // Constructors
130
// ----------------------------------------------------------------------
131
/**
132          * Constructor for use with <code>setArray</code>.
133          * <p>
134          * Using this constructor, the iterator is equivalent to an empty
135          * iterator until {@link #setArray(Object)}is called to establish the
136          * array to iterate over.
137          */

138         public ArrayIterator() {
139             super();
140         }
141
142         /**
143          * Constructs an ArrayIterator that will iterate over the values in the
144          * specified array.
145          *
146          * @param array
147          * the array to iterate over.
148          * @throws IllegalArgumentException
149          * if <code>array</code> is not an array.
150          * @throws NullPointerException
151          * if <code>array</code> is <code>null</code>
152          */

153         public ArrayIterator(final Object JavaDoc array) {
154             super();
155             setArray(array);
156         }
157
158         /**
159          * Constructs an ArrayIterator that will iterate over the values in the
160          * specified array from a specific start index.
161          *
162          * @param array
163          * the array to iterate over.
164          * @param startIndex
165          * the index to start iterating at.
166          * @throws IllegalArgumentException
167          * if <code>array</code> is not an array.
168          * @throws NullPointerException
169          * if <code>array</code> is <code>null</code>
170          * @throws IndexOutOfBoundsException
171          * if the index is invalid
172          */

173         public ArrayIterator(final Object JavaDoc array, final int startIndex) {
174             super();
175             setArray(array);
176             checkBound(startIndex, "start");
177             this.startIndex = startIndex;
178             this.index = startIndex;
179         }
180
181         /**
182          * Construct an ArrayIterator that will iterate over a range of values
183          * in the specified array.
184          *
185          * @param array
186          * the array to iterate over.
187          * @param startIndex
188          * the index to start iterating at.
189          * @param endIndex
190          * the index to finish iterating at.
191          * @throws IllegalArgumentException
192          * if <code>array</code> is not an array.
193          * @throws NullPointerException
194          * if <code>array</code> is <code>null</code>
195          * @throws IndexOutOfBoundsException
196          * if either index is invalid
197          */

198         public ArrayIterator(final Object JavaDoc array, final int startIndex,
199                 final int endIndex) {
200             super();
201             setArray(array);
202             checkBound(startIndex, "start");
203             checkBound(endIndex, "end");
204             if (endIndex < startIndex) {
205                 throw new IllegalArgumentException JavaDoc(
206                         "End index must not be less than start index.");
207             }
208             this.startIndex = startIndex;
209             this.endIndex = endIndex;
210             this.index = startIndex;
211         }
212
213         /**
214          * Checks whether the index is valid or not.
215          *
216          * @param bound
217          * the index to check
218          * @param type
219          * the index type (for error messages)
220          * @throws IndexOutOfBoundsException
221          * if the index is invalid
222          */

223         protected void checkBound(final int bound, final String JavaDoc type) {
224             if (bound > this.endIndex) {
225                 throw new ArrayIndexOutOfBoundsException JavaDoc(
226                         "Attempt to make an ArrayIterator that " + type
227                                 + "s beyond the end of the array. ");
228             }
229             if (bound < 0) {
230                 throw new ArrayIndexOutOfBoundsException JavaDoc(
231                         "Attempt to make an ArrayIterator that " + type
232                                 + "s before the start of the array. ");
233             }
234         }
235
236         // Iterator interface
237
//-----------------------------------------------------------------------
238
/**
239          * Returns true if there are more elements to return from the array.
240          *
241          * @return true if there is a next element to return
242          */

243         public boolean hasNext() {
244             return (index < endIndex);
245         }
246
247         /**
248          * Returns the next element in the array.
249          *
250          * @return the next element in the array
251          * @throws NoSuchElementException
252          * if all the elements in the array have already been
253          * returned
254          */

255         public Object JavaDoc next() {
256             if (hasNext() == false) {
257                 throw new NoSuchElementException JavaDoc();
258             }
259             return Array.get(array, index++);
260         }
261
262         /**
263          * Throws {@link UnsupportedOperationException}.
264          *
265          * @throws UnsupportedOperationException
266          * always
267          */

268         public void remove() {
269             throw new UnsupportedOperationException JavaDoc(
270                     "remove() method is not supported");
271         }
272
273         // Properties
274
//-----------------------------------------------------------------------
275
/**
276          * Gets the array that this iterator is iterating over.
277          *
278          * @return the array this iterator iterates over, or <code>null</code>
279          * if the no-arg constructor was used and
280          * {@link #setArray(Object)}has never been called with a valid
281          * array.
282          */

283         public Object JavaDoc getArray() {
284             return array;
285         }
286
287         /**
288          * Sets the array that the ArrayIterator should iterate over.
289          * <p>
290          * If an array has previously been set (using the single-arg constructor
291          * or this method) then that array is discarded in favour of this one.
292          * Iteration is restarted at the start of the new array. Although this
293          * can be used to reset iteration, the {@link #reset()}method is a more
294          * effective choice.
295          *
296          * @param array
297          * the array that the iterator should iterate over.
298          * @throws IllegalArgumentException
299          * if <code>array</code> is not an array.
300          * @throws NullPointerException
301          * if <code>array</code> is <code>null</code>
302          */

303         public void setArray(final Object JavaDoc array) {
304             // Array.getLength throws IllegalArgumentException if the object is
305
// not
306
// an array or NullPointerException if the object is null. This call
307
// is made before saving the array and resetting the index so that
308
// the
309
// array iterator remains in a consistent state if the argument is
310
// not
311
// an array or is null.
312
this.endIndex = Array.getLength(array);
313             this.startIndex = 0;
314             this.array = array;
315             this.index = 0;
316         }
317
318         /**
319          * Resets the iterator back to the start index.
320          */

321         public void reset() {
322             this.index = this.startIndex;
323         }
324
325     }
326         
327
328     /**
329      * Adapter to make {@link Enumeration Enumeration}instances appear to be
330      * {@link Iterator Iterator}instances. Originated in commons-collections.
331      * Added as a private inner class to break dependency.
332      *
333      * @author <a HREF="mailto:jstrachan@apache.org">James Strachan </a>
334      * @author <a HREF="mailto:dlr@finemaltcoding.com">Daniel Rall </a>
335      */

336      private static final class EnumerationIterator implements Iterator JavaDoc {
337
338         /** The collection to remove elements from */
339         private Collection JavaDoc collection;
340
341         /** The enumeration being converted */
342         private Enumeration JavaDoc enumeration;
343
344         /** The last object retrieved */
345         private Object JavaDoc last;
346
347         // Constructors
348
//-----------------------------------------------------------------------
349
/**
350          * Constructs a new <code>EnumerationIterator</code> that will not
351          * function until {@link #setEnumeration(Enumeration)} is called.
352          */

353         public EnumerationIterator() {
354             this(null, null);
355         }
356
357         /**
358          * Constructs a new <code>EnumerationIterator</code> that provides
359          * an iterator view of the given enumeration.
360          *
361          * @param enumeration the enumeration to use
362          */

363         public EnumerationIterator(final Enumeration JavaDoc enumeration) {
364             this(enumeration, null);
365         }
366
367         /**
368          * Constructs a new <code>EnumerationIterator</code> that will remove
369          * elements from the specified collection.
370          *
371          * @param enumeration the enumeration to use
372          * @param collection the collection to remove elements form
373          */

374         public EnumerationIterator(final Enumeration JavaDoc enumeration,
375                 final Collection JavaDoc collection) {
376             super();
377             this.enumeration = enumeration;
378             this.collection = collection;
379             this.last = null;
380         }
381
382         // Iterator interface
383
//-----------------------------------------------------------------------
384
/**
385          * Returns true if the underlying enumeration has more elements.
386          *
387          * @return true if the underlying enumeration has more elements
388          * @throws NullPointerException if the underlying enumeration is null
389          */

390         public boolean hasNext() {
391             return enumeration.hasMoreElements();
392         }
393
394         /**
395          * Returns the next object from the enumeration.
396          *
397          * @return the next object from the enumeration
398          * @throws NullPointerException if the enumeration is null
399          */

400         public Object JavaDoc next() {
401             last = enumeration.nextElement();
402             return last;
403         }
404
405         /**
406          * Removes the last retrieved element if a collection is attached.
407          * <p>
408          * Functions if an associated <code>Collection</code> is known.
409          * If so, the first occurrence of the last returned object from this
410          * iterator will be removed from the collection.
411          *
412          * @exception IllegalStateException <code>next()</code> not called.
413          * @exception UnsupportedOperationException if no associated collection
414          */

415         public void remove() {
416             if (collection != null) {
417                 if (last != null) {
418                     collection.remove(last);
419                 } else {
420                     throw new IllegalStateException JavaDoc(
421                             "next() must have been called for remove() to function");
422                 }
423             } else {
424                 throw new UnsupportedOperationException JavaDoc(
425                         "No Collection associated with this Iterator");
426             }
427         }
428
429         // Properties
430
//-----------------------------------------------------------------------
431
/**
432          * Returns the underlying enumeration.
433          *
434          * @return the underlying enumeration
435          */

436         public Enumeration JavaDoc getEnumeration() {
437             return enumeration;
438         }
439
440         /**
441          * Sets the underlying enumeration.
442          *
443          * @param enumeration the new underlying enumeration
444          */

445         public void setEnumeration(final Enumeration JavaDoc enumeration) {
446             this.enumeration = enumeration;
447         }
448     }
449
450 }
451
Popular Tags