001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions.downloadtasks; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Component; 007import java.io.IOException; 008import java.text.MessageFormat; 009import java.util.ArrayList; 010import java.util.Collection; 011import java.util.Collections; 012import java.util.List; 013 014import org.openstreetmap.josm.Main; 015import org.openstreetmap.josm.data.osm.Changeset; 016import org.openstreetmap.josm.data.osm.ChangesetCache; 017import org.openstreetmap.josm.data.osm.ChangesetDataSet; 018import org.openstreetmap.josm.gui.ExceptionDialogUtil; 019import org.openstreetmap.josm.io.OsmTransferCanceledException; 020import org.openstreetmap.josm.io.OsmTransferException; 021import org.xml.sax.SAXException; 022 023/** 024 * This is an asynchronous task for downloading the changeset content of a collection of changesets. 025 * @since 2689 026 */ 027public class ChangesetContentDownloadTask extends AbstractChangesetDownloadTask { 028 029 class DownloadTask extends RunnableDownloadTask { 030 /** the list of changeset ids to download */ 031 private final List<Integer> toDownload = new ArrayList<>(); 032 033 DownloadTask(Component parent, Collection<Integer> ids) { 034 super(parent, tr("Downloading changeset content")); 035 for (Integer id: ids != null ? ids : Collections.<Integer>emptyList()) { 036 if (id == null || id <= 0) { 037 continue; 038 } 039 toDownload.add(id); 040 } 041 } 042 043 /** 044 * Downloads the changeset with id <code>changesetId</code> (only "header" information, no content) 045 * 046 * @param changesetId the changeset id 047 * @throws OsmTransferException if something went wrong 048 */ 049 protected void downloadChangeset(int changesetId) throws OsmTransferException { 050 Changeset cs = reader.readChangeset(changesetId, false, getProgressMonitor().createSubTaskMonitor(0, false)); 051 ChangesetCache.getInstance().update(cs); 052 } 053 054 @Override 055 protected void realRun() throws SAXException, IOException, OsmTransferException { 056 try { 057 getProgressMonitor().setTicksCount(toDownload.size()); 058 int i = 0; 059 for (int id: toDownload) { 060 i++; 061 if (!isAvailableLocally(id)) { 062 getProgressMonitor().setCustomText(tr("({0}/{1}) Downloading changeset {2}...", i, toDownload.size(), id)); 063 downloadChangeset(id); 064 } 065 if (isCanceled()) 066 return; 067 getProgressMonitor().setCustomText(tr("({0}/{1}) Downloading content for changeset {2}...", i, toDownload.size(), id)); 068 ChangesetDataSet ds = reader.downloadChangeset(id, getProgressMonitor().createSubTaskMonitor(0, false)); 069 Changeset cs = ChangesetCache.getInstance().get(id); 070 cs.setContent(ds); 071 ChangesetCache.getInstance().update(cs); 072 downloadedChangesets.add(cs); 073 getProgressMonitor().worked(1); 074 } 075 } catch (OsmTransferCanceledException e) { 076 // the download was canceled by the user. This exception is caught if the user canceled the authentication dialog. 077 setCanceled(true); 078 return; 079 } catch (OsmTransferException e) { 080 if (isCanceled()) 081 return; 082 rememberLastException(e); 083 } 084 } 085 086 @Override 087 protected void finish() { 088 rememberDownloadedData(downloadedChangesets); 089 if (isCanceled()) 090 return; 091 if (lastException != null) { 092 ExceptionDialogUtil.explainException(lastException); 093 } 094 } 095 } 096 097 /** 098 * Creates a download task for a single changeset 099 * 100 * @param changesetId the changeset id. > 0 required. 101 * @throws IllegalArgumentException if changesetId <= 0 102 */ 103 public ChangesetContentDownloadTask(int changesetId) { 104 this(Main.parent, changesetId); 105 } 106 107 /** 108 * Creates a download task for a collection of changesets. null values and id <=0 in 109 * the collection are silently discarded. 110 * 111 * @param changesetIds the changeset ids. Empty collection assumed, if null. 112 */ 113 public ChangesetContentDownloadTask(Collection<Integer> changesetIds) { 114 this(Main.parent, changesetIds); 115 } 116 117 /** 118 * Creates a download task for a single changeset 119 * 120 * @param parent the parent component for the {@link org.openstreetmap.josm.gui.PleaseWaitDialog}. Must not be {@code null}. 121 * @param changesetId the changeset id. {@code >0} required. 122 * @throws IllegalArgumentException if {@code changesetId <= 0} 123 * @throws IllegalArgumentException if parent is {@code null} 124 */ 125 public ChangesetContentDownloadTask(Component parent, int changesetId) { 126 if (changesetId <= 0) 127 throw new IllegalArgumentException( 128 MessageFormat.format("Expected integer value > 0 for parameter ''{0}'', got ''{1}''", "changesetId", changesetId)); 129 setDownloadTask(new DownloadTask(parent, Collections.singleton(changesetId))); 130 } 131 132 /** 133 * Creates a download task for a collection of changesets. null values and id <=0 in 134 * the collection are sillently discarded. 135 * 136 * @param parent the parent component for the {@link org.openstreetmap.josm.gui.PleaseWaitDialog}. Must not be {@code null}. 137 * @param changesetIds the changeset ids. Empty collection assumed, if {@code null}. 138 * @throws IllegalArgumentException if parent is {@code null} 139 */ 140 public ChangesetContentDownloadTask(Component parent, Collection<Integer> changesetIds) { 141 setDownloadTask(new DownloadTask(parent, changesetIds)); 142 } 143 144 /** 145 * Replies true if the local {@link ChangesetCache} already includes the changeset with 146 * id <code>changesetId</code>. 147 * 148 * @param changesetId the changeset id 149 * @return true if the local {@link ChangesetCache} already includes the changeset with 150 * id <code>changesetId</code> 151 */ 152 protected static boolean isAvailableLocally(int changesetId) { 153 return ChangesetCache.getInstance().get(changesetId) != null; 154 } 155}