001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.io;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.io.File;
007    import java.io.FileInputStream;
008    import java.io.IOException;
009    import java.io.InputStream;
010    import java.util.zip.GZIPInputStream;
011    
012    import javax.swing.JOptionPane;
013    
014    import org.openstreetmap.josm.Main;
015    import org.openstreetmap.josm.actions.ExtensionFileFilter;
016    import org.openstreetmap.josm.gui.layer.GpxLayer;
017    import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
018    import org.openstreetmap.josm.gui.progress.ProgressMonitor;
019    import org.openstreetmap.josm.gui.util.GuiHelper;
020    import org.xml.sax.SAXException;
021    
022    public class GpxImporter extends FileImporter {
023    
024        public static final ExtensionFileFilter FILE_FILTER = new ExtensionFileFilter(
025                "gpx,gpx.gz", "gpx", tr("GPX Files") + " (*.gpx *.gpx.gz)");
026        
027        protected static class GpxImporterData {
028            public GpxLayer gpxLayer;
029            public MarkerLayer markerLayer;
030            public Runnable postLayerTask;
031        }
032    
033        public GpxImporter() {
034            super(FILE_FILTER);
035        }
036    
037        @Override public void importData(File file, ProgressMonitor progressMonitor) throws IOException {
038            InputStream is;
039            if (file.getName().endsWith(".gpx.gz")) {
040                is = new GZIPInputStream(new FileInputStream(file));
041            } else {
042                is = new FileInputStream(file);
043            }
044            String fileName = file.getName();
045            final GpxImporterData data = loadLayers(is, file, fileName, tr("Markers from {0}", fileName), progressMonitor);
046    
047            // FIXME: remove UI stuff from the IO subsystem
048            GuiHelper.runInEDT(new Runnable() {
049                public void run() {
050                    if (data.markerLayer != null) {
051                        Main.main.addLayer(data.markerLayer);
052                    }
053                    if (data.gpxLayer != null) {
054                        Main.main.addLayer(data.gpxLayer);
055                    }
056                    data.postLayerTask.run();
057                }
058            });
059        }
060    
061        public GpxImporterData loadLayers(InputStream is, final File associatedFile,
062                final String gpxLayerName, String markerLayerName, ProgressMonitor progressMonitor) throws IOException {
063            final GpxImporterData data = new GpxImporterData();
064            try {
065                final GpxReader r = new GpxReader(is);
066                final boolean parsedProperly = r.parse(true);
067                r.data.storageFile = associatedFile;
068                if (r.data.hasRoutePoints() || r.data.hasTrackPoints()) {
069                    data.gpxLayer = new GpxLayer(r.data, gpxLayerName, associatedFile != null);
070                }
071                if (Main.pref.getBoolean("marker.makeautomarkers", true) && !r.data.waypoints.isEmpty()) {
072                    data.markerLayer = new MarkerLayer(r.data, markerLayerName, associatedFile, data.gpxLayer, false);
073                    if (data.markerLayer.data.size() == 0) {
074                        data.markerLayer = null;
075                    }
076                }
077                data.postLayerTask = new Runnable() {
078                    @Override
079                    public void run() {
080                        if (data.markerLayer != null) {
081                            data.markerLayer.addMouseHandler();
082                        }
083                        if (!parsedProperly) {
084                            String msg;
085                            if (associatedFile == null) {
086                                msg = tr("Error occurred while parsing gpx data for layer ''{0}''. Only a part of the file will be available.",
087                                        gpxLayerName);
088                            } else {
089                                msg = tr("Error occurred while parsing gpx file ''{0}''. Only a part of the file will be available.",
090                                        associatedFile.getPath());
091                            }
092                            JOptionPane.showMessageDialog(null, msg);
093                        }
094                    }
095                };
096            } catch (SAXException e) {
097                e.printStackTrace();
098                throw new IOException(tr("Parsing data for layer ''{0}'' failed", gpxLayerName));
099            }
100            return data;
101        }
102    }