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

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

see #19334 - javadoc fixes + protected constructors for abstract classes

  • Property svn:eol-style set to native
File size: 9.3 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;
15import java.util.stream.Collectors;
16
17import javax.swing.JLabel;
18import javax.swing.JOptionPane;
19import javax.swing.JPanel;
20import javax.swing.JScrollPane;
21
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.xml.sax.SAXException;
37
38/**
39 * Task for downloading a set of primitives with all referrers.
40 */
41public class DownloadPrimitivesWithReferrersTask extends PleaseWaitRunnable {
42 /** If true download into a new layer */
43 private final boolean newLayer;
44 /** List of primitives id to download */
45 private final List<PrimitiveId> ids;
46 /** If true, download members for relation */
47 private final boolean full;
48 /** If true, download also referrers */
49 private final boolean downloadReferrers;
50
51 /** Temporary layer where downloaded primitives are put */
52 private final OsmDataLayer tmpLayer;
53 /** Reference to the task that download requested primitives */
54 private DownloadPrimitivesTask mainTask;
55 /** Flag indicated that user ask for cancel this task */
56 private boolean canceled;
57 /** Reference to the task currently running */
58 private PleaseWaitRunnable currentTask;
59
60 /**
61 * Constructor
62 *
63 * @param newLayer if the data should be downloaded into a new layer
64 * @param ids List of primitive id to download
65 * @param downloadReferrers if the referrers of the object should be downloaded as well,
66 * i.e., parent relations, and for nodes, additionally, parent ways
67 * @param full if the members of a relation should be downloaded as well
68 * @param newLayerName the name to use for the new layer, can be null.
69 * @param monitor ProgressMonitor to use, or null to create a new one
70 */
71 public DownloadPrimitivesWithReferrersTask(boolean newLayer, List<PrimitiveId> ids, boolean downloadReferrers,
72 boolean full, String newLayerName, ProgressMonitor monitor) {
73 super(tr("Download objects"), monitor, false);
74 this.ids = ids;
75 this.downloadReferrers = downloadReferrers;
76 this.full = full;
77 this.newLayer = newLayer;
78 // Check we don't try to download new primitives
79 for (PrimitiveId primitiveId : ids) {
80 if (primitiveId.isNew()) {
81 throw new IllegalArgumentException(MessageFormat.format(
82 "Cannot download new primitives (ID {0})", primitiveId.getUniqueId()));
83 }
84 }
85 // All downloaded primitives are put in a tmpLayer
86 tmpLayer = new OsmDataLayer(new DataSet(), newLayerName != null ? newLayerName : OsmDataLayer.createNewName(), null);
87 }
88
89 /**
90 * Cancel recursively the task. Do not call directly
91 * @see DownloadPrimitivesWithReferrersTask#operationCanceled()
92 */
93 @Override
94 protected void cancel() {
95 synchronized (this) {
96 canceled = true;
97 if (currentTask != null)
98 currentTask.operationCanceled();
99 }
100 }
101
102 @Override
103 protected void realRun() throws SAXException, IOException, OsmTransferException {
104 getProgressMonitor().setTicksCount(ids.size()+1);
105 // First, download primitives
106 mainTask = new DownloadPrimitivesTask(tmpLayer, ids, full, getProgressMonitor().createSubTaskMonitor(1, false));
107 synchronized (this) {
108 currentTask = mainTask;
109 if (canceled) {
110 currentTask = null;
111 return;
112 }
113 }
114 currentTask.run();
115 // Then, download referrers for each primitive
116 if (downloadReferrers && tmpLayer.data != null) {
117 // see #18895: don't try to download parents for invisible objects
118 List<PrimitiveId> visible = ids.stream().map(tmpLayer.data::getPrimitiveById)
119 .filter(p -> p != null && p.isVisible()).collect(Collectors.toList());
120 if (!visible.isEmpty()) {
121 currentTask = new DownloadReferrersTask(tmpLayer, visible);
122 currentTask.run();
123 synchronized (this) {
124 if (currentTask.getProgressMonitor().isCanceled())
125 cancel();
126 }
127 }
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 ids of really downloaded primitives.
185 * @return List of primitives id or null if no primitives were 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 public 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(errs.stream().map(pid -> pid.getType().getAPIName().substring(0, 1) + pid.getUniqueId())
223 .collect(Collectors.joining(", ")));
224 JScrollPane scroll = new JScrollPane(txt);
225 p.add(scroll, GBC.eop().weight(1.0, 0.0).fill(GBC.HORIZONTAL));
226
227 return new ExtendedDialog(
228 MainApplication.getMainFrame(),
229 title,
230 tr("Ok"))
231 .setButtonIcons("ok")
232 .setIcon(msgType)
233 .setContent(p, false);
234 }
235}
Note: See TracBrowser for help on using the repository browser.