src/core/net/sf/basedb/util/export/TableWriter.java

Code
Comments
Other
Rev Date Author Line
4926 11 May 09 nicklas 1 /**
4926 11 May 09 nicklas 2   $Id$
4926 11 May 09 nicklas 3
4926 11 May 09 nicklas 4   Copyright (C) 2009 Nicklas Nordborg
4926 11 May 09 nicklas 5
4926 11 May 09 nicklas 6   This file is part of BASE - BioArray Software Environment.
4926 11 May 09 nicklas 7   Available at http://base.thep.lu.se/
4926 11 May 09 nicklas 8
4926 11 May 09 nicklas 9   BASE is free software; you can redistribute it and/or
4926 11 May 09 nicklas 10   modify it under the terms of the GNU General Public License
4926 11 May 09 nicklas 11   as published by the Free Software Foundation; either version 3
4926 11 May 09 nicklas 12   of the License, or (at your option) any later version.
4926 11 May 09 nicklas 13
4926 11 May 09 nicklas 14   BASE is distributed in the hope that it will be useful,
4926 11 May 09 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
4926 11 May 09 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4926 11 May 09 nicklas 17   GNU General Public License for more details.
4926 11 May 09 nicklas 18
4926 11 May 09 nicklas 19   You should have received a copy of the GNU General Public License
4926 11 May 09 nicklas 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
4926 11 May 09 nicklas 21 */
4926 11 May 09 nicklas 22 package net.sf.basedb.util.export;
4926 11 May 09 nicklas 23
4926 11 May 09 nicklas 24 import java.io.PrintWriter;
4926 11 May 09 nicklas 25 import java.io.Writer;
7675 27 Mar 19 nicklas 26 import java.util.Collections;
7675 27 Mar 19 nicklas 27 import java.util.HashMap;
7675 27 Mar 19 nicklas 28 import java.util.Map;
4926 11 May 09 nicklas 29
5188 09 Nov 09 nicklas 30 import net.sf.basedb.util.encode.EncoderDecoder;
5188 09 Nov 09 nicklas 31 import net.sf.basedb.util.encode.IdentityEncoderDecoder;
7675 27 Mar 19 nicklas 32 import net.sf.basedb.util.formatter.Formatter;
5188 09 Nov 09 nicklas 33
4926 11 May 09 nicklas 34 /**
4926 11 May 09 nicklas 35   Wraps a writer stream and provides methods for easier writing
4926 11 May 09 nicklas 36   of tabular data. The writer can be configured with a 
5188 09 Nov 09 nicklas 37   {@link #setDataSeparator(String)} (default is 'tab'),
5188 09 Nov 09 nicklas 38   {@link #setNullValue(String)} (default is an empty string)
5188 09 Nov 09 nicklas 39   and an {@link #setEncoder(EncoderDecoder)} (no default). 
5188 09 Nov 09 nicklas 40   Use {@link #tablePrintData(Object...)} to print a singe line 
5188 09 Nov 09 nicklas 41   with data. Other {@link PrintWriter} methods are not affected 
5188 09 Nov 09 nicklas 42   by those settings.
4926 11 May 09 nicklas 43
4926 11 May 09 nicklas 44   @author Nicklas
4926 11 May 09 nicklas 45   @version 2.12
4926 11 May 09 nicklas 46   @base.modified $Date$
4926 11 May 09 nicklas 47 */
4926 11 May 09 nicklas 48 public class TableWriter
4926 11 May 09 nicklas 49   extends PrintWriter
4926 11 May 09 nicklas 50 {
4926 11 May 09 nicklas 51   
4926 11 May 09 nicklas 52   private String dataSeparator = "\t";
4926 11 May 09 nicklas 53   private String nullValue = "";
5188 09 Nov 09 nicklas 54   private EncoderDecoder encoder;
7675 27 Mar 19 nicklas 55   private final Map<Integer, Formatter<?>> formatters;
4926 11 May 09 nicklas 56
4926 11 May 09 nicklas 57   /**
4926 11 May 09 nicklas 58     Create a new table writer that is writing it's output to the
4926 11 May 09 nicklas 59     given writer.
4926 11 May 09 nicklas 60     @param out The writer to write the data to
4926 11 May 09 nicklas 61   */
4926 11 May 09 nicklas 62   public TableWriter(Writer out)
4926 11 May 09 nicklas 63   {
4926 11 May 09 nicklas 64     super(out);
7675 27 Mar 19 nicklas 65     this.formatters = new HashMap<>();
4926 11 May 09 nicklas 66   }
4926 11 May 09 nicklas 67
4926 11 May 09 nicklas 68   /**
4926 11 May 09 nicklas 69     The data separator string is written between
4926 11 May 09 nicklas 70     each data column in the output. The default value is 'tab'.
4926 11 May 09 nicklas 71     @return The current value of the data separator string
4926 11 May 09 nicklas 72   */
4926 11 May 09 nicklas 73   public String getDataSeparator()
4926 11 May 09 nicklas 74   {
4926 11 May 09 nicklas 75     return dataSeparator;
4926 11 May 09 nicklas 76   }
4926 11 May 09 nicklas 77   
4926 11 May 09 nicklas 78   /**
5188 09 Nov 09 nicklas 79     Change the data separator string. Note! If this value is modified
5188 09 Nov 09 nicklas 80     then a different encoder is probably also needed. See
5188 09 Nov 09 nicklas 81     {@link #setEncoder(EncoderDecoder)}.
4926 11 May 09 nicklas 82     @param dataSeparator The new data separator
4926 11 May 09 nicklas 83   */
4926 11 May 09 nicklas 84   public void setDataSeparator(String dataSeparator)
4926 11 May 09 nicklas 85   {
4926 11 May 09 nicklas 86     this.dataSeparator = dataSeparator;
4926 11 May 09 nicklas 87   }
4926 11 May 09 nicklas 88
4926 11 May 09 nicklas 89   /**
4926 11 May 09 nicklas 90     The null value string is written to the output instead of
4926 11 May 09 nicklas 91     null data values. The default value is an empty string.
4926 11 May 09 nicklas 92     @return The current value of the null value string
4926 11 May 09 nicklas 93   */
4926 11 May 09 nicklas 94   public String getNullValue()
4926 11 May 09 nicklas 95   {
4926 11 May 09 nicklas 96     return nullValue;
4926 11 May 09 nicklas 97   }
4926 11 May 09 nicklas 98   
4926 11 May 09 nicklas 99   /**
4926 11 May 09 nicklas 100     Change the null value string.
4926 11 May 09 nicklas 101     @param nullValue The new null value string
4926 11 May 09 nicklas 102   */
4926 11 May 09 nicklas 103   public void setNullValue(String nullValue)
4926 11 May 09 nicklas 104   {
4926 11 May 09 nicklas 105     this.nullValue = nullValue;
4926 11 May 09 nicklas 106   }
5188 09 Nov 09 nicklas 107
5188 09 Nov 09 nicklas 108   /**
5188 09 Nov 09 nicklas 109     Get the current default encoder for this writer.
5188 09 Nov 09 nicklas 110     @return The current encoder or null
5188 09 Nov 09 nicklas 111     @since 2.15
5188 09 Nov 09 nicklas 112   */
5188 09 Nov 09 nicklas 113   public EncoderDecoder getEncoder()
5188 09 Nov 09 nicklas 114   {
5188 09 Nov 09 nicklas 115     return encoder;
5188 09 Nov 09 nicklas 116   }
4926 11 May 09 nicklas 117   
4926 11 May 09 nicklas 118   /**
5188 09 Nov 09 nicklas 119     Change the encoder.
5188 09 Nov 09 nicklas 120     @param encoder The new encoder or null to not encode
5188 09 Nov 09 nicklas 121     @since 2.15
5188 09 Nov 09 nicklas 122   */
5188 09 Nov 09 nicklas 123   public void setEncoder(EncoderDecoder encoder)
5188 09 Nov 09 nicklas 124   {
5188 09 Nov 09 nicklas 125     this.encoder = encoder;
5188 09 Nov 09 nicklas 126   }
5188 09 Nov 09 nicklas 127
5188 09 Nov 09 nicklas 128   /**
5188 09 Nov 09 nicklas 129     Encode the given string with the default encoder.
5188 09 Nov 09 nicklas 130     @param s The string to encode
5188 09 Nov 09 nicklas 131     @return The encoded string, or the argument if no default encoder
5188 09 Nov 09 nicklas 132       has been specified
5188 09 Nov 09 nicklas 133     @since 2.15
5188 09 Nov 09 nicklas 134   */
5188 09 Nov 09 nicklas 135   public String tableEncode(String s)
5188 09 Nov 09 nicklas 136   {
5188 09 Nov 09 nicklas 137     EncoderDecoder e = getEncoder();
5188 09 Nov 09 nicklas 138     return e == null ? s : e.encode(s);
5188 09 Nov 09 nicklas 139   }
5188 09 Nov 09 nicklas 140
5188 09 Nov 09 nicklas 141   /**
7675 27 Mar 19 nicklas 142     Set a data formatter for a given column. From now on, the
7675 27 Mar 19 nicklas 143     given formatter will be used instead of the toString() method 
7675 27 Mar 19 nicklas 144     to convert data values in that column. It is important that
7675 27 Mar 19 nicklas 145     the data is of the correct type for the formatter.
7675 27 Mar 19 nicklas 146     @since 3.15
7675 27 Mar 19 nicklas 147   */
7675 27 Mar 19 nicklas 148   public void setColumnFormatter(int index, Formatter<?> formatter)
7675 27 Mar 19 nicklas 149   {
7675 27 Mar 19 nicklas 150     this.formatters.put(index, formatter);
7675 27 Mar 19 nicklas 151   }
7675 27 Mar 19 nicklas 152   
7675 27 Mar 19 nicklas 153   /**
7675 27 Mar 19 nicklas 154     @see #setColumnFormatter(int, Formatter)
7675 27 Mar 19 nicklas 155     @since 3.15
7675 27 Mar 19 nicklas 156   */
7675 27 Mar 19 nicklas 157   public Formatter<?> getColumnFormatter(int index)
7675 27 Mar 19 nicklas 158   {
7675 27 Mar 19 nicklas 159     return formatters.get(index);
7675 27 Mar 19 nicklas 160   }
7675 27 Mar 19 nicklas 161
7675 27 Mar 19 nicklas 162   
7675 27 Mar 19 nicklas 163   /**
7675 27 Mar 19 nicklas 164     Print a header line to the parent writer. The only difference between
7675 27 Mar 19 nicklas 165     this method and the {@link #tablePrintData(Object...)} method is that
7675 27 Mar 19 nicklas 166     no column formatters are used (since they operate on data and the headers
7675 27 Mar 19 nicklas 167     are typically strings).
7675 27 Mar 19 nicklas 168     @since 3.15
7675 27 Mar 19 nicklas 169   */
7675 27 Mar 19 nicklas 170   public void tablePrintHeaders(Object... headers)
7675 27 Mar 19 nicklas 171   {
7675 27 Mar 19 nicklas 172     tablePrintData(getEncoder(), null, headers);
7675 27 Mar 19 nicklas 173   }
7675 27 Mar 19 nicklas 174   
7675 27 Mar 19 nicklas 175   /**
5188 09 Nov 09 nicklas 176     Print a data line to the parent writer using the
7675 27 Mar 19 nicklas 177     default encoder and column formatters.
5188 09 Nov 09 nicklas 178
5188 09 Nov 09 nicklas 179     @param data The values to write
5188 09 Nov 09 nicklas 180   */
5188 09 Nov 09 nicklas 181   public void tablePrintData(Object... data)
5188 09 Nov 09 nicklas 182   {
7675 27 Mar 19 nicklas 183     tablePrintData(getEncoder(), formatters, data);
5188 09 Nov 09 nicklas 184   }
5188 09 Nov 09 nicklas 185   
5188 09 Nov 09 nicklas 186   /**
4926 11 May 09 nicklas 187     Print a data line to the parent writer. Each value is separated by the
4926 11 May 09 nicklas 188     data separator string ('tab' by default). Null values are replaced 
4926 11 May 09 nicklas 189     with the null value string (empty string by default). Non-null objects
7675 27 Mar 19 nicklas 190     are converted to strings values by calling either their toString() method or
7675 27 Mar 19 nicklas 191     using the formatter assigned for each column. If an encoder has been specified, 
7675 27 Mar 19 nicklas 192     the value is finally encoded with {@link EncoderDecoder#encode(String)}.
5188 09 Nov 09 nicklas 193   
4926 11 May 09 nicklas 194     @param data The values to write
5188 09 Nov 09 nicklas 195     @param encoder The encoder to use, or null to not use any encoder
5188 09 Nov 09 nicklas 196     @since 2.15
4926 11 May 09 nicklas 197   */
5188 09 Nov 09 nicklas 198   public void tablePrintData(EncoderDecoder encoder, Object... data)
4926 11 May 09 nicklas 199   {
7675 27 Mar 19 nicklas 200     tablePrintData(encoder, formatters, data);
7675 27 Mar 19 nicklas 201   }
7675 27 Mar 19 nicklas 202   
7675 27 Mar 19 nicklas 203   /**
7675 27 Mar 19 nicklas 204     Print a data line to the parent writer. Each value is separated by the
7675 27 Mar 19 nicklas 205     data separator string ('tab' by default). Null values are replaced 
7675 27 Mar 19 nicklas 206     with the null value string (empty string by default). Non-null objects
7675 27 Mar 19 nicklas 207     are converted to strings values by calling either their toString() method or
7675 27 Mar 19 nicklas 208     using the formatter assigned for each column. If an encoder has been specified, 
7675 27 Mar 19 nicklas 209     the value is finally encoded with {@link EncoderDecoder#encode(String)}.
7675 27 Mar 19 nicklas 210   
7675 27 Mar 19 nicklas 211     @param data The values to write
7675 27 Mar 19 nicklas 212     @param formatters Column formatters to use (null to always use the toString() method)
7675 27 Mar 19 nicklas 213     @param encoder The encoder to use, or null to not use any encoder
7675 27 Mar 19 nicklas 214     @since 2.15
7675 27 Mar 19 nicklas 215   */
7675 27 Mar 19 nicklas 216   @SuppressWarnings({ "rawtypes", "unchecked" })
7675 27 Mar 19 nicklas 217   public void tablePrintData(EncoderDecoder encoder, Map<Integer, Formatter<?>> formatters, Object... data)
7675 27 Mar 19 nicklas 218   {
4926 11 May 09 nicklas 219     String ds = getDataSeparator();
4926 11 May 09 nicklas 220     String nv = getNullValue();
7675 27 Mar 19 nicklas 221     if (encoder == null) encoder = new IdentityEncoderDecoder();
7675 27 Mar 19 nicklas 222     if (formatters == null) formatters = Collections.emptyMap();
7675 27 Mar 19 nicklas 223     for (int col = 0; col < data.length; col++)
4926 11 May 09 nicklas 224     {
7675 27 Mar 19 nicklas 225       Object d = data[col];
7675 27 Mar 19 nicklas 226       if (col > 0) print(ds);
7675 27 Mar 19 nicklas 227       Formatter fmt = formatters.get(col);
7675 27 Mar 19 nicklas 228       print(d == null ? nv : encoder.encode(fmt == null ? d.toString() : fmt.format(d)));
4926 11 May 09 nicklas 229     }
5193 27 Nov 09 nicklas 230     print("\n");
4926 11 May 09 nicklas 231   }
4926 11 May 09 nicklas 232   
4926 11 May 09 nicklas 233 }