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}