dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #09410
Fwd: A question on generics
Hi all
I have a small problem which I can't seem to get right. I am sure
Lars, Jo, Saptarshi and all ye java experts will know. Lars I guess
you are pretty familiar with the amplecode jdbc stuff.
I have an interface and a class for iterating over a result set from a
query on the aggregatedatavalue table:
the interface:
package org.hisp.dhis.aggregation;
public interface AggregatedDataValueStoreIterator {
// ----------------------------------------------------------------------
// AggregatedDataValueStoreIterator
// ----------------------------------------------------------------------
/**
* Gets the next AggregatedDataValue
*
* @return the aggregated value or null.
*/
AggregatedDataValue next();
/**
* Close any underlying resources
*
*/
void close();
}
and the class:
public class JdbcAggregatedDataValueStoreIterator implements
AggregatedDataValueStoreIterator {
private static final Log log =
LogFactory.getLog(AggregatedDataValueStoreIterator.class);
static RowMapper<AggregatedDataValue> rowmapper = new
AggregatedDataValueRowMapper();
private ResultSet resultSet;
public ResultSet getResultSet() {
return resultSet;
}
public void setResultSet(ResultSet resultSet) {
this.resultSet = resultSet;
}
private StatementHolder holder;
public StatementHolder getHolder()
{
return holder;
}
public void setHolder( StatementHolder holder )
{
this.holder = holder;
}
public JdbcAggregatedDataValueStoreIterator(ResultSet resultSet,
StatementHolder holder) {
this.resultSet = resultSet;
this.holder = holder;
}
@Override
public AggregatedDataValue next() {
AggregatedDataValue row = null;
try {
if (resultSet.next()) {
row = rowmapper.mapRow(resultSet);
} else {
this.close();
}
} catch (SQLException ex) {
log.warn("Error reading aggregateddatavalue row: " + ex);
}
return row;
}
@Override
public void close() {
try {
if (!resultSet.isClosed()) {
resultSet.close();
}
} catch (SQLException ex) {
log.warn("Error closing resultset: " + ex);
}
holder.close();
}
}
This works very well, but now I also want to iterate over aggregate
indicator values. Now obviously I could just copy and paste the above
with minor adjustments, but it seems to makes sense to do this more
generically. 95% of the code in the class is pretty generic. What I
would like instead to have is an interface like:
public interface StoreIterator<T> {
// ----------------------------------------------------------------------
// generic StoreIterator
// ----------------------------------------------------------------------
/**
* Gets the next object value
*
* @return the object value or null.
*/
T next();
/**
* Close any underlying resources
*
*/
void close();
}
That would be fine and dandy, but I can't implement the class
public class JdbcStoreIterator<T> implements StoreIterator<T>
by parameterizing the above JdbcAggregatedDataValueStoreIterator
class. The problem has to do with the rowmapper in the class.
I can't say:
static RowMapper<T> rowmapper = new AggregatedDataValueRowMapper();
because T is generic so I don't know the type of the rowmapper in
advance and the AggregateDataValueRowMapper (presumably like all the
other row mappers) is declared like:
public class AggregatedDataValueRowMapper
implements RowMapper<AggregatedDataValue>
In desperation I tried adding an extra type parameter to the
JdbcStoreIterator, like
public class JdbcStoreIterator<T, R> implements StoreIterator<T>
to pass in the rowmapper type, but it still defeats me - you can't
"simply" instantiate a new object based on a Type and various tricks
around Class<R> and getInstance() don't seem to work.
Anybody have any good ideas of the best way to do this? Maybe I can
pass in a concrete RowMapper<T> into the JdbcStoreIterator<T>
constructor? Just thought of that now as a possibility and haven't
tried it. I have to confess i have a much better understanding of C++
generics than the Java variant, which is probably working against me
here :-(
Failing which I will either return to copy and paste (which would have
taken all of half an hour instead of 3 hours puzzling over this) or
just do away with using the rowmapper at all and just program directly
to the jdbc resultset.
Cheers
Bob
Follow ups