001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.layer.gpx;
003
004import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
005import static org.openstreetmap.josm.tools.I18n.tr;
006
007import java.awt.GridBagLayout;
008import java.awt.event.ActionEvent;
009import java.io.File;
010import java.util.ArrayList;
011import java.util.List;
012
013import javax.swing.AbstractAction;
014import javax.swing.JLabel;
015import javax.swing.JOptionPane;
016import javax.swing.JPanel;
017
018import org.openstreetmap.josm.Main;
019import org.openstreetmap.josm.data.gpx.GpxConstants;
020import org.openstreetmap.josm.data.gpx.GpxTrack;
021import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
022import org.openstreetmap.josm.data.gpx.WayPoint;
023import org.openstreetmap.josm.data.osm.DataSet;
024import org.openstreetmap.josm.data.osm.Node;
025import org.openstreetmap.josm.data.osm.Way;
026import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
027import org.openstreetmap.josm.gui.layer.GpxLayer;
028import org.openstreetmap.josm.gui.layer.Layer;
029import org.openstreetmap.josm.gui.layer.OsmDataLayer;
030import org.openstreetmap.josm.gui.layer.markerlayer.Marker;
031import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
032import org.openstreetmap.josm.gui.widgets.UrlLabel;
033import org.openstreetmap.josm.tools.GBC;
034import org.openstreetmap.josm.tools.ImageProvider;
035import org.openstreetmap.josm.tools.date.DateUtils;
036
037/**
038 * An abstract action for a conversion from a {@code T} {@link Layer} to a {@link OsmDataLayer}.
039 * @param <T> the source layer class
040 */
041public abstract class ConvertToDataLayerAction<T extends Layer> extends AbstractAction {
042    protected final transient T layer;
043
044    protected ConvertToDataLayerAction(final T layer) {
045        super(tr("Convert to data layer"), ImageProvider.get("converttoosm"));
046        this.layer = layer;
047        putValue("help", ht("/Action/ConvertToDataLayer"));
048    }
049
050    /**
051     * Converts a {@link GpxLayer} to a {@link OsmDataLayer}.
052     */
053    public static class FromGpxLayer extends ConvertToDataLayerAction<GpxLayer> {
054
055        /**
056         * Creates a new {@code FromGpxLayer}.
057         * @param layer the source layer
058         */
059        public FromGpxLayer(GpxLayer layer) {
060            super(layer);
061        }
062
063        @Override
064        public DataSet convert() {
065            final DataSet ds = new DataSet();
066            for (GpxTrack trk : layer.data.tracks) {
067                for (GpxTrackSegment segment : trk.getSegments()) {
068                    List<Node> nodes = new ArrayList<>();
069                    for (WayPoint p : segment.getWayPoints()) {
070                        Node n = new Node(p.getCoor());
071                        String timestr = p.getString(GpxConstants.PT_TIME);
072                        if (timestr != null) {
073                            n.setTimestamp(DateUtils.fromString(timestr));
074                        }
075                        ds.addPrimitive(n);
076                        nodes.add(n);
077                    }
078                    Way w = new Way();
079                    w.setNodes(nodes);
080                    ds.addPrimitive(w);
081                }
082            }
083            return ds;
084        }
085    }
086
087    /**
088     * Converts a {@link MarkerLayer} to a {@link OsmDataLayer}.
089     */
090    public static class FromMarkerLayer extends ConvertToDataLayerAction<MarkerLayer> {
091
092        /**
093         * Converts a {@link MarkerLayer} to a {@link OsmDataLayer}.
094         * @param layer marker layer
095         */
096        public FromMarkerLayer(MarkerLayer layer) {
097            super(layer);
098        }
099
100        @Override
101        public DataSet convert() {
102            final DataSet ds = new DataSet();
103            for (Marker marker : layer.data) {
104                final Node node = new Node(marker.getCoor());
105                node.put("name", marker.getText());
106                ds.addPrimitive(node);
107            }
108            return ds;
109        }
110    }
111
112    /**
113     * Performs the conversion to a {@link DataSet}.
114     * @return the resulting dataset
115     */
116    public abstract DataSet convert();
117
118    @Override
119    public void actionPerformed(ActionEvent e) {
120        JPanel msg = new JPanel(new GridBagLayout());
121        msg.add(new JLabel(
122                // CHECKSTYLE.OFF: LineLength
123                tr("<html>Upload of unprocessed GPS data as map data is considered harmful.<br>If you want to upload traces, look here:</html>")),
124                // CHECKSTYLE.ON: LineLength
125                GBC.eol());
126        msg.add(new UrlLabel(Main.getOSMWebsite() + "/traces", 2), GBC.eop());
127        if (!ConditionalOptionPaneUtil.showConfirmationDialog("convert_to_data", Main.parent, msg, tr("Warning"),
128                JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, JOptionPane.OK_OPTION)) {
129            return;
130        }
131        final DataSet ds = convert();
132        final OsmDataLayer layer = new OsmDataLayer(ds, tr("Converted from: {0}", this.layer.getName()), null);
133        if (this.layer.getAssociatedFile() != null) {
134            layer.setAssociatedFile(new File(this.layer.getAssociatedFile().getParentFile(), this.layer.getAssociatedFile().getName() + ".osm"));
135        }
136        layer.setUploadDiscouraged(true);
137        Main.main.addLayer(layer);
138        Main.main.removeLayer(this.layer);
139    }
140}