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