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

Last change on this file since 13207 was 12713, checked in by bastiK, 7 years ago

see #15229 - remove dependencies of CheckParameterUtil on various data classes

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