001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io.remotecontrol.handler;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Point;
007import java.util.Collections;
008import java.util.Map;
009
010import org.openstreetmap.josm.Main;
011import org.openstreetmap.josm.actions.AutoScaleAction;
012import org.openstreetmap.josm.command.AddCommand;
013import org.openstreetmap.josm.data.coor.LatLon;
014import org.openstreetmap.josm.data.osm.Node;
015import org.openstreetmap.josm.data.osm.OsmPrimitive;
016import org.openstreetmap.josm.gui.util.GuiHelper;
017import org.openstreetmap.josm.io.remotecontrol.AddTagsDialog;
018import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
019
020/**
021 * Handler for add_node request.
022 */
023public class AddNodeHandler extends RequestHandler {
024
025    /**
026     * The remote control command name used to add a node.
027     */
028    public static final String command = "add_node";
029
030    private double lat;
031    private double lon;
032
033    @Override
034    protected void handleRequest() {
035        GuiHelper.runInEDTAndWait(new Runnable() {
036            @Override public void run() {
037                 addNode(args);
038            }
039        });
040    }
041
042    @Override
043    public String[] getMandatoryParams() {
044        return new String[] {"lat", "lon"};
045    }
046
047    @Override
048    public String[] getOptionalParams() {
049        return new String[] {"addtags"};
050    }
051
052    @Override
053    public String getUsage() {
054        return "adds a node (given by its latitude and longitude) to the current dataset";
055    }
056
057    @Override
058    public String[] getUsageExamples() {
059        return new String[] {
060            "/add_node?lat=11&lon=22",
061            "/add_node?lon=13.3&lat=53.2&addtags=natural=tree|name=%20%20%20==Great%20Oak=="
062        };
063    }
064
065    @Override
066    public String getPermissionMessage() {
067        return tr("Remote Control has been asked to create a new node.") +
068                "<br>" + tr("Coordinates: ") + args.get("lat") + ", " + args.get("lon");
069    }
070
071    @Override
072    public PermissionPrefWithDefault getPermissionPref() {
073        return PermissionPrefWithDefault.CREATE_OBJECTS;
074    }
075
076    /**
077     * Adds a node, implements the GET /add_node?lon=...&amp;lat=... request.
078     * @param args request arguments
079     */
080    private void addNode(Map<String, String> args) {
081
082        // Parse the arguments
083        Main.info("Adding node at (" + lat + ", " + lon + ')');
084
085        // Create a new node
086        LatLon ll = new LatLon(lat, lon);
087
088        Node node = null;
089
090        if (Main.isDisplayingMapView()) {
091            Point p = Main.map.mapView.getPoint(ll);
092            node = Main.map.mapView.getNearestNode(p, OsmPrimitive.isUsablePredicate);
093            if (node != null && node.getCoor().greatCircleDistance(ll) > Main.pref.getDouble("remotecontrol.tolerance", 0.1)) {
094                node = null; // node is too far
095            }
096        }
097
098        if (node == null) {
099            node = new Node(ll);
100            // Now execute the commands to add this node.
101            Main.main.undoRedo.add(new AddCommand(node));
102        }
103
104        Main.main.getCurrentDataSet().setSelected(node);
105        if (PermissionPrefWithDefault.CHANGE_VIEWPORT.isAllowed()) {
106            AutoScaleAction.autoScale("selection");
107        } else {
108            Main.map.mapView.repaint();
109        }
110        // parse parameter addtags=tag1=value1|tag2=vlaue2
111        AddTagsDialog.addTags(args, sender, Collections.singleton(node));
112    }
113
114    @Override
115    protected void validateRequest() throws RequestHandlerBadRequestException {
116        try {
117            lat = Double.parseDouble(args != null ? args.get("lat") : "");
118            lon = Double.parseDouble(args != null ? args.get("lon") : "");
119        } catch (NumberFormatException e) {
120            throw new RequestHandlerBadRequestException("NumberFormatException ("+e.getMessage()+')', e);
121        }
122        if (!Main.main.hasEditLayer()) {
123             throw new RequestHandlerBadRequestException(tr("There is no layer opened to add node"));
124        }
125    }
126}