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.util.ArrayList;
007import java.util.Collection;
008import java.util.LinkedHashSet;
009import java.util.List;
010import java.util.Set;
011import java.util.concurrent.Future;
012
013import javax.swing.JOptionPane;
014import javax.swing.SwingUtilities;
015
016import org.openstreetmap.josm.Main;
017import org.openstreetmap.josm.gui.ExceptionDialogUtil;
018import org.openstreetmap.josm.gui.Notification;
019import org.openstreetmap.josm.tools.ExceptionUtil;
020import org.openstreetmap.josm.tools.Utils;
021
022public class PostDownloadHandler implements Runnable {
023    private final DownloadTask task;
024    private final List<Future<?>> futures;
025
026    /**
027     * constructor
028     * @param task the asynchronous download task
029     * @param future the future on which the completion of the download task can be synchronized
030     */
031    public PostDownloadHandler(DownloadTask task, Future<?> future) {
032        this.task = task;
033        this.futures = new ArrayList<>();
034        if (future != null) {
035            this.futures.add(future);
036        }
037    }
038
039    /**
040     * constructor
041     * @param task the asynchronous download task
042     * @param futures the futures on which the completion of the download task can be synchronized
043     */
044    public PostDownloadHandler(DownloadTask task, Future<?> ... futures) {
045        this.task = task;
046        this.futures = new ArrayList<>();
047        if (futures == null) return;
048        for (Future<?> future: futures) {
049            this.futures.add(future);
050        }
051    }
052
053    /**
054     * constructor
055     * @param task the asynchronous download task
056     * @param futures the futures on which the completion of the download task can be synchronized
057     */
058    public PostDownloadHandler(DownloadTask task, List<Future<?>> futures) {
059        this.task = task;
060        this.futures = new ArrayList<>();
061        if (futures == null) return;
062        this.futures.addAll(futures);
063    }
064
065    @Override
066    public void run() {
067        // wait for all downloads task to finish (by waiting for the futures to return a value)
068        //
069        for (Future<?> future: futures) {
070            try {
071                future.get();
072            } catch (Exception e) {
073                Main.error(e);
074                return;
075            }
076        }
077
078        // make sure errors are reported only once
079        //
080        Set<Object> errors = new LinkedHashSet<>();
081        errors.addAll(task.getErrorObjects());
082        if (errors.isEmpty())
083            return;
084
085        // just one error object?
086        //
087        if (errors.size() == 1) {
088            final Object error = errors.iterator().next();
089            SwingUtilities.invokeLater(new Runnable() {
090                @Override
091                public void run() {
092                    if (error instanceof Exception) {
093                        ExceptionDialogUtil.explainException((Exception) error);
094                    } else if (tr("No data found in this area.").equals(error)) {
095                        new Notification(error.toString()).setIcon(JOptionPane.WARNING_MESSAGE).show();
096                    } else {
097                        JOptionPane.showMessageDialog(
098                                Main.parent,
099                                error.toString(),
100                                tr("Error during download"),
101                                JOptionPane.ERROR_MESSAGE);
102                    }
103                }
104            });
105            return;
106        }
107
108        // multiple error object? prepare a HTML list
109        //
110        if (!errors.isEmpty()) {
111            final Collection<String> items = new ArrayList<>();
112            for (Object error:errors) {
113                if (error instanceof String) {
114                    items.add((String) error);
115                } else if (error instanceof Exception) {
116                    items.add(ExceptionUtil.explainException((Exception) error));
117                }
118            }
119
120            SwingUtilities.invokeLater(new Runnable() {
121                @Override
122                public void run() {
123                    JOptionPane.showMessageDialog(
124                            Main.parent,
125                            "<html>"+Utils.joinAsHtmlUnorderedList(items)+"</html>",
126                            tr("Errors during download"),
127                            JOptionPane.ERROR_MESSAGE);
128                }
129            });
130            return;
131        }
132    }
133}