source: josm/trunk/src/org/openstreetmap/josm/gui/io/DownloadPrimitivesWithReferrersTask.java@ 13691

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

fix #16096 - allow only positive ids in DownloadPrimitivesWithReferrersTask constructor

  • Property svn:eol-style set to native
File size: 9.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.awt.Font;
8import java.awt.GridBagLayout;
9import java.io.IOException;
10import java.text.MessageFormat;
11import java.util.ArrayList;
12import java.util.HashSet;
13import java.util.List;
14import java.util.Set;
15
16import javax.swing.JLabel;
17import javax.swing.JOptionPane;
18import javax.swing.JPanel;
19import javax.swing.JScrollPane;
20
21import org.openstreetmap.josm.Main;
22import org.openstreetmap.josm.actions.downloadtasks.DownloadReferrersTask;
23import org.openstreetmap.josm.data.osm.DataSet;
24import org.openstreetmap.josm.data.osm.OsmPrimitive;
25import org.openstreetmap.josm.data.osm.PrimitiveId;
26import org.openstreetmap.josm.gui.ExtendedDialog;
27import org.openstreetmap.josm.gui.MainApplication;
28import org.openstreetmap.josm.gui.PleaseWaitRunnable;
29import org.openstreetmap.josm.gui.layer.OsmDataLayer;
30import org.openstreetmap.josm.gui.progress.ProgressMonitor;
31import org.openstreetmap.josm.gui.util.GuiHelper;
32import org.openstreetmap.josm.gui.widgets.HtmlPanel;
33import org.openstreetmap.josm.gui.widgets.JosmTextArea;
34import org.openstreetmap.josm.io.OsmTransferException;
35import org.openstreetmap.josm.tools.GBC;
36import org.openstreetmap.josm.tools.Utils;
37import org.xml.sax.SAXException;
38
39/**
40 * Task for downloading a set of primitives with all referrers.
41 */
42public class DownloadPrimitivesWithReferrersTask extends PleaseWaitRunnable {
43 /** If true download into a new layer */
44 private final boolean newLayer;
45 /** List of primitives id to download */
46 private final List<PrimitiveId> ids;
47 /** If true, download members for relation */
48 private final boolean full;
49 /** If true, download also referrers */
50 private final boolean downloadReferrers;
51
52 /** Temporary layer where downloaded primitives are put */
53 private final OsmDataLayer tmpLayer;
54 /** Reference to the task that download requested primitives */
55 private DownloadPrimitivesTask mainTask;
56 /** Flag indicated that user ask for cancel this task */
57 private boolean canceled;
58 /** Reference to the task currently running */
59 private PleaseWaitRunnable currentTask;
60
61 /**
62 * Constructor
63 *
64 * @param newLayer if the data should be downloaded into a new layer
65 * @param ids List of primitive id to download
66 * @param downloadReferrers if the referrers of the object should be downloaded as well,
67 * i.e., parent relations, and for nodes, additionally, parent ways
68 * @param full if the members of a relation should be downloaded as well
69 * @param newLayerName the name to use for the new layer, can be {@code null}.
70 * @param monitor ProgressMonitor to use, or null to create a new one
71 */
72 public DownloadPrimitivesWithReferrersTask(boolean newLayer, List<PrimitiveId> ids, boolean downloadReferrers,
73 boolean full, String newLayerName, ProgressMonitor monitor) {
74 super(tr("Download objects"), monitor, false);
75 this.ids = ids;
76 this.downloadReferrers = downloadReferrers;
77 this.full = full;
78 this.newLayer = newLayer;
79 // Check we don't try to download new primitives
80 for (PrimitiveId primitiveId : ids) {
81 if (primitiveId.isNew()) {
82 throw new IllegalArgumentException(MessageFormat.format(
83 "Cannot download new primitives (ID {0})", primitiveId.getUniqueId()));
84 }
85 }
86 // All downloaded primitives are put in a tmpLayer
87 tmpLayer = new OsmDataLayer(new DataSet(), newLayerName != null ? newLayerName : OsmDataLayer.createNewName(), null);
88 }
89
90 /**
91 * Cancel recursively the task. Do not call directly
92 * @see DownloadPrimitivesWithReferrersTask#operationCanceled()
93 */
94 @Override
95 protected void cancel() {
96 synchronized (this) {
97 canceled = true;
98 if (currentTask != null)
99 currentTask.operationCanceled();
100 }
101 }
102
103 @Override
104 protected void realRun() throws SAXException, IOException, OsmTransferException {
105 getProgressMonitor().setTicksCount(ids.size()+1);
106 // First, download primitives
107 mainTask = new DownloadPrimitivesTask(tmpLayer, ids, full, getProgressMonitor().createSubTaskMonitor(1, false));
108 synchronized (this) {
109 currentTask = mainTask;
110 if (canceled) {
111 currentTask = null;
112 return;
113 }
114 }
115 currentTask.run();
116 // Then, download referrers for each primitive
117 if (downloadReferrers)
118 for (PrimitiveId id : ids) {
119 synchronized (this) {
120 if (canceled) {
121 currentTask = null;
122 return;
123 }
124 currentTask = new DownloadReferrersTask(
125 tmpLayer, id, getProgressMonitor().createSubTaskMonitor(1, false));
126 }
127 currentTask.run();
128 }
129 currentTask = null;
130 }
131
132 @Override
133 protected void finish() {
134 synchronized (this) {
135 if (canceled)
136 return;
137 }
138
139 // Append downloaded data to JOSM
140 OsmDataLayer layer = MainApplication.getLayerManager().getEditLayer();
141 if (layer == null || this.newLayer || !layer.isDownloadable())
142 MainApplication.getLayerManager().addLayer(tmpLayer);
143 else
144 layer.mergeFrom(tmpLayer);
145
146 // Warm about missing primitives
147 final Set<PrimitiveId> errs = mainTask.getMissingPrimitives();
148 if (errs != null && !errs.isEmpty())
149 GuiHelper.runInEDTAndWait(() -> reportProblemDialog(errs,
150 trn("Object could not be downloaded", "Some objects could not be downloaded", errs.size()),
151 trn("One object could not be downloaded.<br>",
152 "{0} objects could not be downloaded.<br>",
153 errs.size(),
154 errs.size())
155 + tr("The server replied with response code 404.<br>"
156 + "This usually means, the server does not know an object with the requested id."),
157 tr("missing objects:"),
158 JOptionPane.ERROR_MESSAGE
159 ).showDialog());
160
161 // Warm about deleted primitives
162 final Set<PrimitiveId> del = new HashSet<>();
163 DataSet ds = MainApplication.getLayerManager().getEditDataSet();
164 for (PrimitiveId id : ids) {
165 OsmPrimitive osm = ds.getPrimitiveById(id);
166 if (osm != null && osm.isDeleted()) {
167 del.add(id);
168 }
169 }
170 if (!del.isEmpty())
171 GuiHelper.runInEDTAndWait(() -> reportProblemDialog(del,
172 trn("Object deleted", "Objects deleted", del.size()),
173 trn(
174 "One downloaded object is deleted.",
175 "{0} downloaded objects are deleted.",
176 del.size(),
177 del.size()),
178 null,
179 JOptionPane.WARNING_MESSAGE
180 ).showDialog());
181 }
182
183 /**
184 * Return id of really downloaded primitives.
185 * @return List of primitives id or null if no primitives was downloaded
186 */
187 public List<PrimitiveId> getDownloadedId() {
188 synchronized (this) {
189 if (canceled)
190 return null;
191 }
192 List<PrimitiveId> downloaded = new ArrayList<>(ids);
193 downloaded.removeAll(mainTask.getMissingPrimitives());
194 return downloaded;
195 }
196
197 /**
198 * Dialog for report a problem during download.
199 * @param errs Primitives involved
200 * @param title Title of dialog
201 * @param text Detail message
202 * @param listLabel List of primitives description
203 * @param msgType Type of message, see {@link JOptionPane}
204 * @return The Dialog object
205 */
206 private static ExtendedDialog reportProblemDialog(Set<PrimitiveId> errs,
207 String title, String text, String listLabel, int msgType) {
208 JPanel p = new JPanel(new GridBagLayout());
209 p.add(new HtmlPanel(text), GBC.eop());
210 JosmTextArea txt = new JosmTextArea();
211 if (listLabel != null) {
212 JLabel missing = new JLabel(listLabel);
213 missing.setFont(missing.getFont().deriveFont(Font.PLAIN));
214 missing.setLabelFor(txt);
215 p.add(missing, GBC.eol());
216 }
217 txt.setFont(GuiHelper.getMonospacedFont(txt));
218 txt.setEditable(false);
219 txt.setBackground(p.getBackground());
220 txt.setColumns(40);
221 txt.setRows(1);
222 txt.setText(Utils.join(", ", errs));
223 JScrollPane scroll = new JScrollPane(txt);
224 p.add(scroll, GBC.eop().weight(1.0, 0.0).fill(GBC.HORIZONTAL));
225
226 return new ExtendedDialog(
227 Main.parent,
228 title,
229 tr("Ok"))
230 .setButtonIcons("ok")
231 .setIcon(msgType)
232 .setContent(p, false);
233 }
234}
Note: See TracBrowser for help on using the repository browser.