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

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

fix #7194 - Reworking of osmChange downloads (Fail to update a way loaded from osmChange that have been deleted after)

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