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.util.Collection;
009import java.util.Collections;
010import java.util.HashSet;
011import java.util.Set;
012
013import org.openstreetmap.josm.data.osm.Changeset;
014import org.openstreetmap.josm.data.osm.ChangesetCache;
015import org.openstreetmap.josm.gui.ExceptionDialogUtil;
016import org.openstreetmap.josm.gui.MainApplication;
017import org.openstreetmap.josm.io.OsmTransferException;
018import org.openstreetmap.josm.tools.CheckParameterUtil;
019import org.xml.sax.SAXException;
020
021/**
022 * This is an asynchronous task for downloading a collection of changests from the OSM server.
023 *
024 * The  task only downloads the changeset properties without the changeset content. It
025 * updates the global {@link ChangesetCache}.
026 * @since 2613
027 */
028public class ChangesetHeaderDownloadTask extends AbstractChangesetDownloadTask {
029
030    class DownloadTask extends RunnableDownloadTask {
031        /** the list of changeset ids to download */
032        private final Set<Integer> toDownload = new HashSet<>();
033        /** whether to include discussions or not */
034        private final boolean includeDiscussion;
035
036        DownloadTask(Component parent, Collection<Integer> ids, boolean includeDiscussion) {
037            super(parent, tr("Download changesets"));
038            this.includeDiscussion = includeDiscussion;
039            for (int id: ids != null ? ids : Collections.<Integer>emptyList()) {
040                if (id <= 0) {
041                    continue;
042                }
043                toDownload.add(id);
044            }
045        }
046
047        @Override
048        protected void realRun() throws SAXException, IOException, OsmTransferException {
049            try {
050                downloadedChangesets.addAll(reader.readChangesets(toDownload, includeDiscussion,
051                        getProgressMonitor().createSubTaskMonitor(0, false)));
052            } catch (OsmTransferException e) {
053                if (isCanceled())
054                    // ignore exception if canceled
055                    return;
056                // remember other exceptions
057                rememberLastException(e);
058            }
059        }
060
061        @Override
062        protected void finish() {
063            rememberDownloadedData(downloadedChangesets);
064            if (isCanceled())
065                return;
066            if (lastException != null) {
067                ExceptionDialogUtil.explainException(lastException);
068            }
069            updateChangesets();
070        }
071    }
072
073    /**
074     * Creates the download task for a collection of changeset ids. Uses a {@link org.openstreetmap.josm.gui.PleaseWaitDialog}
075     * whose parent is {@link MainApplication#getMainFrame}.
076     *
077     * Null ids or or ids &lt;= 0 in the id collection are ignored.
078     *
079     * @param ids the collection of ids. Empty collection assumed if null.
080     */
081    public ChangesetHeaderDownloadTask(Collection<Integer> ids) {
082        this(MainApplication.getMainFrame(), ids, false);
083    }
084
085    /**
086     * Creates the download task for a collection of changeset ids. Uses a {@link org.openstreetmap.josm.gui.PleaseWaitDialog}
087     * whose parent is the parent window of <code>dialogParent</code>.
088     *
089     * Null ids or or ids &lt;= 0 in the id collection are ignored.
090     *
091     * @param dialogParent the parent reference component for the {@link org.openstreetmap.josm.gui.PleaseWaitDialog}. Must not be null.
092     * @param ids the collection of ids. Empty collection assumed if null.
093     * @throws IllegalArgumentException if dialogParent is null
094     */
095    public ChangesetHeaderDownloadTask(Component dialogParent, Collection<Integer> ids) {
096        this(dialogParent, ids, false);
097    }
098
099    /**
100     * Creates the download task for a collection of changeset ids, with possibility to download changeset discussion.
101     * Uses a {@link org.openstreetmap.josm.gui.PleaseWaitDialog} whose parent is the parent window of <code>dialogParent</code>.
102     *
103     * Null ids or or ids &lt;= 0 in the id collection are ignored.
104     *
105     * @param dialogParent the parent reference component for the {@link org.openstreetmap.josm.gui.PleaseWaitDialog}. Must not be null.
106     * @param ids the collection of ids. Empty collection assumed if null.
107     * @param includeDiscussion determines if discussion comments must be downloaded or not
108     * @throws IllegalArgumentException if dialogParent is null
109     * @since 7704
110     */
111    public ChangesetHeaderDownloadTask(Component dialogParent, Collection<Integer> ids, boolean includeDiscussion) {
112        setDownloadTask(new DownloadTask(dialogParent, ids, includeDiscussion));
113    }
114
115    /**
116     * Builds a download task from for a collection of changesets.
117     *
118     * Ignores null values and changesets with {@link Changeset#isNew()} == true.
119     *
120     * @param changesets the collection of changesets. Assumes an empty collection if null.
121     * @return the download task
122     */
123    public static ChangesetHeaderDownloadTask buildTaskForChangesets(Collection<Changeset> changesets) {
124        return buildTaskForChangesets(MainApplication.getMainFrame(), changesets);
125    }
126
127    /**
128     * Builds a download task from for a collection of changesets.
129     *
130     * Ignores null values and changesets with {@link Changeset#isNew()} == true.
131     *
132     * @param parent the parent component relative to which the {@link org.openstreetmap.josm.gui.PleaseWaitDialog} is displayed.
133     * Must not be null.
134     * @param changesets the collection of changesets. Assumes an empty collection if null.
135     * @return the download task
136     * @throws IllegalArgumentException if parent is null
137     */
138    public static ChangesetHeaderDownloadTask buildTaskForChangesets(Component parent, Collection<Changeset> changesets) {
139        CheckParameterUtil.ensureParameterNotNull(parent, "parent");
140
141        Set<Integer> ids = new HashSet<>();
142        for (Changeset cs: changesets != null ? changesets : Collections.<Changeset>emptyList()) {
143            if (cs == null || cs.isNew()) {
144                continue;
145            }
146            ids.add(cs.getId());
147        }
148        return new ChangesetHeaderDownloadTask(parent, ids);
149    }
150}