Next Previous Up Contents
Next: VOTable Access
Up: Examples
Previous: Turn a set of arrays into a StarTable

#### 6.4.3 Add a new column

In this example we will append to a table a new column in which each cell contains the sum of all the other numeric cells in that row.

First, we define a wrapper table class which contains only a single column, the one which we want to add. We subclass `AbstractStarTable`, implementing its abstract methods as well as the `getCell` method which may be required if the base table is random-access.

        class SumColumnStarTable extends AbstractStarTable {

            StarTable baseTable_;
            ColumnInfo colInfo0_ =
                new ColumnInfo( "Sum", Double.class, "Sum of other columns" );

            // Constructs a new summation table from a base table.
            SumColumnStarTable( StarTable baseTable ) {
                baseTable_ = baseTable;
            }

            // Has a single column.
            public int getColumnCount() {
                return 1;
            }

            // The single column is the sum of the other columns.
            public ColumnInfo getColumnInfo( int icol ) {
                if ( icol != 0 ) throw new IllegalArgumentException();
                return colInfo0_;
            }

            // Has the same number of rows as the base table.
            public long getRowCount() {
                return baseTable_.getRowCount();
            }

            // Provides random access iff the base table does.
            public boolean isRandom() {
                return baseTable_.isRandom();
            }

            // Get the row from the base table, and sum elements to produce value.
            public Object getCell( long irow, int icol ) throws IOException {
                if ( icol != 0 ) throw new IllegalArgumentException();
                return calculateSum( baseTable_.getRow( irow ) );
            }

            // Use a WrapperRowSequence based on the base table's RowSequence.
            // Wrapping a RowSequence is quite like wrapping the table itself;
            // we just need to override the methods which require new behaviour.
            public RowSequence getRowSequence() throws IOException {
                final RowSequence baseSeq = baseTable_.getRowSequence();
                return new WrapperRowSequence( baseSeq ) {
                    public Object getCell( int icol ) throws IOException {
                        if ( icol != 0 ) throw new IllegalArgumentException();
                        return calculateSum( baseSeq.getRow() );
                    }
                    public Object[] getRow() throws IOException {
                        return new Object[] { getCell( 0 ) };
                    }
                };
            }

            // Do the same for the RowAccess.
            public RowAccess getRowAccess() throws IOException {
                final RowAccess baseAcc = baseTable_.getRowAccess();
                return new WrapperRowAccess( baseAcc ) {
                    public Object getCell( int icol ) throws IOException {
                        if ( icol != 0 ) throw new IllegalArgumentException();
                        return calculateSum( baseAcc.getRow() );
                    }
                    public Object[] getRow() throws IOException {
                        return new Object[] { getCell( 0 ) };
                    }
                };
            }

            // getRowSplittable must also be overridden.  Here we use the
            // basic implementation from the utility class Tables,
            // but if you expect to be doing parallel processing a
            // more careful implementation based on the base table's
            // RowSplittable may be required.
            public RowSplittable getRowSplittable() throws IOException {
                return Tables.getDefaultRowSplittable( this );
            }

            // This method does the arithmetic work, summing all the numeric
            // columns in a row (array of cell value objects) and returning
            // a Double.
            Double calculateSum( Object[] row ) {
                double sum = 0.0;
                for ( int icol = 0; icol < row.length; icol++ ) {
                    Object value = row[ icol ];
                    if ( value instanceof Number ) {
                        sum += ((Number) value).doubleValue();
                    }
                }
                return new Double( sum );
            }
        }

We could use this class on its own if we just wanted a 1-column table containing summed values. The following snippet however combines an instance of this class with the table that it is summing from, resulting in an n+1 column table in which the last column is the sum of the others:

        StarTable getCombinedTable( StarTable inTable ) {
            StarTable[] tableSet = new StarTable[ 2 ];
            tableSet[ 0 ] = inTable;
            tableSet[ 1 ] = new SumColumnStarTable( inTable );
            StarTable combinedTable = new JoinStarTable( tableSet );
            return combinedTable;
        }

Next Previous Up Contents
Next: VOTable Access
Up: Examples
Previous: Turn a set of arrays into a StarTable

STIL - Starlink Tables Infrastructure Library
Starlink User Note252
STIL web page: http://www.starlink.ac.uk/stil/
Author email: m.b.taylor@bristol.ac.uk