001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.io.File; 007import java.io.IOException; 008import java.util.List; 009 010import javax.swing.JOptionPane; 011 012import org.openstreetmap.josm.Main; 013import org.openstreetmap.josm.actions.ExtensionFileFilter; 014import org.openstreetmap.josm.gui.HelpAwareOptionPane; 015import org.openstreetmap.josm.gui.Notification; 016import org.openstreetmap.josm.gui.progress.ProgressMonitor; 017import org.openstreetmap.josm.gui.util.GuiHelper; 018 019/** 020 * Abstract file importer. 021 * @since 1637 022 * @since 10386 (signature) 023 */ 024public abstract class FileImporter implements Comparable<FileImporter> { 025 026 /** 027 * The extension file filter used to accept files. 028 */ 029 public final ExtensionFileFilter filter; 030 031 private boolean enabled; 032 033 /** 034 * Constructs a new {@code FileImporter} with the given extension file filter. 035 * @param filter The extension file filter 036 */ 037 public FileImporter(ExtensionFileFilter filter) { 038 this.filter = filter; 039 this.enabled = true; 040 } 041 042 /** 043 * Determines if this file importer accepts the given file. 044 * @param pathname The file to test 045 * @return {@code true} if this file importer accepts the given file, {@code false} otherwise 046 */ 047 public boolean acceptFile(File pathname) { 048 return filter.acceptName(pathname.getName()); 049 } 050 051 /** 052 * A batch importer is a file importer that prefers to read multiple files at the same time. 053 * @return {@code true} if this importer is a batch importer 054 */ 055 public boolean isBatchImporter() { 056 return false; 057 } 058 059 /** 060 * Needs to be implemented if isBatchImporter() returns false. 061 * @param file file to import 062 * @param progressMonitor progress monitor 063 * @throws IOException if any I/O error occurs 064 * @throws IllegalDataException if invalid data is read 065 */ 066 public void importData(File file, ProgressMonitor progressMonitor) throws IOException, IllegalDataException { 067 throw new IOException(tr("Could not import ''{0}''.", file.getName())); 068 } 069 070 /** 071 * Needs to be implemented if isBatchImporter() returns true. 072 * @param files files to import 073 * @param progressMonitor progress monitor 074 * @throws IOException if any I/O error occurs 075 * @throws IllegalDataException if invalid data is read 076 */ 077 public void importData(List<File> files, ProgressMonitor progressMonitor) throws IOException, IllegalDataException { 078 throw new IOException(tr("Could not import files.")); 079 } 080 081 /** 082 * Wrapper to {@link #importData(File, ProgressMonitor)} to give meaningful output if things go wrong. 083 * @param f data file to import 084 * @param progressMonitor progress monitor 085 * @return true if data import was successful 086 */ 087 public boolean importDataHandleExceptions(File f, ProgressMonitor progressMonitor) { 088 try { 089 Main.info("Open file: " + f.getAbsolutePath() + " (" + f.length() + " bytes)"); 090 importData(f, progressMonitor); 091 return true; 092 } catch (IllegalDataException e) { 093 Throwable cause = e.getCause(); 094 if (cause instanceof ImportCancelException) { 095 displayCancel(cause); 096 } else { 097 displayError(f, e); 098 } 099 return false; 100 } catch (IOException e) { 101 displayError(f, e); 102 return false; 103 } 104 } 105 106 private static void displayError(File f, Exception e) { 107 Main.error(e); 108 HelpAwareOptionPane.showMessageDialogInEDT( 109 Main.parent, 110 tr("<html>Could not read file ''{0}''.<br>Error is:<br>{1}</html>", f.getName(), e.getMessage()), 111 tr("Error"), 112 JOptionPane.ERROR_MESSAGE, null 113 ); 114 } 115 116 private static void displayCancel(final Throwable t) { 117 GuiHelper.runInEDTAndWait(new Runnable() { 118 @Override 119 public void run() { 120 Notification note = new Notification(t.getMessage()); 121 note.setIcon(JOptionPane.INFORMATION_MESSAGE); 122 note.setDuration(Notification.TIME_SHORT); 123 note.show(); 124 } 125 }); 126 } 127 128 /** 129 * Wrapper to {@link #importData(List, ProgressMonitor)} to give meaningful output if things go wrong. 130 * @param files data files to import 131 * @param progressMonitor progress monitor 132 * @return true if data import was successful 133 */ 134 public boolean importDataHandleExceptions(List<File> files, ProgressMonitor progressMonitor) { 135 try { 136 Main.info("Open "+files.size()+" files"); 137 importData(files, progressMonitor); 138 return true; 139 } catch (IOException | IllegalDataException e) { 140 Main.error(e); 141 HelpAwareOptionPane.showMessageDialogInEDT( 142 Main.parent, 143 tr("<html>Could not read files.<br>Error is:<br>{0}</html>", e.getMessage()), 144 tr("Error"), 145 JOptionPane.ERROR_MESSAGE, null 146 ); 147 return false; 148 } 149 } 150 151 /** 152 * If multiple files (with multiple file formats) are selected, 153 * they are opened in the order of their priorities. 154 * Highest priority comes first. 155 * @return priority 156 */ 157 public double getPriority() { 158 return 0; 159 } 160 161 @Override 162 public int compareTo(FileImporter other) { 163 return Double.compare(this.getPriority(), other.getPriority()); 164 } 165 166 /** 167 * Returns the enabled state of this {@code FileImporter}. When enabled, it is listed and usable in "File->Open" dialog. 168 * @return true if this {@code FileImporter} is enabled 169 * @since 5459 170 */ 171 public final boolean isEnabled() { 172 return enabled; 173 } 174 175 /** 176 * Sets the enabled state of the {@code FileImporter}. When enabled, it is listed and usable in "File->Open" dialog. 177 * @param enabled true to enable this {@code FileImporter}, false to disable it 178 * @since 5459 179 */ 180 public final void setEnabled(boolean enabled) { 181 this.enabled = enabled; 182 } 183}