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;
009import java.util.Objects;
010
011import javax.swing.JOptionPane;
012import javax.swing.SwingUtilities;
013
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.layer.GpxLayer;
019import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
020import org.openstreetmap.josm.gui.progress.ProgressMonitor;
021import org.openstreetmap.josm.gui.util.GuiHelper;
022import org.openstreetmap.josm.io.Compression;
023import org.openstreetmap.josm.io.IGpxReader;
024import org.openstreetmap.josm.spi.preferences.Config;
025import org.xml.sax.SAXException;
026
027/**
028 * Abstraction of {@link NMEAImporter}, {@link OziWptImporter} and {@link RtkLibImporter}.
029 * @param <T> GPX reader type
030 * @since 18179
031 */
032public abstract class GpxLikeImporter<T extends IGpxReader> extends FileImporter {
033
034    private Class<T> klass;
035
036    /**
037     * Constructs a new {@code GpxLikeImporter}.
038     * @param filter The extension file filter
039     * @param klass type class
040     */
041    protected GpxLikeImporter(ExtensionFileFilter filter, Class<T> klass) {
042        super(Objects.requireNonNull(filter));
043        this.klass = Objects.requireNonNull(klass);
044    }
045
046    @Override
047    public final void importData(File file, ProgressMonitor progressMonitor) throws IOException {
048        final String fn = file.getName();
049        try (InputStream fis = Compression.getUncompressedFileInputStream(file)) {
050            final T r = buildAndParse(fis, klass);
051            if (r.getNumberOfCoordinates() > 0) {
052                r.getGpxData().storageFile = file;
053                final GpxLayer gpxLayer = new GpxLayer(r.getGpxData(), 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.getGpxData(), tr("Markers from {0}", fn), fileFinal, gpxLayer);
060                        if (!ml.data.isEmpty()) {
061                            MainApplication.getLayerManager().addLayer(ml);
062                        }
063                    }
064                });
065            }
066            showInfobox(r.getNumberOfCoordinates() > 0, r);
067        }
068    }
069
070    protected final void showInfobox(boolean success, T r) {
071        final StringBuilder msg = new StringBuilder(160).append("<html>")
072           .append(tr("Coordinates imported: {0}", r.getNumberOfCoordinates()));
073        appendInfoboxContent(msg, success, r);
074        msg.append("</html>");
075        if (success) {
076            SwingUtilities.invokeLater(() -> new Notification(
077                    "<h3>" + tr("Import success:") + "</h3>" + msg.toString())
078                    .setIcon(JOptionPane.INFORMATION_MESSAGE)
079                    .show());
080        } else {
081            HelpAwareOptionPane.showMessageDialogInEDT(
082                    MainApplication.getMainFrame(),
083                    msg.toString(),
084                    tr("Import failure!"),
085                    JOptionPane.ERROR_MESSAGE, null);
086        }
087    }
088
089    protected void appendInfoboxContent(StringBuilder msg, boolean success, T r) {
090        // Complete if needed
091    }
092
093    protected static final <T extends IGpxReader> T buildAndParse(InputStream fis, Class<T> klass) throws IOException {
094        try {
095            final T r = klass.getConstructor(InputStream.class).newInstance(fis);
096            r.parse(true);
097            return r;
098        } catch (SAXException | ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
099            throw new IOException(e);
100        }
101    }
102}