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

Last change on this file since 5003 was 4497, checked in by simon04, 13 years ago

fix #6542 - option to download relation without its members for "Download object" dialog

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