The following is a cleaned up example to reduce this to a single question. There are 3 class files (with a few class shells bunched in there). What does not work is the first argument casting on each of getTable()
and getCreateTableList()
in the SpanTable
class. I would like to know how to get that argument to have its original Span/SpanTable
subclass type and be passed into the DbTable
calls? Or really, DbTable doesn't need the extra info, but I would like SpanTable, or any caller, to retain its types.
DbRow:
public class DbRow {
static class Span extends DbRow {}
}
DbTable:
import java.util.ArrayList;
abstract public class DbTable<R extends DbRow> {
static class PairList<L, R> {
public void addEntry(L s, R t) { }
public R getRightForLeft(L left) { return null; }
}
static class DbPlatform { }
static class DbSelectStatement { }
public static class Span extends DbRow { }
static class TableList<R extends DbRow, T extends DbTable<R>> extends ArrayList<T> {}
static class PlatformTableList<R extends DbRow, T extends DbTable<R>>
extends PairList<DbPlatform, TableList<R, T>> {}
static DbSelectStatement getDefaultQuery(String tableName) { return null; }
public DbTable(DbPlatform platform, String tableName) { }
public DbSelectStatement getStatement() { return null; }
/** Return the matching DbTable with matching DbSelectStatement or null */
static protected DbTable<DbRow> getTable(
PlatformTableList<DbRow, DbTable<DbRow>> platformList,
DbPlatform platform, DbSelectStatement stmt) {
// Get the table from the list, or create new
TableList<DbRow, DbTable<DbRow>> list =
getCreateTableList(
(PlatformTableList<DbRow, DbTable<DbRow>>) platformList, platform);
// Search the list for a match
for(DbTable<DbRow> table : list)
if(table.getStatement().equals(stmt))
return table;
return null;
}
/** Get or create and return a TableList for the Platform. */
static protected TableList<DbRow, DbTable<DbRow>> getCreateTableList(
PlatformTableList<DbRow, DbTable<DbRow>> platformList, DbPlatform platform) {
TableList<DbRow, DbTable<DbRow>> list = (TableList<DbRow, DbTable<DbRow>>)
platformList.getRightForLeft(platform);
if(list == null) {
list = new TableList<DbRow, DbTable<DbRow>>();
platformList.addEntry(platform, list);
}
return list;
}
}
SpanTable:
class SpanTable<R extends DbTable.Span> extends DbTable<R> {
static private PlatformTableList<Span, SpanTable<Span>> platformList =
new PlatformTableList<Span, SpanTable<Span>>();
static public SpanTable<Span> getCreateSpanTable(DbPlatform platform, String tableName) {
SpanTable<Span> table = (SpanTable<Span>) getTable(platformList, platform,
getDefaultQuery(tableName));
if(table == null) {
table = new SpanTable<Span>(platform, tableName);
getCreateTableList(platformList, platform).add(table);
}
return table;
}
private SpanTable(DbPlatform platform, String tableName) {
super(platform, tableName);
}
}