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

Last change on this file since 12767 was 12675, checked in by Don-vip, 7 years ago

see #15182 - move the Swing-based ProgressMonitor implementations from gui.progress to gui.progress.swing. Progress monitor concept is used in very large parts of JOSM, a console-based implementation could be added later

  • Property svn:eol-style set to native
File size: 7.1 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.Relation;
15import org.openstreetmap.josm.data.osm.Way;
16import org.openstreetmap.josm.gui.ExceptionDialogUtil;
17import org.openstreetmap.josm.gui.MainApplication;
18import org.openstreetmap.josm.gui.PleaseWaitRunnable;
19import org.openstreetmap.josm.gui.layer.OsmDataLayer;
20import org.openstreetmap.josm.gui.progress.ProgressMonitor;
21import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor;
22import org.openstreetmap.josm.gui.util.GuiHelper;
23import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
24import org.openstreetmap.josm.io.OsmServerObjectReader;
25import org.openstreetmap.josm.io.OsmTransferException;
26import org.xml.sax.SAXException;
27
28/**
29 * Abstract superclass of download/update primitives tasks.
30 * @since 10129
31 */
32public abstract class AbstractPrimitiveTask extends PleaseWaitRunnable {
33
34 protected final DataSet ds = new DataSet();
35 protected boolean canceled;
36 protected Exception lastException;
37 private Set<PrimitiveId> missingPrimitives;
38
39 protected final OsmDataLayer layer;
40 protected MultiFetchServerObjectReader multiObjectReader;
41 protected OsmServerObjectReader objectReader;
42
43 private boolean zoom;
44 private boolean downloadRelations;
45 private boolean fullRelation;
46
47 protected AbstractPrimitiveTask(String title, OsmDataLayer layer) {
48 this(title, new PleaseWaitProgressMonitor(title), layer);
49 }
50
51 protected AbstractPrimitiveTask(String title, ProgressMonitor progressMonitor, OsmDataLayer layer) {
52 super(title, progressMonitor, false);
53 ensureParameterNotNull(layer, "layer");
54 this.layer = layer;
55 }
56
57 protected abstract void initMultiFetchReader(MultiFetchServerObjectReader reader);
58
59 /**
60 * Sets whether the map view should zoom to impacted primitives at the end.
61 * @param zoom {@code true} if the map view should zoom to impacted primitives at the end
62 * @return {@code this}
63 */
64 public final AbstractPrimitiveTask setZoom(boolean zoom) {
65 this.zoom = zoom;
66 return this;
67 }
68
69 /**
70 * Sets whether .
71 * @param downloadRelations {@code true} if
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 */
76 public final AbstractPrimitiveTask setDownloadRelations(boolean downloadRelations, boolean fullRelation) {
77 this.downloadRelations = downloadRelations;
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();
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 if (downloadRelations) {
111 loadIncompleteRelationMembers();
112 }
113
114 loadIncompleteNodes();
115 } catch (OsmTransferException e) {
116 if (canceled)
117 return;
118 lastException = e;
119 }
120 }
121
122 protected void loadIncompleteRelationMembers() throws OsmTransferException {
123 // if incomplete relation members exist, download them too
124 for (Relation r : ds.getRelations()) {
125 if (canceled)
126 return;
127 // Relations may be incomplete in case of nested relations if child relations are accessed before their parent
128 // (it may happen because "relations" has no deterministic sort order, see #10388)
129 if (r.isIncomplete() || r.hasIncompleteMembers()) {
130 synchronized (this) {
131 if (canceled)
132 return;
133 objectReader = new OsmServerObjectReader(r.getId(), OsmPrimitiveType.RELATION, fullRelation);
134 }
135 DataSet theirDataSet = objectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
136 synchronized (this) {
137 objectReader = null;
138 }
139 new DataSetMerger(ds, theirDataSet).merge();
140 }
141 }
142 }
143
144 protected void loadIncompleteNodes() throws OsmTransferException {
145 // a way loaded with MultiFetch may have incomplete nodes because at least one of its
146 // nodes isn't present in the local data set. We therefore fully load all ways with incomplete nodes.
147 for (Way w : ds.getWays()) {
148 if (canceled)
149 return;
150 if (w.hasIncompleteNodes()) {
151 synchronized (this) {
152 if (canceled)
153 return;
154 objectReader = new OsmServerObjectReader(w.getId(), OsmPrimitiveType.WAY, true /* full */);
155 }
156 DataSet theirDataSet = objectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
157 synchronized (this) {
158 objectReader = null;
159 }
160 new DataSetMerger(ds, theirDataSet).merge();
161 }
162 }
163 }
164
165 @Override
166 protected void cancel() {
167 canceled = true;
168 synchronized (this) {
169 if (multiObjectReader != null) {
170 multiObjectReader.cancel();
171 }
172 if (objectReader != null) {
173 objectReader.cancel();
174 }
175 }
176 }
177
178 @Override
179 protected void finish() {
180 if (canceled)
181 return;
182 if (lastException != null) {
183 ExceptionDialogUtil.explainException(lastException);
184 return;
185 }
186 GuiHelper.runInEDTAndWait(() -> {
187 layer.mergeFrom(ds);
188 if (zoom && MainApplication.getMap() != null)
189 AutoScaleAction.zoomTo(ds.allPrimitives());
190 layer.onPostDownloadFromServer();
191 });
192 }
193}
Note: See TracBrowser for help on using the repository browser.