001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs.relation; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.io.IOException; 007import java.util.Collection; 008 009import javax.swing.SwingUtilities; 010 011import org.openstreetmap.josm.Main; 012import org.openstreetmap.josm.data.osm.DataSet; 013import org.openstreetmap.josm.data.osm.DataSetMerger; 014import org.openstreetmap.josm.data.osm.Relation; 015import org.openstreetmap.josm.gui.DefaultNameFormatter; 016import org.openstreetmap.josm.gui.ExceptionDialogUtil; 017import org.openstreetmap.josm.gui.PleaseWaitRunnable; 018import org.openstreetmap.josm.gui.layer.OsmDataLayer; 019import org.openstreetmap.josm.io.OsmServerObjectReader; 020import org.openstreetmap.josm.io.OsmTransferException; 021import org.openstreetmap.josm.tools.CheckParameterUtil; 022import org.xml.sax.SAXException; 023 024/** 025 * The asynchronous task for fully downloading a collection of relations. Does a full download 026 * for each relations and merges the relation into an {@link OsmDataLayer} 027 * 028 */ 029public class DownloadRelationTask extends PleaseWaitRunnable { 030 private boolean canceled; 031 private Exception lastException; 032 private final Collection<Relation> relations; 033 private final OsmDataLayer layer; 034 private OsmServerObjectReader objectReader; 035 036 /** 037 * Creates the download task 038 * 039 * @param relations a collection of relations. Must not be null. 040 * @param layer the layer which data is to be merged into 041 * @throws IllegalArgumentException if relations is null 042 * @throws IllegalArgumentException if layer is null 043 */ 044 public DownloadRelationTask(Collection<Relation> relations, OsmDataLayer layer) { 045 super(tr("Download relations"), false /* don't ignore exception */); 046 CheckParameterUtil.ensureParameterNotNull(relations, "relations"); 047 CheckParameterUtil.ensureParameterNotNull(layer, "layer"); 048 this.relations = relations; 049 this.layer = layer; 050 } 051 052 @Override 053 protected void cancel() { 054 canceled = true; 055 synchronized (this) { 056 if (objectReader != null) { 057 objectReader.cancel(); 058 } 059 } 060 } 061 062 @Override 063 protected void finish() { 064 if (canceled) 065 return; 066 if (lastException != null) { 067 ExceptionDialogUtil.explainException(lastException); 068 } 069 } 070 071 @Override 072 protected void realRun() throws SAXException, IOException, OsmTransferException { 073 try { 074 final DataSet allDownloads = new DataSet(); 075 int i = 0; 076 getProgressMonitor().setTicksCount(relations.size()); 077 for (Relation relation: relations) { 078 i++; 079 getProgressMonitor().setCustomText(tr("({0}/{1}): Downloading relation ''{2}''...", i, relations.size(), 080 relation.getDisplayName(DefaultNameFormatter.getInstance()))); 081 synchronized (this) { 082 if (canceled) return; 083 objectReader = new OsmServerObjectReader(relation.getPrimitiveId(), true /* full download */); 084 } 085 DataSet dataSet = objectReader.parseOsm( 086 getProgressMonitor().createSubTaskMonitor(0, false) 087 ); 088 if (dataSet == null) 089 return; 090 synchronized (this) { 091 if (canceled) return; 092 objectReader = null; 093 } 094 DataSetMerger merger = new DataSetMerger(allDownloads, dataSet); 095 merger.merge(); 096 getProgressMonitor().worked(1); 097 } 098 099 SwingUtilities.invokeAndWait( 100 new Runnable() { 101 @Override 102 public void run() { 103 layer.mergeFrom(allDownloads); 104 layer.onPostDownloadFromServer(); 105 Main.map.repaint(); 106 } 107 } 108 ); 109 } catch (Exception e) { 110 if (canceled) { 111 Main.warn(tr("Ignoring exception because task was canceled. Exception: {0}", e.toString())); 112 return; 113 } 114 lastException = e; 115 } 116 } 117}