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    private Node node;
034
035    @Override
036    protected void handleRequest() {
037        GuiHelper.runInEDTAndWait(new Runnable() {
038            @Override public void run() {
039                 addNode(args);
040            }
041        });
042    }
043
044    @Override
045    public String[] getMandatoryParams()
046    {
047        return new String[] { "lat", "lon" };
048    }
049    
050    @Override
051    public String[] getOptionalParams()
052    {
053        return new String[] { "addtags" };
054    }
055
056    @Override
057    public String getUsage() {
058        return "adds a node (given by its latitude and longitude) to the current dataset";
059    }
060
061    @Override
062    public String[] getUsageExamples() {
063        return new String[] {
064            "/add_node?lat=11&lon=22",
065            "/add_node?lon=13.3&lat=53.2&addtags=natural=tree|name=%20%20%20==Great%20Oak==" 
066        };
067    }
068    
069    @Override
070    public String getPermissionMessage() {
071        return tr("Remote Control has been asked to create a new node.") +
072                "<br>" + tr("Coordinates: ") + args.get("lat") + ", " + args.get("lon");
073    }
074
075    @Override
076    public PermissionPrefWithDefault getPermissionPref() {
077        return PermissionPrefWithDefault.CREATE_OBJECTS;
078    }
079
080    /**
081     * Adds a node, implements the GET /add_node?lon=...&amp;lat=... request.
082     * @param args
083     */
084    private void addNode(Map<String, String> args){
085
086        // Parse the arguments
087        Main.info("Adding node at (" + lat + ", " + lon + ")");
088
089        // Create a new node
090        LatLon ll = new LatLon(lat, lon);
091
092        node = null;
093
094        if (Main.isDisplayingMapView()) {
095            Point p = Main.map.mapView.getPoint(ll);
096            node = Main.map.mapView.getNearestNode(p, OsmPrimitive.isUsablePredicate);
097            if (node!=null && node.getCoor().greatCircleDistance(ll) > Main.pref.getDouble("remotecontrol.tolerance", 0.1)) {
098                node = null; // node is too far
099            }
100        }
101
102        if (node==null) {
103            node = new Node(ll);
104            // Now execute the commands to add this node.
105            Main.main.undoRedo.add(new AddCommand(node));
106        }
107
108        Main.main.getCurrentDataSet().setSelected(node);
109        if (PermissionPrefWithDefault.CHANGE_VIEWPORT.isAllowed()) {
110            AutoScaleAction.autoScale("selection");
111        } else {
112            Main.map.mapView.repaint();
113        }
114        // parse parameter addtags=tag1=value1|tag2=vlaue2
115        AddTagsDialog.addTags(args, sender, Collections.singleton(node));
116    }
117
118    @Override
119    protected void validateRequest() throws RequestHandlerBadRequestException {
120        try {
121            lat = Double.parseDouble(args.get("lat"));
122            lon = Double.parseDouble(args.get("lon"));
123        } catch (NumberFormatException e) {
124            throw new RequestHandlerBadRequestException("NumberFormatException ("+e.getMessage()+")");
125        }
126        if (!Main.main.hasEditLayer()) {
127             throw new RequestHandlerBadRequestException(tr("There is no layer opened to add node"));
128        }
129    }
130}