source: josm/trunk/src/org/openstreetmap/josm/gui/io/AbstractPrimitiveTask.java@ 17041

Last change on this file since 17041 was 15811, checked in by GerdP, 4 years ago

fix #18566: Download object: member of relations always downloaded (18566.3.patch)

  • return same result when downloading objects, no matter if overpass api is enabled or not.
  • fix an EDT violation in class ChildRelationBrowser
  • let MultiFetchOverpassObjectReader create a single overpass query, no matter how many objects are requested

(gives much better reaction times).

  • use multi-fetch in ChildRelationBrowser to reduce duplicated code. Small disadvantage: When downloading multiple members of a relation the dialog doesn't update after each member. Should not matter much as the overall time for multiple members is shorter

I tried to keep the code backward compatible. Plugins reverter and undelete should continue to work.

  • Property svn:eol-style set to native
File size: 6.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.openstreetmap.josm.tools.CheckParameterUtil.ensureParameterNotNull;
5
6import java.io.IOException;
7import java.util.Set;
8
9import org.openstreetmap.josm.actions.AutoScaleAction;
10import org.openstreetmap.josm.data.osm.DataSet;
11import org.openstreetmap.josm.data.osm.DataSetMerger;
12import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
13import org.openstreetmap.josm.data.osm.PrimitiveId;
14import org.openstreetmap.josm.data.osm.Way;
15import org.openstreetmap.josm.gui.ExceptionDialogUtil;
16import org.openstreetmap.josm.gui.MainApplication;
17import org.openstreetmap.josm.gui.PleaseWaitRunnable;
18import org.openstreetmap.josm.gui.layer.OsmDataLayer;
19import org.openstreetmap.josm.gui.progress.ProgressMonitor;
20import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor;
21import org.openstreetmap.josm.gui.util.GuiHelper;
22import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
23import org.openstreetmap.josm.io.OsmServerObjectReader;
24import org.openstreetmap.josm.io.OsmTransferException;
25import org.xml.sax.SAXException;
26
27/**
28 * Abstract superclass of download/update primitives tasks.
29 * @since 10129
30 */
31public abstract class AbstractPrimitiveTask extends PleaseWaitRunnable {
32
33 protected final DataSet ds = new DataSet();
34 protected boolean canceled;
35 protected Exception lastException;
36 private Set<PrimitiveId> missingPrimitives;
37
38 protected final OsmDataLayer layer;
39 protected MultiFetchServerObjectReader multiObjectReader;
40 protected OsmServerObjectReader objectReader;
41
42 private boolean zoom;
43 protected boolean fullRelation;
44
45 protected AbstractPrimitiveTask(String title, OsmDataLayer layer) {
46 this(title, new PleaseWaitProgressMonitor(title), layer);
47 }
48
49 protected AbstractPrimitiveTask(String title, ProgressMonitor progressMonitor, OsmDataLayer layer) {
50 super(title, progressMonitor, false);
51 ensureParameterNotNull(layer, "layer");
52 this.layer = layer;
53 if (!layer.isDownloadable()) {
54 throw new IllegalArgumentException("Non-downloadable layer: " + layer);
55 }
56 }
57
58 protected abstract void initMultiFetchReader(MultiFetchServerObjectReader reader);
59
60 /**
61 * Sets whether the map view should zoom to impacted primitives at the end.
62 * @param zoom {@code true} if the map view should zoom to impacted primitives at the end
63 * @return {@code this}
64 */
65 public final AbstractPrimitiveTask setZoom(boolean zoom) {
66 this.zoom = zoom;
67 return this;
68 }
69
70 /**
71 * Sets whether all members of the relation should be downloaded completely.
72 * @param fullRelation {@code true} if a full download is required,
73 * i.e., a download including the immediate children of a relation.
74 * @return {@code this}
75 * since 15811 (changed parameter list)
76 */
77 public final AbstractPrimitiveTask setDownloadRelations(boolean fullRelation) {
78 this.fullRelation = fullRelation;
79 return this;
80 }
81
82 /**
83 * Replies the set of ids of all primitives for which a fetch request to the
84 * server was submitted but which are not available from the server (the server
85 * replied a return code of 404)
86 *
87 * @return the set of ids of missing primitives
88 */
89 public Set<PrimitiveId> getMissingPrimitives() {
90 return missingPrimitives;
91 }
92
93 @Override
94 protected void realRun() throws SAXException, IOException, OsmTransferException {
95 DataSet theirDataSet;
96 try {
97 synchronized (this) {
98 if (canceled)
99 return;
100 multiObjectReader = MultiFetchServerObjectReader.create().setRecurseDownRelations(fullRelation);
101 }
102 initMultiFetchReader(multiObjectReader);
103 theirDataSet = multiObjectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
104 missingPrimitives = multiObjectReader.getMissingPrimitives();
105 synchronized (this) {
106 multiObjectReader = null;
107 }
108 new DataSetMerger(ds, theirDataSet).merge();
109
110 loadIncompleteNodes();
111 } catch (OsmTransferException e) {
112 if (canceled)
113 return;
114 lastException = e;
115 }
116 }
117
118 protected void loadIncompleteNodes() throws OsmTransferException {
119 // a way loaded with MultiFetch may have incomplete nodes because at least one of its
120 // nodes isn't present in the local data set. We therefore fully load all ways with incomplete nodes.
121 for (Way w : ds.getWays()) {
122 if (canceled)
123 return;
124 if (w.hasIncompleteNodes()) {
125 synchronized (this) {
126 if (canceled)
127 return;
128 objectReader = new OsmServerObjectReader(w.getId(), OsmPrimitiveType.WAY, true /* full */);
129 }
130 DataSet theirDataSet = objectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
131 synchronized (this) {
132 objectReader = null;
133 }
134 new DataSetMerger(ds, theirDataSet).merge();
135 }
136 }
137 }
138
139 @Override
140 protected void cancel() {
141 canceled = true;
142 synchronized (this) {
143 if (multiObjectReader != null) {
144 multiObjectReader.cancel();
145 }
146 if (objectReader != null) {
147 objectReader.cancel();
148 }
149 }
150 }
151
152 @Override
153 protected void finish() {
154 if (canceled)
155 return;
156 if (lastException != null) {
157 ExceptionDialogUtil.explainException(lastException);
158 return;
159 }
160 GuiHelper.runInEDTAndWait(() -> {
161 layer.mergeFrom(ds);
162 if (zoom && MainApplication.getMap() != null)
163 AutoScaleAction.zoomTo(ds.allPrimitives());
164 layer.onPostDownloadFromServer();
165 });
166 }
167}
Note: See TracBrowser for help on using the repository browser.