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.util.LinkedList; 007import java.util.List; 008import java.util.concurrent.ExecutionException; 009import java.util.concurrent.TimeUnit; 010import java.util.concurrent.TimeoutException; 011import java.util.stream.Collectors; 012 013import org.openstreetmap.josm.data.osm.DataSet; 014import org.openstreetmap.josm.data.osm.PrimitiveId; 015import org.openstreetmap.josm.data.osm.SimplePrimitiveId; 016import org.openstreetmap.josm.gui.MainApplication; 017import org.openstreetmap.josm.gui.io.DownloadPrimitivesWithReferrersTask; 018import org.openstreetmap.josm.gui.util.GuiHelper; 019import org.openstreetmap.josm.io.remotecontrol.AddTagsDialog; 020import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault; 021import org.openstreetmap.josm.tools.Logging; 022 023/** 024 * Loads OSM primitives using their ID 025 * similar to the "Download object" dialog (@see DownloadPrimitiveAction}. 026 * For instance, {@code /load_object?objects=n1,w2,r3[&new_layer=false&relation_members=true]}. 027 */ 028public class LoadObjectHandler extends RequestHandler { 029 030 /** 031 * The remote control command name used to load objects using their ID. 032 */ 033 public static final String command = "load_object"; 034 035 private final List<PrimitiveId> ps = new LinkedList<>(); 036 037 @Override 038 public String[] getMandatoryParams() { 039 return new String[]{"objects"}; 040 } 041 042 @Override 043 public String[] getOptionalParams() { 044 return new String[] {"new_layer", "layer_name", "layer_locked", "download_policy", "upload_policy", 045 "addtags", "relation_members", "referrers"}; 046 } 047 048 @Override 049 public String getUsage() { 050 return "downloads the specified objects from the server"; 051 } 052 053 @Override 054 public String[] getUsageExamples() { 055 return new String[] {"/load_object?new_layer=true&objects=w106159509", 056 "/load_object?new_layer=true&objects=r2263653&relation_members=true", 057 "/load_object?objects=n100000&referrers=false" 058 }; 059 } 060 061 @Override 062 protected void handleRequest() throws RequestHandlerErrorException, RequestHandlerBadRequestException { 063 if (!PermissionPrefWithDefault.LOAD_DATA.isAllowed()) { 064 Logging.info("RemoteControl: download forbidden by preferences"); 065 } 066 if (!ps.isEmpty()) { 067 final boolean newLayer = getDownloadParams().isNewLayer(); 068 final boolean relationMembers = Boolean.parseBoolean(args.get("relation_members")); 069 final boolean referrers = Boolean.parseBoolean(args.get("referrers")); 070 final DownloadPrimitivesWithReferrersTask task = new DownloadPrimitivesWithReferrersTask( 071 newLayer, ps, referrers, relationMembers, args.get("layer_name"), null); 072 try { 073 MainApplication.worker.submit(task).get(OSM_DOWNLOAD_TIMEOUT.get(), TimeUnit.SECONDS); 074 } catch (InterruptedException | ExecutionException | TimeoutException e) { 075 Logging.error(e); 076 } 077 MainApplication.worker.submit(() -> { 078 final List<PrimitiveId> downloaded = task.getDownloadedId(); 079 final DataSet ds = MainApplication.getLayerManager().getEditDataSet(); 080 if (downloaded != null) { 081 GuiHelper.runInEDT(() -> ds.setSelected(downloaded)); 082 AddTagsDialog.addTags(args, sender, downloaded.stream().map(ds::getPrimitiveById).collect(Collectors.toSet())); 083 } 084 ps.clear(); 085 }); 086 } 087 } 088 089 @Override 090 public String getPermissionMessage() { 091 return tr("Remote Control has been asked to load objects (specified by their id) from the API."); 092 } 093 094 @Override 095 public PermissionPrefWithDefault getPermissionPref() { 096 return PermissionPrefWithDefault.LOAD_DATA; 097 } 098 099 @Override 100 protected void validateRequest() throws RequestHandlerBadRequestException { 101 validateDownloadParams(); 102 ps.clear(); 103 for (String i : splitArg("objects", SPLITTER_COMMA)) { 104 if (!i.isEmpty()) { 105 try { 106 ps.add(SimplePrimitiveId.fromString(i)); 107 } catch (IllegalArgumentException e) { 108 Logging.log(Logging.LEVEL_WARN, "RemoteControl: invalid selection '"+i+"' ignored.", e); 109 } 110 } 111 } 112 if (ps.isEmpty()) { 113 throw new RequestHandlerBadRequestException(tr("No valid object identifier has been provided")); 114 } 115 } 116}