source: josm/trunk/src/org/openstreetmap/josm/gui/io/DownloadPrimitivesTask.java@ 9371

Last change on this file since 9371 was 9241, checked in by simon04, 9 years ago

see #7670 - Possibility to download from mirror with all download action

Set preference key download.overpass.for-multi-fetch to true in order to use Overpass API

  • Property svn:eol-style set to native
File size: 8.2 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;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.io.IOException;
8import java.util.List;
9import java.util.Set;
10
11import org.openstreetmap.josm.Main;
12import org.openstreetmap.josm.actions.AutoScaleAction;
13import org.openstreetmap.josm.data.osm.DataSet;
14import org.openstreetmap.josm.data.osm.DataSetMerger;
15import org.openstreetmap.josm.data.osm.Node;
16import org.openstreetmap.josm.data.osm.OsmPrimitive;
17import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
18import org.openstreetmap.josm.data.osm.PrimitiveId;
19import org.openstreetmap.josm.data.osm.Relation;
20import org.openstreetmap.josm.data.osm.Way;
21import org.openstreetmap.josm.gui.ExceptionDialogUtil;
22import org.openstreetmap.josm.gui.PleaseWaitRunnable;
23import org.openstreetmap.josm.gui.layer.OsmDataLayer;
24import org.openstreetmap.josm.gui.progress.ProgressMonitor;
25import org.openstreetmap.josm.gui.util.GuiHelper;
26import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
27import org.openstreetmap.josm.io.OsmServerObjectReader;
28import org.openstreetmap.josm.io.OsmTransferException;
29import org.xml.sax.SAXException;
30
31/**
32 * Task downloading a set of OSM primitives.
33 * @since 4081
34 */
35public class DownloadPrimitivesTask extends PleaseWaitRunnable {
36 private DataSet ds;
37 private boolean canceled;
38 private Exception lastException;
39 private final List<PrimitiveId> ids;
40
41 private Set<PrimitiveId> missingPrimitives;
42
43 private final OsmDataLayer layer;
44 private final boolean fullRelation;
45 private MultiFetchServerObjectReader multiObjectReader;
46 private OsmServerObjectReader objectReader;
47
48 /**
49 * Constructs a new {@code DownloadPrimitivesTask}.
50 *
51 * @param layer the layer in which primitives are updated. Must not be null.
52 * @param ids a collection of primitives to update from the server. Set to
53 * the empty collection if null.
54 * @param fullRelation true if a full download is required, i.e.,
55 * a download including the immediate children of a relation.
56 * @throws IllegalArgumentException if layer is null.
57 */
58 public DownloadPrimitivesTask(OsmDataLayer layer, List<PrimitiveId> ids, boolean fullRelation) {
59 this(layer, ids, fullRelation, null);
60 }
61
62 /**
63 * Constructs a new {@code DownloadPrimitivesTask}.
64 *
65 * @param layer the layer in which primitives are updated. Must not be null.
66 * @param ids a collection of primitives to update from the server. Set to
67 * the empty collection if null.
68 * @param fullRelation true if a full download is required, i.e.,
69 * a download including the immediate children of a relation.
70 * @param progressMonitor ProgressMonitor to use or null to create a new one.
71 * @throws IllegalArgumentException if layer is null.
72 */
73 public DownloadPrimitivesTask(OsmDataLayer layer, List<PrimitiveId> ids, boolean fullRelation,
74 ProgressMonitor progressMonitor) {
75 super(tr("Download objects"), progressMonitor, false /* don't ignore exception */);
76 ensureParameterNotNull(layer, "layer");
77 this.ids = ids;
78 this.layer = layer;
79 this.fullRelation = fullRelation;
80 }
81
82 @Override
83 protected void cancel() {
84 canceled = true;
85 synchronized (this) {
86 if (multiObjectReader != null) {
87 multiObjectReader.cancel();
88 }
89 if (objectReader != null) {
90 objectReader.cancel();
91 }
92 }
93 }
94
95 @Override
96 protected void finish() {
97 if (canceled)
98 return;
99 if (lastException != null) {
100 ExceptionDialogUtil.explainException(lastException);
101 return;
102 }
103 GuiHelper.runInEDTAndWait(new Runnable() {
104 @Override
105 public void run() {
106 layer.mergeFrom(ds);
107 if (Main.map != null)
108 AutoScaleAction.zoomTo(ds.allPrimitives());
109 layer.onPostDownloadFromServer();
110 }
111 });
112 }
113
114 protected void initMultiFetchReader(MultiFetchServerObjectReader reader) {
115 getProgressMonitor().indeterminateSubTask(tr("Initializing nodes to download ..."));
116 for (PrimitiveId id : ids) {
117 OsmPrimitive osm = layer.data.getPrimitiveById(id);
118 if (osm == null) {
119 switch (id.getType()) {
120 case NODE:
121 osm = new Node(id.getUniqueId());
122 break;
123 case WAY:
124 osm = new Way(id.getUniqueId());
125 break;
126 case RELATION:
127 osm = new Relation(id.getUniqueId());
128 break;
129 default: throw new AssertionError();
130 }
131 }
132 reader.append(osm);
133 }
134 }
135
136 @Override
137 protected void realRun() throws SAXException, IOException, OsmTransferException {
138 this.ds = new DataSet();
139 DataSet theirDataSet;
140 try {
141 synchronized (this) {
142 if (canceled) return;
143 multiObjectReader = MultiFetchServerObjectReader.create();
144 }
145 initMultiFetchReader(multiObjectReader);
146 theirDataSet = multiObjectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
147 missingPrimitives = multiObjectReader.getMissingPrimitives();
148 synchronized (this) {
149 multiObjectReader = null;
150 }
151 DataSetMerger merger = new DataSetMerger(ds, theirDataSet);
152 merger.merge();
153
154 // if incomplete relation members exist, download them too
155 for (Relation r : ds.getRelations()) {
156 if (canceled) return;
157 // Relations may be incomplete in case of nested relations if child relations are accessed before their parent
158 // (it may happen because "relations" has no deterministic sort order, see #10388)
159 if (r.isIncomplete() || r.hasIncompleteMembers()) {
160 synchronized (this) {
161 if (canceled) return;
162 objectReader = new OsmServerObjectReader(r.getId(), OsmPrimitiveType.RELATION, fullRelation);
163 }
164 theirDataSet = objectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
165 synchronized (this) {
166 objectReader = null;
167 }
168 merger = new DataSetMerger(ds, theirDataSet);
169 merger.merge();
170 }
171 }
172
173 // a way loaded with MultiFetch may have incomplete nodes because at least one of its
174 // nodes isn't present in the local data set. We therefore fully load all
175 // ways with incomplete nodes.
176 //
177 for (Way w : ds.getWays()) {
178 if (canceled) return;
179 if (w.hasIncompleteNodes()) {
180 synchronized (this) {
181 if (canceled) return;
182 objectReader = new OsmServerObjectReader(w.getId(), OsmPrimitiveType.WAY, true /* full */);
183 }
184 theirDataSet = objectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
185 synchronized (this) {
186 objectReader = null;
187 }
188 merger = new DataSetMerger(ds, theirDataSet);
189 merger.merge();
190 }
191 }
192
193 } catch (Exception e) {
194 if (canceled) return;
195 lastException = e;
196 }
197 }
198
199 /**
200 * replies the set of ids of all primitives for which a fetch request to the
201 * server was submitted but which are not available from the server (the server
202 * replied a return code of 404)
203 *
204 * @return the set of ids of missing primitives
205 */
206 public Set<PrimitiveId> getMissingPrimitives() {
207 return missingPrimitives;
208 }
209
210}
Note: See TracBrowser for help on using the repository browser.