package org.sql2o;
import org.sql2o.quirks.Quirks;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Iterator for a {@link java.sql.ResultSet}. Tricky part here is getting {@link #hasNext()}
* to work properly, meaning it can be called multiple times without calling {@link #next()}.
*
* @author aldenquimby@gmail.com
*/
public abstract class ResultSetIteratorBase<T> implements Iterator<T> {
// fields needed to read result set
protected ResultSet rs;
protected boolean isCaseSensitive;
protected Quirks quirks;
protected ResultSetMetaData meta;
public ResultSetIteratorBase(ResultSet rs, boolean isCaseSensitive, Quirks quirks) {
this.rs = rs;
this.isCaseSensitive = isCaseSensitive;
this.quirks = quirks;
try {
meta = rs.getMetaData();
}
catch(SQLException ex) {
throw new Sql2oException("Database error: " + ex.getMessage(), ex);
}
}
// fields needed to properly implement
private ResultSetValue<T> next; // keep track of next item in case hasNext() is called multiple times
private boolean resultSetFinished; // used to note when result set exhausted
public boolean hasNext() {
// check if we already fetched next item
if (next != null) {
return true;
}
// check if result set already finished
if (resultSetFinished) {
return false;
}
// now fetch next item
next = safeReadNext();
// check if we got something
if (next != null) {
return true;
}
// no more items
resultSetFinished = true;
return false;
}
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
T result = next.value;
next = null;
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
private ResultSetValue<T> safeReadNext()
{
try {
if (!rs.next())
return null;
@SuppressWarnings("unchecked")
ResultSetValue<T> resultSetValue = new <T>ResultSetValue(readNext());
return resultSetValue;
}
catch (SQLException ex) {
throw new Sql2oException("Database error: " + ex.getMessage(), ex);
}
}
protected abstract T readNext() throws SQLException;
protected String getColumnName(int colIdx) throws SQLException {
return quirks.getColumnName(meta, colIdx);
}
private final class ResultSetValue<T> {
public final T value;
public ResultSetValue(T value){
this.value = value;
}
}
}