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