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    
019    package org.apache.commons.beanutils;
020    
021    
022    import java.sql.SQLException;
023    import java.util.Iterator;
024    import 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    
037    public 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    }