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 }