source: josm/trunk/src/org/openstreetmap/josm/gui/history/HistoryLoadTask.java@ 13924

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

add IPrimitive.getOsm*Id()

  • 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.history;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.Component;
8import java.io.IOException;
9import java.util.ArrayList;
10import java.util.Collection;
11import java.util.HashSet;
12import java.util.List;
13import java.util.Set;
14
15import org.openstreetmap.josm.data.osm.Changeset;
16import org.openstreetmap.josm.data.osm.OsmPrimitive;
17import org.openstreetmap.josm.data.osm.PrimitiveId;
18import org.openstreetmap.josm.data.osm.history.History;
19import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
20import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
21import org.openstreetmap.josm.gui.ExceptionDialogUtil;
22import org.openstreetmap.josm.gui.PleaseWaitRunnable;
23import org.openstreetmap.josm.gui.progress.ProgressMonitor;
24import org.openstreetmap.josm.io.ChangesetQuery;
25import org.openstreetmap.josm.io.OsmServerChangesetReader;
26import org.openstreetmap.josm.io.OsmServerHistoryReader;
27import org.openstreetmap.josm.io.OsmTransferException;
28import org.openstreetmap.josm.tools.CheckParameterUtil;
29import org.xml.sax.SAXException;
30
31/**
32 * Loads the object history of a collection of objects from the server.
33 *
34 * It provides a fluent API for configuration.
35 *
36 * Sample usage:
37 *
38 * <pre>
39 * HistoryLoadTask task = new HistoryLoadTask()
40 * .add(node)
41 * .add(way)
42 * .add(relation)
43 * .add(aHistoryItem);
44 *
45 * MainApplication.worker.execute(task);
46 * </pre>
47 */
48public class HistoryLoadTask extends PleaseWaitRunnable {
49
50 private boolean canceled;
51 private Exception lastException;
52 private final Set<PrimitiveId> toLoad = new HashSet<>();
53 private HistoryDataSet loadedData;
54 private OsmServerHistoryReader reader;
55
56 /**
57 * Constructs a new {@code HistoryLoadTask}.
58 */
59 public HistoryLoadTask() {
60 super(tr("Load history"), true);
61 }
62
63 /**
64 * Constructs a new {@code HistoryLoadTask}.
65 *
66 * @param parent the component to be used as reference to find the
67 * parent for {@link org.openstreetmap.josm.gui.PleaseWaitDialog}.
68 * Must not be <code>null</code>.
69 * @throws IllegalArgumentException if parent is <code>null</code>
70 */
71 public HistoryLoadTask(Component parent) {
72 super(parent, tr("Load history"), true);
73 CheckParameterUtil.ensureParameterNotNull(parent, "parent");
74 }
75
76 /**
77 * Adds an object whose history is to be loaded.
78 *
79 * @param pid the primitive id. Must not be null. Id &gt; 0 required.
80 * @return this task
81 */
82 public HistoryLoadTask add(PrimitiveId pid) {
83 CheckParameterUtil.ensure(pid, "pid", "pid > 0", id -> id.getUniqueId() > 0);
84 toLoad.add(pid);
85 return this;
86 }
87
88 /**
89 * Adds an object to be loaded, the object is specified by a history item.
90 *
91 * @param primitive the history item
92 * @return this task
93 * @throws IllegalArgumentException if primitive is null
94 */
95 public HistoryLoadTask add(HistoryOsmPrimitive primitive) {
96 CheckParameterUtil.ensureParameterNotNull(primitive, "primitive");
97 return add(primitive.getPrimitiveId());
98 }
99
100 /**
101 * Adds an object to be loaded, the object is specified by an already loaded object history.
102 *
103 * @param history the history. Must not be null.
104 * @return this task
105 * @throws IllegalArgumentException if history is null
106 */
107 public HistoryLoadTask add(History history) {
108 CheckParameterUtil.ensureParameterNotNull(history, "history");
109 return add(history.getPrimitiveId());
110 }
111
112 /**
113 * Adds an object to be loaded, the object is specified by an OSM primitive.
114 *
115 * @param primitive the OSM primitive. Must not be null. primitive.getOsmId() &gt; 0 required.
116 * @return this task
117 * @throws IllegalArgumentException if the primitive is null
118 * @throws IllegalArgumentException if primitive.getOsmId() &lt;= 0
119 */
120 public HistoryLoadTask add(OsmPrimitive primitive) {
121 CheckParameterUtil.ensure(primitive, "primitive", "id > 0", prim -> prim.getOsmId() > 0);
122 return add(primitive.getOsmPrimitiveId());
123 }
124
125 /**
126 * Adds a collection of objects to loaded, specified by a collection of OSM primitives.
127 *
128 * @param primitives the OSM primitives. Must not be <code>null</code>.
129 * <code>primitive.getId() &gt; 0</code> required.
130 * @return this task
131 * @throws IllegalArgumentException if primitives is <code>null</code>
132 * @throws IllegalArgumentException if one of the ids in the collection &lt;= 0
133 */
134 public HistoryLoadTask add(Collection<? extends OsmPrimitive> primitives) {
135 CheckParameterUtil.ensureParameterNotNull(primitives, "primitives");
136 for (OsmPrimitive primitive: primitives) {
137 if (primitive != null) {
138 add(primitive);
139 }
140 }
141 return this;
142 }
143
144 @Override
145 protected void cancel() {
146 if (reader != null) {
147 reader.cancel();
148 }
149 canceled = true;
150 }
151
152 @Override
153 protected void finish() {
154 if (isCanceled())
155 return;
156 if (lastException != null) {
157 ExceptionDialogUtil.explainException(lastException);
158 return;
159 }
160 HistoryDataSet.getInstance().mergeInto(loadedData);
161 }
162
163 @Override
164 protected void realRun() throws SAXException, IOException, OsmTransferException {
165 loadedData = new HistoryDataSet();
166 try {
167 progressMonitor.setTicksCount(toLoad.size());
168 for (PrimitiveId pid: toLoad) {
169 if (canceled) {
170 break;
171 }
172 loadHistory(pid);
173 }
174 } catch (OsmTransferException e) {
175 lastException = e;
176 }
177 }
178
179 private void loadHistory(PrimitiveId pid) throws OsmTransferException {
180 String msg = getLoadingMessage(pid);
181 progressMonitor.indeterminateSubTask(tr(msg, Long.toString(pid.getUniqueId())));
182 reader = null;
183 HistoryDataSet ds;
184 try {
185 reader = new OsmServerHistoryReader(pid.getType(), pid.getUniqueId());
186 ds = loadHistory(reader, progressMonitor);
187 } catch (OsmTransferException e) {
188 if (canceled)
189 return;
190 throw e;
191 }
192 loadedData.mergeInto(ds);
193 }
194
195 protected static HistoryDataSet loadHistory(OsmServerHistoryReader reader, ProgressMonitor progressMonitor) throws OsmTransferException {
196 HistoryDataSet ds = reader.parseHistory(progressMonitor.createSubTaskMonitor(1, false));
197 if (ds != null) {
198 // load corresponding changesets (mostly for changeset comment)
199 OsmServerChangesetReader changesetReader = new OsmServerChangesetReader();
200 List<Long> changesetIds = new ArrayList<>(ds.getChangesetIds());
201
202 // query changesets 100 by 100 (OSM API limit)
203 int n = ChangesetQuery.MAX_CHANGESETS_NUMBER;
204 for (int i = 0; i < changesetIds.size(); i += n) {
205 for (Changeset c : changesetReader.queryChangesets(
206 new ChangesetQuery().forChangesetIds(changesetIds.subList(i, Math.min(i + n, changesetIds.size()))),
207 progressMonitor.createSubTaskMonitor(1, false))) {
208 ds.putChangeset(c);
209 }
210 }
211 }
212 return ds;
213 }
214
215 protected static String getLoadingMessage(PrimitiveId pid) {
216 switch (pid.getType()) {
217 case NODE:
218 return marktr("Loading history for node {0}");
219 case WAY:
220 return marktr("Loading history for way {0}");
221 case RELATION:
222 return marktr("Loading history for relation {0}");
223 default:
224 return "";
225 }
226 }
227
228 /**
229 * Determines if this task has ben canceled.
230 * @return {@code true} if this task has ben canceled
231 */
232 public boolean isCanceled() {
233 return canceled;
234 }
235
236 /**
237 * Returns the last exception that occured during loading, if any.
238 * @return the last exception that occured during loading, or {@code null}
239 */
240 public Exception getLastException() {
241 return lastException;
242 }
243}
Note: See TracBrowser for help on using the repository browser.