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

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

see #11428 - Overpass Download: use Monospace font for query

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