001 // License: GPL. For details, see LICENSE file. 002 package org.openstreetmap.josm.gui.dialogs.relation; 003 004 import static org.openstreetmap.josm.tools.I18n.tr; 005 006 import java.io.IOException; 007 import java.util.Collection; 008 009 import javax.swing.SwingUtilities; 010 011 import org.openstreetmap.josm.Main; 012 import org.openstreetmap.josm.data.osm.DataSet; 013 import org.openstreetmap.josm.data.osm.DataSetMerger; 014 import org.openstreetmap.josm.data.osm.Relation; 015 import org.openstreetmap.josm.gui.DefaultNameFormatter; 016 import org.openstreetmap.josm.gui.ExceptionDialogUtil; 017 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 018 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 019 import org.openstreetmap.josm.io.OsmServerObjectReader; 020 import org.openstreetmap.josm.io.OsmTransferException; 021 import org.openstreetmap.josm.tools.CheckParameterUtil; 022 import 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 */ 029 public class DownloadRelationTask extends PleaseWaitRunnable { 030 private boolean canceled; 031 private Exception lastException; 032 private Collection<Relation> relations; 033 private 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 thrown if relations is null 042 * @throws IllegalArgumentException thrown if layer is null 043 */ 044 public DownloadRelationTask(Collection<Relation> relations, OsmDataLayer layer) throws IllegalArgumentException{ 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(),relation.getDisplayName(DefaultNameFormatter.getInstance()))); 080 synchronized (this) { 081 if (canceled) return; 082 objectReader = new OsmServerObjectReader(relation.getPrimitiveId(), true /* full download */); 083 } 084 DataSet dataSet = objectReader.parseOsm( 085 getProgressMonitor().createSubTaskMonitor(0, false) 086 ); 087 if (dataSet == null) 088 return; 089 synchronized (this) { 090 if (canceled) return; 091 objectReader = null; 092 } 093 DataSetMerger merger = new DataSetMerger(allDownloads, dataSet); 094 merger.merge(); 095 getProgressMonitor().worked(1); 096 } 097 098 SwingUtilities.invokeAndWait( 099 new Runnable() { 100 public void run() { 101 layer.mergeFrom(allDownloads); 102 layer.onPostDownloadFromServer(); 103 Main.map.repaint(); 104 } 105 } 106 ); 107 } catch (Exception e) { 108 if (canceled) { 109 System.out.println(tr("Warning: Ignoring exception because task was canceled. Exception: {0}", e 110 .toString())); 111 return; 112 } 113 lastException = e; 114 } 115 } 116 }