source: josm/trunk/src/org/openstreetmap/josm/io/OsmServerBackreferenceReader.java@ 7013

Last change on this file since 7013 was 7005, checked in by Don-vip, 10 years ago

see #8465 - use diamond operator where applicable

  • Property svn:eol-style set to native
File size: 11.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.InputStream;
7import java.text.MessageFormat;
8import java.util.ArrayList;
9import java.util.Collection;
10
11import org.openstreetmap.josm.data.osm.DataSet;
12import org.openstreetmap.josm.data.osm.DataSetMerger;
13import org.openstreetmap.josm.data.osm.OsmPrimitive;
14import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
15import org.openstreetmap.josm.data.osm.Relation;
16import org.openstreetmap.josm.data.osm.Way;
17import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
18import org.openstreetmap.josm.gui.progress.ProgressMonitor;
19import org.openstreetmap.josm.tools.CheckParameterUtil;
20import org.openstreetmap.josm.tools.Utils;
21
22/**
23 * OsmServerBackreferenceReader fetches the primitives from the OSM server which
24 * refer to a specific primitive. For a {@link org.openstreetmap.josm.data.osm.Node Node}, ways and relations are retrieved
25 * which refer to the node. For a {@link Way} or a {@link Relation}, only relations are
26 * read.
27 *
28 * OsmServerBackreferenceReader uses the API calls <code>[node|way|relation]/#id/relations</code>
29 * and <code>node/#id/ways</code> to retrieve the referring primitives. The default behaviour
30 * of these calls is to reply incomplete primitives only.
31 *
32 * If you set {@link #setReadFull(boolean)} to true this reader uses a {@link MultiFetchServerObjectReader}
33 * to complete incomplete primitives.
34 *
35 *
36 */
37public class OsmServerBackreferenceReader extends OsmServerReader {
38
39 /** the id of the primitive whose referrers are to be read */
40 private long id;
41 /** the type of the primitive */
42 private OsmPrimitiveType primitiveType;
43 /** true if this reader should complete incomplete primitives */
44 private boolean readFull;
45
46 /**
47 * constructor
48 *
49 * @param primitive the primitive to be read. Must not be null. primitive.id &gt; 0 expected
50 *
51 * @exception IllegalArgumentException thrown if primitive is null
52 * @exception IllegalArgumentException thrown if primitive.id &lt;= 0
53 */
54 public OsmServerBackreferenceReader(OsmPrimitive primitive) throws IllegalArgumentException {
55 CheckParameterUtil.ensureValidPrimitiveId(primitive, "primitive");
56 this.id = primitive.getId();
57 this.primitiveType = OsmPrimitiveType.from(primitive);
58 this.readFull = false;
59 }
60
61 /**
62 * constructor
63 *
64 * @param id the id of the primitive. &gt; 0 expected
65 * @param type the type of the primitive. Must not be null.
66 *
67 * @exception IllegalArgumentException thrown if id &lt;= 0
68 * @exception IllegalArgumentException thrown if type is null
69 *
70 */
71 public OsmServerBackreferenceReader(long id, OsmPrimitiveType type) throws IllegalArgumentException {
72 if (id <= 0)
73 throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' > 0 expected. Got ''{1}''.", "id", id));
74 CheckParameterUtil.ensureParameterNotNull(type, "type");
75 this.id = id;
76 this.primitiveType = type;
77 this.readFull = false;
78 }
79
80 /**
81 * Creates a back reference reader for given primitive
82 *
83 * @param primitive the primitive
84 * @param readFull <code>true</code>, if referers should be read fully (i.e. including their immediate children)
85 *
86 */
87 public OsmServerBackreferenceReader(OsmPrimitive primitive, boolean readFull) {
88 this(primitive);
89 this.readFull = readFull;
90 }
91
92 /**
93 * Creates a back reference reader for given primitive id
94 *
95 * @param id the id of the primitive whose referers are to be read
96 * @param type the type of the primitive
97 * @param readFull true, if referers should be read fully (i.e. including their immediate children)
98 *
99 * @exception IllegalArgumentException thrown if id &lt;= 0
100 * @exception IllegalArgumentException thrown if type is null
101 *
102 */
103 public OsmServerBackreferenceReader(long id, OsmPrimitiveType type, boolean readFull) throws IllegalArgumentException {
104 this(id, type);
105 this.readFull = readFull;
106 }
107
108 /**
109 * Replies true if this reader also reads immediate children of referring primitives
110 *
111 * @return true if this reader also reads immediate children of referring primitives
112 */
113 public boolean isReadFull() {
114 return readFull;
115 }
116
117 /**
118 * Set true if this reader should reads immediate children of referring primitives too. False, otherweise.
119 *
120 * @param readFull true if this reader should reads immediate children of referring primitives too. False, otherweise.
121 */
122 public void setReadFull(boolean readFull) {
123 this.readFull = readFull;
124 }
125
126 /**
127 * Reads referring ways from the API server and replies them in a {@link DataSet}
128 *
129 * @return the data set
130 * @throws OsmTransferException
131 */
132 protected DataSet getReferringWays(ProgressMonitor progressMonitor) throws OsmTransferException {
133 InputStream in = null;
134 progressMonitor.beginTask(null, 2);
135 try {
136 progressMonitor.indeterminateSubTask(tr("Downloading from OSM Server..."));
137 StringBuilder sb = new StringBuilder();
138 sb.append(primitiveType.getAPIName())
139 .append("/").append(id).append("/ways");
140
141 in = getInputStream(sb.toString(), progressMonitor.createSubTaskMonitor(1, true));
142 if (in == null)
143 return null;
144 progressMonitor.subTask(tr("Downloading referring ways ..."));
145 return OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, true));
146 } catch(OsmTransferException e) {
147 throw e;
148 } catch (Exception e) {
149 if (cancel)
150 return null;
151 throw new OsmTransferException(e);
152 } finally {
153 progressMonitor.finishTask();
154 Utils.close(in);
155 activeConnection = null;
156 }
157 }
158
159 /**
160 * Reads referring relations from the API server and replies them in a {@link DataSet}
161 *
162 * @param progressMonitor the progress monitor
163 * @return the data set
164 * @throws OsmTransferException
165 */
166 protected DataSet getReferringRelations(ProgressMonitor progressMonitor) throws OsmTransferException {
167 InputStream in = null;
168 progressMonitor.beginTask(null, 2);
169 try {
170 progressMonitor.subTask(tr("Contacting OSM Server..."));
171 StringBuilder sb = new StringBuilder();
172 sb.append(primitiveType.getAPIName())
173 .append("/").append(id).append("/relations");
174
175 in = getInputStream(sb.toString(), progressMonitor.createSubTaskMonitor(1, true));
176 if (in == null)
177 return null;
178 progressMonitor.subTask(tr("Downloading referring relations ..."));
179 return OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, true));
180 } catch(OsmTransferException e) {
181 throw e;
182 } catch (Exception e) {
183 if (cancel)
184 return null;
185 throw new OsmTransferException(e);
186 } finally {
187 progressMonitor.finishTask();
188 Utils.close(in);
189 activeConnection = null;
190 }
191 }
192
193 /**
194 * Scans a dataset for incomplete primitives. Depending on the configuration of this reader
195 * incomplete primitives are read from the server with an individual <tt>/api/0.6/[way,relation]/#id/full</tt>
196 * request.
197 *
198 * <ul>
199 * <li>if this reader reads referers for a {@link org.openstreetmap.josm.data.osm.Node}, referring ways are always
200 * read individually from the server</li>
201 * <li>if this reader reads referers for an {@link Way} or a {@link Relation}, referring relations
202 * are only read fully if {@link #setReadFull(boolean)} is set to true.</li>
203 * </ul>
204 *
205 * The method replies the modified dataset.
206 *
207 * @param ds the original dataset
208 * @param progressMonitor the progress monitor
209 * @return the modified dataset
210 * @throws OsmTransferException thrown if an exception occurs.
211 */
212 protected DataSet readIncompletePrimitives(DataSet ds, ProgressMonitor progressMonitor) throws OsmTransferException {
213 progressMonitor.beginTask(null, 2);
214 try {
215 Collection<Way> waysToCheck = new ArrayList<>(ds.getWays());
216 if (isReadFull() ||primitiveType.equals(OsmPrimitiveType.NODE)) {
217 for (Way way: waysToCheck) {
218 if (!way.isNew() && way.hasIncompleteNodes()) {
219 OsmServerObjectReader reader = new OsmServerObjectReader(way.getId(), OsmPrimitiveType.from(way), true /* read full */);
220 DataSet wayDs = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
221 DataSetMerger visitor = new DataSetMerger(ds, wayDs);
222 visitor.merge();
223 }
224 }
225 }
226 if (isReadFull()) {
227 Collection<Relation> relationsToCheck = new ArrayList<>(ds.getRelations());
228 for (Relation relation: relationsToCheck) {
229 if (!relation.isNew() && relation.hasIncompleteMembers()) {
230 OsmServerObjectReader reader = new OsmServerObjectReader(relation.getId(), OsmPrimitiveType.from(relation), true /* read full */);
231 DataSet wayDs = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
232 DataSetMerger visitor = new DataSetMerger(ds, wayDs);
233 visitor.merge();
234 }
235 }
236 }
237 return ds;
238 } finally {
239 progressMonitor.finishTask();
240 }
241 }
242
243 /**
244 * Reads the referring primitives from the OSM server, parses them and
245 * replies them as {@link DataSet}
246 *
247 * @param progressMonitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null.
248 * @return the dataset with the referring primitives
249 * @exception OsmTransferException thrown if an error occurs while communicating with the server
250 */
251 @Override
252 public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
253 if (progressMonitor == null) {
254 progressMonitor = NullProgressMonitor.INSTANCE;
255 }
256 try {
257 progressMonitor.beginTask(null, 3);
258 DataSet ret = new DataSet();
259 if (primitiveType.equals(OsmPrimitiveType.NODE)) {
260 DataSet ds = getReferringWays(progressMonitor.createSubTaskMonitor(1, false));
261 DataSetMerger visitor = new DataSetMerger(ret,ds);
262 visitor.merge();
263 ret = visitor.getTargetDataSet();
264 }
265 DataSet ds = getReferringRelations(progressMonitor.createSubTaskMonitor(1, false));
266 DataSetMerger visitor = new DataSetMerger(ret,ds);
267 visitor.merge();
268 ret = visitor.getTargetDataSet();
269 readIncompletePrimitives(ret, progressMonitor.createSubTaskMonitor(1, false));
270 if (ret != null) {
271 ret.deleteInvisible();
272 }
273 return ret;
274 } finally {
275 progressMonitor.finishTask();
276 }
277 }
278}
Note: See TracBrowser for help on using the repository browser.