001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018
019package org.apache.commons.beanutils;
020
021
022import java.sql.SQLException;
023import java.util.Iterator;
024import java.util.NoSuchElementException;
025
026
027/**
028 * <p>Implementation of <code>java.util.Iterator</code> returned by the
029 * <code>iterator()</code> method of {@link ResultSetDynaClass}.  Each
030 * object returned by this iterator will be a {@link DynaBean} that
031 * represents a single row from the result set being wrapped.</p>
032 *
033 * @author Craig R. McClanahan
034 * @version $Revision: 556221 $ $Date: 2007-07-14 05:19:21 +0100 (Sat, 14 Jul 2007) $
035 */
036
037public class ResultSetIterator implements DynaBean, Iterator {
038
039
040    // ------------------------------------------------------------ Constructor
041
042
043    /**
044     * <p>Construct an <code>Iterator</code> for the result set being wrapped
045     * by the specified {@link ResultSetDynaClass}.</p>
046     *
047     * @param dynaClass The {@link ResultSetDynaClass} wrapping the
048     *  result set we will iterate over
049     */
050    ResultSetIterator(ResultSetDynaClass dynaClass) {
051
052        this.dynaClass = dynaClass;
053
054    }
055
056
057    // ----------------------------------------------------- Instance Variables
058
059
060
061    /**
062     * <p>Flag indicating whether the result set is currently positioned at a
063     * row for which we have not yet returned an element in the iteration.</p>
064     */
065    protected boolean current = false;
066
067
068    /**
069     * <p>The {@link ResultSetDynaClass} we are associated with.</p>
070     */
071    protected ResultSetDynaClass dynaClass = null;
072
073
074    /**
075     * <p>Flag indicating whether the result set has indicated that there are
076     * no further rows.</p>
077     */
078    protected boolean eof = false;
079
080
081    // ------------------------------------------------------- DynaBean Methods
082
083
084    /**
085     * Does the specified mapped property contain a value for the specified
086     * key value?
087     *
088     * @param name Name of the property to check
089     * @param key Name of the key to check
090     * @return <code>true<code> if the mapped property contains a value for
091     * the specified key, otherwise <code>false</code>
092     *
093     * @exception IllegalArgumentException if there is no property
094     *  of the specified name
095     */
096    public boolean contains(String name, String key) {
097
098        throw new UnsupportedOperationException
099            ("FIXME - mapped properties not currently supported");
100
101    }
102
103
104    /**
105     * Return the value of a simple property with the specified name.
106     *
107     * @param name Name of the property whose value is to be retrieved
108     * @return The property's value
109     *
110     * @exception IllegalArgumentException if there is no property
111     *  of the specified name
112     */
113    public Object get(String name) {
114
115        if (dynaClass.getDynaProperty(name) == null) {
116            throw new IllegalArgumentException(name);
117        }
118        try {
119            return dynaClass.getObjectFromResultSet(name);
120        } catch (SQLException e) {
121            throw new RuntimeException
122                ("get(" + name + "): SQLException: " + e);
123        }
124
125    }
126
127
128    /**
129     * Return the value of an indexed property with the specified name.
130     *
131     * @param name Name of the property whose value is to be retrieved
132     * @param index Index of the value to be retrieved
133     * @return The indexed property's value
134     *
135     * @exception IllegalArgumentException if there is no property
136     *  of the specified name
137     * @exception IllegalArgumentException if the specified property
138     *  exists, but is not indexed
139     * @exception IndexOutOfBoundsException if the specified index
140     *  is outside the range of the underlying property
141     * @exception NullPointerException if no array or List has been
142     *  initialized for this property
143     */
144    public Object get(String name, int index) {
145
146        throw new UnsupportedOperationException
147            ("FIXME - indexed properties not currently supported");
148
149    }
150
151
152    /**
153     * Return the value of a mapped property with the specified name,
154     * or <code>null</code> if there is no value for the specified key.
155     *
156     * @param name Name of the property whose value is to be retrieved
157     * @param key Key of the value to be retrieved
158     * @return The mapped property's value
159     *
160     * @exception IllegalArgumentException if there is no property
161     *  of the specified name
162     * @exception IllegalArgumentException if the specified property
163     *  exists, but is not mapped
164     */
165    public Object get(String name, String key) {
166
167        throw new UnsupportedOperationException
168            ("FIXME - mapped properties not currently supported");
169
170    }
171
172
173    /**
174     * Return the <code>DynaClass</code> instance that describes the set of
175     * properties available for this DynaBean.
176     *
177     * @return The associated DynaClass
178     */
179    public DynaClass getDynaClass() {
180
181        return (this.dynaClass);
182
183    }
184
185
186    /**
187     * Remove any existing value for the specified key on the
188     * specified mapped property.
189     *
190     * @param name Name of the property for which a value is to
191     *  be removed
192     * @param key Key of the value to be removed
193     *
194     * @exception IllegalArgumentException if there is no property
195     *  of the specified name
196     */
197    public void remove(String name, String key) {
198
199        throw new UnsupportedOperationException
200            ("FIXME - mapped operations not currently supported");
201
202    }
203
204
205    /**
206     * Set the value of a simple property with the specified name.
207     *
208     * @param name Name of the property whose value is to be set
209     * @param value Value to which this property is to be set
210     *
211     * @exception ConversionException if the specified value cannot be
212     *  converted to the type required for this property
213     * @exception IllegalArgumentException if there is no property
214     *  of the specified name
215     * @exception NullPointerException if an attempt is made to set a
216     *  primitive property to null
217     */
218    public void set(String name, Object value) {
219
220        if (dynaClass.getDynaProperty(name) == null) {
221            throw new IllegalArgumentException(name);
222        }
223        try {
224            dynaClass.getResultSet().updateObject(name, value);
225        } catch (SQLException e) {
226            throw new RuntimeException
227                ("set(" + name + "): SQLException: " + e);
228        }
229
230    }
231
232
233    /**
234     * Set the value of an indexed property with the specified name.
235     *
236     * @param name Name of the property whose value is to be set
237     * @param index Index of the property to be set
238     * @param value Value to which this property is to be set
239     *
240     * @exception ConversionException if the specified value cannot be
241     *  converted to the type required for this property
242     * @exception IllegalArgumentException if there is no property
243     *  of the specified name
244     * @exception IllegalArgumentException if the specified property
245     *  exists, but is not indexed
246     * @exception IndexOutOfBoundsException if the specified index
247     *  is outside the range of the underlying property
248     */
249    public void set(String name, int index, Object value) {
250
251        throw new UnsupportedOperationException
252            ("FIXME - indexed properties not currently supported");
253
254    }
255
256
257    /**
258     * Set the value of a mapped property with the specified name.
259     *
260     * @param name Name of the property whose value is to be set
261     * @param key Key of the property to be set
262     * @param value Value to which this property is to be set
263     *
264     * @exception ConversionException if the specified value cannot be
265     *  converted to the type required for this property
266     * @exception IllegalArgumentException if there is no property
267     *  of the specified name
268     * @exception IllegalArgumentException if the specified property
269     *  exists, but is not mapped
270     */
271    public void set(String name, String key, Object value) {
272
273        throw new UnsupportedOperationException
274            ("FIXME - mapped properties not currently supported");
275
276    }
277
278
279    // ------------------------------------------------------- Iterator Methods
280
281
282    /**
283     * <p>Return <code>true</code> if the iteration has more elements.</p>
284     *
285     * @return <code>true</code> if the result set has another
286     * row, otherwise <code>false</code>
287     */
288    public boolean hasNext() {
289
290        try {
291            advance();
292            return (!eof);
293        } catch (SQLException e) {
294            throw new RuntimeException("hasNext():  SQLException:  " + e);
295        }
296
297    }
298
299
300    /**
301     * <p>Return the next element in the iteration.</p>
302     *
303     * @return advance to the new row and return this
304     */
305    public Object next() {
306
307        try {
308            advance();
309            if (eof) {
310                throw new NoSuchElementException();
311            }
312            current = false;
313            return (this);
314        } catch (SQLException e) {
315            throw new RuntimeException("next():  SQLException:  " + e);
316        }
317
318    }
319
320
321    /**
322     * <p>Remove the current element from the iteration.  This method is
323     * not supported.</p>
324     */
325    public void remove() {
326
327        throw new UnsupportedOperationException("remove()");
328
329    }
330
331
332    // ------------------------------------------------------ Protected Methods
333
334
335    /**
336     * <p>Advance the result set to the next row, if there is not a current
337     * row (and if we are not already at eof).</p>
338     *
339     * @exception SQLException if the result set throws an exception
340     */
341    protected void advance() throws SQLException {
342
343        if (!current && !eof) {
344            if (dynaClass.getResultSet().next()) {
345                current = true;
346                eof = false;
347            } else {
348                current = false;
349                eof = true;
350            }
351        }
352
353    }
354
355
356}