001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.io.IOException; 007import java.io.InputStream; 008import java.text.MessageFormat; 009 010import org.openstreetmap.josm.data.osm.DataSet; 011import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 012import org.openstreetmap.josm.data.osm.PrimitiveId; 013import org.openstreetmap.josm.data.osm.SimplePrimitiveId; 014import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 015import org.openstreetmap.josm.gui.progress.ProgressMonitor; 016import org.openstreetmap.josm.tools.CheckParameterUtil; 017 018/** 019 * OsmServerObjectReader reads an individual object from the OSM server. 020 * 021 * It can either download the object including or not including its immediate children. 022 * The former case is called a "full download". 023 * 024 * It can also download a specific version of the object (however, "full" download is not possible 025 * in that case). 026 * 027 */ 028public class OsmServerObjectReader extends OsmServerReader { 029 /** the id of the object to download */ 030 private PrimitiveId id; 031 /** true if a full download is required, i.e. a download including the immediate children */ 032 private boolean full; 033 /** the specific version number, if required (incompatible with full), or -1 else */ 034 private int version; 035 036 /** 037 * Creates a new server object reader for a given id and a primitive type. 038 * 039 * @param id the object id. > 0 required. 040 * @param type the type. Must not be null. 041 * @param full true, if a full download is requested (i.e. a download including 042 * immediate children); false, otherwise 043 * @throws IllegalArgumentException if id <= 0 044 * @throws IllegalArgumentException if type is null 045 */ 046 public OsmServerObjectReader(long id, OsmPrimitiveType type, boolean full) { 047 this(id, type, full, -1); 048 } 049 050 /** 051 * Creates a new server object reader for a given id and a primitive type. 052 * 053 * @param id the object id. > 0 required. 054 * @param type the type. Must not be null. 055 * @param version the specific version number, if required; -1, otherwise 056 * @throws IllegalArgumentException if id <= 0 057 * @throws IllegalArgumentException if type is null 058 */ 059 public OsmServerObjectReader(long id, OsmPrimitiveType type, int version) { 060 this(id, type, false, version); 061 } 062 063 protected OsmServerObjectReader(long id, OsmPrimitiveType type, boolean full, int version) { 064 if (id <= 0) 065 throw new IllegalArgumentException(MessageFormat.format("Expected value > 0 for parameter ''{0}'', got {1}", "id", id)); 066 CheckParameterUtil.ensureParameterNotNull(type, "type"); 067 this.id = new SimplePrimitiveId(id, type); 068 this.full = full; 069 this.version = version; 070 } 071 072 /** 073 * Creates a new server object reader for an object with the given <code>id</code> 074 * 075 * @param id the object id. Must not be null. Unique id > 0 required. 076 * @param full true, if a full download is requested (i.e. a download including 077 * immediate children); false, otherwise 078 * @throws IllegalArgumentException if id is null 079 * @throws IllegalArgumentException if id.getUniqueId() <= 0 080 */ 081 public OsmServerObjectReader(PrimitiveId id, boolean full) { 082 this(id, full, -1); 083 } 084 085 /** 086 * Creates a new server object reader for an object with the given <code>id</code> 087 * 088 * @param id the object id. Must not be null. Unique id > 0 required. 089 * @param version the specific version number, if required; -1, otherwise 090 * @throws IllegalArgumentException if id is null 091 * @throws IllegalArgumentException if id.getUniqueId() <= 0 092 */ 093 public OsmServerObjectReader(PrimitiveId id, int version) { 094 this(id, false, version); 095 } 096 097 protected OsmServerObjectReader(PrimitiveId id, boolean full, int version) { 098 CheckParameterUtil.ensure(id, "id", "id > 0", pid -> pid.getUniqueId() > 0); 099 this.id = id; 100 this.full = full; 101 this.version = version; 102 } 103 104 /** 105 * Downloads and parses the data. 106 * 107 * @param progressMonitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null 108 * @return the downloaded data 109 * @throws OsmTransferException if any error occurs during dialog with OSM API 110 */ 111 @Override 112 public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException { 113 if (progressMonitor == null) { 114 progressMonitor = NullProgressMonitor.INSTANCE; 115 } 116 progressMonitor.beginTask("", 1); 117 try { 118 progressMonitor.indeterminateSubTask(tr("Downloading OSM data...")); 119 StringBuilder sb = new StringBuilder(); 120 sb.append(id.getType().getAPIName()) 121 .append('/') 122 .append(id.getUniqueId()); 123 if (full && id.getType() != OsmPrimitiveType.NODE) { 124 sb.append("/full"); 125 } else if (version > 0) { 126 sb.append('/').append(version); 127 } 128 129 try (InputStream in = getInputStream(sb.toString(), progressMonitor.createSubTaskMonitor(1, true))) { 130 if (in == null) 131 return null; 132 return OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)); 133 } 134 } catch (OsmTransferException e) { 135 if (cancel) return null; 136 throw e; 137 } catch (IOException | IllegalDataException e) { 138 if (cancel) return null; 139 throw new OsmTransferException(e); 140 } finally { 141 progressMonitor.finishTask(); 142 activeConnection = null; 143 } 144 } 145}