// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.opendata.core.io.archive;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLStreamException;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.gui.progress.ProgressMonitor;
import org.openstreetmap.josm.io.AbstractReader;
import org.openstreetmap.josm.io.IllegalDataException;
import org.openstreetmap.josm.plugins.opendata.OdPlugin;
import org.openstreetmap.josm.plugins.opendata.core.OdConstants;
import org.openstreetmap.josm.plugins.opendata.core.datasets.AbstractDataSetHandler;
import org.openstreetmap.josm.plugins.opendata.core.gui.DialogPrompter;
import org.openstreetmap.josm.plugins.opendata.core.io.NeptuneReader;
import org.openstreetmap.josm.plugins.opendata.core.io.NetworkReader;
import org.openstreetmap.josm.plugins.opendata.core.io.XmlImporter;
import org.openstreetmap.josm.plugins.opendata.core.io.geographic.GmlReader;
import org.openstreetmap.josm.plugins.opendata.core.io.geographic.KmlReader;
import org.openstreetmap.josm.plugins.opendata.core.io.geographic.KmzReader;
import org.openstreetmap.josm.plugins.opendata.core.io.geographic.MifReader;
import org.openstreetmap.josm.plugins.opendata.core.io.geographic.ShpReader;
import org.openstreetmap.josm.plugins.opendata.core.io.geographic.TabReader;
import org.openstreetmap.josm.plugins.opendata.core.io.tabular.CsvReader;
import org.openstreetmap.josm.plugins.opendata.core.io.tabular.OdsReader;
import org.openstreetmap.josm.plugins.opendata.core.io.tabular.XlsReader;
import org.openstreetmap.josm.plugins.opendata.core.util.OdUtils;
public abstract class ArchiveReader extends AbstractReader {
protected final AbstractDataSetHandler handler;
protected final ArchiveHandler archiveHandler;
protected final boolean promptUser;
private File file;
public ArchiveReader(AbstractDataSetHandler handler, ArchiveHandler archiveHandler, boolean promptUser) {
this.handler = handler;
this.archiveHandler = archiveHandler;
this.promptUser = promptUser;
}
public final File getReadFile() {
return file;
}
protected abstract void extractArchive(File temp, List<File> candidates) throws IOException, FileNotFoundException;
protected abstract String getTaskMessage();
protected Collection<File> getDocsToParse(final File temp, final ProgressMonitor progressMonitor) throws FileNotFoundException, IOException {
final List<File> candidates = new ArrayList<>();
if (progressMonitor != null) {
progressMonitor.beginTask(getTaskMessage());
}
extractArchive(temp, candidates);
if (promptUser && candidates.size() > 1) {
DialogPrompter<CandidateChooser> prompt = new DialogPrompter<CandidateChooser>() {
@Override
protected CandidateChooser buildDialog() {
return new CandidateChooser(progressMonitor.getWindowParent(), candidates);
}
};
if (prompt.promptInEdt().getValue() == 1) {
return Collections.singleton(prompt.getDialog().getSelectedFile());
}
} else if (!candidates.isEmpty()) {
return candidates;
}
return Collections.emptyList();
}
public Map<File, DataSet> parseDocs(final ProgressMonitor progressMonitor)
throws IOException, XMLStreamException, FactoryConfigurationError, IllegalDataException {
Map<File, DataSet> result = new HashMap<>();
File temp = OdUtils.createTempDir();
try {
file = null;
for (File f : getDocsToParse(temp, progressMonitor)) {
DataSet from = getDataForFile(f, progressMonitor);
if (from != null) {
result.put(f, from);
}
}
} finally {
OdUtils.deleteDir(temp);
if (progressMonitor != null) {
progressMonitor.finishTask();
}
}
return result;
}
public DataSet parseDoc(final ProgressMonitor progressMonitor)
throws IOException, XMLStreamException, FactoryConfigurationError, IllegalDataException {
File temp = OdUtils.createTempDir();
try {
file = null;
Collection<File> files = getDocsToParse(temp, progressMonitor);
if (!files.isEmpty()) {
file = files.iterator().next();
}
DataSet from = getDataForFile(file, progressMonitor);
if (from != null) {
ds = from;
}
} catch (IllegalArgumentException e) {
Main.error(e.getMessage());
} finally {
OdUtils.deleteDir(temp);
if (progressMonitor != null) {
progressMonitor.finishTask();
}
}
return ds;
}
@Override
protected DataSet doParseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
return null;
}
protected DataSet getDataForFile(File f, final ProgressMonitor progressMonitor)
throws FileNotFoundException, IOException, XMLStreamException, FactoryConfigurationError, IllegalDataException {
if (f == null) {
return null;
} else if (!f.exists()) {
Main.warn("File does not exist: "+f.getPath());
return null;
} else {
Main.info("Parsing file "+f.getName());
DataSet from = null;
FileInputStream in = new FileInputStream(f);
ProgressMonitor instance = null;
if (progressMonitor != null) {
instance = progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false);
}
if (f.getName().toLowerCase().endsWith(OdConstants.CSV_EXT)) {
from = CsvReader.parseDataSet(in, handler, instance);
} else if (f.getName().toLowerCase().endsWith(OdConstants.KML_EXT)) {
from = KmlReader.parseDataSet(in, instance);
} else if (f.getName().toLowerCase().endsWith(OdConstants.KMZ_EXT)) {
from = KmzReader.parseDataSet(in, instance);
} else if (f.getName().toLowerCase().endsWith(OdConstants.XLS_EXT)) {
from = XlsReader.parseDataSet(in, handler, instance);
} else if (f.getName().toLowerCase().endsWith(OdConstants.ODS_EXT)) {
from = OdsReader.parseDataSet(in, handler, instance);
} else if (f.getName().toLowerCase().endsWith(OdConstants.SHP_EXT)) {
from = ShpReader.parseDataSet(in, f, handler, instance);
} else if (f.getName().toLowerCase().endsWith(OdConstants.MIF_EXT)) {
from = MifReader.parseDataSet(in, f, handler, instance);
} else if (f.getName().toLowerCase().endsWith(OdConstants.TAB_EXT)) {
from = TabReader.parseDataSet(in, f, handler, instance);
} else if (f.getName().toLowerCase().endsWith(OdConstants.GML_EXT)) {
from = GmlReader.parseDataSet(in, handler, instance);
} else if (f.getName().toLowerCase().endsWith(OdConstants.XML_EXT)) {
if (OdPlugin.getInstance().xmlImporter.acceptFile(f)) {
from = NeptuneReader.parseDataSet(in, handler, instance);
} else {
Main.warn("Unsupported XML file: "+f.getName());
}
} else {
Main.warn("Unsupported file extension: "+f.getName());
}
return from;
}
}
protected final void lookForCandidate(String entryName, final List<File> candidates, File file) {
// Test file name to see if it may contain useful data
for (String ext : NetworkReader.FILE_READERS.keySet()) {
if (entryName.toLowerCase().endsWith("."+ext)) {
candidates.add(file);
break;
}
}
// Special treatment for XML files (check supported XSD), unless handler explicitely skip it
if (XmlImporter.XML_FILE_FILTER.accept(file) && ((archiveHandler != null && archiveHandler.skipXsdValidation())
|| OdPlugin.getInstance().xmlImporter.acceptFile(file))) {
candidates.add(file);
}
}
}