source: josm/trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmChangeTask.java@ 5171

Last change on this file since 5171 was 5171, checked in by Don-vip, 12 years ago

history/osmChange handling: fix an issue when downloading osmChange that could lead to the creation of empty ways (0 node) + fix spelling of a getter

File size: 8.0 KB
Line 
1package org.openstreetmap.josm.actions.downloadtasks;
2
3import java.util.ArrayList;
4import java.util.Date;
5import java.util.HashSet;
6import java.util.Iterator;
7import java.util.List;
8import java.util.Set;
9import java.util.concurrent.Future;
10
11import org.openstreetmap.josm.Main;
12import org.openstreetmap.josm.data.Bounds;
13import org.openstreetmap.josm.data.osm.DataSet;
14import org.openstreetmap.josm.data.osm.NodeData;
15import org.openstreetmap.josm.data.osm.OsmPrimitive;
16import org.openstreetmap.josm.data.osm.PrimitiveData;
17import org.openstreetmap.josm.data.osm.PrimitiveId;
18import org.openstreetmap.josm.data.osm.RelationData;
19import org.openstreetmap.josm.data.osm.WayData;
20import org.openstreetmap.josm.data.osm.history.History;
21import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
22import org.openstreetmap.josm.data.osm.history.HistoryDataSetListener;
23import org.openstreetmap.josm.data.osm.history.HistoryNode;
24import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
25import org.openstreetmap.josm.data.osm.history.HistoryRelation;
26import org.openstreetmap.josm.data.osm.history.HistoryWay;
27import org.openstreetmap.josm.gui.history.HistoryLoadTask;
28import org.openstreetmap.josm.gui.progress.ProgressMonitor;
29import org.openstreetmap.josm.io.OsmServerLocationReader;
30import org.openstreetmap.josm.io.OsmServerReader;
31import org.openstreetmap.josm.io.OsmTransferException;
32import org.openstreetmap.josm.tools.Pair;
33
34public class DownloadOsmChangeTask extends DownloadOsmTask {
35
36 @Override
37 public boolean acceptsUrl(String url) {
38 return url != null && url.matches("http://.*/api/0.6/changeset/\\p{Digit}+/download");
39 }
40
41 /* (non-Javadoc)
42 * @see org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask#download(boolean, org.openstreetmap.josm.data.Bounds, org.openstreetmap.josm.gui.progress.ProgressMonitor)
43 */
44 @Override
45 public Future<?> download(boolean newLayer, Bounds downloadArea,
46 ProgressMonitor progressMonitor) {
47 return null;
48 }
49
50 /* (non-Javadoc)
51 * @see org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask#loadUrl(boolean, java.lang.String, org.openstreetmap.josm.gui.progress.ProgressMonitor)
52 */
53 @Override
54 public Future<?> loadUrl(boolean new_layer, String url,
55 ProgressMonitor progressMonitor) {
56 downloadTask = new DownloadTask(new_layer,
57 new OsmServerLocationReader(url),
58 progressMonitor);
59 return Main.worker.submit(downloadTask);
60 }
61
62 protected class DownloadTask extends DownloadOsmTask.DownloadTask {
63
64 public DownloadTask(boolean newLayer, OsmServerReader reader,
65 ProgressMonitor progressMonitor) {
66 super(newLayer, reader, progressMonitor);
67 }
68
69 /* (non-Javadoc)
70 * @see org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask.DownloadTask#parseDataSet()
71 */
72 @Override
73 protected DataSet parseDataSet() throws OsmTransferException {
74 return reader.parseOsmChange(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
75 }
76
77 /* (non-Javadoc)
78 * @see org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask.DownloadTask#finish()
79 */
80 @Override
81 protected void finish() {
82 super.finish();
83 if (isFailed() || isCanceled() || downloadedData == null)
84 return; // user canceled download or error occurred
85 try {
86 // A changeset does not contain all referred primitives, this is the list of incomplete ones
87 Set<OsmPrimitive> toLoad = new HashSet<OsmPrimitive>();
88 // For each incomplete primitive, we'll have to get its state at date it was referred
89 List<Pair<OsmPrimitive, Date>> toMonitor = new ArrayList<Pair<OsmPrimitive, Date>>();
90 for (OsmPrimitive p : downloadedData.allNonDeletedPrimitives()) {
91 if (p.isIncomplete()) {
92 Date timestamp = null;
93 for (OsmPrimitive ref : p.getReferrers()) {
94 if (!ref.isTimestampEmpty()) {
95 timestamp = ref.getTimestamp();
96 break;
97 }
98 }
99 if (toLoad.add(p)) {
100 toMonitor.add(new Pair<OsmPrimitive, Date>(p, timestamp));
101 }
102 }
103 }
104 if (isCanceled()) return;
105 // Updating process is asynchronous and done after each history request
106 HistoryDataSet.getInstance().addHistoryDataSetListener(new HistoryListener(toMonitor));
107 // Let's load all required history
108 Main.worker.submit(new HistoryLoadTask().add(toLoad));
109 } catch (Exception e) {
110 rememberException(e);
111 setFailed(true);
112 }
113 }
114 }
115 /**
116 * Asynchroneous updater of incomplete primitives.
117 *
118 */
119 private static class HistoryListener implements HistoryDataSetListener {
120
121 private final List<Pair<OsmPrimitive, Date>> toMonitor;
122
123 public HistoryListener(List<Pair<OsmPrimitive, Date>> toMonitor) {
124 this.toMonitor = toMonitor;
125 }
126
127 @Override
128 public void historyUpdated(HistoryDataSet source, PrimitiveId id) {
129 for (Iterator<Pair<OsmPrimitive, Date>> it = toMonitor.iterator(); it.hasNext();) {
130 Pair<OsmPrimitive, Date> pair = it.next();
131 History history = source.getHistory(pair.a.getPrimitiveId());
132 // If the history has been loaded and a timestamp is known
133 if (history != null && pair.b != null) {
134 // Lookup for the primitive version at the specified timestamp
135 HistoryOsmPrimitive hp = history.getByDate(pair.b);
136 if (hp != null) {
137 PrimitiveData data = null;
138
139 switch (pair.a.getType()) {
140 case NODE:
141 data = new NodeData();
142 ((NodeData)data).setCoor(((HistoryNode)hp).getCoords());
143 break;
144 case WAY:
145 data = new WayData();
146 ((WayData)data).setNodes(((HistoryWay)hp).getNodes());
147 break;
148 case RELATION:
149 data = new RelationData();
150 ((RelationData)data).setMembers(((HistoryRelation)hp).getMembers());
151 break;
152 default: throw new AssertionError();
153 }
154
155 data.setUser(hp.getUser());
156 try {
157 data.setVisible(hp.isVisible());
158 } catch (IllegalStateException e) {
159 System.err.println("Cannot change visibility for "+pair.a+": "+e.getMessage());
160 }
161 data.setTimestamp(hp.getTimestamp());
162 data.setKeys(hp.getTags());
163 data.setOsmId(hp.getChangesetId(), (int) hp.getVersion());
164
165 // Load the history data
166 pair.a.load(data);
167 // Forget this primitive
168 it.remove();
169 }
170 }
171 }
172 if (toMonitor.isEmpty()) {
173 // No more primitive to update. Processing is finished
174 source.removeHistoryDataSetListener(this);
175 // Be sure all updated primitives are correctly drawn
176 Main.map.repaint();
177 }
178 }
179
180 @Override
181 public void historyDataSetCleared(HistoryDataSet source) {
182 }
183 }
184}
Note: See TracBrowser for help on using the repository browser.