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

Last change on this file since 7783 was 7463, checked in by Don-vip, 10 years ago

fix #10392 - rework of MenuScroller to replace static scrollCount approach by dynamic behaviour (fix regressions from #10207)

File size: 8.9 KB
RevLine 
[5927]1// License: GPL. For details, see LICENSE file.
[4530]2package org.openstreetmap.josm.actions.downloadtasks;
3
[6248]4import static org.openstreetmap.josm.tools.I18n.tr;
5
[4734]6import java.util.Date;
[5476]7import java.util.HashMap;
[4734]8import java.util.Iterator;
9import java.util.List;
[5476]10import java.util.Map;
[4530]11import java.util.concurrent.Future;
12
13import org.openstreetmap.josm.Main;
14import org.openstreetmap.josm.data.Bounds;
15import org.openstreetmap.josm.data.osm.DataSet;
[5476]16import org.openstreetmap.josm.data.osm.Node;
[4734]17import org.openstreetmap.josm.data.osm.NodeData;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
[5476]19import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
[4734]20import org.openstreetmap.josm.data.osm.PrimitiveData;
21import org.openstreetmap.josm.data.osm.PrimitiveId;
22import org.openstreetmap.josm.data.osm.RelationData;
[5476]23import org.openstreetmap.josm.data.osm.RelationMemberData;
[4734]24import org.openstreetmap.josm.data.osm.WayData;
25import org.openstreetmap.josm.data.osm.history.History;
26import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
27import org.openstreetmap.josm.data.osm.history.HistoryDataSetListener;
28import org.openstreetmap.josm.data.osm.history.HistoryNode;
29import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
30import org.openstreetmap.josm.data.osm.history.HistoryRelation;
31import org.openstreetmap.josm.data.osm.history.HistoryWay;
32import org.openstreetmap.josm.gui.history.HistoryLoadTask;
[4530]33import org.openstreetmap.josm.gui.progress.ProgressMonitor;
34import org.openstreetmap.josm.io.OsmServerLocationReader;
35import org.openstreetmap.josm.io.OsmServerReader;
36import org.openstreetmap.josm.io.OsmTransferException;
37
[5921]38/**
39 * Task allowing to download OsmChange data (http://wiki.openstreetmap.org/wiki/OsmChange).
40 * @since 4530
41 */
[4530]42public class DownloadOsmChangeTask extends DownloadOsmTask {
43
44 @Override
[6031]45 public String[] getPatterns() {
[6920]46 return new String[]{"https?://.*/api/0.6/changeset/\\p{Digit}+/download", // OSM API 0.6 changesets
[6031]47 "https?://.*/.*\\.osc" // Remote .osc files
48 };
[4530]49 }
50
[6031]51 @Override
52 public String getTitle() {
53 return tr("Download OSM Change");
54 }
[6920]55
[4530]56 @Override
57 public Future<?> download(boolean newLayer, Bounds downloadArea,
58 ProgressMonitor progressMonitor) {
59 return null;
60 }
61
62 @Override
63 public Future<?> loadUrl(boolean new_layer, String url,
64 ProgressMonitor progressMonitor) {
65 downloadTask = new DownloadTask(new_layer,
66 new OsmServerLocationReader(url),
67 progressMonitor);
[5345]68 // Extract .osc filename from URL to set the new layer name
[5486]69 extractOsmFilename("https?://.*/(.*\\.osc)", url);
[4530]70 return Main.worker.submit(downloadTask);
71 }
[4874]72
[4530]73 protected class DownloadTask extends DownloadOsmTask.DownloadTask {
74
75 public DownloadTask(boolean newLayer, OsmServerReader reader,
76 ProgressMonitor progressMonitor) {
77 super(newLayer, reader, progressMonitor);
78 }
79
80 @Override
81 protected DataSet parseDataSet() throws OsmTransferException {
82 return reader.parseOsmChange(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
83 }
84
85 @Override
86 protected void finish() {
87 super.finish();
[4661]88 if (isFailed() || isCanceled() || downloadedData == null)
89 return; // user canceled download or error occurred
[4734]90 try {
[5476]91 // A changeset does not contain all referred primitives, this is the map of incomplete ones
[4734]92 // For each incomplete primitive, we'll have to get its state at date it was referred
[7005]93 Map<OsmPrimitive, Date> toLoad = new HashMap<>();
[4734]94 for (OsmPrimitive p : downloadedData.allNonDeletedPrimitives()) {
95 if (p.isIncomplete()) {
96 Date timestamp = null;
97 for (OsmPrimitive ref : p.getReferrers()) {
98 if (!ref.isTimestampEmpty()) {
99 timestamp = ref.getTimestamp();
100 break;
101 }
102 }
[5476]103 toLoad.put(p, timestamp);
[4734]104 }
105 }
106 if (isCanceled()) return;
107 // Let's load all required history
[5476]108 Main.worker.submit(new HistoryLoaderAndListener(toLoad));
[4734]109 } catch (Exception e) {
110 rememberException(e);
111 setFailed(true);
112 }
[4530]113 }
114 }
[6920]115
[4734]116 /**
[5476]117 * Loads history and updates incomplete primitives.
[4734]118 */
[5476]119 private static class HistoryLoaderAndListener extends HistoryLoadTask implements HistoryDataSetListener {
[4734]120
[5476]121 private final Map<OsmPrimitive, Date> toLoad;
[4874]122
[5476]123 public HistoryLoaderAndListener(Map<OsmPrimitive, Date> toLoad) {
124 this.toLoad = toLoad;
125 add(toLoad.keySet());
126 // Updating process is done after all history requests have been made
127 HistoryDataSet.getInstance().addHistoryDataSetListener(this);
[4734]128 }
129
130 @Override
131 public void historyUpdated(HistoryDataSet source, PrimitiveId id) {
[7005]132 Map<OsmPrimitive, Date> toLoadNext = new HashMap<>();
[5476]133 for (Iterator<OsmPrimitive> it = toLoad.keySet().iterator(); it.hasNext();) {
134 OsmPrimitive p = it.next();
135 History history = source.getHistory(p.getPrimitiveId());
136 Date date = toLoad.get(p);
[4734]137 // If the history has been loaded and a timestamp is known
[5476]138 if (history != null && date != null) {
[4734]139 // Lookup for the primitive version at the specified timestamp
[5476]140 HistoryOsmPrimitive hp = history.getByDate(date);
[4734]141 if (hp != null) {
142 PrimitiveData data = null;
[4874]143
[5476]144 switch (p.getType()) {
[4874]145 case NODE:
146 data = new NodeData();
147 ((NodeData)data).setCoor(((HistoryNode)hp).getCoords());
148 break;
149 case WAY:
150 data = new WayData();
[5476]151 List<Long> nodeIds = ((HistoryWay)hp).getNodes();
152 ((WayData)data).setNodes(nodeIds);
153 // Find incomplete nodes to load at next run
154 for (Long nodeId : nodeIds) {
155 if (p.getDataSet().getPrimitiveById(nodeId, OsmPrimitiveType.NODE) == null) {
156 Node n = new Node(nodeId);
157 p.getDataSet().addPrimitive(n);
158 toLoadNext.put(n, date);
159 }
160 }
[4874]161 break;
162 case RELATION:
163 data = new RelationData();
[5476]164 List<RelationMemberData> members = ((HistoryRelation)hp).getMembers();
165 ((RelationData)data).setMembers(members);
[4874]166 break;
[5476]167 default: throw new AssertionError("Unknown primitive type");
[4734]168 }
[4874]169
[4734]170 data.setUser(hp.getUser());
[5171]171 try {
172 data.setVisible(hp.isVisible());
173 } catch (IllegalStateException e) {
[6248]174 Main.error("Cannot change visibility for "+p+": "+e.getMessage());
[5171]175 }
[4734]176 data.setTimestamp(hp.getTimestamp());
177 data.setKeys(hp.getTags());
[5921]178 data.setOsmId(hp.getId(), (int) hp.getVersion());
[4874]179
[4734]180 // Load the history data
[5476]181 try {
182 p.load(data);
183 // Forget this primitive
184 it.remove();
185 } catch (AssertionError e) {
[6248]186 Main.error("Cannot load "+p + ": " + e.getMessage());
[5476]187 }
[4734]188 }
189 }
190 }
[5476]191 source.removeHistoryDataSetListener(this);
192 if (toLoadNext.isEmpty()) {
[4734]193 // No more primitive to update. Processing is finished
194 // Be sure all updated primitives are correctly drawn
195 Main.map.repaint();
[5476]196 } else {
197 // Some primitives still need to be loaded
198 // Let's load all required history
199 Main.worker.submit(new HistoryLoaderAndListener(toLoadNext));
[4734]200 }
201 }
202
203 @Override
204 public void historyDataSetCleared(HistoryDataSet source) {
205 }
206 }
[4530]207}
Note: See TracBrowser for help on using the repository browser.