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 */
017package org.apache.commons.dbutils;
018
019import java.sql.ResultSet;
020import java.sql.SQLException;
021import java.util.Iterator;
022
023/**
024 * <p>
025 * Wraps a {@code ResultSet} in an {@code Iterator&lt;Object[]&gt;}.  This is useful
026 * when you want to present a non-database application layer with domain
027 * neutral data.
028 * </p>
029 *
030 * <p>
031 * This implementation requires the {@code ResultSet.isLast()} method
032 * to be implemented.
033 * </p>
034 */
035public class ResultSetIterator implements Iterator<Object[]> {
036
037    /**
038     * The wrapped {@code ResultSet}.
039     */
040    private final ResultSet rs;
041
042    /**
043     * The processor to use when converting a row into an Object[].
044     */
045    private final RowProcessor convert;
046
047    /**
048     * Constructor for ResultSetIterator.
049     * @param rs Wrap this {@code ResultSet} in an {@code Iterator}.
050     */
051    public ResultSetIterator(final ResultSet rs) {
052        this(rs, new BasicRowProcessor());
053    }
054
055    /**
056     * Constructor for ResultSetIterator.
057     * @param rs Wrap this {@code ResultSet} in an {@code Iterator}.
058     * @param convert The processor to use when converting a row into an
059     * {@code Object[]}.  Defaults to a
060     * {@code BasicRowProcessor}.
061     */
062    public ResultSetIterator(final ResultSet rs, final RowProcessor convert) {
063        this.rs = rs;
064        this.convert = convert;
065    }
066
067    /**
068     * Returns true if there are more rows in the ResultSet.
069     * @return boolean {@code true} if there are more rows
070     * @throws RuntimeException if an SQLException occurs.
071     */
072    @Override
073    public boolean hasNext() {
074        try {
075            return !rs.isLast();
076        } catch (final SQLException e) {
077            rethrow(e);
078            return false;
079        }
080    }
081
082    /**
083     * Returns the next row as an {@code Object[]}.
084     * @return An {@code Object[]} with the same number of elements as
085     * columns in the {@code ResultSet}.
086     * @see java.util.Iterator#next()
087     * @throws RuntimeException if an SQLException occurs.
088     */
089    @Override
090    public Object[] next() {
091        try {
092            rs.next();
093            return this.convert.toArray(rs);
094        } catch (final SQLException e) {
095            rethrow(e);
096            return null;
097        }
098    }
099
100    /**
101     * Deletes the current row from the {@code ResultSet}.
102     * @see java.util.Iterator#remove()
103     * @throws RuntimeException if an SQLException occurs.
104     */
105    @Override
106    public void remove() {
107        try {
108            this.rs.deleteRow();
109        } catch (final SQLException e) {
110            rethrow(e);
111        }
112    }
113
114    /**
115     * Rethrow the SQLException as a RuntimeException.  This implementation
116     * creates a new RuntimeException with the SQLException's error message.
117     * @param e SQLException to rethrow
118     * @since DbUtils 1.1
119     */
120    protected void rethrow(final SQLException e) {
121        throw new RuntimeException(e.getMessage());
122    }
123
124    /**
125     * Generates an {@code Iterable}, suitable for use in for-each loops.
126     *
127     * @param rs Wrap this {@code ResultSet} in an {@code Iterator}.
128     * @return an {@code Iterable}, suitable for use in for-each loops.
129     */
130    public static Iterable<Object[]> iterable(final ResultSet rs) {
131        return new Iterable<Object[]>() {
132
133            @Override
134            public Iterator<Object[]> iterator() {
135                return new ResultSetIterator(rs);
136            }
137
138        };
139    }
140
141}