001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs.relation; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005import static org.openstreetmap.josm.tools.I18n.trn; 006 007import java.awt.Dialog; 008import java.io.IOException; 009import java.util.Collection; 010import java.util.HashSet; 011import java.util.Set; 012 013import javax.swing.SwingUtilities; 014 015import org.openstreetmap.josm.Main; 016import org.openstreetmap.josm.data.osm.DataSet; 017import org.openstreetmap.josm.data.osm.OsmPrimitive; 018import org.openstreetmap.josm.data.osm.Relation; 019import org.openstreetmap.josm.gui.DefaultNameFormatter; 020import org.openstreetmap.josm.gui.ExceptionDialogUtil; 021import org.openstreetmap.josm.gui.PleaseWaitRunnable; 022import org.openstreetmap.josm.gui.layer.OsmDataLayer; 023import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor; 024import org.openstreetmap.josm.gui.progress.ProgressMonitor; 025import org.openstreetmap.josm.io.MultiFetchServerObjectReader; 026import org.openstreetmap.josm.io.OsmTransferException; 027import org.xml.sax.SAXException; 028 029/** 030 * The asynchronous task for downloading relation members. 031 * 032 */ 033public class DownloadRelationMemberTask extends PleaseWaitRunnable { 034 private boolean canceled; 035 private Exception lastException; 036 private final Set<Relation> parents = new HashSet<>(); 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.isEmpty()) { 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 @Override 138 public void run() { 139 curLayer.mergeFrom(dataSet); 140 curLayer.onPostDownloadFromServer(); 141 } 142 } 143 ); 144 145 } catch (Exception e) { 146 if (canceled) { 147 Main.warn(tr("Ignoring exception because task was canceled. Exception: {0}", e.toString())); 148 return; 149 } 150 lastException = e; 151 } 152 } 153}