Skip to content

Commit daa8561

Browse files
committed
Clean up the DefaultTableIOPlugin
* Support non-file locations based on location name extension. * Make private methods static as appropriate. * Sort methods in standard SciJava order. * Label method sections properly.
1 parent 4742b69 commit daa8561

2 files changed

Lines changed: 121 additions & 112 deletions

File tree

src/main/java/org/scijava/table/io/DefaultTableIOPlugin.java

Lines changed: 120 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030

3131
package org.scijava.table.io;
3232

33-
import java.io.File;
3433
import java.io.IOException;
3534
import java.util.ArrayList;
3635
import java.util.Arrays;
@@ -46,19 +45,19 @@
4645
import org.scijava.io.AbstractIOPlugin;
4746
import org.scijava.io.handle.DataHandle;
4847
import org.scijava.io.handle.DataHandleService;
49-
import org.scijava.io.location.FileLocation;
5048
import org.scijava.io.location.Location;
49+
import org.scijava.log.LogService;
5150
import org.scijava.plugin.Parameter;
5251
import org.scijava.plugin.Plugin;
5352
import org.scijava.table.DefaultGenericTable;
5453
import org.scijava.table.GenericTable;
5554
import org.scijava.table.Table;
56-
import org.scijava.util.FileUtils;
5755

5856
/**
5957
* Plugin for reading/writing {@link Table}s.
6058
*
6159
* @author Leon Yang
60+
* @author Curtis Rueden
6261
*/
6362
@SuppressWarnings("rawtypes")
6463
@Plugin(type = TableIOPlugin.class, priority = Priority.LOW)
@@ -69,96 +68,55 @@ public class DefaultTableIOPlugin extends AbstractIOPlugin<Table> implements
6968
@Parameter
7069
private DataHandleService dataHandleService;
7170

71+
@Parameter
72+
private LogService log;
73+
7274
// FIXME: The "txt" extension is extremely general and will conflict with
7375
// other plugins. Consider another way to check supportsOpen/Close.
7476
private static final Set<String> SUPPORTED_EXTENSIONS = //
7577
Collections.unmodifiableSet(new HashSet<>(//
7678
Arrays.asList("csv", "txt", "prn", "dif", "rtf")));
7779

80+
// -- TableIOPlugin methods --
81+
7882
@Override
79-
public boolean supportsOpen(final Location source) {
80-
if (!(source instanceof FileLocation)) return false;
81-
final File file = ((FileLocation) source).getFile();
82-
// NB: For opening, the file must exist or it's not readable.
83-
return file.exists() && supportsFile(file);
83+
public GenericTable open(final Location source, final TableIOOptions options)
84+
throws IOException
85+
{
86+
return open(source, options.values);
8487
}
8588

8689
@Override
87-
public boolean supportsSave(final Location source) {
88-
if (!(source instanceof FileLocation)) return false;
89-
final File file = ((FileLocation) source).getFile();
90-
// NB: For saving, it's OK if the file does not exist yet.
91-
return supportsFile(file);
90+
public void save(final Table table, final Location destination,
91+
final TableIOOptions options) throws IOException
92+
{
93+
save(table, destination, options.values);
9294
}
9395

94-
/**
95-
* Process a given line into a list of tokens.
96-
*/
97-
private ArrayList<String> processRow(final String line, final char separator,
98-
final char quote) throws IOException
99-
{
100-
final ArrayList<String> row = new ArrayList<>();
101-
final StringBuilder sb = new StringBuilder();
102-
int idx = 0;
103-
int start = idx;
104-
while (idx < line.length()) {
105-
if (line.charAt(idx) == quote) {
106-
sb.append(line, start, idx);
107-
boolean quoted = true;
108-
idx++;
109-
start = idx;
110-
// find quoted string
111-
while (idx < line.length()) {
112-
if (line.charAt(idx) == quote) {
113-
sb.append(line, start, idx);
114-
if (idx + 1 < line.length() && line.charAt(idx + 1) == quote) {
115-
sb.append(quote);
116-
idx += 2;
117-
start = idx;
118-
}
119-
else {
120-
idx++;
121-
start = idx;
122-
quoted = false;
123-
break;
124-
}
125-
}
126-
else {
127-
idx++;
128-
}
129-
}
130-
if (quoted) {
131-
throw new IOException(String.format(
132-
"Unbalanced quote at position %d: %s", idx, line));
133-
}
134-
}
135-
else if (line.charAt(idx) == separator) {
136-
sb.append(line, start, idx);
137-
row.add(sb.toString());
138-
sb.setLength(0);
139-
idx++;
140-
start = idx;
141-
}
142-
else {
143-
idx++;
144-
}
96+
// -- IOPlugin methods --
97+
98+
@Override
99+
public boolean supportsOpen(final Location source) {
100+
if (!supportsLocation(source)) return false;
101+
try {
102+
return dataHandleService.exists(source);
103+
}
104+
catch (IOException exc) {
105+
log.debug(exc);
106+
return false;
145107
}
146-
sb.append(line, start, idx);
147-
row.add(sb.toString());
148-
return row;
149108
}
150109

151110
@Override
152-
public GenericTable open(final Location source, final TableIOOptions options)
153-
throws IOException
154-
{
155-
return open(source, options.values);
111+
public boolean supportsSave(final Location source) {
112+
return supportsLocation(source);
156113
}
157114

115+
// -- Helper methods --
116+
158117
private GenericTable open(final Location source,
159118
final TableIOOptions.Values options) throws IOException
160119
{
161-
162120
final GenericTable table = new DefaultGenericTable();
163121

164122
try (final DataHandle<? extends Location> handle = //
@@ -240,46 +198,9 @@ private GenericTable open(final Location source,
240198
return table;
241199
}
242200

243-
private static Function<String, ?> getParser(final String content,
244-
final int column, final TableIOOptions.Values options)
245-
{
246-
final ColumnTableIOOptions.Values colOptions = options.column(column);
247-
if (colOptions != null) return colOptions.parser();
248-
if (options.guessParser()) return guessParser(content);
249-
return options.parser();
250-
}
251-
252-
static Function<String, ?> guessParser(final String content) {
253-
try {
254-
final Function<String, ?> function = s -> Double.valueOf(s.replace(
255-
"infinity", "Infinity").replace("Nan", "NaN"));
256-
function.apply(content);
257-
return function;
258-
}
259-
catch (final NumberFormatException ignored) {}
260-
if (content.equalsIgnoreCase("true") || content.equalsIgnoreCase("false")) {
261-
return Boolean::valueOf;
262-
}
263-
return String::valueOf;
264-
}
265-
266-
@Override
267-
public void save(final Table table, final Location destination,
268-
final TableIOOptions options) throws IOException
269-
{
270-
save(table, destination, options.values);
271-
}
272-
273-
private boolean supportsFile(final File file) {
274-
if (file.isDirectory()) return false;
275-
final String ext = FileUtils.getExtension(file).toLowerCase();
276-
return SUPPORTED_EXTENSIONS.contains(ext);
277-
}
278-
279201
private void save(final Table table, final Location destination,
280202
final TableIOOptions.Values options) throws IOException
281203
{
282-
283204
try (final DataHandle<Location> handle = //
284205
dataHandleService.create(destination))
285206
{
@@ -338,10 +259,84 @@ else if (table.getColumnCount() > 0) {
338259
sb.setLength(0);
339260
}
340261
}
262+
}
341263

264+
private static boolean supportsLocation(Location location) {
265+
final String name = location.getName();
266+
if (name == null) return false;
267+
final int dot = name.lastIndexOf('.');
268+
if (dot < 0) return false;
269+
String extension = name.substring(dot + 1).toLowerCase();
270+
return SUPPORTED_EXTENSIONS.contains(extension);
342271
}
343272

344-
private Function<Object, String> getFormatter(
273+
/**
274+
* Process a given line into a list of tokens.
275+
*/
276+
private static ArrayList<String> processRow(final String line, final char separator,
277+
final char quote) throws IOException
278+
{
279+
final ArrayList<String> row = new ArrayList<>();
280+
final StringBuilder sb = new StringBuilder();
281+
int idx = 0;
282+
int start = idx;
283+
while (idx < line.length()) {
284+
if (line.charAt(idx) == quote) {
285+
sb.append(line, start, idx);
286+
boolean quoted = true;
287+
idx++;
288+
start = idx;
289+
// find quoted string
290+
while (idx < line.length()) {
291+
if (line.charAt(idx) == quote) {
292+
sb.append(line, start, idx);
293+
if (idx + 1 < line.length() && line.charAt(idx + 1) == quote) {
294+
sb.append(quote);
295+
idx += 2;
296+
start = idx;
297+
}
298+
else {
299+
idx++;
300+
start = idx;
301+
quoted = false;
302+
break;
303+
}
304+
}
305+
else {
306+
idx++;
307+
}
308+
}
309+
if (quoted) {
310+
throw new IOException(String.format(
311+
"Unbalanced quote at position %d: %s", idx, line));
312+
}
313+
}
314+
else if (line.charAt(idx) == separator) {
315+
sb.append(line, start, idx);
316+
row.add(sb.toString());
317+
sb.setLength(0);
318+
idx++;
319+
start = idx;
320+
}
321+
else {
322+
idx++;
323+
}
324+
}
325+
sb.append(line, start, idx);
326+
row.add(sb.toString());
327+
return row;
328+
}
329+
330+
private static Function<String, ?> getParser(final String content,
331+
final int column, final TableIOOptions.Values options)
332+
{
333+
final ColumnTableIOOptions.Values colOptions = options.column(column);
334+
if (colOptions != null) return colOptions.parser();
335+
if (options.guessParser()) return guessParser(content);
336+
return options.parser();
337+
}
338+
339+
private static Function<Object, String> getFormatter(
345340
final TableIOOptions.Values options, final int i)
346341
{
347342
final ColumnTableIOOptions.Values columnOptions = options.column(i);
@@ -358,7 +353,7 @@ private Function<Object, String> getFormatter(
358353
* @param str string to quote
359354
* @return string, possibly quoted
360355
*/
361-
private String tryQuote(final String str, final char separator,
356+
private static String tryQuote(final String str, final char separator,
362357
final char quote)
363358
{
364359
if (str == null || str.length() == 0) return "" + quote + quote;
@@ -368,4 +363,18 @@ private String tryQuote(final String str, final char separator,
368363
if (str.indexOf(separator) != -1) return quote + str + quote;
369364
return str;
370365
}
366+
367+
static Function<String, ?> guessParser(final String content) {
368+
try {
369+
final Function<String, ?> function = s -> Double.valueOf(s.replace(
370+
"infinity", "Infinity").replace("Nan", "NaN"));
371+
function.apply(content);
372+
return function;
373+
}
374+
catch (final NumberFormatException ignored) {}
375+
if (content.equalsIgnoreCase("true") || content.equalsIgnoreCase("false")) {
376+
return Boolean::valueOf;
377+
}
378+
return String::valueOf;
379+
}
371380
}

src/main/java/org/scijava/table/io/TableIOPlugin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
import org.scijava.table.Table;
3838

3939
/**
40-
* Abstract plugin class for saving and loading tables
40+
* SciJava plugin type for saving and loading tables.
4141
*
4242
* @author Deborah Schmidt
4343
*/

0 commit comments

Comments
 (0)