source: josm/trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/LoadAndZoomHandler.java@ 10446

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

see #13001 - replace calls to Main.main.getCurrentDataSet() by Main.getLayerManager().getEditDataSet()

  • Property svn:eol-style set to native
File size: 13.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io.remotecontrol.handler;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.geom.Area;
7import java.awt.geom.Rectangle2D;
8import java.util.Collection;
9import java.util.Collections;
10import java.util.HashSet;
11import java.util.Set;
12import java.util.concurrent.Future;
13
14import org.openstreetmap.josm.Main;
15import org.openstreetmap.josm.actions.AutoScaleAction;
16import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
17import org.openstreetmap.josm.actions.downloadtasks.DownloadTask;
18import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
19import org.openstreetmap.josm.actions.search.SearchCompiler;
20import org.openstreetmap.josm.data.Bounds;
21import org.openstreetmap.josm.data.coor.LatLon;
22import org.openstreetmap.josm.data.osm.BBox;
23import org.openstreetmap.josm.data.osm.DataSet;
24import org.openstreetmap.josm.data.osm.OsmPrimitive;
25import org.openstreetmap.josm.data.osm.Relation;
26import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
27import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
28import org.openstreetmap.josm.gui.util.GuiHelper;
29import org.openstreetmap.josm.io.remotecontrol.AddTagsDialog;
30import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
31import org.openstreetmap.josm.tools.Utils;
32
33/**
34 * Handler for {@code load_and_zoom} and {@code zoom} requests.
35 * @since 3707
36 */
37public class LoadAndZoomHandler extends RequestHandler {
38
39 /**
40 * The remote control command name used to load data and zoom.
41 */
42 public static final String command = "load_and_zoom";
43
44 /**
45 * The remote control command name used to zoom.
46 */
47 public static final String command2 = "zoom";
48
49 // Mandatory arguments
50 private double minlat;
51 private double maxlat;
52 private double minlon;
53 private double maxlon;
54
55 // Optional argument 'select'
56 private final Set<SimplePrimitiveId> toSelect = new HashSet<>();
57
58 @Override
59 public String getPermissionMessage() {
60 String msg = tr("Remote Control has been asked to load data from the API.") +
61 "<br>" + tr("Bounding box: ") + new BBox(minlon, minlat, maxlon, maxlat).toStringCSV(", ");
62 if (args.containsKey("select") && !toSelect.isEmpty()) {
63 msg += "<br>" + tr("Selection: {0}", toSelect.size());
64 }
65 return msg;
66 }
67
68 @Override
69 public String[] getMandatoryParams() {
70 return new String[] {"bottom", "top", "left", "right"};
71 }
72
73 @Override
74 public String[] getOptionalParams() {
75 return new String[] {"new_layer", "layer_name", "addtags", "select", "zoom_mode", "changeset_comment", "changeset_source", "search"};
76 }
77
78 @Override
79 public String getUsage() {
80 return "download a bounding box from the API, zoom to the downloaded area and optionally select one or more objects";
81 }
82
83 @Override
84 public String[] getUsageExamples() {
85 return getUsageExamples(myCommand);
86 }
87
88 @Override
89 public String[] getUsageExamples(String cmd) {
90 if (command.equals(cmd)) {
91 return new String[] {
92 "/load_and_zoom?addtags=wikipedia:de=Wei%C3%9Fe_Gasse|maxspeed=5&select=way23071688,way23076176,way23076177," +
93 "&left=13.740&right=13.741&top=51.05&bottom=51.049",
94 "/load_and_zoom?left=8.19&right=8.20&top=48.605&bottom=48.590&select=node413602999&new_layer=true"};
95 } else {
96 return new String[] {
97 "/zoom?left=8.19&right=8.20&top=48.605&bottom=48.590&select=node413602999",
98 "/zoom?left=8.19&right=8.20&top=48.605&bottom=48.590&search=highway+OR+railway",
99 };
100 }
101 }
102
103 @Override
104 protected void handleRequest() throws RequestHandlerErrorException {
105 DownloadTask osmTask = new DownloadOsmTask() {
106 {
107 newLayerName = args.get("layer_name");
108 }
109 };
110 try {
111 boolean newLayer = isLoadInNewLayer();
112
113 if (command.equals(myCommand)) {
114 if (!PermissionPrefWithDefault.LOAD_DATA.isAllowed()) {
115 Main.info("RemoteControl: download forbidden by preferences");
116 } else {
117 Area toDownload = null;
118 if (!newLayer) {
119 // find out whether some data has already been downloaded
120 Area present = null;
121 DataSet ds = Main.getLayerManager().getEditDataSet();
122 if (ds != null) {
123 present = ds.getDataSourceArea();
124 }
125 if (present != null && !present.isEmpty()) {
126 toDownload = new Area(new Rectangle2D.Double(minlon, minlat, maxlon-minlon, maxlat-minlat));
127 toDownload.subtract(present);
128 if (!toDownload.isEmpty()) {
129 // the result might not be a rectangle (L shaped etc)
130 Rectangle2D downloadBounds = toDownload.getBounds2D();
131 minlat = downloadBounds.getMinY();
132 minlon = downloadBounds.getMinX();
133 maxlat = downloadBounds.getMaxY();
134 maxlon = downloadBounds.getMaxX();
135 }
136 }
137 }
138 if (toDownload != null && toDownload.isEmpty()) {
139 Main.info("RemoteControl: no download necessary");
140 } else {
141 Future<?> future = osmTask.download(newLayer, new Bounds(minlat, minlon, maxlat, maxlon),
142 null /* let the task manage the progress monitor */);
143 Main.worker.submit(new PostDownloadHandler(osmTask, future));
144 }
145 }
146 }
147 } catch (RuntimeException ex) {
148 Main.warn("RemoteControl: Error parsing load_and_zoom remote control request:");
149 Main.error(ex);
150 throw new RequestHandlerErrorException(ex);
151 }
152
153 /**
154 * deselect objects if parameter addtags given
155 */
156 if (args.containsKey("addtags")) {
157 GuiHelper.executeByMainWorkerInEDT(new Runnable() {
158 @Override
159 public void run() {
160 DataSet ds = Main.getLayerManager().getEditDataSet();
161 if (ds == null) // e.g. download failed
162 return;
163 ds.clearSelection();
164 }
165 });
166 }
167
168 final Collection<OsmPrimitive> forTagAdd = new HashSet<>();
169 final Bounds bbox = new Bounds(minlat, minlon, maxlat, maxlon);
170 if (args.containsKey("select") && PermissionPrefWithDefault.CHANGE_SELECTION.isAllowed()) {
171 // select objects after downloading, zoom to selection.
172 GuiHelper.executeByMainWorkerInEDT(new Runnable() {
173 @Override
174 public void run() {
175 Set<OsmPrimitive> newSel = new HashSet<>();
176 DataSet ds = Main.getLayerManager().getEditDataSet();
177 if (ds == null) // e.g. download failed
178 return;
179 for (SimplePrimitiveId id : toSelect) {
180 final OsmPrimitive p = ds.getPrimitiveById(id);
181 if (p != null) {
182 newSel.add(p);
183 forTagAdd.add(p);
184 }
185 }
186 toSelect.clear();
187 ds.setSelected(newSel);
188 zoom(newSel, bbox);
189 if (Main.isDisplayingMapView() && Main.map.relationListDialog != null) {
190 Main.map.relationListDialog.selectRelations(null); // unselect all relations to fix #7342
191 Main.map.relationListDialog.dataChanged(null);
192 Main.map.relationListDialog.selectRelations(Utils.filteredCollection(newSel, Relation.class));
193 }
194 }
195 });
196 } else if (args.containsKey("search") && PermissionPrefWithDefault.CHANGE_SELECTION.isAllowed()) {
197 try {
198 final SearchCompiler.Match search = SearchCompiler.compile(args.get("search"));
199 Main.worker.submit(new Runnable() {
200 @Override
201 public void run() {
202 final DataSet ds = Main.getLayerManager().getEditDataSet();
203 final Collection<OsmPrimitive> filteredPrimitives = Utils.filter(ds.allPrimitives(), search);
204 ds.setSelected(filteredPrimitives);
205 forTagAdd.addAll(filteredPrimitives);
206 zoom(filteredPrimitives, bbox);
207 }
208 });
209 } catch (SearchCompiler.ParseError ex) {
210 Main.error(ex);
211 throw new RequestHandlerErrorException(ex);
212 }
213 } else {
214 // after downloading, zoom to downloaded area.
215 zoom(Collections.<OsmPrimitive>emptySet(), bbox);
216 }
217
218 // add changeset tags after download if necessary
219 if (args.containsKey("changeset_comment") || args.containsKey("changeset_source")) {
220 Main.worker.submit(new Runnable() {
221 @Override
222 public void run() {
223 if (Main.getLayerManager().getEditDataSet() != null) {
224 if (args.containsKey("changeset_comment")) {
225 Main.getLayerManager().getEditDataSet().addChangeSetTag("comment", args.get("changeset_comment"));
226 }
227 if (args.containsKey("changeset_source")) {
228 Main.getLayerManager().getEditDataSet().addChangeSetTag("source", args.get("changeset_source"));
229 }
230 }
231 }
232 });
233 }
234
235 AddTagsDialog.addTags(args, sender, forTagAdd);
236 }
237
238 protected void zoom(Collection<OsmPrimitive> primitives, final Bounds bbox) {
239 if (!PermissionPrefWithDefault.CHANGE_VIEWPORT.isAllowed()) {
240 return;
241 }
242 // zoom_mode=(download|selection), defaults to selection
243 if (!"download".equals(args.get("zoom_mode")) && !primitives.isEmpty()) {
244 AutoScaleAction.autoScale("selection");
245 } else if (Main.isDisplayingMapView()) {
246 // make sure this isn't called unless there *is* a MapView
247 GuiHelper.executeByMainWorkerInEDT(new Runnable() {
248 @Override
249 public void run() {
250 BoundingXYVisitor bbox1 = new BoundingXYVisitor();
251 bbox1.visit(bbox);
252 Main.map.mapView.zoomTo(bbox1);
253 }
254 });
255 }
256 }
257
258 @Override
259 public PermissionPrefWithDefault getPermissionPref() {
260 return null;
261 }
262
263 @Override
264 protected void validateRequest() throws RequestHandlerBadRequestException {
265 // Process mandatory arguments
266 minlat = 0;
267 maxlat = 0;
268 minlon = 0;
269 maxlon = 0;
270 try {
271 minlat = LatLon.roundToOsmPrecision(Double.parseDouble(args != null ? args.get("bottom") : ""));
272 maxlat = LatLon.roundToOsmPrecision(Double.parseDouble(args != null ? args.get("top") : ""));
273 minlon = LatLon.roundToOsmPrecision(Double.parseDouble(args != null ? args.get("left") : ""));
274 maxlon = LatLon.roundToOsmPrecision(Double.parseDouble(args != null ? args.get("right") : ""));
275 } catch (NumberFormatException e) {
276 throw new RequestHandlerBadRequestException("NumberFormatException ("+e.getMessage()+')', e);
277 }
278
279 // Current API 0.6 check: "The latitudes must be between -90 and 90"
280 if (!LatLon.isValidLat(minlat) || !LatLon.isValidLat(maxlat)) {
281 throw new RequestHandlerBadRequestException(tr("The latitudes must be between {0} and {1}", -90d, 90d));
282 }
283 // Current API 0.6 check: "longitudes between -180 and 180"
284 if (!LatLon.isValidLon(minlon) || !LatLon.isValidLon(maxlon)) {
285 throw new RequestHandlerBadRequestException(tr("The longitudes must be between {0} and {1}", -180d, 180d));
286 }
287 // Current API 0.6 check: "the minima must be less than the maxima"
288 if (minlat > maxlat || minlon > maxlon) {
289 throw new RequestHandlerBadRequestException(tr("The minima must be less than the maxima"));
290 }
291
292 // Process optional argument 'select'
293 if (args != null && args.containsKey("select")) {
294 toSelect.clear();
295 for (String item : args.get("select").split(",")) {
296 try {
297 toSelect.add(SimplePrimitiveId.fromString(item));
298 } catch (IllegalArgumentException ex) {
299 Main.warn("RemoteControl: invalid selection '" + item + "' ignored");
300 }
301 }
302 }
303 }
304}
Note: See TracBrowser for help on using the repository browser.