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 import static org.openstreetmap.josm.tools.I18n.trn; 006 007 import java.awt.Dialog; 008 import java.io.IOException; 009 import java.util.Collection; 010 import java.util.HashSet; 011 import java.util.Set; 012 013 import javax.swing.SwingUtilities; 014 015 import org.openstreetmap.josm.Main; 016 import org.openstreetmap.josm.data.osm.DataSet; 017 import org.openstreetmap.josm.data.osm.OsmPrimitive; 018 import org.openstreetmap.josm.data.osm.Relation; 019 import org.openstreetmap.josm.gui.DefaultNameFormatter; 020 import org.openstreetmap.josm.gui.ExceptionDialogUtil; 021 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 022 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 023 import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor; 024 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 025 import org.openstreetmap.josm.io.MultiFetchServerObjectReader; 026 import org.openstreetmap.josm.io.OsmTransferException; 027 import org.xml.sax.SAXException; 028 029 /** 030 * The asynchronous task for downloading relation members. 031 * 032 */ 033 public class DownloadRelationMemberTask extends PleaseWaitRunnable { 034 private boolean canceled; 035 private Exception lastException; 036 private final Set<Relation> parents = new HashSet<Relation>(); 037 private Collection<OsmPrimitive> children; 038 private OsmDataLayer curLayer; 039 private MultiFetchServerObjectReader objectReader; 040 041 public DownloadRelationMemberTask(Relation parent, Collection<OsmPrimitive> children, OsmDataLayer curLayer, Dialog dialog) { 042 super(tr("Download relation members"), new PleaseWaitProgressMonitor(dialog), false /* don't ignore exception */); 043 if(parent != null) 044 this.parents.add(parent); 045 this.children = children; 046 this.curLayer = curLayer; 047 } 048 049 public DownloadRelationMemberTask(Relation parent, Collection<OsmPrimitive> children, OsmDataLayer curLayer) { 050 super(tr("Download relation members"), false /* don't ignore exception */); 051 if(parent != null) 052 this.parents.add(parent); 053 this.children = children; 054 this.curLayer = curLayer; 055 } 056 057 /** 058 * Creates a download task for downloading the child primitives {@code children} for all parent 059 * relations in {@code parents}. 060 * 061 * @param parents the collection of parent relations 062 * @param children the collection of child primitives to download 063 * @param curLayer the current OSM layer 064 */ 065 public DownloadRelationMemberTask(Collection<Relation> parents, Collection<OsmPrimitive> children, OsmDataLayer curLayer) { 066 super(tr("Download relation members"), false /* don't ignore exception */); 067 this.parents.addAll(parents); 068 this.children = children; 069 this.curLayer = curLayer; 070 } 071 072 @Override 073 protected void cancel() { 074 canceled = true; 075 synchronized(this) { 076 if (objectReader != null) { 077 objectReader.cancel(); 078 } 079 } 080 } 081 082 @Override 083 protected void finish() { 084 Main.map.repaint(); 085 if (canceled) 086 return; 087 if (lastException != null) { 088 ExceptionDialogUtil.explainException(lastException); 089 } 090 } 091 092 protected String buildDownloadFeedbackMessage() { 093 if (parents.size() == 0) { 094 return trn("Downloading {0} incomplete object", 095 "Downloading {0} incomplete objects", 096 children.size(), 097 children.size()); 098 } else if (parents.size() == 1) { 099 Relation parent = parents.iterator().next(); 100 return trn("Downloading {0} incomplete child of relation ''{1}''", 101 "Downloading {0} incomplete children of relation ''{1}''", 102 children.size(), 103 children.size(), 104 parent.getDisplayName(DefaultNameFormatter.getInstance())); 105 } else { 106 return trn("Downloading {0} incomplete child of {1} parent relations", 107 "Downloading {0} incomplete children of {1} parent relations", 108 children.size(), 109 children.size(), 110 parents.size()); 111 } 112 } 113 114 @Override 115 protected void realRun() throws SAXException, IOException, OsmTransferException { 116 try { 117 synchronized (this) { 118 if (canceled) return; 119 objectReader = new MultiFetchServerObjectReader(); 120 } 121 objectReader.append(children); 122 progressMonitor.indeterminateSubTask( 123 buildDownloadFeedbackMessage() 124 ); 125 final DataSet dataSet = objectReader.parseOsm(progressMonitor 126 .createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)); 127 if (dataSet == null) 128 return; 129 dataSet.deleteInvisible(); 130 synchronized (this) { 131 if (canceled) return; 132 objectReader = null; 133 } 134 135 SwingUtilities.invokeLater( 136 new Runnable() { 137 public void run() { 138 curLayer.mergeFrom(dataSet); 139 curLayer.onPostDownloadFromServer(); 140 } 141 } 142 ); 143 144 } catch (Exception e) { 145 if (canceled) { 146 System.out.println(tr("Warning: Ignoring exception because task was canceled. Exception: {0}", e 147 .toString())); 148 return; 149 } 150 lastException = e; 151 } 152 } 153 }