4926 |
11 May 09 |
nicklas |
1 |
/** |
4926 |
11 May 09 |
nicklas |
$Id$ |
4926 |
11 May 09 |
nicklas |
3 |
|
4926 |
11 May 09 |
nicklas |
Copyright (C) 2009 Nicklas Nordborg |
4926 |
11 May 09 |
nicklas |
5 |
|
4926 |
11 May 09 |
nicklas |
This file is part of BASE - BioArray Software Environment. |
4926 |
11 May 09 |
nicklas |
Available at http://base.thep.lu.se/ |
4926 |
11 May 09 |
nicklas |
8 |
|
4926 |
11 May 09 |
nicklas |
BASE is free software; you can redistribute it and/or |
4926 |
11 May 09 |
nicklas |
modify it under the terms of the GNU General Public License |
4926 |
11 May 09 |
nicklas |
as published by the Free Software Foundation; either version 3 |
4926 |
11 May 09 |
nicklas |
of the License, or (at your option) any later version. |
4926 |
11 May 09 |
nicklas |
13 |
|
4926 |
11 May 09 |
nicklas |
BASE is distributed in the hope that it will be useful, |
4926 |
11 May 09 |
nicklas |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
4926 |
11 May 09 |
nicklas |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4926 |
11 May 09 |
nicklas |
GNU General Public License for more details. |
4926 |
11 May 09 |
nicklas |
18 |
|
4926 |
11 May 09 |
nicklas |
You should have received a copy of the GNU General Public License |
4926 |
11 May 09 |
nicklas |
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 |
Wraps a writer stream and provides methods for easier writing |
4926 |
11 May 09 |
nicklas |
of tabular data. The writer can be configured with a |
5188 |
09 Nov 09 |
nicklas |
{@link #setDataSeparator(String)} (default is 'tab'), |
5188 |
09 Nov 09 |
nicklas |
{@link #setNullValue(String)} (default is an empty string) |
5188 |
09 Nov 09 |
nicklas |
and an {@link #setEncoder(EncoderDecoder)} (no default). |
5188 |
09 Nov 09 |
nicklas |
Use {@link #tablePrintData(Object...)} to print a singe line |
5188 |
09 Nov 09 |
nicklas |
with data. Other {@link PrintWriter} methods are not affected |
5188 |
09 Nov 09 |
nicklas |
by those settings. |
4926 |
11 May 09 |
nicklas |
43 |
|
4926 |
11 May 09 |
nicklas |
@author Nicklas |
4926 |
11 May 09 |
nicklas |
@version 2.12 |
4926 |
11 May 09 |
nicklas |
@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 |
Create a new table writer that is writing it's output to the |
4926 |
11 May 09 |
nicklas |
given writer. |
4926 |
11 May 09 |
nicklas |
@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 |
The data separator string is written between |
4926 |
11 May 09 |
nicklas |
each data column in the output. The default value is 'tab'. |
4926 |
11 May 09 |
nicklas |
@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 |
Change the data separator string. Note! If this value is modified |
5188 |
09 Nov 09 |
nicklas |
then a different encoder is probably also needed. See |
5188 |
09 Nov 09 |
nicklas |
{@link #setEncoder(EncoderDecoder)}. |
4926 |
11 May 09 |
nicklas |
@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 |
The null value string is written to the output instead of |
4926 |
11 May 09 |
nicklas |
null data values. The default value is an empty string. |
4926 |
11 May 09 |
nicklas |
@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 |
Change the null value string. |
4926 |
11 May 09 |
nicklas |
@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 |
Get the current default encoder for this writer. |
5188 |
09 Nov 09 |
nicklas |
@return The current encoder or null |
5188 |
09 Nov 09 |
nicklas |
@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 |
Change the encoder. |
5188 |
09 Nov 09 |
nicklas |
@param encoder The new encoder or null to not encode |
5188 |
09 Nov 09 |
nicklas |
@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 |
Encode the given string with the default encoder. |
5188 |
09 Nov 09 |
nicklas |
@param s The string to encode |
5188 |
09 Nov 09 |
nicklas |
@return The encoded string, or the argument if no default encoder |
5188 |
09 Nov 09 |
nicklas |
has been specified |
5188 |
09 Nov 09 |
nicklas |
@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 |
Set a data formatter for a given column. From now on, the |
7675 |
27 Mar 19 |
nicklas |
given formatter will be used instead of the toString() method |
7675 |
27 Mar 19 |
nicklas |
to convert data values in that column. It is important that |
7675 |
27 Mar 19 |
nicklas |
the data is of the correct type for the formatter. |
7675 |
27 Mar 19 |
nicklas |
@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 |
@see #setColumnFormatter(int, Formatter) |
7675 |
27 Mar 19 |
nicklas |
@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 |
Print a header line to the parent writer. The only difference between |
7675 |
27 Mar 19 |
nicklas |
this method and the {@link #tablePrintData(Object...)} method is that |
7675 |
27 Mar 19 |
nicklas |
no column formatters are used (since they operate on data and the headers |
7675 |
27 Mar 19 |
nicklas |
are typically strings). |
7675 |
27 Mar 19 |
nicklas |
@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 |
Print a data line to the parent writer using the |
7675 |
27 Mar 19 |
nicklas |
default encoder and column formatters. |
5188 |
09 Nov 09 |
nicklas |
178 |
|
5188 |
09 Nov 09 |
nicklas |
@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 |
Print a data line to the parent writer. Each value is separated by the |
4926 |
11 May 09 |
nicklas |
data separator string ('tab' by default). Null values are replaced |
4926 |
11 May 09 |
nicklas |
with the null value string (empty string by default). Non-null objects |
7675 |
27 Mar 19 |
nicklas |
are converted to strings values by calling either their toString() method or |
7675 |
27 Mar 19 |
nicklas |
using the formatter assigned for each column. If an encoder has been specified, |
7675 |
27 Mar 19 |
nicklas |
the value is finally encoded with {@link EncoderDecoder#encode(String)}. |
5188 |
09 Nov 09 |
nicklas |
193 |
|
4926 |
11 May 09 |
nicklas |
@param data The values to write |
5188 |
09 Nov 09 |
nicklas |
@param encoder The encoder to use, or null to not use any encoder |
5188 |
09 Nov 09 |
nicklas |
@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 |
Print a data line to the parent writer. Each value is separated by the |
7675 |
27 Mar 19 |
nicklas |
data separator string ('tab' by default). Null values are replaced |
7675 |
27 Mar 19 |
nicklas |
with the null value string (empty string by default). Non-null objects |
7675 |
27 Mar 19 |
nicklas |
are converted to strings values by calling either their toString() method or |
7675 |
27 Mar 19 |
nicklas |
using the formatter assigned for each column. If an encoder has been specified, |
7675 |
27 Mar 19 |
nicklas |
the value is finally encoded with {@link EncoderDecoder#encode(String)}. |
7675 |
27 Mar 19 |
nicklas |
210 |
|
7675 |
27 Mar 19 |
nicklas |
@param data The values to write |
7675 |
27 Mar 19 |
nicklas |
@param formatters Column formatters to use (null to always use the toString() method) |
7675 |
27 Mar 19 |
nicklas |
@param encoder The encoder to use, or null to not use any encoder |
7675 |
27 Mar 19 |
nicklas |
@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 |
} |