001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.layer.gpx;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.io.File;
007import java.io.IOException;
008import java.io.InputStream;
009import java.util.Arrays;
010
011import javax.swing.JFileChooser;
012import javax.swing.JOptionPane;
013
014import org.openstreetmap.josm.actions.ExtensionFileFilter;
015import org.openstreetmap.josm.data.gpx.GpxData;
016import org.openstreetmap.josm.gui.MainApplication;
017import org.openstreetmap.josm.gui.io.importexport.GpxImporter;
018import org.openstreetmap.josm.gui.io.importexport.NMEAImporter;
019import org.openstreetmap.josm.gui.io.importexport.RtkLibImporter;
020import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;
021import org.openstreetmap.josm.gui.widgets.FileChooserManager;
022import org.openstreetmap.josm.io.Compression;
023import org.openstreetmap.josm.io.GpxReader;
024import org.openstreetmap.josm.io.IGpxReader;
025import org.openstreetmap.josm.io.nmea.NmeaReader;
026import org.openstreetmap.josm.io.rtklib.RtkLibPosReader;
027import org.openstreetmap.josm.tools.Logging;
028import org.xml.sax.SAXException;
029
030/**
031 * Helper class to select and load "GPX data" (GPX, NMEA, pos) files.
032 * @since 18042
033 */
034public final class GpxDataHelper {
035
036    private GpxDataHelper() {
037        // Hide public constructor
038    }
039
040    /**
041     * Opens a file chooser to let the user select a "GPX data" file and returns it.
042     * @return the file chosen by the user, or {@code null}
043     */
044    public static File chooseGpxDataFile() {
045        ExtensionFileFilter gpxFilter = GpxImporter.getFileFilter();
046        AbstractFileChooser fc = new FileChooserManager(true, null).createFileChooser(false, null,
047                Arrays.asList(gpxFilter, NMEAImporter.FILE_FILTER, RtkLibImporter.FILE_FILTER), gpxFilter, JFileChooser.FILES_ONLY)
048                .openFileChooser();
049        return fc != null ? fc.getSelectedFile() : null;
050    }
051
052    /**
053     * Loads {@link GpxData} from the given file and returns it. Shows message dialog in case of error.
054     * @param file gpx data file, must not be null
055     * @return {@code GpxData} file, or null in case of error
056     */
057    public static GpxData loadGpxData(File file) {
058        GpxData data = null;
059        try (InputStream iStream = Compression.getUncompressedFileInputStream(file)) {
060            IGpxReader reader = GpxImporter.getFileFilter().accept(file) ? new GpxReader(iStream)
061                    : NMEAImporter.FILE_FILTER.accept(file) ? new NmeaReader(iStream)
062                            : new RtkLibPosReader(iStream);
063            reader.parse(false);
064            data = reader.getGpxData();
065            data.storageFile = file;
066        } catch (SAXException ex) {
067            Logging.error(ex);
068            JOptionPane.showMessageDialog(
069                    MainApplication.getMainFrame(),
070                    tr("Error while parsing {0}", file.getName()) + ": " + ex.getMessage(),
071                    tr("Error"),
072                    JOptionPane.ERROR_MESSAGE
073            );
074        } catch (IOException | UnsupportedOperationException ex) {
075            Logging.error(ex);
076            JOptionPane.showMessageDialog(
077                    MainApplication.getMainFrame(),
078                    tr("Could not read \"{0}\"", file.getName()) + '\n' + ex.getMessage(),
079                    tr("Error"),
080                    JOptionPane.ERROR_MESSAGE
081            );
082        }
083        return data;
084    }
085}