// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.opendata.core.io.geographic;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.List;
import org.geotools.data.shapefile.dbf.DbaseFileReader;
import org.geotools.data.shapefile.dbf.DbaseFileReader.Row;
import org.geotools.data.shapefile.files.TabFiles;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.gui.progress.ProgressMonitor;
import org.openstreetmap.josm.plugins.opendata.core.OdConstants;
import org.openstreetmap.josm.plugins.opendata.core.datasets.AbstractDataSetHandler;
import org.openstreetmap.josm.plugins.opendata.core.io.tabular.SpreadSheetHandler;
import org.openstreetmap.josm.plugins.opendata.core.io.tabular.SpreadSheetReader;
/**
* MapInfo TAB reader
*
*/
public class TabReader extends AbstractMapInfoReader {
private Charset datCharset;
private final AbstractDataSetHandler handler;
public TabReader(AbstractDataSetHandler handler) {
this.handler = handler;
}
public static DataSet parseDataSet(InputStream in, File file,
AbstractDataSetHandler handler, ProgressMonitor instance) throws IOException {
return new TabReader(handler).parse(in, file, instance, Charset.forName(OdConstants.ISO8859_15));
}
private class TabOsmReader extends SpreadSheetReader {
private final DbaseFileReader dbfReader;
TabOsmReader(SpreadSheetHandler handler, TabFiles tabFiles) throws IOException {
super(handler);
this.dbfReader = new DbaseFileReader(tabFiles, false, datCharset, null);
}
@Override
protected void initResources(InputStream in,
ProgressMonitor progressMonitor) throws IOException {
}
@Override
protected String[] readLine(ProgressMonitor progressMonitor)
throws IOException {
if (!dbfReader.hasNext()) {
return null;
}
List<String> result = new ArrayList<>();
Row row = dbfReader.readRow();
for (int i = 0; i < columns.size(); i++) {
Object o = row.read(i);
if (o != null) {
result.add(o.toString());
} else {
result.add("");
}
}
return result.toArray(new String[0]);
}
}
private DataSet parse(InputStream in, File file, ProgressMonitor instance, Charset charset) throws IOException {
headerReader = new BufferedReader(new InputStreamReader(in, charset));
parseHeader();
try {
File dataFile = getDataFile(file, ".dat");
ds = new TabOsmReader(handler != null ? handler.getSpreadSheetHandler() : null, new TabFiles(file, dataFile)).
doParse(columns.toArray(new String[0]), instance);
} catch (IOException e) {
Main.error(e.getMessage());
}
return ds;
}
@Override
protected void parseHeaderLine(String[] words) throws IOException {
if (words[0].equalsIgnoreCase("!table")) {
// Do nothing
} else if (words[0].equalsIgnoreCase("!version")) {
parseVersion(words);
} else if (words[0].equalsIgnoreCase("!charset")) {
parseCharset(words);
} else if (numcolumns > 0) {
parseField(words);
} else if (words[0].equalsIgnoreCase("Definition")) {
// Do nothing
} else if (words[0].equalsIgnoreCase("Type")) {
parseType(words);
} else if (words[0].equalsIgnoreCase("Fields")) {
parseColumns(words);
} else if (!line.isEmpty()) {
Main.warn("Line "+lineNum+". Unknown clause in header: "+line);
}
}
private void parseField(String[] words) {
columns.add(words[0]);
--numcolumns;
}
private void parseType(String[] words) throws IllegalCharsetNameException, UnsupportedCharsetException {
if (words[1].equalsIgnoreCase("NATIVE") && words[2].equalsIgnoreCase("Charset")) {
datCharset = parseCharset(words, 3);
} else {
Main.warn("Line "+lineNum+". Unknown Type clause in header: "+line);
}
}
}