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

Last change on this file since 10670 was 10106, checked in by Don-vip, 8 years ago

fix coverity 1353523 + 1347995

  • 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 * Main.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.ensureValidPrimitiveId(pid, "pid");
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.getId() &gt; 0 required.
116 * @return this task
117 * @throws IllegalArgumentException if the primitive is null
118 * @throws IllegalArgumentException if primitive.getId() &lt;= 0
119 */
120 public HistoryLoadTask add(OsmPrimitive primitive) {
121 CheckParameterUtil.ensureValidPrimitiveId(primitive, "primitive");
122 return add(primitive.getPrimitiveId());
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 continue;
139 }
140 add(primitive);
141 }
142 return this;
143 }
144
145 @Override
146 protected void cancel() {
147 if (reader != null) {
148 reader.cancel();
149 }
150 canceled = true;
151 }
152
153 @Override
154 protected void finish() {
155 if (isCanceled())
156 return;
157 if (lastException != null) {
158 ExceptionDialogUtil.explainException(lastException);
159 return;
160 }
161 HistoryDataSet.getInstance().mergeInto(loadedData);
162 }
163
164 @Override
165 protected void realRun() throws SAXException, IOException, OsmTransferException {
166 loadedData = new HistoryDataSet();
167 try {
168 progressMonitor.setTicksCount(toLoad.size());
169 for (PrimitiveId pid: toLoad) {
170 if (canceled) {
171 break;
172 }
173 String msg = getLoadingMessage(pid);
174 progressMonitor.indeterminateSubTask(tr(msg, Long.toString(pid.getUniqueId())));
175 reader = null;
176 HistoryDataSet ds;
177 try {
178 reader = new OsmServerHistoryReader(pid.getType(), pid.getUniqueId());
179 ds = loadHistory(reader, progressMonitor);
180 } catch (OsmTransferException e) {
181 if (canceled)
182 return;
183 throw e;
184 }
185 loadedData.mergeInto(ds);
186 }
187 } catch (OsmTransferException e) {
188 lastException = e;
189 return;
190 }
191 }
192
193 protected static HistoryDataSet loadHistory(OsmServerHistoryReader reader, ProgressMonitor progressMonitor) throws OsmTransferException {
194 HistoryDataSet ds = reader.parseHistory(progressMonitor.createSubTaskMonitor(1, false));
195 if (ds != null) {
196 // load corresponding changesets (mostly for changeset comment)
197 OsmServerChangesetReader changesetReader = new OsmServerChangesetReader();
198 List<Long> changesetIds = new ArrayList<>(ds.getChangesetIds());
199
200 // query changesets 100 by 100 (OSM API limit)
201 int n = ChangesetQuery.MAX_CHANGESETS_NUMBER;
202 for (int i = 0; i < changesetIds.size(); i += n) {
203 for (Changeset c : changesetReader.queryChangesets(
204 new ChangesetQuery().forChangesetIds(changesetIds.subList(i, Math.min(i + n, changesetIds.size()))),
205 progressMonitor.createSubTaskMonitor(1, false))) {
206 ds.putChangeset(c);
207 }
208 }
209 }
210 return ds;
211 }
212
213 protected static String getLoadingMessage(PrimitiveId pid) {
214 switch (pid.getType()) {
215 case NODE:
216 return marktr("Loading history for node {0}");
217 case WAY:
218 return marktr("Loading history for way {0}");
219 case RELATION:
220 return marktr("Loading history for relation {0}");
221 default:
222 return "";
223 }
224 }
225
226 /**
227 * Determines if this task has ben canceled.
228 * @return {@code true} if this task has ben canceled
229 */
230 public boolean isCanceled() {
231 return canceled;
232 }
233
234 /**
235 * Returns the last exception that occured during loading, if any.
236 * @return the last exception that occured during loading, or {@code null}
237 */
238 public Exception getLastException() {
239 return lastException;
240 }
241}
Note: See TracBrowser for help on using the repository browser.