001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.io.importexport;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.io.File;
007import java.io.IOException;
008import java.io.InputStream;
009
010import javax.swing.JOptionPane;
011import javax.swing.SwingUtilities;
012
013import org.openstreetmap.josm.Main;
014import org.openstreetmap.josm.actions.ExtensionFileFilter;
015import org.openstreetmap.josm.gui.HelpAwareOptionPane;
016import org.openstreetmap.josm.gui.MainApplication;
017import org.openstreetmap.josm.gui.Notification;
018import org.openstreetmap.josm.gui.io.importexport.GpxImporter.GpxImporterData;
019import org.openstreetmap.josm.gui.layer.GpxLayer;
020import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
021import org.openstreetmap.josm.gui.progress.ProgressMonitor;
022import org.openstreetmap.josm.gui.util.GuiHelper;
023import org.openstreetmap.josm.io.Compression;
024import org.openstreetmap.josm.io.nmea.NmeaReader;
025import org.openstreetmap.josm.spi.preferences.Config;
026
027/**
028 * File importer allowing to import NMEA-0183 files (*.nmea/nme/nma/log/txt files).
029 * @since 1637
030 */
031public class NMEAImporter extends FileImporter {
032
033    /**
034     * The NMEA file filter (*.nmea *.nme *.nma *.log *.txt files).
035     */
036    public static final ExtensionFileFilter FILE_FILTER = ExtensionFileFilter.newFilterWithArchiveExtensions(
037            "nmea,nme,nma,log,txt", "nmea", tr("NMEA-0183 Files"), false);
038
039    /**
040     * Constructs a new {@code NMEAImporter}.
041     */
042    public NMEAImporter() {
043        super(FILE_FILTER);
044    }
045
046    @Override
047    public void importData(File file, ProgressMonitor progressMonitor) throws IOException {
048        final String fn = file.getName();
049        try (InputStream fis = Compression.getUncompressedFileInputStream(file)) {
050            final NmeaReader r = new NmeaReader(fis);
051            if (r.getNumberOfCoordinates() > 0) {
052                r.data.storageFile = file;
053                final GpxLayer gpxLayer = new GpxLayer(r.data, fn, true);
054                final File fileFinal = file;
055
056                GuiHelper.runInEDT(() -> {
057                    MainApplication.getLayerManager().addLayer(gpxLayer);
058                    if (Config.getPref().getBoolean("marker.makeautomarkers", true)) {
059                        MarkerLayer ml = new MarkerLayer(r.data, tr("Markers from {0}", fn), fileFinal, gpxLayer);
060                        if (!ml.data.isEmpty()) {
061                            MainApplication.getLayerManager().addLayer(ml);
062                        }
063                    }
064                });
065            }
066            showNmeaInfobox(r.getNumberOfCoordinates() > 0, r);
067        }
068    }
069
070    private static void showNmeaInfobox(boolean success, NmeaReader r) {
071        final StringBuilder msg = new StringBuilder(160).append("<html>")
072           .append(tr("Coordinates imported: {0}", r.getNumberOfCoordinates())).append("<br>")
073           .append(tr("Malformed sentences: {0}", r.getParserMalformed())).append("<br>")
074           .append(tr("Checksum errors: {0}", r.getParserChecksumErrors())).append("<br>");
075        if (!success) {
076            msg.append(tr("Unknown sentences: {0}", r.getParserUnknown())).append("<br>");
077        }
078        msg.append(tr("Zero coordinates: {0}", r.getParserZeroCoordinates()))
079           .append("</html>");
080        if (success) {
081            SwingUtilities.invokeLater(() -> new Notification(
082                    "<h3>" + tr("NMEA import success:") + "</h3>" + msg.toString())
083                    .setIcon(JOptionPane.INFORMATION_MESSAGE)
084                    .show());
085        } else {
086            HelpAwareOptionPane.showMessageDialogInEDT(
087                    Main.parent,
088                    msg.toString(),
089                    tr("NMEA import failure!"),
090                    JOptionPane.ERROR_MESSAGE, null);
091        }
092    }
093
094    /**
095     * Replies the new GPX and marker layers corresponding to the specified NMEA file.
096     * @param is input stream to NMEA 0183 data
097     * @param associatedFile NMEA file
098     * @param gpxLayerName The GPX layer name
099     * @param markerLayerName The marker layer name
100     * @return the new GPX and marker layers corresponding to the specified NMEA file
101     * @throws IOException if an I/O error occurs
102     */
103    public static GpxImporterData loadLayers(InputStream is, final File associatedFile,
104            final String gpxLayerName, String markerLayerName) throws IOException {
105        final NmeaReader r = new NmeaReader(is);
106        final boolean parsedProperly = r.getNumberOfCoordinates() > 0;
107        r.data.storageFile = associatedFile;
108        return GpxImporter.loadLayers(r.data, parsedProperly, gpxLayerName, markerLayerName);
109    }
110}