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; 026import org.xml.sax.SAXException; 027 028/** 029 * File importer allowing to import NMEA-0183 files (*.nmea/nme/nma/log/txt files). 030 * @since 1637 031 */ 032public class NMEAImporter extends FileImporter { 033 034 /** 035 * The NMEA file filter (*.nmea *.nme *.nma *.log *.txt files). 036 */ 037 public static final ExtensionFileFilter FILE_FILTER = ExtensionFileFilter.newFilterWithArchiveExtensions( 038 "nmea,nme,nma,log,txt", "nmea", tr("NMEA-0183 Files"), false); 039 040 /** 041 * Constructs a new {@code NMEAImporter}. 042 */ 043 public NMEAImporter() { 044 super(FILE_FILTER); 045 } 046 047 @Override 048 public void importData(File file, ProgressMonitor progressMonitor) throws IOException { 049 final String fn = file.getName(); 050 try (InputStream fis = Compression.getUncompressedFileInputStream(file)) { 051 final NmeaReader r = buildAndParse(fis); 052 if (r.getNumberOfCoordinates() > 0) { 053 r.getGpxData().storageFile = file; 054 final GpxLayer gpxLayer = new GpxLayer(r.getGpxData(), fn, true); 055 final File fileFinal = file; 056 057 GuiHelper.runInEDT(() -> { 058 MainApplication.getLayerManager().addLayer(gpxLayer); 059 if (Config.getPref().getBoolean("marker.makeautomarkers", true)) { 060 MarkerLayer ml = new MarkerLayer(r.getGpxData(), tr("Markers from {0}", fn), fileFinal, gpxLayer); 061 if (!ml.data.isEmpty()) { 062 MainApplication.getLayerManager().addLayer(ml); 063 } 064 } 065 }); 066 } 067 showNmeaInfobox(r.getNumberOfCoordinates() > 0, r); 068 } 069 } 070 071 private static void showNmeaInfobox(boolean success, NmeaReader r) { 072 final StringBuilder msg = new StringBuilder(160).append("<html>") 073 .append(tr("Coordinates imported: {0}", r.getNumberOfCoordinates())).append("<br>") 074 .append(tr("Malformed sentences: {0}", r.getParserMalformed())).append("<br>") 075 .append(tr("Checksum errors: {0}", r.getParserChecksumErrors())).append("<br>"); 076 if (!success) { 077 msg.append(tr("Unknown sentences: {0}", r.getParserUnknown())).append("<br>"); 078 } 079 msg.append(tr("Zero coordinates: {0}", r.getParserZeroCoordinates())) 080 .append("</html>"); 081 if (success) { 082 SwingUtilities.invokeLater(() -> new Notification( 083 "<h3>" + tr("NMEA import success:") + "</h3>" + msg.toString()) 084 .setIcon(JOptionPane.INFORMATION_MESSAGE) 085 .show()); 086 } else { 087 HelpAwareOptionPane.showMessageDialogInEDT( 088 Main.parent, 089 msg.toString(), 090 tr("NMEA import failure!"), 091 JOptionPane.ERROR_MESSAGE, null); 092 } 093 } 094 095 /** 096 * Replies the new GPX and marker layers corresponding to the specified NMEA file. 097 * @param is input stream to NMEA 0183 data 098 * @param associatedFile NMEA file 099 * @param gpxLayerName The GPX layer name 100 * @param markerLayerName The marker layer name 101 * @return the new GPX and marker layers corresponding to the specified NMEA file 102 * @throws IOException if an I/O error occurs 103 */ 104 public static GpxImporterData loadLayers(InputStream is, final File associatedFile, 105 final String gpxLayerName, String markerLayerName) throws IOException { 106 final NmeaReader r = buildAndParse(is); 107 final boolean parsedProperly = r.getNumberOfCoordinates() > 0; 108 r.getGpxData().storageFile = associatedFile; 109 return GpxImporter.loadLayers(r.getGpxData(), parsedProperly, gpxLayerName, markerLayerName); 110 } 111 112 static NmeaReader buildAndParse(InputStream fis) throws IOException { 113 final NmeaReader r = new NmeaReader(fis); 114 try { 115 r.parse(true); 116 } catch (SAXException e) { 117 throw new IOException(e); 118 } 119 return r; 120 } 121}