source: josm/trunk/src/org/openstreetmap/josm/actions/OverpassDownloadAction.java@ 8718

Last change on this file since 8718 was 8718, checked in by simon04, 9 years ago

Fix checkstyle warnings

File size: 10.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.Component;
8import java.awt.event.ActionEvent;
9import java.awt.event.KeyEvent;
10import java.io.UnsupportedEncodingException;
11import java.net.URLEncoder;
12import java.util.ArrayList;
13import java.util.Arrays;
14import java.util.Collections;
15import java.util.concurrent.Future;
16
17import javax.swing.AbstractAction;
18import javax.swing.JButton;
19import javax.swing.JLabel;
20import javax.swing.JOptionPane;
21import javax.swing.JPanel;
22import javax.swing.JScrollPane;
23
24import org.openstreetmap.josm.Main;
25import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
26import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
27import org.openstreetmap.josm.data.Bounds;
28import org.openstreetmap.josm.data.DataSource;
29import org.openstreetmap.josm.data.osm.DataSet;
30import org.openstreetmap.josm.data.preferences.CollectionProperty;
31import org.openstreetmap.josm.data.preferences.StringProperty;
32import org.openstreetmap.josm.gui.HelpAwareOptionPane;
33import org.openstreetmap.josm.gui.download.DownloadDialog;
34import org.openstreetmap.josm.gui.progress.ProgressMonitor;
35import org.openstreetmap.josm.gui.util.GuiHelper;
36import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
37import org.openstreetmap.josm.gui.widgets.JosmTextArea;
38import org.openstreetmap.josm.io.BoundingBoxDownloader;
39import org.openstreetmap.josm.io.OsmTransferException;
40import org.openstreetmap.josm.tools.GBC;
41import org.openstreetmap.josm.tools.Shortcut;
42import org.openstreetmap.josm.tools.Utils;
43
44/**
45 * Download map data from Overpass API server.
46 * @since 8684
47 */
48public class OverpassDownloadAction extends JosmAction {
49
50 /**
51 * Constructs a new {@code OverpassDownloadAction}.
52 */
53 public OverpassDownloadAction() {
54 super(tr("Download from Overpass API ..."), "download-overpass", tr("Download map data from Overpass API server."),
55 Shortcut.registerShortcut("file:download-overpass", tr("File: {0}", tr("Download from Overpass API ...")), KeyEvent.VK_DOWN, Shortcut.ALT_SHIFT),
56 true, "overpassdownload/download", true);
57 putValue("help", ht("/Action/OverpassDownload"));
58 }
59
60 @Override
61 public void actionPerformed(ActionEvent e) {
62 OverpassDownloadDialog dialog = OverpassDownloadDialog.getInstance();
63 dialog.restoreSettings();
64 dialog.setVisible(true);
65 if (!dialog.isCanceled()) {
66 dialog.rememberSettings();
67 Bounds area = dialog.getSelectedDownloadArea();
68 DownloadOsmTask task = new DownloadOsmTask();
69 Future<?> future = task.download(
70 new OverpassDownloadReader(area, dialog.getOverpassServer(), dialog.getOverpassQuery()),
71 dialog.isNewLayerRequired(), area, null);
72 Main.worker.submit(new PostDownloadHandler(task, future));
73 }
74 }
75
76 static final class OverpassDownloadDialog extends DownloadDialog {
77
78 protected HistoryComboBox overpassServer;
79 protected HistoryComboBox overpassWizard;
80 protected JosmTextArea overpassQuery;
81 private static OverpassDownloadDialog instance;
82 static final StringProperty OVERPASS_SERVER = new StringProperty("download.overpass.server", "http://overpass-api.de/api/");
83 static final CollectionProperty OVERPASS_SERVER_HISTORY = new CollectionProperty("download.overpass.servers",
84 Arrays.asList("http://overpass-api.de/api/", "http://overpass.osm.rambler.ru/cgi/"));
85 static final CollectionProperty OVERPASS_WIZARD_HISTORY = new CollectionProperty("download.overpass.wizard", new ArrayList<String>());
86
87 private OverpassDownloadDialog(Component parent) {
88 super(parent, ht("/Action/OverpassDownload"));
89 cbDownloadOsmData.setEnabled(false);
90 cbDownloadOsmData.setSelected(false);
91 cbDownloadGpxData.setVisible(false);
92 cbDownloadNotes.setVisible(false);
93 cbStartup.setVisible(false);
94 }
95
96 public static OverpassDownloadDialog getInstance() {
97 if (instance == null) {
98 instance = new OverpassDownloadDialog(Main.parent);
99 }
100 return instance;
101 }
102
103 @Override
104 protected void buildMainPanelAboveDownloadSelections(JPanel pnl) {
105
106 pnl.add(new JLabel(), GBC.eol()); // needed for the invisible checkboxes cbDownloadGpxData, cbDownloadNotes
107
108 final String tooltip = tr("Builds an Overpass query using the Overpass Turbo query wizard");
109 overpassWizard = new HistoryComboBox();
110 overpassWizard.setToolTipText(tooltip);
111 final JButton buildQuery = new JButton(tr("Build query"));
112 buildQuery.addActionListener(new AbstractAction() {
113 @Override
114 public void actionPerformed(ActionEvent e) {
115 final String overpassWizardText = overpassWizard.getText();
116 try {
117 overpassQuery.setText(OverpassTurboQueryWizard.getInstance().constructQuery(overpassWizardText));
118 } catch (OverpassTurboQueryWizard.ParseException ex) {
119 HelpAwareOptionPane.showOptionDialog(
120 Main.parent,
121 tr("<html>The Overpass wizard could not parse the following query:"
122 + Utils.joinAsHtmlUnorderedList(Collections.singleton(overpassWizardText))),
123 tr("Parse error"),
124 JOptionPane.ERROR_MESSAGE,
125 null
126 );
127 }
128 }
129 });
130 buildQuery.setToolTipText(tooltip);
131 pnl.add(buildQuery, GBC.std().insets(5, 5, 5, 5));
132 pnl.add(overpassWizard, GBC.eol().fill(GBC.HORIZONTAL));
133
134 overpassQuery = new JosmTextArea("[timeout:15];", 8, 80);
135 overpassQuery.setFont(GuiHelper.getMonospacedFont(overpassQuery));
136 JScrollPane scrollPane = new JScrollPane(overpassQuery);
137 pnl.add(new JLabel(tr("Overpass query: ")), GBC.std().insets(5, 5, 5, 5));
138 GBC gbc = GBC.eol().fill(GBC.HORIZONTAL);
139 gbc.ipady = 200;
140 pnl.add(scrollPane, gbc);
141
142 overpassServer = new HistoryComboBox();
143 pnl.add(new JLabel(tr("Overpass server: ")), GBC.std().insets(5, 5, 5, 5));
144 pnl.add(overpassServer, GBC.eol().fill(GBC.HORIZONTAL));
145
146 }
147
148 public String getOverpassServer() {
149 return overpassServer.getText();
150 }
151
152 public String getOverpassQuery() {
153 return overpassQuery.getText();
154 }
155
156 @Override
157 public void restoreSettings() {
158 super.restoreSettings();
159 overpassServer.setPossibleItems(OVERPASS_SERVER_HISTORY.get());
160 overpassServer.setText(OVERPASS_SERVER.get());
161 overpassWizard.setPossibleItems(OVERPASS_WIZARD_HISTORY.get());
162 }
163
164 @Override
165 public void rememberSettings() {
166 super.rememberSettings();
167 overpassWizard.addCurrentItemToHistory();
168 OVERPASS_SERVER.put(getOverpassServer());
169 OVERPASS_SERVER_HISTORY.put(overpassServer.getHistory());
170 OVERPASS_WIZARD_HISTORY.put(overpassWizard.getHistory());
171 }
172
173 }
174
175 static class OverpassDownloadReader extends BoundingBoxDownloader {
176
177 final String overpassServer;
178 final String overpassQuery;
179
180 public OverpassDownloadReader(Bounds downloadArea, String overpassServer, String overpassQuery) {
181 super(downloadArea);
182 this.overpassServer = overpassServer;
183 this.overpassQuery = overpassQuery.trim();
184 }
185
186 @Override
187 protected String getBaseUrl() {
188 return overpassServer;
189 }
190
191 @Override
192 protected String getRequestForBbox(double lon1, double lat1, double lon2, double lat2) {
193 if (overpassQuery.isEmpty())
194 return super.getRequestForBbox(lon1, lat1, lon2, lat2);
195 else {
196 String realQuery = completeOverpassQuery(overpassQuery);
197 try {
198 return "interpreter?data=" + URLEncoder.encode(realQuery, "UTF-8")
199 + "&bbox=" + lon1 + "," + lat1 + "," + lon2 + "," + lat2;
200 } catch (UnsupportedEncodingException e) {
201 throw new IllegalStateException();
202 }
203 }
204 }
205
206 private String completeOverpassQuery(String query) {
207 int firstColon = query.indexOf(";");
208 if (firstColon == -1) {
209 return "[bbox];" + query;
210 }
211 int bboxPos = query.indexOf("[bbox");
212 if (bboxPos > -1 && bboxPos < firstColon) {
213 return query;
214 }
215
216 int bracketCount = 0;
217 int pos = 0;
218 for (; pos < firstColon; ++pos) {
219 if (query.charAt(pos) == '[')
220 ++bracketCount;
221 else if (query.charAt(pos) == '[')
222 --bracketCount;
223 else if (bracketCount == 0) {
224 if (!Character.isWhitespace(query.charAt(pos)))
225 break;
226 }
227 }
228
229 if (pos < firstColon) {
230 // We start with a statement, not with declarations
231 return "[bbox];" + query;
232 }
233
234 // We start with declarations. Add just one more declaration in this case.
235 return "[bbox]" + query;
236 }
237
238 @Override
239 public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
240
241 DataSet ds = super.parseOsm(progressMonitor);
242
243 // add bounds if necessary (note that Overpass API does not return bounds in the response XML)
244 if (ds != null && ds.dataSources.isEmpty()) {
245 if (crosses180th) {
246 Bounds bounds = new Bounds(lat1, lon1, lat2, 180.0);
247 DataSource src = new DataSource(bounds, getBaseUrl());
248 ds.dataSources.add(src);
249
250 bounds = new Bounds(lat1, -180.0, lat2, lon2);
251 src = new DataSource(bounds, getBaseUrl());
252 ds.dataSources.add(src);
253 } else {
254 Bounds bounds = new Bounds(lat1, lon1, lat2, lon2);
255 DataSource src = new DataSource(bounds, getBaseUrl());
256 ds.dataSources.add(src);
257 }
258 }
259
260 return ds;
261 }
262 }
263}
Note: See TracBrowser for help on using the repository browser.