uk.ac.starlink.table.CalcStarTable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of stil Show documentation
Show all versions of stil Show documentation
Starlink Tables Infrastructure Library
package uk.ac.starlink.table;
import java.io.IOException;
import java.util.List;
import java.util.function.LongSupplier;
/**
* StarTable implementation whose column values are derived from
* some single calculation on the column values of another table.
* The idea is that the cell values in a given row of an instance
* of this table are cheaply-obtained members of an object which
* is obtained by a potentially expensive calculation on the cell
* values of the corresponding row in the other table.
*
* @param type of object that is calculated from each row of the
* input table, and supplies values to the corresponding
* row of this table
*/
public abstract class CalcStarTable extends AbstractStarTable {
private final StarTable base_;
private final Col[] columns_;
private RowCalculation rowCalc_;
/**
* Constructor.
*
* @param base input table
* @param columns array defining the columns of this table
*/
public CalcStarTable( StarTable base, Col[] columns ) {
base_ = base;
columns_ = columns;
}
/**
* Creates the calculation object for the current row of the input table.
*
* @param baseRow row from base table
* @return calculation object corresponding to baseRow
*/
public abstract C createCalculation( RowData baseRow )
throws IOException;
/**
* Creates the calculation object for the given row of the input table.
* Only works for random-access tables.
*
* @param irow row index for which calculation is required
* @return calculation object for input table row irow
*/
public abstract C createCalculation( long irow ) throws IOException;
/**
* Returns the input table on which this table is based.
*
* @return base table
*/
public StarTable getBaseTable() {
return base_;
}
public ColumnInfo getColumnInfo( int icol ) {
return columns_[ icol ].getInfo();
}
public int getColumnCount() {
return columns_.length;
}
public long getRowCount() {
return base_.getRowCount();
}
@Override
public boolean isRandom() {
return base_.isRandom();
}
public RowSequence getRowSequence() throws IOException {
final RowSequence baseSeq = base_.getRowSequence();
return new RowSequence() {
private C calc_;
public boolean next() throws IOException {
calc_ = null;
return baseSeq.next();
}
public Object getCell( int icol ) throws IOException {
return getCalculatedCell( getCalculation(), icol );
}
public Object[] getRow() throws IOException {
return getCalculatedRow( getCalculation() );
}
public void close() throws IOException {
baseSeq.close();
}
private C getCalculation() throws IOException {
if ( calc_ == null ) {
calc_ = createCalculation( baseSeq );
}
return calc_;
}
};
}
public RowSplittable getRowSplittable() throws IOException {
return new CalcRowSplittable( base_.getRowSplittable() );
}
/**
* RowSplittable for use with CalcStarTable.
*/
private class CalcRowSplittable extends WrapperRowSequence
implements RowSplittable {
private C calc_;
private final RowSplittable baseSplit_;
CalcRowSplittable( RowSplittable base ) {
super( base );
baseSplit_ = base;
}
public long splittableSize() {
return baseSplit_.splittableSize();
}
public LongSupplier rowIndex() {
return baseSplit_.rowIndex();
}
@Override
public boolean next() throws IOException {
calc_ = null;
return baseSplit_.next();
}
@Override
public Object getCell( int icol ) throws IOException {
return getCalculatedCell( getCalculation(), icol );
}
@Override
public Object[] getRow() throws IOException {
return getCalculatedRow( getCalculation() );
}
public CalcRowSplittable split() {
RowSplittable spl = baseSplit_.split();
return spl == null ? null
: new CalcRowSplittable( spl );
}
private C getCalculation() throws IOException {
if ( calc_ == null ) {
calc_ = createCalculation( baseSplit_ );
}
return calc_;
}
}
public RowAccess getRowAccess() throws IOException {
final RowAccess baseAcc = base_.getRowAccess();
return new RowAccess() {
private C calc_;
private long irow_ = -1;
public void setRowIndex( long irow ) throws IOException {
if ( irow != irow_ ) {
irow_ = irow;
calc_ = null;
baseAcc.setRowIndex( irow );
}
}
public Object getCell( int icol ) throws IOException {
return getCalculatedCell( getCalculation(), icol );
}
public Object[] getRow() throws IOException {
return getCalculatedRow( getCalculation() );
}
public void close() throws IOException {
baseAcc.close();
}
private C getCalculation() throws IOException {
if ( calc_ == null ) {
calc_ = createCalculation( baseAcc );
}
return calc_;
}
};
}
public Object[] getRow( long irow ) throws IOException {
return getCalculatedRow( getCalculation( irow ) );
}
public Object getCell( long irow, int icol ) throws IOException {
return getCalculatedCell( getCalculation( irow ), icol );
}
/**
* Returns the calculation object for a given row.
*
* @param irow row index for which calculation is required
* @return calculation object for input table row irow
,
* lazily evaluated
*/
private C getCalculation( long irow ) throws IOException {
RowCalculation rowCalc = rowCalc_;
if ( rowCalc != null && rowCalc.irow_ == irow ) {
return rowCalc.calc_;
}
else {
C calc = createCalculation( irow );
rowCalc_ = new RowCalculation( irow, calc );
return calc;
}
}
/**
* Returns the cell value for a given column of this table,
* given the corresponding calculation object.
*
* @param calculation calculation object
* @param icol column index
* @return cell value
*/
private Object getCalculatedCell( C calculation, int icol ) {
return columns_[ icol ].getValue( calculation );
}
/**
* Returns the row value for this table,
* given the corresponding calculation object.
*
* @param calculation calculation object
* @return row array value
*/
private Object[] getCalculatedRow( C calculation ) {
int nc = columns_.length;
Object[] row = new Object[ nc ];
for ( int ic = 0; ic < nc; ic++ ) {
row[ ic ] = columns_[ ic ].getValue( calculation );
}
return row;
}
/**
* Defines a column for use with this table implementation.
* It supplies column metadata, and a mapping from a calculation object
* to the column data.
*
* @param calculation object type
* @param column content class type
* (must match ColumnInfo.getContentClass() result)
*/
public interface Col {
/**
* Returns the metadata for this column.
*
* @return column metadata
*/
ColumnInfo getInfo();
/**
* Returns the value for this column extracted from a given
* calculation object.
*
* @param calculation calculation object
* @return column value
*/
T getValue( C calculation );
}
/**
* Utility class aggregating a row index and a calculation object.
*
* @param calculation object type
*/
private static class RowCalculation {
final long irow_;
final C calc_;
/**
* Constructor.
*
* @param irow row index
* @parma calc calculation object
*/
RowCalculation( long irow, C calc ) {
irow_ = irow;
calc_ = calc;
}
}
}