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