source: josm/trunk/src/org/openstreetmap/josm/gui/layer/gpx/ConvertToDataLayerAction.java@ 11486

Last change on this file since 11486 was 11486, checked in by Don-vip, 8 years ago

fix #14275 - robustness against invalid timestamps in GPX files

  • Property svn:eol-style set to native
File size: 6.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.layer.gpx;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.GridBagLayout;
8import java.awt.event.ActionEvent;
9import java.io.File;
10import java.util.ArrayList;
11import java.util.Arrays;
12import java.util.Collection;
13import java.util.Iterator;
14import java.util.List;
15import java.util.Optional;
16
17import javax.swing.AbstractAction;
18import javax.swing.JLabel;
19import javax.swing.JOptionPane;
20import javax.swing.JPanel;
21
22import org.openstreetmap.josm.Main;
23import org.openstreetmap.josm.data.gpx.GpxConstants;
24import org.openstreetmap.josm.data.gpx.GpxTrack;
25import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
26import org.openstreetmap.josm.data.gpx.WayPoint;
27import org.openstreetmap.josm.data.osm.DataSet;
28import org.openstreetmap.josm.data.osm.Node;
29import org.openstreetmap.josm.data.osm.Way;
30import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
31import org.openstreetmap.josm.gui.layer.GpxLayer;
32import org.openstreetmap.josm.gui.layer.Layer;
33import org.openstreetmap.josm.gui.layer.OsmDataLayer;
34import org.openstreetmap.josm.gui.layer.markerlayer.Marker;
35import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
36import org.openstreetmap.josm.gui.widgets.UrlLabel;
37import org.openstreetmap.josm.tools.GBC;
38import org.openstreetmap.josm.tools.ImageProvider;
39import org.openstreetmap.josm.tools.UncheckedParseException;
40import org.openstreetmap.josm.tools.date.DateUtils;
41
42/**
43 * An abstract action for a conversion from a {@code T} {@link Layer} to a {@link OsmDataLayer}.
44 * @param <T> the source layer class
45 */
46public abstract class ConvertToDataLayerAction<T extends Layer> extends AbstractAction {
47 /** source layer */
48 protected final transient T layer;
49
50 /**
51 * Constructs a new {@code ConvertToDataLayerAction}
52 * @param layer source layer
53 */
54 protected ConvertToDataLayerAction(final T layer) {
55 super(tr("Convert to data layer"), ImageProvider.get("converttoosm"));
56 this.layer = layer;
57 putValue("help", ht("/Action/ConvertToDataLayer"));
58 }
59
60 /**
61 * Converts a {@link GpxLayer} to a {@link OsmDataLayer}.
62 */
63 public static class FromGpxLayer extends ConvertToDataLayerAction<GpxLayer> {
64
65 /**
66 * Creates a new {@code FromGpxLayer}.
67 * @param layer the source layer
68 */
69 public FromGpxLayer(GpxLayer layer) {
70 super(layer);
71 }
72
73 @Override
74 public DataSet convert() {
75 final DataSet ds = new DataSet();
76 for (GpxTrack trk : layer.data.tracks) {
77 for (GpxTrackSegment segment : trk.getSegments()) {
78 List<Node> nodes = new ArrayList<>();
79 for (WayPoint p : segment.getWayPoints()) {
80 Node n = new Node(p.getCoor());
81 String timestr = p.getString(GpxConstants.PT_TIME);
82 if (timestr != null) {
83 try {
84 n.setTimestamp(DateUtils.fromString(timestr));
85 } catch (UncheckedParseException e) {
86 Main.warn(e, false);
87 }
88 }
89 ds.addPrimitive(n);
90 nodes.add(n);
91 }
92 Way w = new Way();
93 w.setNodes(nodes);
94 ds.addPrimitive(w);
95 }
96 }
97 return ds;
98 }
99 }
100
101 /**
102 * Converts a {@link MarkerLayer} to a {@link OsmDataLayer}.
103 */
104 public static class FromMarkerLayer extends ConvertToDataLayerAction<MarkerLayer> {
105
106 /**
107 * Converts a {@link MarkerLayer} to a {@link OsmDataLayer}.
108 * @param layer marker layer
109 */
110 public FromMarkerLayer(MarkerLayer layer) {
111 super(layer);
112 }
113
114 @Override
115 public DataSet convert() {
116 final DataSet ds = new DataSet();
117 for (Marker marker : layer.data) {
118 final Node node = new Node(marker.getCoor());
119 final Collection<String> mapping = Main.pref.getCollection("gpx.to-osm-mapping", Arrays.asList(
120 GpxConstants.GPX_NAME, "name",
121 GpxConstants.GPX_DESC, "description",
122 GpxConstants.GPX_CMT, "note",
123 GpxConstants.GPX_SRC, "source",
124 GpxConstants.PT_SYM, "gpxicon"));
125 if (mapping.size() % 2 == 0) {
126 final Iterator<String> it = mapping.iterator();
127 while (it.hasNext()) {
128 final String gpxKey = it.next();
129 final String osmKey = it.next();
130 Optional.ofNullable(marker.getTemplateValue(gpxKey, false))
131 .map(String::valueOf)
132 .ifPresent(s -> node.put(osmKey, s));
133 }
134 } else {
135 Main.warn("Invalid gpx.to-osm-mapping Einstein setting: expecting even number of entries");
136 }
137 ds.addPrimitive(node);
138 }
139 return ds;
140 }
141 }
142
143 /**
144 * Performs the conversion to a {@link DataSet}.
145 * @return the resulting dataset
146 */
147 public abstract DataSet convert();
148
149 @Override
150 public void actionPerformed(ActionEvent e) {
151 JPanel msg = new JPanel(new GridBagLayout());
152 msg.add(new JLabel(
153 // CHECKSTYLE.OFF: LineLength
154 tr("<html>Upload of unprocessed GPS data as map data is considered harmful.<br>If you want to upload traces, look here:</html>")),
155 // CHECKSTYLE.ON: LineLength
156 GBC.eol());
157 msg.add(new UrlLabel(Main.getOSMWebsite() + "/traces", 2), GBC.eop());
158 if (!ConditionalOptionPaneUtil.showConfirmationDialog("convert_to_data", Main.parent, msg, tr("Warning"),
159 JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, JOptionPane.OK_OPTION)) {
160 return;
161 }
162 final DataSet ds = convert();
163 final OsmDataLayer osmLayer = new OsmDataLayer(ds, tr("Converted from: {0}", layer.getName()), null);
164 if (layer.getAssociatedFile() != null) {
165 osmLayer.setAssociatedFile(new File(layer.getAssociatedFile().getParentFile(), layer.getAssociatedFile().getName() + ".osm"));
166 }
167 osmLayer.setUploadDiscouraged(true);
168 Main.getLayerManager().addLayer(osmLayer);
169 Main.getLayerManager().removeLayer(layer);
170 }
171}
Note: See TracBrowser for help on using the repository browser.