5193 |
27 Nov 09 |
nicklas |
1 |
/** |
5193 |
27 Nov 09 |
nicklas |
$Id$ |
5193 |
27 Nov 09 |
nicklas |
3 |
|
5193 |
27 Nov 09 |
nicklas |
Copyright (C) 2009 Nicklas Nordborg |
5193 |
27 Nov 09 |
nicklas |
5 |
|
5193 |
27 Nov 09 |
nicklas |
This file is part of BASE - BioArray Software Environment. |
5193 |
27 Nov 09 |
nicklas |
Available at http://base.thep.lu.se/ |
5193 |
27 Nov 09 |
nicklas |
8 |
|
5193 |
27 Nov 09 |
nicklas |
BASE is free software; you can redistribute it and/or |
5193 |
27 Nov 09 |
nicklas |
modify it under the terms of the GNU General Public License |
5193 |
27 Nov 09 |
nicklas |
as published by the Free Software Foundation; either version 3 |
5193 |
27 Nov 09 |
nicklas |
of the License, or (at your option) any later version. |
5193 |
27 Nov 09 |
nicklas |
13 |
|
5193 |
27 Nov 09 |
nicklas |
BASE is distributed in the hope that it will be useful, |
5193 |
27 Nov 09 |
nicklas |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
5193 |
27 Nov 09 |
nicklas |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
5193 |
27 Nov 09 |
nicklas |
GNU General Public License for more details. |
5193 |
27 Nov 09 |
nicklas |
18 |
|
5193 |
27 Nov 09 |
nicklas |
You should have received a copy of the GNU General Public License |
5193 |
27 Nov 09 |
nicklas |
along with BASE. If not, see <http://www.gnu.org/licenses/>. |
5193 |
27 Nov 09 |
nicklas |
21 |
*/ |
5193 |
27 Nov 09 |
nicklas |
22 |
package net.sf.basedb.util.bfs; |
5193 |
27 Nov 09 |
nicklas |
23 |
|
5384 |
13 Aug 10 |
nicklas |
24 |
import java.io.FileNotFoundException; |
5219 |
18 Jan 10 |
nicklas |
25 |
import java.io.FileOutputStream; |
5219 |
18 Jan 10 |
nicklas |
26 |
import java.io.IOException; |
5198 |
15 Dec 09 |
nicklas |
27 |
import java.io.OutputStream; |
5198 |
15 Dec 09 |
nicklas |
28 |
import java.io.OutputStreamWriter; |
5193 |
27 Nov 09 |
nicklas |
29 |
import java.io.PrintWriter; |
5193 |
27 Nov 09 |
nicklas |
30 |
import java.io.Writer; |
7714 |
21 May 19 |
nicklas |
31 |
import java.nio.charset.StandardCharsets; |
5193 |
27 Nov 09 |
nicklas |
32 |
import java.util.HashSet; |
5193 |
27 Nov 09 |
nicklas |
33 |
import java.util.Set; |
5193 |
27 Nov 09 |
nicklas |
34 |
|
5210 |
11 Jan 10 |
nicklas |
35 |
import net.sf.basedb.core.File; |
5193 |
27 Nov 09 |
nicklas |
36 |
import net.sf.basedb.util.encode.EncoderDecoder; |
5193 |
27 Nov 09 |
nicklas |
37 |
import net.sf.basedb.util.encode.TabCrLfEncoderDecoder; |
5193 |
27 Nov 09 |
nicklas |
38 |
import net.sf.basedb.util.formatter.Formatter; |
5193 |
27 Nov 09 |
nicklas |
39 |
import net.sf.basedb.util.formatter.ToStringFormatter; |
5193 |
27 Nov 09 |
nicklas |
40 |
|
5193 |
27 Nov 09 |
nicklas |
41 |
/** |
5193 |
27 Nov 09 |
nicklas |
Writer implementation for writing BFS metadata files. The start |
5193 |
27 Nov 09 |
nicklas |
of file marker (BFSformat) is written immediately at object |
5193 |
27 Nov 09 |
nicklas |
construction. Use the {@link #bfsPrintSection(String, boolean, boolean)} |
5193 |
27 Nov 09 |
nicklas |
to start a new section, and {@link #bfsPrintValue(String, String...)} |
5193 |
27 Nov 09 |
nicklas |
to print a section entry. It is not recommended that any of |
5193 |
27 Nov 09 |
nicklas |
the superclass methods (eg. {@link PrintWriter} methods} are used |
5193 |
27 Nov 09 |
nicklas |
directly as it can create an invalid BFS metadata file. |
5193 |
27 Nov 09 |
nicklas |
<p> |
5193 |
27 Nov 09 |
nicklas |
50 |
|
5193 |
27 Nov 09 |
nicklas |
This class can be subclassed to get specific functionality in specific |
5193 |
27 Nov 09 |
nicklas |
use cases. |
5193 |
27 Nov 09 |
nicklas |
53 |
|
5193 |
27 Nov 09 |
nicklas |
@author Nicklas |
5193 |
27 Nov 09 |
nicklas |
@version 2.15 |
5193 |
27 Nov 09 |
nicklas |
@base.modified $Date$ |
5193 |
27 Nov 09 |
nicklas |
57 |
*/ |
5193 |
27 Nov 09 |
nicklas |
58 |
public class MetadataWriter |
5193 |
27 Nov 09 |
nicklas |
59 |
extends PrintWriter |
5193 |
27 Nov 09 |
nicklas |
60 |
{ |
5193 |
27 Nov 09 |
nicklas |
61 |
|
5193 |
27 Nov 09 |
nicklas |
62 |
public static final String BOF_MARKER = "BFSformat"; |
5193 |
27 Nov 09 |
nicklas |
63 |
|
5198 |
15 Dec 09 |
nicklas |
64 |
/** |
5198 |
15 Dec 09 |
nicklas |
Utility method for creating a metadata writer when you have an |
5198 |
15 Dec 09 |
nicklas |
output stream. |
5198 |
15 Dec 09 |
nicklas |
@param out The output stream the metadata writer should print to |
5198 |
15 Dec 09 |
nicklas |
@param filename Optional, the name of the file the output stream |
5198 |
15 Dec 09 |
nicklas |
is printing to |
5198 |
15 Dec 09 |
nicklas |
70 |
*/ |
5198 |
15 Dec 09 |
nicklas |
71 |
public static MetadataWriter create(OutputStream out, String filename) |
5198 |
15 Dec 09 |
nicklas |
72 |
{ |
5384 |
13 Aug 10 |
nicklas |
73 |
if (out == null) throw new NullPointerException("out"); |
5198 |
15 Dec 09 |
nicklas |
74 |
MetadataWriter writer = new MetadataWriter( |
7714 |
21 May 19 |
nicklas |
75 |
new OutputStreamWriter(out, StandardCharsets.UTF_8)); |
5198 |
15 Dec 09 |
nicklas |
76 |
writer.setFilename(filename); |
5198 |
15 Dec 09 |
nicklas |
77 |
return writer; |
5198 |
15 Dec 09 |
nicklas |
78 |
} |
5198 |
15 Dec 09 |
nicklas |
79 |
|
5210 |
11 Jan 10 |
nicklas |
80 |
/** |
5210 |
11 Jan 10 |
nicklas |
Utility method for creating a metadata writer to a file in the BASE |
5210 |
11 Jan 10 |
nicklas |
file system. The character set and MIME type on the file are automatically |
5210 |
11 Jan 10 |
nicklas |
updated. |
5210 |
11 Jan 10 |
nicklas |
@param file The file in the BASE file system |
5210 |
11 Jan 10 |
nicklas |
85 |
*/ |
5210 |
11 Jan 10 |
nicklas |
86 |
public static MetadataWriter create(File file) |
5210 |
11 Jan 10 |
nicklas |
87 |
{ |
5384 |
13 Aug 10 |
nicklas |
88 |
if (file == null) throw new NullPointerException("file"); |
5210 |
11 Jan 10 |
nicklas |
89 |
file.setCharacterSet("UTF-8"); |
5210 |
11 Jan 10 |
nicklas |
90 |
file.setMimeType("text/plain"); |
5210 |
11 Jan 10 |
nicklas |
91 |
return create(file.getUploadStream(false), file.getName()); |
5210 |
11 Jan 10 |
nicklas |
92 |
} |
5210 |
11 Jan 10 |
nicklas |
93 |
|
5219 |
18 Jan 10 |
nicklas |
94 |
/** |
5219 |
18 Jan 10 |
nicklas |
Utility method for creating a metadata writer to a file in the native |
5219 |
18 Jan 10 |
nicklas |
file system. If the file doesn't exists, it is created. |
5219 |
18 Jan 10 |
nicklas |
@param file The file in the native file system |
5219 |
18 Jan 10 |
nicklas |
98 |
*/ |
5219 |
18 Jan 10 |
nicklas |
99 |
public static MetadataWriter create(java.io.File file) |
5219 |
18 Jan 10 |
nicklas |
100 |
throws IOException |
5219 |
18 Jan 10 |
nicklas |
101 |
{ |
5384 |
13 Aug 10 |
nicklas |
102 |
if (file == null) throw new NullPointerException("file"); |
5384 |
13 Aug 10 |
nicklas |
103 |
if (!file.createNewFile() && !file.exists()) |
5384 |
13 Aug 10 |
nicklas |
104 |
{ |
5384 |
13 Aug 10 |
nicklas |
105 |
throw new FileNotFoundException(file.toString()); |
5384 |
13 Aug 10 |
nicklas |
106 |
} |
5219 |
18 Jan 10 |
nicklas |
107 |
return create(new FileOutputStream(file), file.getName()); |
5219 |
18 Jan 10 |
nicklas |
108 |
} |
5219 |
18 Jan 10 |
nicklas |
109 |
|
5210 |
11 Jan 10 |
nicklas |
110 |
|
5193 |
27 Nov 09 |
nicklas |
111 |
private final EncoderDecoder encoder; |
5198 |
15 Dec 09 |
nicklas |
112 |
private String filename; |
5194 |
04 Dec 09 |
nicklas |
113 |
private String subtype; |
5193 |
27 Nov 09 |
nicklas |
114 |
private Set<String> usedSections; |
5193 |
27 Nov 09 |
nicklas |
115 |
private Set<String> usedKeys; |
5193 |
27 Nov 09 |
nicklas |
116 |
private String currentSection; |
5193 |
27 Nov 09 |
nicklas |
117 |
private boolean uniqueKeys; |
5193 |
27 Nov 09 |
nicklas |
118 |
private int lineCount; |
5193 |
27 Nov 09 |
nicklas |
119 |
private int sectionCount; |
5193 |
27 Nov 09 |
nicklas |
120 |
private int valueCount; |
5193 |
27 Nov 09 |
nicklas |
121 |
|
5193 |
27 Nov 09 |
nicklas |
122 |
/** |
5193 |
27 Nov 09 |
nicklas |
Create a new BFS metadata writer. |
5193 |
27 Nov 09 |
nicklas |
124 |
|
5193 |
27 Nov 09 |
nicklas |
@param out The parent writer which this writer will print to |
5193 |
27 Nov 09 |
nicklas |
126 |
*/ |
5194 |
04 Dec 09 |
nicklas |
127 |
public MetadataWriter(Writer out) |
5193 |
27 Nov 09 |
nicklas |
128 |
{ |
5193 |
27 Nov 09 |
nicklas |
129 |
super(out); |
5193 |
27 Nov 09 |
nicklas |
130 |
this.usedSections = new HashSet<String>(); |
5193 |
27 Nov 09 |
nicklas |
131 |
this.usedKeys = new HashSet<String>(); |
5193 |
27 Nov 09 |
nicklas |
132 |
this.encoder = new TabCrLfEncoderDecoder(true); |
5193 |
27 Nov 09 |
nicklas |
133 |
} |
5193 |
27 Nov 09 |
nicklas |
134 |
|
5193 |
27 Nov 09 |
nicklas |
135 |
/** |
5198 |
15 Dec 09 |
nicklas |
Get the file name that this writer is printing to. |
5198 |
15 Dec 09 |
nicklas |
@return The file name or null if not known |
5198 |
15 Dec 09 |
nicklas |
138 |
*/ |
5198 |
15 Dec 09 |
nicklas |
139 |
public String getFilename() |
5198 |
15 Dec 09 |
nicklas |
140 |
{ |
5198 |
15 Dec 09 |
nicklas |
141 |
return filename; |
5198 |
15 Dec 09 |
nicklas |
142 |
} |
5198 |
15 Dec 09 |
nicklas |
143 |
|
5198 |
15 Dec 09 |
nicklas |
144 |
/** |
5198 |
15 Dec 09 |
nicklas |
Set the file name that this writer is printing to. |
5198 |
15 Dec 09 |
nicklas |
146 |
*/ |
5198 |
15 Dec 09 |
nicklas |
147 |
public void setFilename(String filename) |
5198 |
15 Dec 09 |
nicklas |
148 |
{ |
5198 |
15 Dec 09 |
nicklas |
149 |
this.filename = filename; |
5198 |
15 Dec 09 |
nicklas |
150 |
} |
5198 |
15 Dec 09 |
nicklas |
151 |
|
5198 |
15 Dec 09 |
nicklas |
152 |
/** |
5193 |
27 Nov 09 |
nicklas |
Get the BFS subtype. |
5193 |
27 Nov 09 |
nicklas |
@return The unencoded subtype, or null if no subtype was specified |
5193 |
27 Nov 09 |
nicklas |
when the object was created |
5193 |
27 Nov 09 |
nicklas |
156 |
*/ |
5193 |
27 Nov 09 |
nicklas |
157 |
public String getSubtype() |
5193 |
27 Nov 09 |
nicklas |
158 |
{ |
5193 |
27 Nov 09 |
nicklas |
159 |
return subtype; |
5193 |
27 Nov 09 |
nicklas |
160 |
} |
5193 |
27 Nov 09 |
nicklas |
161 |
|
5193 |
27 Nov 09 |
nicklas |
162 |
/** |
5194 |
04 Dec 09 |
nicklas |
Set the BFS subtype for this writer. This method must be called |
5194 |
04 Dec 09 |
nicklas |
before any printing method is called. |
5194 |
04 Dec 09 |
nicklas |
@param subtype The subtype |
5194 |
04 Dec 09 |
nicklas |
@throws IllegalStateException If data has already been written |
5194 |
04 Dec 09 |
nicklas |
167 |
*/ |
5194 |
04 Dec 09 |
nicklas |
168 |
public void setSubtype(String subtype) |
5194 |
04 Dec 09 |
nicklas |
169 |
{ |
5194 |
04 Dec 09 |
nicklas |
170 |
if (getLineCount() > 0) |
5194 |
04 Dec 09 |
nicklas |
171 |
{ |
5194 |
04 Dec 09 |
nicklas |
172 |
throw new IllegalStateException("Can't change the subtype after data has been printed"); |
5194 |
04 Dec 09 |
nicklas |
173 |
} |
5194 |
04 Dec 09 |
nicklas |
174 |
this.subtype = subtype; |
5194 |
04 Dec 09 |
nicklas |
175 |
} |
5194 |
04 Dec 09 |
nicklas |
176 |
|
5194 |
04 Dec 09 |
nicklas |
177 |
/** |
5193 |
27 Nov 09 |
nicklas |
Get the name of the current section. |
5193 |
27 Nov 09 |
nicklas |
@return The unencoded name of the section, or null if no |
5193 |
27 Nov 09 |
nicklas |
section has been started yet |
5193 |
27 Nov 09 |
nicklas |
181 |
*/ |
5193 |
27 Nov 09 |
nicklas |
182 |
public String getCurrentSection() |
5193 |
27 Nov 09 |
nicklas |
183 |
{ |
5193 |
27 Nov 09 |
nicklas |
184 |
return currentSection; |
5193 |
27 Nov 09 |
nicklas |
185 |
} |
5193 |
27 Nov 09 |
nicklas |
186 |
|
5193 |
27 Nov 09 |
nicklas |
187 |
/** |
5193 |
27 Nov 09 |
nicklas |
Checks if the current section requires entry names to be unique |
5193 |
27 Nov 09 |
nicklas |
or not. |
5193 |
27 Nov 09 |
nicklas |
190 |
*/ |
5193 |
27 Nov 09 |
nicklas |
191 |
public boolean getUniqueKeys() |
5193 |
27 Nov 09 |
nicklas |
192 |
{ |
5193 |
27 Nov 09 |
nicklas |
193 |
return uniqueKeys; |
5193 |
27 Nov 09 |
nicklas |
194 |
} |
5193 |
27 Nov 09 |
nicklas |
195 |
|
5193 |
27 Nov 09 |
nicklas |
196 |
/** |
5193 |
27 Nov 09 |
nicklas |
Checks if the current section already has an entry for the given |
5193 |
27 Nov 09 |
nicklas |
key or not. |
5193 |
27 Nov 09 |
nicklas |
@param key The key to check |
5193 |
27 Nov 09 |
nicklas |
@return TRUE if the current section already has an entry for this key, |
5193 |
27 Nov 09 |
nicklas |
FALSE otherwise |
5193 |
27 Nov 09 |
nicklas |
202 |
*/ |
5193 |
27 Nov 09 |
nicklas |
203 |
public boolean isUsedKey(String key) |
5193 |
27 Nov 09 |
nicklas |
204 |
{ |
5193 |
27 Nov 09 |
nicklas |
205 |
return usedKeys.contains(key); |
5193 |
27 Nov 09 |
nicklas |
206 |
} |
5193 |
27 Nov 09 |
nicklas |
207 |
|
5193 |
27 Nov 09 |
nicklas |
208 |
/** |
5193 |
27 Nov 09 |
nicklas |
Encode a value for use in a BFS file. There is usually no need |
5193 |
27 Nov 09 |
nicklas |
to call this method, since values are automatically encoded. |
5193 |
27 Nov 09 |
nicklas |
@param value The value to encode, may be null |
5193 |
27 Nov 09 |
nicklas |
@return The encoded value |
5193 |
27 Nov 09 |
nicklas |
213 |
*/ |
5193 |
27 Nov 09 |
nicklas |
214 |
public String encodeValue(String value) |
5193 |
27 Nov 09 |
nicklas |
215 |
{ |
5193 |
27 Nov 09 |
nicklas |
216 |
return encoder.encode(value); |
5193 |
27 Nov 09 |
nicklas |
217 |
} |
5193 |
27 Nov 09 |
nicklas |
218 |
|
5193 |
27 Nov 09 |
nicklas |
219 |
/** |
5193 |
27 Nov 09 |
nicklas |
Get the number of lines that has been written to this |
5193 |
27 Nov 09 |
nicklas |
file so far, including all comment lines, empty lines, |
5193 |
27 Nov 09 |
nicklas |
sections headers, etc. |
5193 |
27 Nov 09 |
nicklas |
223 |
*/ |
5193 |
27 Nov 09 |
nicklas |
224 |
public int getLineCount() |
5193 |
27 Nov 09 |
nicklas |
225 |
{ |
5193 |
27 Nov 09 |
nicklas |
226 |
return lineCount; |
5193 |
27 Nov 09 |
nicklas |
227 |
} |
5193 |
27 Nov 09 |
nicklas |
228 |
|
5193 |
27 Nov 09 |
nicklas |
229 |
/** |
5193 |
27 Nov 09 |
nicklas |
Get the number of sections that has been written to this |
5193 |
27 Nov 09 |
nicklas |
file so far. |
5193 |
27 Nov 09 |
nicklas |
232 |
*/ |
5193 |
27 Nov 09 |
nicklas |
233 |
public int getSectionCount() |
5193 |
27 Nov 09 |
nicklas |
234 |
{ |
5193 |
27 Nov 09 |
nicklas |
235 |
return sectionCount; |
5193 |
27 Nov 09 |
nicklas |
236 |
} |
5193 |
27 Nov 09 |
nicklas |
237 |
|
5193 |
27 Nov 09 |
nicklas |
238 |
/** |
5193 |
27 Nov 09 |
nicklas |
Get the number of values that has been written to the current |
5193 |
27 Nov 09 |
nicklas |
section so far. |
5193 |
27 Nov 09 |
nicklas |
241 |
*/ |
5193 |
27 Nov 09 |
nicklas |
242 |
public int getValueCount() |
5193 |
27 Nov 09 |
nicklas |
243 |
{ |
5193 |
27 Nov 09 |
nicklas |
244 |
return valueCount; |
5193 |
27 Nov 09 |
nicklas |
245 |
} |
5193 |
27 Nov 09 |
nicklas |
246 |
|
5193 |
27 Nov 09 |
nicklas |
247 |
/** |
5193 |
27 Nov 09 |
nicklas |
Print one or more empty lines to the metadata file. |
5193 |
27 Nov 09 |
nicklas |
@param num The number of empty lines to print. If 0 or negative |
5193 |
27 Nov 09 |
nicklas |
nothing is written |
5193 |
27 Nov 09 |
nicklas |
251 |
*/ |
5193 |
27 Nov 09 |
nicklas |
252 |
public void bfsPrintEmptyLine(int num) |
5193 |
27 Nov 09 |
nicklas |
253 |
{ |
5194 |
04 Dec 09 |
nicklas |
254 |
if (getLineCount() == 0) internalPrintBofMarker(); |
5193 |
27 Nov 09 |
nicklas |
255 |
for (int i = 0; i < num; ++i) |
5193 |
27 Nov 09 |
nicklas |
256 |
{ |
5193 |
27 Nov 09 |
nicklas |
257 |
print("\n"); |
5193 |
27 Nov 09 |
nicklas |
258 |
} |
5194 |
04 Dec 09 |
nicklas |
259 |
lineCount += num; |
5193 |
27 Nov 09 |
nicklas |
260 |
} |
5193 |
27 Nov 09 |
nicklas |
261 |
|
5193 |
27 Nov 09 |
nicklas |
262 |
/** |
5193 |
27 Nov 09 |
nicklas |
Prints one or more comment lines to the metadata file. A null |
5193 |
27 Nov 09 |
nicklas |
comment is ignored. If the comment contains line-breaks and/or |
5193 |
27 Nov 09 |
nicklas |
carriage returns, it will be split and written to multiple lines. |
5193 |
27 Nov 09 |
nicklas |
@param comment The comment string |
5193 |
27 Nov 09 |
nicklas |
267 |
*/ |
5193 |
27 Nov 09 |
nicklas |
268 |
public void bfsPrintComment(String comment) |
5193 |
27 Nov 09 |
nicklas |
269 |
{ |
5193 |
27 Nov 09 |
nicklas |
270 |
if (comment == null) return; |
5194 |
04 Dec 09 |
nicklas |
271 |
if (getLineCount() == 0) internalPrintBofMarker(); |
5193 |
27 Nov 09 |
nicklas |
272 |
String[] lines = comment.split("\\n|\\r|\\r\\n"); |
5193 |
27 Nov 09 |
nicklas |
273 |
for (String line : lines) |
5193 |
27 Nov 09 |
nicklas |
274 |
{ |
5193 |
27 Nov 09 |
nicklas |
275 |
internalPrintComment(line); |
5193 |
27 Nov 09 |
nicklas |
276 |
} |
5193 |
27 Nov 09 |
nicklas |
277 |
} |
5193 |
27 Nov 09 |
nicklas |
278 |
|
5193 |
27 Nov 09 |
nicklas |
279 |
/** |
5193 |
27 Nov 09 |
nicklas |
Start a new section. |
5193 |
27 Nov 09 |
nicklas |
281 |
|
5193 |
27 Nov 09 |
nicklas |
@param name The name of the section, null is not allowed |
5193 |
27 Nov 09 |
nicklas |
@param unique TRUE if this section must be unique within the metadata |
5193 |
27 Nov 09 |
nicklas |
file |
5193 |
27 Nov 09 |
nicklas |
@param uniqueKeys TRUE if all keys in this section must be unique |
5193 |
27 Nov 09 |
nicklas |
@throws NullPointerException If the section name is null |
5193 |
27 Nov 09 |
nicklas |
@throws IllegalArgumentException If the name is not unique and |
5193 |
27 Nov 09 |
nicklas |
the writer requires unique sections |
5193 |
27 Nov 09 |
nicklas |
289 |
*/ |
5193 |
27 Nov 09 |
nicklas |
290 |
public void bfsPrintSection(String name, boolean unique, boolean uniqueKeys) |
5193 |
27 Nov 09 |
nicklas |
291 |
{ |
5194 |
04 Dec 09 |
nicklas |
292 |
if (getLineCount() == 0) internalPrintBofMarker(); |
5193 |
27 Nov 09 |
nicklas |
293 |
if (name == null) throw new NullPointerException("name"); |
5193 |
27 Nov 09 |
nicklas |
294 |
if (unique) |
5193 |
27 Nov 09 |
nicklas |
295 |
{ |
5193 |
27 Nov 09 |
nicklas |
296 |
if (usedSections.contains(name)) |
5193 |
27 Nov 09 |
nicklas |
297 |
{ |
5193 |
27 Nov 09 |
nicklas |
298 |
throw new IllegalArgumentException("Section '" + name + "' is not unique"); |
5193 |
27 Nov 09 |
nicklas |
299 |
} |
5193 |
27 Nov 09 |
nicklas |
300 |
} |
5193 |
27 Nov 09 |
nicklas |
301 |
usedSections.add(name); |
5193 |
27 Nov 09 |
nicklas |
302 |
|
5193 |
27 Nov 09 |
nicklas |
303 |
this.currentSection = name; |
5193 |
27 Nov 09 |
nicklas |
304 |
this.uniqueKeys = uniqueKeys; |
5193 |
27 Nov 09 |
nicklas |
305 |
usedKeys.clear(); |
5193 |
27 Nov 09 |
nicklas |
306 |
internalPrintSection(encodeValue(name)); |
5193 |
27 Nov 09 |
nicklas |
307 |
} |
5193 |
27 Nov 09 |
nicklas |
308 |
|
5193 |
27 Nov 09 |
nicklas |
309 |
/** |
5193 |
27 Nov 09 |
nicklas |
Prints a section entry. A section must have been started with |
5193 |
27 Nov 09 |
nicklas |
{@link #bfsPrintSection(String, boolean, boolean)} before this |
5193 |
27 Nov 09 |
nicklas |
method is invoked. |
5193 |
27 Nov 09 |
nicklas |
313 |
|
5193 |
27 Nov 09 |
nicklas |
@param key The entry key; null is not allowed and it may not |
5193 |
27 Nov 09 |
nicklas |
start with '[' or '#' |
5193 |
27 Nov 09 |
nicklas |
@param values An array of string values, each value will be encoded |
5193 |
27 Nov 09 |
nicklas |
independently and separated with a tab |
5193 |
27 Nov 09 |
nicklas |
@throws NullPointerException If the key is null |
5193 |
27 Nov 09 |
nicklas |
@throws IllegalArgumentException If the key starts with '[' or |
5193 |
27 Nov 09 |
nicklas |
'#', or if the key is not unique within a section that requires |
5193 |
27 Nov 09 |
nicklas |
unique keys |
5193 |
27 Nov 09 |
nicklas |
@throws IllegalStateException If no section has been started |
5193 |
27 Nov 09 |
nicklas |
323 |
*/ |
5193 |
27 Nov 09 |
nicklas |
324 |
public void bfsPrintValue(String key, String... values) |
5193 |
27 Nov 09 |
nicklas |
325 |
{ |
5193 |
27 Nov 09 |
nicklas |
326 |
bfsPrintValue(key, null, values); |
5193 |
27 Nov 09 |
nicklas |
327 |
} |
5193 |
27 Nov 09 |
nicklas |
328 |
|
5193 |
27 Nov 09 |
nicklas |
329 |
/** |
5193 |
27 Nov 09 |
nicklas |
Prints a section entry. A section must have been started with |
5193 |
27 Nov 09 |
nicklas |
{@link #bfsPrintSection(String, boolean, boolean)} before this |
5193 |
27 Nov 09 |
nicklas |
method is invoked. |
5193 |
27 Nov 09 |
nicklas |
333 |
|
5193 |
27 Nov 09 |
nicklas |
@param key The entry key; null is not allowed and it may not |
5193 |
27 Nov 09 |
nicklas |
start with '[' or '#' |
5193 |
27 Nov 09 |
nicklas |
@param values An array of objects, each value will be be converted to |
5193 |
27 Nov 09 |
nicklas |
a string by calling the toString() method |
5193 |
27 Nov 09 |
nicklas |
@throws NullPointerException If the key is null |
5193 |
27 Nov 09 |
nicklas |
@throws IllegalArgumentException If the key starts with '[' or |
5193 |
27 Nov 09 |
nicklas |
'#', or if the key is not unique within a section that requires |
5193 |
27 Nov 09 |
nicklas |
unique keys |
5193 |
27 Nov 09 |
nicklas |
@throws IllegalStateException If no section has been started |
5193 |
27 Nov 09 |
nicklas |
343 |
*/ |
6125 |
14 Sep 12 |
nicklas |
344 |
@SuppressWarnings("unchecked") |
5193 |
27 Nov 09 |
nicklas |
345 |
public <T> void bfsPrintValue(String key, T... values) |
5193 |
27 Nov 09 |
nicklas |
346 |
{ |
5193 |
27 Nov 09 |
nicklas |
347 |
bfsPrintValue(key, null, values); |
5193 |
27 Nov 09 |
nicklas |
348 |
} |
5193 |
27 Nov 09 |
nicklas |
349 |
|
5193 |
27 Nov 09 |
nicklas |
350 |
/** |
5193 |
27 Nov 09 |
nicklas |
Prints a section entry. A section must have been started with |
5193 |
27 Nov 09 |
nicklas |
{@link #bfsPrintSection(String, boolean, boolean)} before this |
5193 |
27 Nov 09 |
nicklas |
method is invoked. |
5193 |
27 Nov 09 |
nicklas |
354 |
|
5193 |
27 Nov 09 |
nicklas |
@param key The entry key; null is not allowed and it may not |
5193 |
27 Nov 09 |
nicklas |
start with '[' or '#' |
5193 |
27 Nov 09 |
nicklas |
@param formatter A formatter that should be used to convert the |
5193 |
27 Nov 09 |
nicklas |
values to strings, or null to simply use the toString() method |
5193 |
27 Nov 09 |
nicklas |
@param values An array of objects, each value will be encoded |
5193 |
27 Nov 09 |
nicklas |
independently and separated with a tab |
5193 |
27 Nov 09 |
nicklas |
@throws NullPointerException If the key is null |
5193 |
27 Nov 09 |
nicklas |
@throws IllegalArgumentException If the key starts with '[' or |
5193 |
27 Nov 09 |
nicklas |
'#', or if the key is not unique within a section that requires |
5193 |
27 Nov 09 |
nicklas |
unique keys |
5193 |
27 Nov 09 |
nicklas |
@throws IllegalStateException If no section has been started |
5193 |
27 Nov 09 |
nicklas |
366 |
*/ |
6125 |
14 Sep 12 |
nicklas |
367 |
@SuppressWarnings({"unchecked"}) |
5193 |
27 Nov 09 |
nicklas |
368 |
public <T> void bfsPrintValue(String key, Formatter<T> formatter, T... values) |
5193 |
27 Nov 09 |
nicklas |
369 |
{ |
5193 |
27 Nov 09 |
nicklas |
370 |
if (sectionCount == 0) throw new IllegalStateException("No section has been started"); |
5193 |
27 Nov 09 |
nicklas |
371 |
if (key == null) throw new NullPointerException("key"); |
5193 |
27 Nov 09 |
nicklas |
372 |
if (key.startsWith("[") || key.startsWith("#")) |
5193 |
27 Nov 09 |
nicklas |
373 |
{ |
5193 |
27 Nov 09 |
nicklas |
374 |
throw new IllegalArgumentException("A key may not start with [ or #: '" + key + "'"); |
5193 |
27 Nov 09 |
nicklas |
375 |
} |
5193 |
27 Nov 09 |
nicklas |
376 |
if (getUniqueKeys()) |
5193 |
27 Nov 09 |
nicklas |
377 |
{ |
5193 |
27 Nov 09 |
nicklas |
378 |
if (isUsedKey(key)) |
5193 |
27 Nov 09 |
nicklas |
379 |
{ |
5193 |
27 Nov 09 |
nicklas |
380 |
throw new IllegalArgumentException("Key '" + key + |
5193 |
27 Nov 09 |
nicklas |
381 |
"' is not unique in section '" + getCurrentSection() + "'"); |
5193 |
27 Nov 09 |
nicklas |
382 |
} |
5193 |
27 Nov 09 |
nicklas |
383 |
} |
5193 |
27 Nov 09 |
nicklas |
384 |
usedKeys.add(key); |
5193 |
27 Nov 09 |
nicklas |
385 |
|
5193 |
27 Nov 09 |
nicklas |
386 |
if (formatter == null) formatter = new ToStringFormatter<T>(); |
5193 |
27 Nov 09 |
nicklas |
387 |
StringBuilder value = new StringBuilder(); |
5193 |
27 Nov 09 |
nicklas |
388 |
if (values != null) |
5193 |
27 Nov 09 |
nicklas |
389 |
{ |
5193 |
27 Nov 09 |
nicklas |
390 |
String sep = ""; |
5193 |
27 Nov 09 |
nicklas |
391 |
for (T v : values) |
5193 |
27 Nov 09 |
nicklas |
392 |
{ |
5193 |
27 Nov 09 |
nicklas |
393 |
value.append(sep); |
5193 |
27 Nov 09 |
nicklas |
394 |
value.append(encodeValue(formatter.format(v))); |
5193 |
27 Nov 09 |
nicklas |
395 |
sep = "\t"; |
5193 |
27 Nov 09 |
nicklas |
396 |
} |
5193 |
27 Nov 09 |
nicklas |
397 |
} |
5193 |
27 Nov 09 |
nicklas |
398 |
internalPrintValue(encodeValue(key), value.toString()); |
5193 |
27 Nov 09 |
nicklas |
399 |
} |
5193 |
27 Nov 09 |
nicklas |
400 |
|
5193 |
27 Nov 09 |
nicklas |
401 |
/** |
5193 |
27 Nov 09 |
nicklas |
Prints the beginning-of-file marker. Eg. |
5193 |
27 Nov 09 |
nicklas |
<code>BFSformat<tab>subtype</code> |
5193 |
27 Nov 09 |
nicklas |
404 |
*/ |
5193 |
27 Nov 09 |
nicklas |
405 |
protected void internalPrintBofMarker() |
5193 |
27 Nov 09 |
nicklas |
406 |
{ |
5193 |
27 Nov 09 |
nicklas |
407 |
print(BOF_MARKER); |
5193 |
27 Nov 09 |
nicklas |
408 |
String subtype = getSubtype(); |
5193 |
27 Nov 09 |
nicklas |
409 |
if (subtype != null) print("\t" + encodeValue(subtype)); |
5193 |
27 Nov 09 |
nicklas |
410 |
print("\n"); |
5193 |
27 Nov 09 |
nicklas |
411 |
lineCount++; |
5193 |
27 Nov 09 |
nicklas |
412 |
} |
5193 |
27 Nov 09 |
nicklas |
413 |
|
5193 |
27 Nov 09 |
nicklas |
414 |
/** |
5193 |
27 Nov 09 |
nicklas |
Print a single-line comment. This method should not be |
5193 |
27 Nov 09 |
nicklas |
called with comment string that is null or contain |
5193 |
27 Nov 09 |
nicklas |
line-breaks. Updates the line counter. |
5193 |
27 Nov 09 |
nicklas |
418 |
*/ |
5193 |
27 Nov 09 |
nicklas |
419 |
protected void internalPrintComment(String comment) |
5193 |
27 Nov 09 |
nicklas |
420 |
{ |
5193 |
27 Nov 09 |
nicklas |
421 |
print("#" + comment + "\n"); |
5193 |
27 Nov 09 |
nicklas |
422 |
lineCount++; |
5193 |
27 Nov 09 |
nicklas |
423 |
} |
5193 |
27 Nov 09 |
nicklas |
424 |
|
5193 |
27 Nov 09 |
nicklas |
425 |
/** |
5193 |
27 Nov 09 |
nicklas |
Prints a section header assuming that the name has already |
5193 |
27 Nov 09 |
nicklas |
been encoded. Updates line and section counters and resets |
5193 |
27 Nov 09 |
nicklas |
the value counter. |
5193 |
27 Nov 09 |
nicklas |
429 |
*/ |
5193 |
27 Nov 09 |
nicklas |
430 |
protected void internalPrintSection(String encodedName) |
5193 |
27 Nov 09 |
nicklas |
431 |
{ |
5193 |
27 Nov 09 |
nicklas |
432 |
print("[" + encodedName + "]\n"); |
5193 |
27 Nov 09 |
nicklas |
433 |
lineCount++; |
5193 |
27 Nov 09 |
nicklas |
434 |
sectionCount++; |
5193 |
27 Nov 09 |
nicklas |
435 |
valueCount = 0; |
5193 |
27 Nov 09 |
nicklas |
436 |
} |
5193 |
27 Nov 09 |
nicklas |
437 |
|
5193 |
27 Nov 09 |
nicklas |
438 |
/** |
5193 |
27 Nov 09 |
nicklas |
Prints a section entry assuming that the key and value has |
5193 |
27 Nov 09 |
nicklas |
already been encoded. Updates the line and value counters. |
5193 |
27 Nov 09 |
nicklas |
441 |
*/ |
5193 |
27 Nov 09 |
nicklas |
442 |
protected void internalPrintValue(String encodedKey, String encodedValue) |
5193 |
27 Nov 09 |
nicklas |
443 |
{ |
5193 |
27 Nov 09 |
nicklas |
444 |
print(encodedKey + "\t" + encodedValue + "\n"); |
5193 |
27 Nov 09 |
nicklas |
445 |
lineCount++; |
5193 |
27 Nov 09 |
nicklas |
446 |
valueCount++; |
5193 |
27 Nov 09 |
nicklas |
447 |
} |
5193 |
27 Nov 09 |
nicklas |
448 |
|
5193 |
27 Nov 09 |
nicklas |
449 |
} |