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