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}