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

uk.ac.starlink.table.formats.HTMLTableWriter Maven / Gradle / Ivy

There is a newer version: 4.3
Show newest version
package uk.ac.starlink.table.formats;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import uk.ac.starlink.table.ColumnInfo;
import uk.ac.starlink.table.MultiStarTableWriter;
import uk.ac.starlink.table.RowSequence;
import uk.ac.starlink.table.StarTable;
import uk.ac.starlink.table.StarTableOutput;
import uk.ac.starlink.table.StarTableWriter;
import uk.ac.starlink.table.TableSequence;
import uk.ac.starlink.table.Tables;
import uk.ac.starlink.util.ConfigMethod;

/**
 * A StarTableWriter that outputs text to HTML.
 * Depending on the value of the standalone attribute, 
 * the output may either be a complete HTML document or just a 
 * <TABLE> element suitable for inserting into an existing document.
 * The output HTML is intended to conform to HTML 3.2 or 4.01,
 * depending on options.
 *
 * @author   Mark Taylor (Starlink)
 * @see      HTML 3.2
 * @see      HTML 4.01
 */
public class HTMLTableWriter extends DocumentedStreamStarTableWriter
                             implements MultiStarTableWriter {

    private boolean standalone_;
    private boolean useRowGroups_;
    private int maxWidth_;
    private static final int DFLT_MAX_WIDTH = 200;

    /**
     * Constructs a new writer with default characteristics.
     */
    public HTMLTableWriter() {
        this( false, true );
    }

    /**
     * Constructs a new writer indicating whether it will produce complete
     * or partial HTML documents.
     */
    public HTMLTableWriter( boolean standalone, boolean useRowGroups ) {
        super( new String[] { "html", "htm" } );
        setStandalone( standalone );
        useRowGroups_ = useRowGroups;
        maxWidth_ = DFLT_MAX_WIDTH;
    }

    /**
     * Sets whether output tables should be complete HTML documents.
     *
     * @param   standalone  true if the output document should be a
     *          complete HTML document
     */
    @ConfigMethod(
        property = "standalone",
        doc = "If true, the output is a freestanding HTML document "
            + "complete with HTML, HEAD and BODY tags. "
            + "If false, the output is just a TABLE element."
    )
    public void setStandalone( boolean standalone ) {
        standalone_ = standalone;
    }

    /**
     * Indicates whether output tables will be complete HTML documents.
     *
     * @return  true if the output documents will be complete HTML docs
     */
    public boolean isStandalone() {
        return standalone_;
    }

    /**
     * Sets the maximum output width in characters for a single cell.
     *
     * @param   maxWidth  new maximum cell width
     */
    @ConfigMethod(
        property = "maxCell",
        doc = "Maximum width in characters of an output table cell. "
            + "Cells longer than this will be truncated."
    )
    public void setMaxWidth( int maxWidth ) {
        maxWidth_ = maxWidth;
    }

    /**
     * Returns the maximum output width in characters for a single cell.
     *
     * @return  maximum cell width
     */
    public int getMaxWidth() {
        return maxWidth_;
    }

    public String getFormatName() {
        return "HTML";
    }

    public String getMimeType() {
        return "text/html";
    }

    public boolean docIncludesExample() {
        return true;
    }

    public String getXmlDescription() {
        return String.join( "\n",
            "

Writes a basic HTML TABLE element", "suitable for use as a web page or for insertion into one.", "

", "" ); } public void writeStarTable( StarTable table, OutputStream out ) throws IOException { if ( standalone_ ) { printHeader( out, table ); } writeTableElement( table, out ); if ( standalone_ ) { printFooter( out ); } } public void writeStarTables( TableSequence tableSeq, OutputStream out ) throws IOException { if ( standalone_ ) { printHeader( out, null ); } for ( StarTable table; ( table = tableSeq.nextTable() ) != null; ) { printLine( out, "

" ); writeTableElement( table, out ); printLine( out, "

" ); } if ( standalone_ ) { printFooter( out ); } } public void writeStarTables( TableSequence tableSeq, String location, StarTableOutput sto ) throws IOException { OutputStream out = sto.getOutputStream( location ); try { out = new BufferedOutputStream( out ); writeStarTables( tableSeq, out ); out.flush(); } finally { out.close(); } } private void writeTableElement( StarTable table, OutputStream ostrm ) throws IOException { /* Get an iterator over the table data. */ RowSequence rseq = table.getRowSequence(); /* Output table header. */ try { printLine( ostrm, "" ); String tname = table.getName(); if ( tname != null ) { printLine( ostrm, "" ); } /* Output column headings. */ int ncol = table.getColumnCount(); ColumnInfo[] colinfos = Tables.getColumnInfos( table ); String[] names = new String[ ncol ]; String[] units = new String[ ncol ]; boolean hasUnits = false; for ( int icol = 0; icol < ncol; icol++ ) { ColumnInfo colinfo = colinfos[ icol ]; String name = colinfo.getName(); String unit = colinfo.getUnitString(); if ( unit != null ) { hasUnits = true; unit = "(" + unit + ")"; } names[ icol ] = name; units[ icol ] = unit; } String[] headings = new String[ ncol ]; for ( int icol = 0; icol < ncol; icol++ ) { String heading = names[ icol ]; String unit = units[ icol ]; if ( hasUnits ) { heading += "
"; if ( unit != null ){ heading += "(" + unit + ")"; } } headings[ icol ] = heading; } if ( useRowGroups_ ) { printLine( ostrm, "" ); } outputRow( ostrm, "TH", null, names ); if ( hasUnits ) { outputRow( ostrm, "TH", null, units ); } /* Separator. */ printLine( ostrm, "" ); if ( useRowGroups_ ) { printLine( ostrm, "" ); } /* Output the table data. */ if ( useRowGroups_ ) { printLine( ostrm, "" ); } while ( rseq.next() ) { Object[] row = rseq.getRow(); String[] cells = new String[ ncol ]; for ( int icol = 0; icol < ncol; icol++ ) { cells[ icol ] = colinfos[ icol ] .formatValue( row[ icol ], getMaxWidth() ); } outputRow( ostrm, "TD", null, cells ); } if ( useRowGroups_ ) { printLine( ostrm, "" ); } /* Finish up. */ printLine( ostrm, "
" + tname + "
" ); } finally { rseq.close(); } } /** * Returns a selection of useful HTMLTableWriters. * * @return array containing one standalone and one TABLE-only writer */ public static StarTableWriter[] getStarTableWriters() { return new StarTableWriter[] { new HTMLTableWriter( true, true ), new HTMLTableWriter( false, true ), }; } /** * Outputs a row of header or data cells. * * @param ostrm the stream for output * @param tagname the name of the element in which to wrap each * cell ("TH" or "TD") * @param attlist any attributes to put on the elements * @param values the array of values providing cell contents */ private void outputRow( OutputStream ostrm, String tagname, String attlist, String[] values ) throws IOException { int ncol = values.length; StringBuffer sbuf = new StringBuffer(); sbuf.append( "" ); for ( int icol = 0; icol < ncol; icol++ ) { sbuf.append( ' ' ) .append( '<' ) .append( tagname ); if ( attlist != null ) { sbuf.append( " " + attlist ); } sbuf.append( '>' ); String value = values[ icol ] == null ? null : escape( values[ icol ] ); if ( value == null || value.length() == 0 ) { sbuf.append( " " ); } else if ( isUrl( value ) ) { sbuf.append( "" ) .append( value ) .append( "" ); } else { sbuf.append( value ); } sbuf.append( "" ); } sbuf.append( "" ); printLine( ostrm, sbuf.toString() ); } /** * Outputs a line of text, terminated by a newline, to a stream. * * @param ostrm output stream * @param str string to write */ private void printLine( OutputStream ostrm, String str ) throws IOException { ostrm.write( str.getBytes() ); ostrm.write( (int) '\n' ); } /** * For standalone output, this method is invoked to output any text * preceding the <TABLE> start tag. May be overridden to * modify the form of output documents. * * @param ostrm output stream * @param table table for which header is required; may be null * for multi-table output */ protected void printHeader( OutputStream ostrm, StarTable table ) throws IOException { String publicId = useRowGroups_ ? "-//W3C//DTD HTML 4.01 Transitional//EN" : "-//W3C//DTD HTML 3.2 Final//EN"; String declaration = ""; printLine( ostrm, declaration ); printLine( ostrm, "" ); String tname = table == null ? null : table.getName(); if ( tname != null && tname.trim().length() > 0 ) { printLine( ostrm, "Table " + escape( tname ) + "" ); } printLine( ostrm, "" ); } /** * For standalone output, this method is invoked to output any text * following the </TABLE> end tag. May be overridden to * modify the form of output documents. * * @param ostrm output stream */ protected void printFooter( OutputStream ostrm ) throws IOException { printLine( ostrm, "" ); printLine( ostrm, "" ); } /** * Turns a string into a one suitable for inclusion in HTML text - * any special characters are escaped in an HTML-friendly fashion. * * @param line string to escape * @return an HTML-friendly version of line */ private String escape( String line ) { StringBuffer sbuf = new StringBuffer(); for ( int i = 0; i < line.length(); i++ ) { char chr = line.charAt( i ); switch ( chr ) { case '&': sbuf.append( "&" ); break; case '<': sbuf.append( "<" ); break; case '>': sbuf.append( ">" ); break; case '"': sbuf.append( """ ); break; case '\'': sbuf.append( "'" ); break; default: sbuf.append( ( chr > 0 && chr < 254 ) ? chr : '?' ); } } return sbuf.toString(); } /** * Determines whether a string is apparently a URL. * If this returns true, it is appropriate to format it within an HTML * "a" element. * * @param txt string to test * @return true iff txt looks like a URL */ protected boolean isUrl( String txt ) { if ( txt.startsWith( "http:" ) || txt.startsWith( "ftp:" ) || txt.startsWith( "mailto:" ) ) { try { new URL( txt ); return true; } catch ( MalformedURLException e ) { return false; } } else { return false; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy