org.openstreetmap.osmosis.pgsimple.common.BaseTableReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of osmosis-pgsimple Show documentation
Show all versions of osmosis-pgsimple Show documentation
Osmosis is a Java application and library for processing OSM data.
// This software is released into the Public Domain. See copying.txt for details.
package org.openstreetmap.osmosis.pgsimple.common;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openstreetmap.osmosis.core.OsmosisRuntimeException;
import org.openstreetmap.osmosis.core.lifecycle.ReleasableIterator;
/**
* Provides the base implementation of all database table readers.
*
* @author Brett Henderson
*
* @param
* The type of entity to retrieved.
*/
public abstract class BaseTableReader implements ReleasableIterator {
private static final Logger LOG = Logger.getLogger(BaseTableReader.class.getName());
private DatabaseContext dbCtx;
private ResultSet resultSet;
private T nextValue;
/**
* Creates a new instance.
*
* @param dbCtx
* The active connection to use for reading from the database.
*/
public BaseTableReader(DatabaseContext dbCtx) {
this.dbCtx = dbCtx;
}
/**
* Builds the result set that the reader will iterate over.
*
* @param queryDbCtx
* The database context to query against.
* @return A result set positioned before the first record.
*/
protected abstract ResultSet createResultSet(DatabaseContext queryDbCtx);
/**
* Builds an entity object from the current recordset row.
*
* @param activeResultSet
* The record set to retrieve the data from.
* @return The result of the read.
*/
protected abstract ReadResult createNextValue(ResultSet activeResultSet);
/**
* If the implementation requires multiple rows to build an entity object,
* this method allows the implementation to return an entity based on the
* fact that no more rows are available. This default implementation returns
* a blank result.
*
* @return The last result record.
*/
protected ReadResult createLastValue() {
return new ReadResult(true, null);
}
/**
* Reads the next entity from the database and stores it in the internal
* nextValue variable. This will be set to null if no more data is
* available.
*/
private void readNextValue() {
if (resultSet == null) {
resultSet = createResultSet(dbCtx);
}
try {
ReadResult readResult;
// Loop until a valid result is determined. Typically a loop is
// required when a record on the result set is skipped over by the
// reader implementation.
do {
if (resultSet.next()) {
readResult = createNextValue(resultSet);
} else {
readResult = createLastValue();
}
} while (!readResult.isUsableResult());
nextValue = readResult.getEntity();
} catch (SQLException e) {
throw new OsmosisRuntimeException("Unable to move to next record.", e);
}
}
/**
* {@inheritDoc}
*/
public boolean hasNext() {
if (resultSet == null) {
readNextValue();
}
return (nextValue != null);
}
/**
* {@inheritDoc}
*/
public T next() {
T result;
if (!hasNext()) {
throw new NoSuchElementException();
}
result = nextValue;
readNextValue();
return result;
}
/**
* {@inheritDoc}
*/
public void close() {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// We cannot throw an exception within a release method.
LOG.log(Level.WARNING, "Unable to close result set.", e);
}
resultSet = null;
}
}
/**
* {@inheritDoc}
*/
public void remove() {
throw new UnsupportedOperationException();
}
/**
* Represents the result of an entity read from the result set at the current position.
*
* @param
* The type of entity to retrieved.
*/
protected static class ReadResult {
private boolean usableResult;
private T entity;
/**
* Creates a new instance.
*
* @param usableResult
* Indicates if this result should be used.
* @param entity
* The entity being read.
*/
public ReadResult(boolean usableResult, T entity) {
this.usableResult = usableResult;
this.entity = entity;
}
/**
* Returns the usable result flag.
*
* @return The usable result flag.
*/
public boolean isUsableResult() {
return usableResult;
}
/**
* Returns the entity.
*
* @return The entity.
*/
public T getEntity() {
return entity;
}
}
}