All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.ac.starlink.gbin.GbinStarTable Maven / Gradle / Ivy

package uk.ac.starlink.gbin;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import uk.ac.starlink.table.AbstractStarTable;
import uk.ac.starlink.table.ColumnInfo;
import uk.ac.starlink.table.DescribedValue;
import uk.ac.starlink.table.RowSequence;


/**
 * Partial StarTable implementation for use with GBIN files.
 *
 * @author   Mark Taylor
 * @since    6 Jun 2017
 */
public abstract class GbinStarTable extends AbstractStarTable {

    private final Class gobjClazz_;
    private final int ncol_;
    private final ItemReader[] itemReaders_;
    private final ColumnInfo[] colInfos_;

    /**
     * Constructor.
     *
     * @param  profile  configures how GBIN files will be mapped to a table
     * @param  gobjClazz   class of all objects in GBIN file
     */
    protected GbinStarTable( GbinTableProfile profile, Class gobjClazz ) {
        gobjClazz_ = gobjClazz;

        /* Table metadata. */
        setParameter( new DescribedValue( GbinTableBuilder.CLASSNAME_INFO,
                                          gobjClazz.getName() ) );

        /* Get the "official" gaia table name from the class of this object,
         * if it has one. */
        String gaiaTableName = GbinMetadataReader.getGaiaTableName( gobjClazz );

        /* Get additional metadata about this table from the classpath
         * data model classes if available. */
        final GaiaTableMetadata tmeta;
        if ( gaiaTableName != null ) {
            setName( gaiaTableName );
            setParameter( new DescribedValue( GbinTableBuilder
                                             .GAIATABLENAME_INFO,
                                              gaiaTableName ) );
            tmeta = GbinMetadataReader.getTableMetadata( gaiaTableName );
        }
        else {
            tmeta = null;
        }

        /* Table description. */
        if ( tmeta != null ) {
            String descrip = tmeta.getTableDescription();
            if ( descrip != null ) {
                setParameter( new DescribedValue( GbinTableBuilder.DESCRIP_INFO,
                                                  descrip ) );
            }
        }

        /* Construct an array of readers, one for each column, based on
         * the object class. */
        itemReaders_ = ItemReader.createItemReaders( gobjClazz, profile );
        ncol_ = itemReaders_.length;

        /* Group readers by the leaf name of the items they read.
         * The main purpose of this is so we can tell if there are
         * duplicate names, which in turn will affect how columns
         * are named. */
        Map> nameMap =
            new HashMap>();
        boolean forceHier = profile.isHierarchicalNames();
        String separator = profile.getNameSeparator();
        if ( ! forceHier ) {
            for ( int ic = 0; ic < ncol_; ic++ ) {
                ItemReader irdr = itemReaders_[ ic ];
                String name = irdr.getItemName();
                if ( ! nameMap.containsKey( name ) ) {
                    nameMap.put( name, new ArrayList() );
                }
                nameMap.get( name ).add( irdr );
            }
        }

        /* Construct a list of column infos based on what we have. */
        colInfos_ = new ColumnInfo[ ncol_ ];
        for ( int ic = 0; ic < ncol_; ic++ ) {

            /* Basic column info. */
            ItemReader irdr = itemReaders_[ ic ];
            String cname =
                ItemReader.getColumnName( irdr, nameMap, forceHier, separator );
            ColumnInfo cinfo =
                new ColumnInfo( cname, irdr.getItemContentClass(), null );
            colInfos_[ ic ] = cinfo;

            /* Additional column info from GbinMetadataReader if available. */
            String archName = GbinMetadataReader
                             .convertNameToArchiveFormat( cinfo.getName() );
            if ( archName != null ) {
                cinfo.setName( archName );
            }
            if ( tmeta != null ) {

                /* Column description. */
                String descrip = tmeta.getParameterDescription( cname );
                if ( descrip != null && descrip.trim().length() > 0 ) {
                    cinfo.setDescription( descrip );
                }

                /* Column UCDs. */
                List ucdList = tmeta.getUcds( cname );
                if ( ucdList != null && ucdList.size() > 0 ) {
                    StringBuffer ucdBuf = new StringBuffer();
                    for ( Object ucd : ucdList ) {
                        if ( ucdBuf.length() > 0 ) {
                            ucdBuf.append( ";" );
                        }
                        ucdBuf.append( ucd );
                    }
                    if ( ucdBuf.length() > 0 ) {
                        cinfo.setUCD( ucdBuf.toString() );
                    }
                }

                /* Column extra detail (ends up in STIL but probably
                 * not in any serialized formats). */
                String detail =
                    tmeta.getParameterDetailedDescription( cname );
                if ( detail != null && detail.trim().length() > 0 ) {
                    cinfo.setAuxDatum( new DescribedValue( GbinTableBuilder
                                                          .COLDETAIL_INFO,
                                                           detail ) );
                }
            }
        }
    }

    public int getColumnCount() {
        return ncol_;
    }

    public ColumnInfo getColumnInfo( int icol ) {
        return colInfos_[ icol ];
    }

    /**
     * Returns a row sequence for this table based on some required objects.
     *
     * @param   reader  gbin object reader positioned after the first object
     *                  in the stream; must read objects suitable for this table
     * @param   gobj0   first object read from reader
     * @return  new row sequence for this table
     */
    public RowSequence createRowSequence( final GbinObjectReader reader,
                                          final Object gobj0 ) {
        final Map itemMap = new HashMap();
        return new RowSequence() {
            boolean started;
            public boolean next() throws IOException {
                itemMap.clear();
                if ( started ) {
                    if ( reader.hasNext() ) {
                        itemMap.put( ItemReader.ROOT, reader.next() );
                        return true;
                    }
                    else {
                        return false;
                    }
                }
                else {
                    started = true;
                    itemMap.put( ItemReader.ROOT, gobj0 );
                    return true;
                }
            }
            public Object getCell( int icol ) throws IOException {
                return itemReaders_[ icol ].readItem( itemMap );
            }
            public Object[] getRow() throws IOException {
                Object[] row = new Object[ ncol_ ];
                for ( int ic = 0; ic < ncol_; ic++ ) {
                    row[ ic ] = itemReaders_[ ic ].readItem( itemMap );
                }
                return row;
            }
            public void close() {
            }
        };
    }

    /**
     * Returns the class of the elements contained in the GBIN file.
     *
     * @return  element class
     */
    public Class getGaiaObjectClass() {
        return gobjClazz_;
    }

    /**
     * Returns the ItemReaders used by this table.
     *
     * @return   array of ItemReaders, one for each column
     */
    ItemReader[] getItemReaders() {
        return itemReaders_;
    }

    /**
     * Returns a table instance based on a collection of gaia objects.
     * The returned table is not random access.
     *
     * 

A random-access implementation is possible, but trying to * implement getCell efficiently would be a bit fiddly * because of the way that column values are extracted. * * @param profile configures how Gaia objects will be mapped to columns * @param gobjClazz class of all objects representing rows * @param gobjList collection of typed objects, one for each table row * @return sequential-access table based on array of gaia objects */ public static GbinStarTable createCollectionTable( GbinTableProfile profile, Class gobjClazz, final Collection gobjList ) { return new GbinStarTable( profile, gobjClazz ) { public long getRowCount() { return gobjList.size(); } public RowSequence getRowSequence() { final Iterator it = gobjList.iterator(); final Map itemMap = new HashMap(); final ItemReader[] itemReaders = getItemReaders(); final int ncol = itemReaders.length; return new RowSequence() { public boolean next() { itemMap.clear(); if ( it.hasNext() ) { itemMap.put( ItemReader.ROOT, it.next() ); return true; } else { return false; } } public Object getCell( int icol ) throws IOException { return itemReaders[ icol ].readItem( itemMap ); } public Object[] getRow() throws IOException { Object[] row = new Object[ ncol ]; for ( int ic = 0; ic < ncol; ic++ ) { row[ ic ] = itemReaders[ ic ].readItem( itemMap ); } return row; } public void close() { } }; } }; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy