Ignore:
Timestamp:
2016-04-09T16:08:55+02:00 (8 years ago)
Author:
Don-vip
Message:

refactor and move changeset download tasks to actions.downloadtasks package

Location:
trunk/src/org/openstreetmap/josm/actions/downloadtasks
Files:
1 edited
4 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/downloadtasks/AbstractChangesetDownloadTask.java

    r10113 r10124  
    11// License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.dialogs.changeset;
     2package org.openstreetmap.josm.actions.downloadtasks;
    33
     4import java.awt.Component;
     5import java.net.URL;
     6import java.util.HashSet;
    47import java.util.Set;
     8import java.util.concurrent.Future;
    59
     10import org.openstreetmap.josm.Main;
     11import org.openstreetmap.josm.data.Bounds;
    612import org.openstreetmap.josm.data.osm.Changeset;
     13import org.openstreetmap.josm.gui.PleaseWaitRunnable;
     14import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     15import org.openstreetmap.josm.io.OsmServerChangesetReader;
    716
    8 public interface ChangesetDownloadTask extends Runnable {
    9     Set<Changeset> getDownloadedChangesets();
     17/**
     18 * Common abstract implementation of other changeset download tasks.
     19 * @since 10124
     20 */
     21public abstract class AbstractChangesetDownloadTask extends AbstractDownloadTask<Set<Changeset>> {
    1022
    11     boolean isCanceled();
     23    abstract class RunnableDownloadTask extends PleaseWaitRunnable {
     24        /** the reader object used to read changesets from the API */
     25        protected final OsmServerChangesetReader reader = new OsmServerChangesetReader();
     26        /** the set of downloaded changesets */
     27        protected final Set<Changeset> downloadedChangesets = new HashSet<>();
     28        /** keeps the last exception thrown in the task, if any */
     29        protected Exception lastException;
    1230
    13     boolean isFailed();
     31        RunnableDownloadTask(Component parent, String title) {
     32            super(parent, title, false /* don't ignore exceptions */);
     33        }
     34
     35        @Override
     36        protected void cancel() {
     37            setCanceled(true);
     38            synchronized (this) {
     39                if (reader != null) {
     40                    reader.cancel();
     41                }
     42            }
     43        }
     44
     45        protected final void rememberLastException(Exception e) {
     46            lastException = e;
     47            setFailed(true);
     48        }
     49    }
     50
     51    private RunnableDownloadTask downloadTaskRunnable;
     52
     53    protected final void setDownloadTask(RunnableDownloadTask downloadTask) {
     54        this.downloadTaskRunnable = downloadTask;
     55    }
     56
     57    @Override
     58    public final Future<?> download(boolean newLayer, Bounds downloadArea, ProgressMonitor progressMonitor) {
     59        return download();
     60    }
     61
     62    /**
     63     * Asynchronously launches the changeset download task. This is equivalent to {@code download(false, null, null)}.
     64     *
     65     * You can wait for the asynchronous download task to finish by synchronizing on the returned
     66     * {@link Future}, but make sure not to freeze up JOSM. Example:
     67     * <pre>
     68     *    Future&lt;?&gt; future = task.download();
     69     *    // DON'T run this on the Swing EDT or JOSM will freeze
     70     *    future.get(); // waits for the dowload task to complete
     71     * </pre>
     72     *
     73     * The following example uses a pattern which is better suited if a task is launched from the Swing EDT:
     74     * <pre>
     75     *    final Future&lt;?&gt; future = task.download();
     76     *    Runnable runAfterTask = new Runnable() {
     77     *       public void run() {
     78     *           // this is not strictly necessary because of the type of executor service
     79     *           // Main.worker is initialized with, but it doesn't harm either
     80     *           //
     81     *           future.get(); // wait for the download task to complete
     82     *           doSomethingAfterTheTaskCompleted();
     83     *       }
     84     *    }
     85     *    Main.worker.submit(runAfterTask);
     86     * </pre>
     87     *
     88     * @return the future representing the asynchronous task
     89     */
     90    public final Future<?> download() {
     91        return Main.worker.submit(downloadTaskRunnable);
     92    }
     93
     94    @Override
     95    public final Future<?> loadUrl(boolean newLayer, String url, ProgressMonitor progressMonitor) {
     96        return Main.worker.submit(downloadTaskRunnable);
     97    }
     98
     99    @Override
     100    public final void cancel() {
     101        downloadTaskRunnable.cancel();
     102    }
     103
     104    @Override
     105    public String getConfirmationMessage(URL url) {
     106        return null;
     107    }
    14108}
  • trunk/src/org/openstreetmap/josm/actions/downloadtasks/AbstractDownloadTask.java

    r9067 r10124  
    88
    99/**
    10  * Common abstract implementation of other download tasks
     10 * Common abstract implementation of other download tasks.
    1111 * @param <T> The downloaded data type
    1212 * @since 2322
     
    1818    protected T downloadedData;
    1919
     20    /**
     21     * Constructs a new {@code AbstractDownloadTask}.
     22     */
    2023    public AbstractDownloadTask() {
    2124        errorMessages = new ArrayList<>();
    2225    }
    2326
     27    /**
     28     * Determines if the download task has been canceled.
     29     * @return {@code true} if the download task has been canceled
     30     */
    2431    public boolean isCanceled() {
    2532        return canceled;
    2633    }
    2734
     35    /**
     36     * Marks this download task as canceled.
     37     * @param canceled {@code true} to mark this download task as canceled
     38     */
    2839    public void setCanceled(boolean canceled) {
    2940        this.canceled = canceled;
    3041    }
    3142
     43    /**
     44     * Determines if the download task has failed.
     45     * @return {@code true} if the download task has failed
     46     */
    3247    public boolean isFailed() {
    3348        return failed;
    3449    }
    3550
     51    /**
     52     * Marks this download task as failed.
     53     * @param failed {@code true} to mark this download task as failed
     54     */
    3655    public void setFailed(boolean failed) {
    3756        this.failed = failed;
     
    82101    }
    83102
    84     // Can be overridden for more complex checking logic
     103    /**
     104     * Determines if the given URL is accepted by {@link #getPatterns}.
     105     * Can be overridden for more complex checking logic.
     106     * @param url URL to donwload
     107     * @return {@code true} if this URL is accepted
     108     */
    85109    public boolean acceptsUrl(String url) {
    86         if (url == null) return false;
     110        if (url == null)
     111            return false;
    87112        for (String p: getPatterns()) {
    88113            if (url.matches(p)) {
     
    113138    @Override
    114139    public boolean acceptsUrl(String url, boolean isRemotecontrol) {
    115         if (isRemotecontrol && !isSafeForRemotecontrolRequests()) return false;
     140        if (isRemotecontrol && !isSafeForRemotecontrolRequests())
     141            return false;
    116142        return acceptsUrl(url);
    117143    }
     
    133159        return new String[]{};
    134160    }
    135 
    136161}
  • trunk/src/org/openstreetmap/josm/actions/downloadtasks/ChangesetContentDownloadTask.java

    r10113 r10124  
    11// License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.dialogs.changeset;
     2package org.openstreetmap.josm.actions.downloadtasks;
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
     
    1010import java.util.Collection;
    1111import java.util.Collections;
    12 import java.util.HashSet;
    1312import java.util.List;
    14 import java.util.Set;
    1513
     14import org.openstreetmap.josm.Main;
    1615import org.openstreetmap.josm.data.osm.Changeset;
    1716import org.openstreetmap.josm.data.osm.ChangesetCache;
    1817import org.openstreetmap.josm.data.osm.ChangesetDataSet;
    1918import org.openstreetmap.josm.gui.ExceptionDialogUtil;
    20 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    21 import org.openstreetmap.josm.io.OsmServerChangesetReader;
    2219import org.openstreetmap.josm.io.OsmTransferCanceledException;
    2320import org.openstreetmap.josm.io.OsmTransferException;
     
    2522
    2623/**
    27  * This is an asynchronous task for downloading the changeset content of a collection of
    28  * changesets.
    29  *
     24 * This is an asynchronous task for downloading the changeset content of a collection of changesets.
     25 * @since 2689
    3026 */
    31 public class ChangesetContentDownloadTask extends PleaseWaitRunnable implements ChangesetDownloadTask {
     27public class ChangesetContentDownloadTask extends AbstractChangesetDownloadTask {
    3228
    33     /** the list of changeset ids to download */
    34     private final List<Integer> toDownload = new ArrayList<>();
    35     /** true if the task was canceled */
    36     private boolean canceled;
    37     /** keeps the last exception thrown in the task, if any */
    38     private Exception lastException;
    39     /** the reader object used to read changesets from the API */
    40     private OsmServerChangesetReader reader;
    41     /** the set of downloaded changesets */
    42     private Set<Changeset> downloadedChangesets;
     29    private final DownloadTask downloadTask;
    4330
    44     /**
    45      * Initialize the task with a collection of changeset ids to download
    46      *
    47      * @param ids the collection of ids. May be null.
    48      */
    49     protected void init(Collection<Integer> ids) {
    50         if (ids == null) {
    51             ids = Collections.emptyList();
     31    class DownloadTask extends RunnableDownloadTask {
     32        /** the list of changeset ids to download */
     33        private final List<Integer> toDownload = new ArrayList<>();
     34
     35        DownloadTask(Component parent, Collection<Integer> ids) {
     36            super(parent, tr("Downloading changeset content"));
     37            for (Integer id: ids != null ? ids : Collections.<Integer>emptyList()) {
     38                if (id == null || id <= 0) {
     39                    continue;
     40                }
     41                toDownload.add(id);
     42            }
    5243        }
    53         for (Integer id: ids) {
    54             if (id == null || id <= 0) {
    55                 continue;
     44
     45        /**
     46         * Downloads the changeset with id <code>changesetId</code> (only "header" information, no content)
     47         *
     48         * @param changesetId the changeset id
     49         * @throws OsmTransferException if something went wrong
     50         */
     51        protected void downloadChangeset(int changesetId) throws OsmTransferException {
     52            Changeset cs = reader.readChangeset(changesetId, false, getProgressMonitor().createSubTaskMonitor(0, false));
     53            ChangesetCache.getInstance().update(cs);
     54        }
     55
     56        @Override
     57        protected void realRun() throws SAXException, IOException, OsmTransferException {
     58            try {
     59                getProgressMonitor().setTicksCount(toDownload.size());
     60                int i = 0;
     61                for (int id: toDownload) {
     62                    i++;
     63                    if (!isAvailableLocally(id)) {
     64                        getProgressMonitor().setCustomText(tr("({0}/{1}) Downloading changeset {2}...", i, toDownload.size(), id));
     65                        downloadChangeset(id);
     66                    }
     67                    if (isCanceled())
     68                        return;
     69                    getProgressMonitor().setCustomText(tr("({0}/{1}) Downloading content for changeset {2}...", i, toDownload.size(), id));
     70                    ChangesetDataSet ds = reader.downloadChangeset(id, getProgressMonitor().createSubTaskMonitor(0, false));
     71                    Changeset cs = ChangesetCache.getInstance().get(id);
     72                    cs.setContent(ds);
     73                    ChangesetCache.getInstance().update(cs);
     74                    downloadedChangesets.add(cs);
     75                    getProgressMonitor().worked(1);
     76                }
     77            } catch (OsmTransferCanceledException e) {
     78                // the download was canceled by the user. This exception is caught if the user canceled the authentication dialog.
     79                setCanceled(true);
     80                return;
     81            } catch (OsmTransferException e) {
     82                if (isCanceled())
     83                    return;
     84                rememberLastException(e);
    5685            }
    57             toDownload.add(id);
    5886        }
    59         downloadedChangesets = new HashSet<>();
     87
     88        @Override
     89        protected void finish() {
     90            rememberDownloadedData(downloadedChangesets);
     91            if (isCanceled())
     92                return;
     93            if (lastException != null) {
     94                ExceptionDialogUtil.explainException(lastException);
     95            }
     96        }
    6097    }
    6198
     
    67104     */
    68105    public ChangesetContentDownloadTask(int changesetId) {
    69         super(tr("Downloading changeset content"), false /* don't ignore exceptions */);
    70         if (changesetId <= 0)
    71             throw new IllegalArgumentException(
    72                     MessageFormat.format("Expected integer value > 0 for parameter ''{0}'', got ''{1}''", "changesetId", changesetId));
    73         init(Collections.singleton(changesetId));
     106        this(Main.parent, changesetId);
    74107    }
    75108
    76109    /**
    77110     * Creates a download task for a collection of changesets. null values and id &lt;=0 in
    78      * the collection are sillently discarded.
     111     * the collection are silently discarded.
    79112     *
    80113     * @param changesetIds the changeset ids. Empty collection assumed, if null.
    81114     */
    82115    public ChangesetContentDownloadTask(Collection<Integer> changesetIds) {
    83         super(tr("Downloading changeset content"), false /* don't ignore exceptions */);
    84         init(changesetIds);
     116        this(Main.parent, changesetIds);
    85117    }
    86118
     
    94126     */
    95127    public ChangesetContentDownloadTask(Component parent, int changesetId) {
    96         super(parent, tr("Downloading changeset content"), false /* don't ignore exceptions */);
    97128        if (changesetId <= 0)
    98129            throw new IllegalArgumentException(
    99130                    MessageFormat.format("Expected integer value > 0 for parameter ''{0}'', got ''{1}''", "changesetId", changesetId));
    100         init(Collections.singleton(changesetId));
     131        downloadTask = new DownloadTask(parent, Collections.singleton(changesetId));
     132        setDownloadTask(downloadTask);
    101133    }
    102134
     
    110142     */
    111143    public ChangesetContentDownloadTask(Component parent, Collection<Integer> changesetIds) {
    112         super(parent, tr("Downloading changeset content"), false /* don't ignore exceptions */);
    113         init(changesetIds);
     144        downloadTask = new DownloadTask(parent, changesetIds);
     145        setDownloadTask(downloadTask);
    114146    }
    115147
     
    122154     * id <code>changesetId</code>
    123155     */
    124     protected boolean isAvailableLocally(int changesetId) {
     156    protected static boolean isAvailableLocally(int changesetId) {
    125157        return ChangesetCache.getInstance().get(changesetId) != null;
    126158    }
    127 
    128     /**
    129      * Downloads the changeset with id <code>changesetId</code> (only "header"
    130      * information, no content)
    131      *
    132      * @param changesetId the changeset id
    133      * @throws OsmTransferException if something went wrong
    134      */
    135     protected void downloadChangeset(int changesetId) throws OsmTransferException {
    136         synchronized (this) {
    137             reader = new OsmServerChangesetReader();
    138         }
    139         Changeset cs = reader.readChangeset(changesetId, false, getProgressMonitor().createSubTaskMonitor(0, false));
    140         synchronized (this) {
    141             reader = null;
    142         }
    143         ChangesetCache.getInstance().update(cs);
    144     }
    145 
    146     @Override
    147     protected void cancel() {
    148         canceled = true;
    149         synchronized (this) {
    150             if (reader != null) {
    151                 reader.cancel();
    152             }
    153         }
    154     }
    155 
    156     @Override
    157     protected void finish() {
    158         if (canceled) return;
    159         if (lastException != null) {
    160             ExceptionDialogUtil.explainException(lastException);
    161         }
    162     }
    163 
    164     @Override
    165     protected void realRun() throws SAXException, IOException, OsmTransferException {
    166         try {
    167             getProgressMonitor().setTicksCount(toDownload.size());
    168             int i = 0;
    169             for (int id: toDownload) {
    170                 i++;
    171                 if (!isAvailableLocally(id)) {
    172                     getProgressMonitor().setCustomText(tr("({0}/{1}) Downloading changeset {2}...", i, toDownload.size(), id));
    173                     downloadChangeset(id);
    174                 }
    175                 if (canceled) return;
    176                 synchronized (this) {
    177                     reader = new OsmServerChangesetReader();
    178                 }
    179                 getProgressMonitor().setCustomText(tr("({0}/{1}) Downloading content for changeset {2}...", i, toDownload.size(), id));
    180                 ChangesetDataSet ds = reader.downloadChangeset(id, getProgressMonitor().createSubTaskMonitor(0, false));
    181                 synchronized (this) {
    182                     reader = null;
    183                 }
    184                 Changeset cs = ChangesetCache.getInstance().get(id);
    185                 cs.setContent(ds);
    186                 ChangesetCache.getInstance().update(cs);
    187                 downloadedChangesets.add(cs);
    188                 getProgressMonitor().worked(1);
    189             }
    190         } catch (OsmTransferCanceledException e) {
    191             // the download was canceled by the user. This exception is caught if the
    192             // user canceled the authentication dialog.
    193             //
    194             canceled = true;
    195             return;
    196         } catch (OsmTransferException e) {
    197             if (canceled)
    198                 return;
    199             lastException = e;
    200         }
    201     }
    202 
    203     /* ------------------------------------------------------------------------------- */
    204     /* interface ChangesetDownloadTask                                                 */
    205     /* ------------------------------------------------------------------------------- */
    206     @Override
    207     public Set<Changeset> getDownloadedChangesets() {
    208         return downloadedChangesets;
    209     }
    210 
    211     @Override
    212     public boolean isCanceled() {
    213         return canceled;
    214     }
    215 
    216     @Override
    217     public boolean isFailed() {
    218         return lastException != null;
    219     }
    220159}
  • trunk/src/org/openstreetmap/josm/actions/downloadtasks/ChangesetHeaderDownloadTask.java

    r10113 r10124  
    11// License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.dialogs.changeset;
     2package org.openstreetmap.josm.actions.downloadtasks;
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
     
    1818import org.openstreetmap.josm.data.osm.ChangesetCache;
    1919import org.openstreetmap.josm.gui.ExceptionDialogUtil;
    20 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    21 import org.openstreetmap.josm.io.OsmServerChangesetReader;
    2220import org.openstreetmap.josm.io.OsmTransferException;
    2321import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    2725
    2826/**
    29  * This is an asynchronous task for downloading a collection of changests from the OSM
    30  * server.
     27 * This is an asynchronous task for downloading a collection of changests from the OSM server.
    3128 *
    3229 * The  task only downloads the changeset properties without the changeset content. It
    3330 * updates the global {@link ChangesetCache}.
    34  *
     31 * @since 2613
    3532 */
    36 public class ChangesetHeaderDownloadTask extends PleaseWaitRunnable implements ChangesetDownloadTask {
     33public class ChangesetHeaderDownloadTask extends AbstractChangesetDownloadTask {
    3734
    38     /**
    39      * Builds a download task from for a collection of changesets.
    40      *
    41      * Ignores null values and changesets with {@link Changeset#isNew()} == true.
    42      *
    43      * @param changesets the collection of changesets. Assumes an empty collection if null.
    44      * @return the download task
    45      */
    46     public static ChangesetHeaderDownloadTask buildTaskForChangesets(Collection<Changeset> changesets) {
    47         return buildTaskForChangesets(Main.parent, changesets);
    48     }
     35    private final DownloadTask downloadTask;
    4936
    50     /**
    51      * Builds a download task from for a collection of changesets.
    52      *
    53      * Ignores null values and changesets with {@link Changeset#isNew()} == true.
    54      *
    55      * @param parent the parent component relative to which the {@link org.openstreetmap.josm.gui.PleaseWaitDialog} is displayed.
    56      * Must not be null.
    57      * @param changesets the collection of changesets. Assumes an empty collection if null.
    58      * @return the download task
    59      * @throws IllegalArgumentException if parent is null
    60      */
    61     public static ChangesetHeaderDownloadTask buildTaskForChangesets(Component parent, Collection<Changeset> changesets) {
    62         CheckParameterUtil.ensureParameterNotNull(parent, "parent");
    63         if (changesets == null) {
    64             changesets = Collections.emptyList();
     37    class DownloadTask extends RunnableDownloadTask {
     38        /** the list of changeset ids to download */
     39        private final Set<Integer> toDownload = new HashSet<>();
     40        /** whether to include discussions or not */
     41        private final boolean includeDiscussion;
     42
     43        DownloadTask(Component parent, Collection<Integer> ids, boolean includeDiscussion) {
     44            super(parent, tr("Download changesets"));
     45            this.includeDiscussion = includeDiscussion;
     46            for (int id: ids != null ? ids : Collections.<Integer>emptyList()) {
     47                if (id <= 0) {
     48                    continue;
     49                }
     50                toDownload.add(id);
     51            }
    6552        }
    6653
    67         Set<Integer> ids = new HashSet<>();
    68         for (Changeset cs: changesets) {
    69             if (cs == null || cs.isNew()) {
    70                 continue;
     54        @Override
     55        protected void realRun() throws SAXException, IOException, OsmTransferException {
     56            try {
     57                downloadedChangesets.addAll(reader.readChangesets(toDownload, includeDiscussion,
     58                        getProgressMonitor().createSubTaskMonitor(0, false)));
     59            } catch (OsmTransferException e) {
     60                if (isCanceled())
     61                    // ignore exception if canceled
     62                    return;
     63                // remember other exceptions
     64                rememberLastException(e);
    7165            }
    72             ids.add(cs.getId());
    7366        }
    74         if (parent == null)
    75             return new ChangesetHeaderDownloadTask(ids);
    76         else
    77             return new ChangesetHeaderDownloadTask(parent, ids);
    7867
    79     }
     68        @Override
     69        protected void finish() {
     70            rememberDownloadedData(downloadedChangesets);
     71            if (isCanceled())
     72                return;
     73            if (lastException != null) {
     74                ExceptionDialogUtil.explainException(lastException);
     75            }
     76            Runnable r = new Runnable() {
     77                @Override
     78                public void run() {
     79                    ChangesetCache.getInstance().update(downloadedChangesets);
     80                }
     81            };
    8082
    81     private Set<Integer> idsToDownload;
    82     private OsmServerChangesetReader reader;
    83     private boolean canceled;
    84     private Exception lastException;
    85     private Set<Changeset> downloadedChangesets;
    86     private final boolean includeDiscussion;
    87 
    88     protected void init(Collection<Integer> ids) {
    89         if (ids == null) {
    90             ids = Collections.emptyList();
    91         }
    92         idsToDownload = new HashSet<>();
    93         if (ids == null ||  ids.isEmpty())
    94             return;
    95         for (int id: ids) {
    96             if (id <= 0) {
    97                 continue;
     83            if (SwingUtilities.isEventDispatchThread()) {
     84                r.run();
     85            } else {
     86                try {
     87                    SwingUtilities.invokeAndWait(r);
     88                } catch (InterruptedException e) {
     89                    Main.warn("InterruptedException in "+getClass().getSimpleName()+" while updating changeset cache");
     90                } catch (InvocationTargetException e) {
     91                    Throwable t = e.getTargetException();
     92                    if (t instanceof RuntimeException) {
     93                        BugReportExceptionHandler.handleException(t);
     94                    } else if (t instanceof Exception) {
     95                        ExceptionUtil.explainException(e);
     96                    } else {
     97                        BugReportExceptionHandler.handleException(t);
     98                    }
     99                }
    98100            }
    99             idsToDownload.add(id);
    100101        }
    101102    }
     
    110111     */
    111112    public ChangesetHeaderDownloadTask(Collection<Integer> ids) {
    112         // parent for dialog is Main.parent
    113         super(tr("Download changesets"), false /* don't ignore exceptions */);
    114         init(ids);
    115         this.includeDiscussion = false;
     113        this(Main.parent, ids, false);
    116114    }
    117115
     
    143141     */
    144142    public ChangesetHeaderDownloadTask(Component dialogParent, Collection<Integer> ids, boolean includeDiscussion) {
    145         super(dialogParent, tr("Download changesets"), false /* don't ignore exceptions */);
    146         init(ids);
    147         this.includeDiscussion = includeDiscussion;
     143        downloadTask = new DownloadTask(dialogParent, ids, includeDiscussion);
     144        setDownloadTask(downloadTask);
    148145    }
    149146
    150     @Override
    151     protected void cancel() {
    152         canceled = true;
    153         synchronized (this) {
    154             if (reader != null) {
    155                 reader.cancel();
    156             }
    157         }
     147    /**
     148     * Builds a download task from for a collection of changesets.
     149     *
     150     * Ignores null values and changesets with {@link Changeset#isNew()} == true.
     151     *
     152     * @param changesets the collection of changesets. Assumes an empty collection if null.
     153     * @return the download task
     154     */
     155    public static ChangesetHeaderDownloadTask buildTaskForChangesets(Collection<Changeset> changesets) {
     156        return buildTaskForChangesets(Main.parent, changesets);
    158157    }
    159158
    160     @Override
    161     protected void finish() {
    162         if (canceled)
    163             return;
    164         if (lastException != null) {
    165             ExceptionDialogUtil.explainException(lastException);
     159    /**
     160     * Builds a download task from for a collection of changesets.
     161     *
     162     * Ignores null values and changesets with {@link Changeset#isNew()} == true.
     163     *
     164     * @param parent the parent component relative to which the {@link org.openstreetmap.josm.gui.PleaseWaitDialog} is displayed.
     165     * Must not be null.
     166     * @param changesets the collection of changesets. Assumes an empty collection if null.
     167     * @return the download task
     168     * @throws IllegalArgumentException if parent is null
     169     */
     170    public static ChangesetHeaderDownloadTask buildTaskForChangesets(Component parent, Collection<Changeset> changesets) {
     171        CheckParameterUtil.ensureParameterNotNull(parent, "parent");
     172
     173        Set<Integer> ids = new HashSet<>();
     174        for (Changeset cs: changesets != null ? changesets : Collections.<Changeset>emptyList()) {
     175            if (cs == null || cs.isNew()) {
     176                continue;
     177            }
     178            ids.add(cs.getId());
    166179        }
    167         Runnable r = new Runnable() {
    168             @Override
    169             public void run() {
    170                 ChangesetCache.getInstance().update(downloadedChangesets);
    171             }
    172         };
    173 
    174         if (SwingUtilities.isEventDispatchThread()) {
    175             r.run();
    176         } else {
    177             try {
    178                 SwingUtilities.invokeAndWait(r);
    179             } catch (InterruptedException e) {
    180                 Main.warn("InterruptedException in "+getClass().getSimpleName()+" while updating changeset cache");
    181             } catch (InvocationTargetException e) {
    182                 Throwable t = e.getTargetException();
    183                 if (t instanceof RuntimeException) {
    184                     BugReportExceptionHandler.handleException(t);
    185                 } else if (t instanceof Exception) {
    186                     ExceptionUtil.explainException(e);
    187                 } else {
    188                     BugReportExceptionHandler.handleException(t);
    189                 }
    190             }
    191         }
    192     }
    193 
    194     @Override
    195     protected void realRun() throws SAXException, IOException, OsmTransferException {
    196         try {
    197             synchronized (this) {
    198                 reader = new OsmServerChangesetReader();
    199             }
    200             downloadedChangesets = new HashSet<>();
    201             downloadedChangesets.addAll(reader.readChangesets(idsToDownload, includeDiscussion,
    202                     getProgressMonitor().createSubTaskMonitor(0, false)));
    203         } catch (OsmTransferException e) {
    204             if (canceled)
    205                 // ignore exception if canceled
    206                 return;
    207             // remember other exceptions
    208             lastException = e;
    209         }
    210     }
    211 
    212     /* ------------------------------------------------------------------------------- */
    213     /* interface ChangesetDownloadTask                                                 */
    214     /* ------------------------------------------------------------------------------- */
    215     @Override
    216     public Set<Changeset> getDownloadedChangesets() {
    217         return downloadedChangesets;
    218     }
    219 
    220     @Override
    221     public boolean isCanceled() {
    222         return canceled;
    223     }
    224 
    225     @Override
    226     public boolean isFailed() {
    227         return lastException != null;
     180        if (parent == null)
     181            return new ChangesetHeaderDownloadTask(ids);
     182        else
     183            return new ChangesetHeaderDownloadTask(parent, ids);
    228184    }
    229185}
  • trunk/src/org/openstreetmap/josm/actions/downloadtasks/ChangesetQueryTask.java

    r10113 r10124  
    11// License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.dialogs.changeset.query;
     2package org.openstreetmap.josm.actions.downloadtasks;
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
     
    77import java.io.IOException;
    88import java.lang.reflect.InvocationTargetException;
    9 import java.util.HashSet;
    10 import java.util.Set;
    119
    1210import javax.swing.JOptionPane;
     
    1412
    1513import org.openstreetmap.josm.Main;
    16 import org.openstreetmap.josm.data.osm.Changeset;
    1714import org.openstreetmap.josm.data.osm.ChangesetCache;
    1815import org.openstreetmap.josm.data.osm.UserInfo;
    1916import org.openstreetmap.josm.gui.JosmUserIdentityManager;
    20 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    21 import org.openstreetmap.josm.gui.dialogs.changeset.ChangesetDownloadTask;
    2217import org.openstreetmap.josm.gui.util.GuiHelper;
    2318import org.openstreetmap.josm.io.ChangesetQuery;
    24 import org.openstreetmap.josm.io.OsmServerChangesetReader;
    2519import org.openstreetmap.josm.io.OsmServerUserInfoReader;
    2620import org.openstreetmap.josm.io.OsmTransferCanceledException;
     
    3529 * @since 2689
    3630 */
    37 public class ChangesetQueryTask extends PleaseWaitRunnable implements ChangesetDownloadTask {
     31public class ChangesetQueryTask extends AbstractChangesetDownloadTask {
    3832
    39     /** the changeset query */
    40     private ChangesetQuery query;
    41     /** true if the task was canceled */
    42     private boolean canceled;
    43     /** the set of downloaded changesets */
    44     private Set<Changeset> downloadedChangesets;
    45     /** the last exception remembered, if any */
    46     private Exception lastException;
    47     /** the reader object used to read information about the current user from the API */
    48     private OsmServerUserInfoReader userInfoReader;
    49     /** the reader object used to submit the changeset query to the API */
    50     private OsmServerChangesetReader changesetReader;
     33    private final DownloadTask downloadTask;
     34
     35    class DownloadTask extends RunnableDownloadTask {
     36        /** the changeset query */
     37        private ChangesetQuery query;
     38        /** the reader object used to read information about the current user from the API */
     39        private final OsmServerUserInfoReader userInfoReader = new OsmServerUserInfoReader();
     40
     41        DownloadTask(Component parent, ChangesetQuery query) {
     42            super(parent, tr("Querying and downloading changesets"));
     43            this.query = query;
     44        }
     45
     46        /**
     47         * Tries to fully identify the current JOSM user
     48         *
     49         * @throws OsmTransferException if something went wrong
     50         */
     51        protected void fullyIdentifyCurrentUser() throws OsmTransferException {
     52            getProgressMonitor().indeterminateSubTask(tr("Determine user id for current user..."));
     53
     54            UserInfo info = userInfoReader.fetchUserInfo(getProgressMonitor().createSubTaskMonitor(1, false));
     55            JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
     56            im.setFullyIdentified(im.getUserName(), info);
     57        }
     58
     59        @Override
     60        protected void realRun() throws SAXException, IOException, OsmTransferException {
     61            try {
     62                JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
     63                if (query.isRestrictedToPartiallyIdentifiedUser() && im.isCurrentUser(query.getUserName())) {
     64                    // if we query changesets for the current user, make sure we query against
     65                    // its user id, not its user name. If necessary, determine the user id first.
     66                    //
     67                    if (im.isPartiallyIdentified()) {
     68                        fullyIdentifyCurrentUser();
     69                    }
     70                    query = query.forUser(JosmUserIdentityManager.getInstance().getUserId());
     71                }
     72                if (isCanceled())
     73                    return;
     74                getProgressMonitor().indeterminateSubTask(tr("Query and download changesets ..."));
     75                downloadedChangesets.addAll(reader.queryChangesets(query, getProgressMonitor().createSubTaskMonitor(0, false)));
     76            } catch (OsmTransferCanceledException e) {
     77                // thrown if user cancel the authentication dialog
     78                setCanceled(true);
     79            }  catch (OsmTransferException e) {
     80                if (isCanceled())
     81                    return;
     82                rememberLastException(e);
     83            }
     84        }
     85
     86        @Override
     87        protected void finish() {
     88            rememberDownloadedData(downloadedChangesets);
     89            if (isCanceled())
     90                return;
     91            if (lastException != null) {
     92                GuiHelper.runInEDTAndWait(new Runnable() {
     93                    private final Component parent = progressMonitor != null ? progressMonitor.getWindowParent() : null;
     94                    @Override
     95                    public void run() {
     96                        JOptionPane.showMessageDialog(
     97                                parent != null ? parent : Main.parent,
     98                                ExceptionUtil.explainException(lastException),
     99                                tr("Errors during download"),
     100                                JOptionPane.ERROR_MESSAGE);
     101                    }
     102                });
     103                return;
     104            }
     105
     106            // update the global changeset cache with the downloaded changesets.
     107            // this will trigger change events which views are listening to. They
     108            // will update their views accordingly.
     109            //
     110            // Run on the EDT because UI updates are triggered.
     111            //
     112            Runnable r = new Runnable() {
     113                @Override public void run() {
     114                    ChangesetCache.getInstance().update(downloadedChangesets);
     115                }
     116            };
     117            if (SwingUtilities.isEventDispatchThread()) {
     118                r.run();
     119            } else {
     120                try {
     121                    SwingUtilities.invokeAndWait(r);
     122                } catch (InterruptedException e) {
     123                    Main.warn("InterruptedException in "+getClass().getSimpleName()+" while updating changeset cache");
     124                } catch (InvocationTargetException e) {
     125                    Throwable t = e.getTargetException();
     126                    if (t instanceof RuntimeException) {
     127                        BugReportExceptionHandler.handleException(t);
     128                    } else if (t instanceof Exception) {
     129                        ExceptionUtil.explainException(e);
     130                    } else {
     131                        BugReportExceptionHandler.handleException(t);
     132                    }
     133                }
     134            }
     135        }
     136
     137        @Override
     138        protected void cancel() {
     139            super.cancel();
     140            synchronized (this) {
     141                if (userInfoReader != null) {
     142                    userInfoReader.cancel();
     143                }
     144            }
     145        }
     146    }
    51147
    52148    /**
     
    57153     */
    58154    public ChangesetQueryTask(ChangesetQuery query) {
    59         super(tr("Querying and downloading changesets"), false /* don't ignore exceptions */);
    60         CheckParameterUtil.ensureParameterNotNull(query, "query");
    61         this.query = query;
     155        this(Main.parent, query);
    62156    }
    63157
     
    72166     */
    73167    public ChangesetQueryTask(Component parent, ChangesetQuery query) {
    74         super(parent, tr("Querying and downloading changesets"), false /* don't ignore exceptions */);
    75168        CheckParameterUtil.ensureParameterNotNull(query, "query");
    76         this.query = query;
    77     }
    78 
    79     @Override
    80     protected void cancel() {
    81         canceled = true;
    82         synchronized (this) {
    83             if (userInfoReader != null) {
    84                 userInfoReader.cancel();
    85             }
    86         }
    87         synchronized (this) {
    88             if (changesetReader != null) {
    89                 changesetReader.cancel();
    90             }
    91         }
    92     }
    93 
    94     @Override
    95     protected void finish() {
    96         if (canceled) return;
    97         if (lastException != null) {
    98             GuiHelper.runInEDTAndWait(new Runnable() {
    99                 private final Component parent = progressMonitor != null ? progressMonitor.getWindowParent() : null;
    100                 @Override
    101                 public void run() {
    102                     JOptionPane.showMessageDialog(
    103                             parent != null ? parent : Main.parent,
    104                             ExceptionUtil.explainException(lastException),
    105                             tr("Errors during download"),
    106                             JOptionPane.ERROR_MESSAGE);
    107                 }
    108             });
    109             return;
    110         }
    111 
    112         // update the global changeset cache with the downloaded changesets.
    113         // this will trigger change events which views are listening to. They
    114         // will update their views accordingly.
    115         //
    116         // Run on the EDT because UI updates are triggered.
    117         //
    118         Runnable r = new Runnable() {
    119             @Override public void run() {
    120                 ChangesetCache.getInstance().update(downloadedChangesets);
    121             }
    122         };
    123         if (SwingUtilities.isEventDispatchThread()) {
    124             r.run();
    125         } else {
    126             try {
    127                 SwingUtilities.invokeAndWait(r);
    128             } catch (InterruptedException e) {
    129                 Main.warn("InterruptedException in "+getClass().getSimpleName()+" while updating changeset cache");
    130             } catch (InvocationTargetException e) {
    131                 Throwable t = e.getTargetException();
    132                 if (t instanceof RuntimeException) {
    133                     BugReportExceptionHandler.handleException(t);
    134                 } else if (t instanceof Exception) {
    135                     ExceptionUtil.explainException(e);
    136                 } else {
    137                     BugReportExceptionHandler.handleException(t);
    138                 }
    139             }
    140         }
    141     }
    142 
    143     /**
    144      * Tries to fully identify the current JOSM user
    145      *
    146      * @throws OsmTransferException if something went wrong
    147      */
    148     protected void fullyIdentifyCurrentUser() throws OsmTransferException {
    149         getProgressMonitor().indeterminateSubTask(tr("Determine user id for current user..."));
    150 
    151         synchronized (this) {
    152             userInfoReader = new OsmServerUserInfoReader();
    153         }
    154         UserInfo info = userInfoReader.fetchUserInfo(getProgressMonitor().createSubTaskMonitor(1, false));
    155         synchronized (this) {
    156             userInfoReader = null;
    157         }
    158         JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
    159         im.setFullyIdentified(im.getUserName(), info);
    160     }
    161 
    162     @Override
    163     protected void realRun() throws SAXException, IOException, OsmTransferException {
    164         try {
    165             JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
    166             if (query.isRestrictedToPartiallyIdentifiedUser() && im.isCurrentUser(query.getUserName())) {
    167                 // if we query changesets for the current user, make sure we query against
    168                 // its user id, not its user name. If necessary, determine the user id first.
    169                 //
    170                 if (im.isPartiallyIdentified()) {
    171                     fullyIdentifyCurrentUser();
    172                 }
    173                 query = query.forUser(JosmUserIdentityManager.getInstance().getUserId());
    174             }
    175             if (canceled) return;
    176             getProgressMonitor().indeterminateSubTask(tr("Query and download changesets ..."));
    177             synchronized (this) {
    178                 changesetReader = new OsmServerChangesetReader();
    179             }
    180             downloadedChangesets = new HashSet<>();
    181             downloadedChangesets.addAll(changesetReader.queryChangesets(query, getProgressMonitor().createSubTaskMonitor(0, false)));
    182             synchronized (this) {
    183                 changesetReader = null;
    184             }
    185         } catch (OsmTransferCanceledException e) {
    186             // thrown if user cancel the authentication dialog
    187             canceled = true;
    188         }  catch (OsmTransferException e) {
    189             if (canceled)
    190                 return;
    191             this.lastException = e;
    192         }
    193     }
    194 
    195     /* ------------------------------------------------------------------------------- */
    196     /* interface ChangesetDownloadTask                                                 */
    197     /* ------------------------------------------------------------------------------- */
    198     @Override
    199     public Set<Changeset> getDownloadedChangesets() {
    200         return downloadedChangesets;
    201     }
    202 
    203     @Override
    204     public boolean isCanceled() {
    205         return canceled;
    206     }
    207 
    208     @Override
    209     public boolean isFailed() {
    210         return lastException != null;
     169        downloadTask = new DownloadTask(parent, query);
     170        setDownloadTask(downloadTask);
    211171    }
    212172}
Note: See TracChangeset for help on using the changeset viewer.