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

Last change on this file since 5876 was 5876, checked in by akks, 11 years ago

Remote control: allow adding tags without confirmation for current session (add_tags), see #8612
added parsing of request headers and detecting request sender by IP and "referer" HTTP header

  • Property svn:eol-style set to native
File size: 10.3 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.HashSet;
9import java.util.Set;
10import java.util.concurrent.Future;
11
12import org.openstreetmap.josm.Main;
13import org.openstreetmap.josm.actions.AutoScaleAction;
14import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
15import org.openstreetmap.josm.actions.downloadtasks.DownloadTask;
16import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
17import org.openstreetmap.josm.data.Bounds;
18import org.openstreetmap.josm.data.coor.LatLon;
19import org.openstreetmap.josm.data.osm.BBox;
20import org.openstreetmap.josm.data.osm.DataSet;
21import org.openstreetmap.josm.data.osm.Node;
22import org.openstreetmap.josm.data.osm.OsmPrimitive;
23import org.openstreetmap.josm.data.osm.Relation;
24import org.openstreetmap.josm.data.osm.Way;
25import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
26import org.openstreetmap.josm.gui.util.GuiHelper;
27import org.openstreetmap.josm.io.remotecontrol.AddTagsDialog;
28import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
29import org.openstreetmap.josm.tools.Utils;
30
31/**
32 * Handler for load_and_zoom request.
33 */
34public class LoadAndZoomHandler extends RequestHandler
35{
36 /**
37 * The remote control command name used to load data and zoom.
38 */
39 public static final String command = "load_and_zoom";
40
41 /**
42 * The remote control command name used to zoom.
43 */
44 public static final String command2 = "zoom";
45
46 // Mandatory arguments
47 private double minlat;
48 private double maxlat;
49 private double minlon;
50 private double maxlon;
51
52 // Optional argument 'select'
53 private final Set<Long> ways = new HashSet<Long>();
54 private final Set<Long> nodes = new HashSet<Long>();
55 private final Set<Long> relations = new HashSet<Long>();
56
57 @Override
58 public String getPermissionMessage()
59 {
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") && ways.size()+nodes.size()+relations.size() > 0) {
63 msg += "<br>" + tr("Sel.: Rel.:{0} / Ways:{1} / Nodes:{2}", relations.size(), ways.size(), nodes.size());
64 }
65 return msg;
66 }
67
68 @Override
69 public String[] getMandatoryParams()
70 {
71 return new String[] { "bottom", "top", "left", "right" };
72 }
73
74 @Override
75 protected void handleRequest() throws RequestHandlerErrorException
76 {
77 DownloadTask osmTask = new DownloadOsmTask();
78 try {
79 boolean newLayer = isLoadInNewLayer();
80
81 if(command.equals(myCommand))
82 {
83 if (!PermissionPrefWithDefault.LOAD_DATA.isAllowed())
84 {
85 System.out.println("RemoteControl: download forbidden by preferences");
86 }
87 else
88 {
89 Area toDownload = null;
90 if (!newLayer) {
91 // find out whether some data has already been downloaded
92 Area present = null;
93 DataSet ds = Main.main.getCurrentDataSet();
94 if (ds != null) {
95 present = ds.getDataSourceArea();
96 }
97 if (present != null && !present.isEmpty()) {
98 toDownload = new Area(new Rectangle2D.Double(minlon,minlat,maxlon-minlon,maxlat-minlat));
99 toDownload.subtract(present);
100 if (!toDownload.isEmpty())
101 {
102 // the result might not be a rectangle (L shaped etc)
103 Rectangle2D downloadBounds = toDownload.getBounds2D();
104 minlat = downloadBounds.getMinY();
105 minlon = downloadBounds.getMinX();
106 maxlat = downloadBounds.getMaxY();
107 maxlon = downloadBounds.getMaxX();
108 }
109 }
110 }
111 if (toDownload != null && toDownload.isEmpty())
112 {
113 System.out.println("RemoteControl: no download necessary");
114 }
115 else
116 {
117 Future<?> future = osmTask.download(newLayer, new Bounds(minlat,minlon,maxlat,maxlon), null /* let the task manage the progress monitor */);
118 Main.worker.submit(new PostDownloadHandler(osmTask, future));
119 }
120 }
121 }
122 } catch (Exception ex) {
123 System.out.println("RemoteControl: Error parsing load_and_zoom remote control request:");
124 ex.printStackTrace();
125 throw new RequestHandlerErrorException();
126 }
127
128 /**
129 * deselect objects if parameter addtags given
130 */
131 if (args.containsKey("addtags")) {
132 GuiHelper.executeByMainWorkerInEDT(new Runnable() {
133 public void run() {
134 DataSet ds = Main.main.getCurrentDataSet();
135 if(ds == null) // e.g. download failed
136 return;
137 ds.clearSelection();
138 }
139 });
140 }
141
142 final Bounds bbox = new Bounds(new LatLon(minlat, minlon), new LatLon(maxlat, maxlon));
143 if (args.containsKey("select") && PermissionPrefWithDefault.CHANGE_SELECTION.isAllowed()) {
144 // select objects after downloading, zoom to selection.
145 GuiHelper.executeByMainWorkerInEDT(new Runnable() {
146 public void run() {
147 HashSet<OsmPrimitive> newSel = new HashSet<OsmPrimitive>();
148 DataSet ds = Main.main.getCurrentDataSet();
149 if(ds == null) // e.g. download failed
150 return;
151 for (Way w : ds.getWays()) {
152 if (ways.contains(w.getId())) {
153 newSel.add(w);
154 }
155 }
156 ways.clear();
157 for (Node n : ds.getNodes()) {
158 if (nodes.contains(n.getId())) {
159 newSel.add(n);
160 }
161 }
162 nodes.clear();
163 for (Relation r : ds.getRelations()) {
164 if (relations.contains(r.getId())) {
165 newSel.add(r);
166 }
167 }
168 relations.clear();
169 ds.setSelected(newSel);
170 if (PermissionPrefWithDefault.CHANGE_VIEWPORT.isAllowed()) {
171 // zoom_mode=(download|selection), defaults to selection
172 if (!"download".equals(args.get("zoom_mode")) && !newSel.isEmpty()) {
173 AutoScaleAction.autoScale("selection");
174 } else {
175 zoom(bbox);
176 }
177 }
178 if (Main.isDisplayingMapView() && Main.map.relationListDialog != null) {
179 Main.map.relationListDialog.selectRelations(null); // unselect all relations to fix #7342
180 Main.map.relationListDialog.dataChanged(null);
181 Main.map.relationListDialog.selectRelations(Utils.filteredCollection(newSel, Relation.class));
182 }
183 }
184 });
185 } else if (PermissionPrefWithDefault.CHANGE_VIEWPORT.isAllowed()) {
186 // after downloading, zoom to downloaded area.
187 zoom(bbox);
188 }
189
190 AddTagsDialog.addTags(args, sender);
191 }
192
193 protected void zoom(final Bounds bounds) {
194 // make sure this isn't called unless there *is* a MapView
195 if (Main.isDisplayingMapView()) {
196 GuiHelper.executeByMainWorkerInEDT(new Runnable() {
197 public void run() {
198 BoundingXYVisitor bbox = new BoundingXYVisitor();
199 bbox.visit(bounds);
200 Main.map.mapView.recalculateCenterScale(bbox);
201 }
202 });
203 }
204 }
205
206 @Override
207 public PermissionPrefWithDefault getPermissionPref() {
208 return null;
209 }
210
211 @Override
212 protected void validateRequest() throws RequestHandlerBadRequestException {
213 // Process mandatory arguments
214 minlat = 0;
215 maxlat = 0;
216 minlon = 0;
217 maxlon = 0;
218 try {
219 minlat = LatLon.roundToOsmPrecision(Double.parseDouble(args.get("bottom")));
220 maxlat = LatLon.roundToOsmPrecision(Double.parseDouble(args.get("top")));
221 minlon = LatLon.roundToOsmPrecision(Double.parseDouble(args.get("left")));
222 maxlon = LatLon.roundToOsmPrecision(Double.parseDouble(args.get("right")));
223 } catch (NumberFormatException e) {
224 throw new RequestHandlerBadRequestException("NumberFormatException ("+e.getMessage()+")");
225 }
226
227 // Process optional argument 'select'
228 if (args.containsKey("select")) {
229 ways.clear();
230 nodes.clear();
231 relations.clear();
232 for (String item : args.get("select").split(",")) {
233 try {
234 if (item.startsWith("way")) {
235 ways.add(Long.parseLong(item.substring(3)));
236 } else if (item.startsWith("node")) {
237 nodes.add(Long.parseLong(item.substring(4)));
238 } else if (item.startsWith("relation")) {
239 relations.add(Long.parseLong(item.substring(8)));
240 } else if (item.startsWith("rel")) {
241 relations.add(Long.parseLong(item.substring(3)));
242 } else {
243 System.out.println("RemoteControl: invalid selection '"+item+"' ignored");
244 }
245 } catch (NumberFormatException e) {
246 System.out.println("RemoteControl: invalid selection '"+item+"' ignored");
247 }
248 }
249 }
250 }
251}
Note: See TracBrowser for help on using the repository browser.