001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.actions.downloadtasks;
003
004import java.net.URL;
005import java.util.List;
006import java.util.Objects;
007import java.util.concurrent.Future;
008import java.util.stream.Collectors;
009
010import org.openstreetmap.josm.data.Bounds;
011import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
012import org.openstreetmap.josm.gui.progress.ProgressMonitor;
013import org.openstreetmap.josm.tools.ExceptionUtil;
014
015/**
016 * Interface defining a general download task used to download geographic data (OSM data, GPX tracks, etc.) for a given URL or geographic area.
017 */
018public interface DownloadTask {
019
020    /**
021     * Asynchronously launches the download task for a given bounding box.
022     *
023     * Set <code>progressMonitor</code> to null, if the task should create, open, and close a progress monitor.
024     * Set progressMonitor to {@link NullProgressMonitor#INSTANCE} if progress information is to
025     * be discarded.
026     *
027     * You can wait for the asynchronous download task to finish by synchronizing on the returned
028     * {@link Future}, but make sure not to freeze up JOSM. Example:
029     * <pre>
030     *    Future&lt;?&gt; future = task.download(...);
031     *    // DON'T run this on the Swing EDT or JOSM will freeze
032     *    future.get(); // waits for the dowload task to complete
033     * </pre>
034     *
035     * The following example uses a pattern which is better suited if a task is launched from
036     * the Swing EDT:
037     * <pre>
038     *    final Future&lt;?&gt; future = task.download(...);
039     *    Runnable runAfterTask = new Runnable() {
040     *       public void run() {
041     *           // this is not strictly necessary because of the type of executor service
042     *           // Main.worker is initialized with, but it doesn't harm either
043     *           //
044     *           future.get(); // wait for the download task to complete
045     *           doSomethingAfterTheTaskCompleted();
046     *       }
047     *    }
048     *    MainApplication.worker.submit(runAfterTask);
049     * </pre>
050     *
051     * @param settings download settings
052     *
053     * @param downloadArea the area to download
054     * @param progressMonitor the progressMonitor
055     * @return the future representing the asynchronous task
056     * @since 13927
057     */
058    Future<?> download(DownloadParams settings, Bounds downloadArea, ProgressMonitor progressMonitor);
059
060    /**
061     * Asynchronously launches the download task for a given bounding URL.
062     *
063     * Set progressMonitor to null, if the task should create, open, and close a progress monitor.
064     * Set progressMonitor to {@link NullProgressMonitor#INSTANCE} if progress information is to
065     * be discarded.
066
067     * @param settings download settings
068     * @param url the url to download from
069     * @param progressMonitor the progressMonitor
070     * @return the future representing the asynchronous task
071     *
072     * @see #download(DownloadParams, Bounds, ProgressMonitor)
073     * @since 13927
074     */
075    Future<?> loadUrl(DownloadParams settings, String url, ProgressMonitor progressMonitor);
076
077    /**
078     * Returns true if the task is able to open the given URL, false otherwise.
079     * @param url the url to download from
080     * @param isRemotecontrol True if download request comes from remotecontrol.
081     * @return True if the task is able to open the given URL, false otherwise.
082     * Return false, if the request comes from remotecontrol, but the task is not
083     * safe for remotecontrol.
084     * A task is not safe for remotecontrol if it is possible to prepare a file
085     * for download which does something unintended, e.g. gain access to the
086     * local file system.
087     */
088    boolean acceptsUrl(String url, boolean isRemotecontrol);
089
090    /**
091     * Returns a short HTML documentation string, describing acceptable URLs.
092     * @return The HTML documentation
093     * @since 6031
094     */
095    String acceptsDocumentationSummary();
096
097    /**
098     * Returns human-readable description of the task
099     * @return The task description
100     * @since 6031
101     */
102    String getTitle();
103
104    /**
105     * Returns regular expressions that match the URLs
106     * @return The array of accepted URL patterns
107     * @since 6031
108     */
109    String[] getPatterns();
110
111    /**
112     * Replies the error objects of the task. Empty list, if no error messages are available.
113     *
114     * Error objects are either {@link String}s with error messages or {@link Exception}s.
115     *
116     * @return the list of error objects
117     */
118    List<Object> getErrorObjects();
119
120    /**
121     * Replies the error messages of the task. Empty list, if no error messages are available.
122     *
123     * @return the list of error messages
124     * @since 17330
125     */
126    default List<String> getErrorMessages() {
127        return getErrorObjects().stream().map(o -> {
128            if (o instanceof String) {
129                return (String) o;
130            } else if (o instanceof Exception) {
131                return ExceptionUtil.explainException((Exception) o).replace("<html>", "").replace("</html>", "");
132            } else {
133                return (String) null;
134            }
135        }).filter(Objects::nonNull).collect(Collectors.toList());
136    }
137
138    /**
139     * Cancels the asynchronous download task.
140     *
141     */
142    void cancel();
143
144    /**
145     * Replies the HTML-formatted confirmation message to be shown to user when the given URL needs to be confirmed before loading.
146     * @param url The URL to be confirmed
147     * @return The HTML-formatted confirmation message to be shown to user
148     * @since 5691
149     */
150    String getConfirmationMessage(URL url);
151
152    /**
153     * Sets whether the map view will zoom to download area after download
154     * @param zoomAfterDownload if true, the map view will zoom to download area after download
155     * @since 13261
156     */
157    void setZoomAfterDownload(boolean zoomAfterDownload);
158}