001 // License: GPL. Copyright 2007 by Immanuel Scholz and others 002 package org.openstreetmap.josm.actions; 003 004 import java.io.File; 005 import java.util.ArrayList; 006 import java.util.Collections; 007 import java.util.Comparator; 008 import java.util.LinkedList; 009 import java.util.List; 010 011 import javax.swing.JFileChooser; 012 import javax.swing.filechooser.FileFilter; 013 014 import org.openstreetmap.josm.gui.MapView; 015 import org.openstreetmap.josm.io.AllFormatsImporter; 016 import org.openstreetmap.josm.io.FileExporter; 017 import org.openstreetmap.josm.io.FileImporter; 018 019 /** 020 * A file filter that filters after the extension. Also includes a list of file 021 * filters used in JOSM. 022 * @since 32 023 */ 024 public class ExtensionFileFilter extends FileFilter { 025 026 /** 027 * List of supported formats for import. 028 * @since 4869 029 */ 030 public static final ArrayList<FileImporter> importers; 031 032 /** 033 * List of supported formats for export. 034 * @since 4869 035 */ 036 public static final ArrayList<FileExporter> exporters; 037 038 // add some file types only if the relevant classes are there; 039 // this gives us the option to painlessly drop them from the .jar 040 // and build JOSM versions without support for these formats 041 042 static { 043 044 importers = new ArrayList<FileImporter>(); 045 046 String[] importerNames = { 047 "org.openstreetmap.josm.io.OsmImporter", 048 "org.openstreetmap.josm.io.OsmGzipImporter", 049 "org.openstreetmap.josm.io.OsmChangeImporter", 050 "org.openstreetmap.josm.io.GpxImporter", 051 "org.openstreetmap.josm.io.NMEAImporter", 052 "org.openstreetmap.josm.io.OsmBzip2Importer", 053 "org.openstreetmap.josm.io.JpgImporter", 054 "org.openstreetmap.josm.io.WMSLayerImporter", 055 "org.openstreetmap.josm.io.AllFormatsImporter" 056 }; 057 058 for (String classname : importerNames) { 059 try { 060 FileImporter importer = (FileImporter) Class.forName(classname).newInstance(); 061 importers.add(importer); 062 MapView.addLayerChangeListener(importer); 063 } catch (Throwable t) { } 064 } 065 066 exporters = new ArrayList<FileExporter>(); 067 068 String[] exporterNames = { 069 "org.openstreetmap.josm.io.GpxExporter", 070 "org.openstreetmap.josm.io.OsmExporter", 071 "org.openstreetmap.josm.io.OsmGzipExporter", 072 "org.openstreetmap.josm.io.OsmBzip2Exporter", 073 "org.openstreetmap.josm.io.GeoJSONExporter", 074 "org.openstreetmap.josm.io.WMSLayerExporter" 075 }; 076 077 for (String classname : exporterNames) { 078 try { 079 FileExporter exporter = (FileExporter)Class.forName(classname).newInstance(); 080 exporters.add(exporter); 081 MapView.addLayerChangeListener(exporter); 082 } catch (Throwable t) { } 083 } 084 } 085 086 private final String extensions; 087 private final String description; 088 private final String defaultExtension; 089 090 static protected void sort(List<ExtensionFileFilter> filters) { 091 Collections.sort( 092 filters, 093 new Comparator<ExtensionFileFilter>() { 094 private AllFormatsImporter all = new AllFormatsImporter(); 095 public int compare(ExtensionFileFilter o1, ExtensionFileFilter o2) { 096 if (o1.getDescription().equals(all.filter.getDescription())) return 1; 097 if (o2.getDescription().equals(all.filter.getDescription())) return -1; 098 return o1.getDescription().compareTo(o2.getDescription()); 099 } 100 } 101 ); 102 } 103 104 /** 105 * Updates the {@link AllFormatsImporter} that is contained in the importers list. If 106 * you do not use the importers variable directly, you don???t need to call this. 107 * <p> 108 * Updating the AllFormatsImporter is required when plugins add new importers that 109 * support new file extensions. The old AllFormatsImporter doesn???t include the new 110 * extensions and thus will not display these files. 111 * 112 * @since 5131 113 */ 114 public static void updateAllFormatsImporter() { 115 for(int i=0; i < importers.size(); i++) { 116 if(importers.get(i) instanceof AllFormatsImporter) { 117 importers.set(i, new AllFormatsImporter()); 118 } 119 } 120 } 121 122 /** 123 * Replies an ordered list of {@link ExtensionFileFilter}s for importing. 124 * The list is ordered according to their description, an {@link AllFormatsImporter} 125 * is append at the end. 126 * 127 * @return an ordered list of {@link ExtensionFileFilter}s for importing. 128 * @since 2029 129 */ 130 public static List<ExtensionFileFilter> getImportExtensionFileFilters() { 131 updateAllFormatsImporter(); 132 LinkedList<ExtensionFileFilter> filters = new LinkedList<ExtensionFileFilter>(); 133 for (FileImporter importer : importers) { 134 filters.add(importer.filter); 135 } 136 sort(filters); 137 return filters; 138 } 139 140 /** 141 * Replies an ordered list of enabled {@link ExtensionFileFilter}s for exporting. 142 * The list is ordered according to their description, an {@link AllFormatsImporter} 143 * is append at the end. 144 * 145 * @return an ordered list of enabled {@link ExtensionFileFilter}s for exporting. 146 * @since 2029 147 */ 148 public static List<ExtensionFileFilter> getExportExtensionFileFilters() { 149 LinkedList<ExtensionFileFilter> filters = new LinkedList<ExtensionFileFilter>(); 150 for (FileExporter exporter : exporters) { 151 if (filters.contains(exporter.filter) || !exporter.isEnabled()) { 152 continue; 153 } 154 filters.add(exporter.filter); 155 } 156 sort(filters); 157 return filters; 158 } 159 160 /** 161 * Replies the default {@link ExtensionFileFilter} for a given extension 162 * 163 * @param extension the extension 164 * @return the default {@link ExtensionFileFilter} for a given extension 165 * @since 2029 166 */ 167 public static ExtensionFileFilter getDefaultImportExtensionFileFilter(String extension) { 168 if (extension == null) return new AllFormatsImporter().filter; 169 for (FileImporter importer : importers) { 170 if (extension.equals(importer.filter.getDefaultExtension())) 171 return importer.filter; 172 } 173 return new AllFormatsImporter().filter; 174 } 175 176 /** 177 * Replies the default {@link ExtensionFileFilter} for a given extension 178 * 179 * @param extension the extension 180 * @return the default {@link ExtensionFileFilter} for a given extension 181 * @since 2029 182 */ 183 public static ExtensionFileFilter getDefaultExportExtensionFileFilter(String extension) { 184 if (extension == null) return new AllFormatsImporter().filter; 185 for (FileExporter exporter : exporters) { 186 if (extension.equals(exporter.filter.getDefaultExtension())) 187 return exporter.filter; 188 } 189 return new AllFormatsImporter().filter; 190 } 191 192 /** 193 * Applies the choosable {@link FileFilter} to a {@link JFileChooser} before using the 194 * file chooser for selecting a file for reading. 195 * 196 * @param fileChooser the file chooser 197 * @param extension the default extension 198 * @param allTypes If true, all the files types known by JOSM will be proposed in the "file type" combobox. 199 * If false, only the file filters that include {@code extension} will be proposed 200 * @since 5438 201 */ 202 public static void applyChoosableImportFileFilters(JFileChooser fileChooser, String extension, boolean allTypes) { 203 for (ExtensionFileFilter filter: getImportExtensionFileFilters()) { 204 if (allTypes || filter.acceptName("file."+extension)) { 205 fileChooser.addChoosableFileFilter(filter); 206 } 207 } 208 fileChooser.setFileFilter(getDefaultImportExtensionFileFilter(extension)); 209 } 210 211 /** 212 * Applies the choosable {@link FileFilter} to a {@link JFileChooser} before using the 213 * file chooser for selecting a file for writing. 214 * 215 * @param fileChooser the file chooser 216 * @param extension the default extension 217 * @param allTypes If true, all the files types known by JOSM will be proposed in the "file type" combobox. 218 * If false, only the file filters that include {@code extension} will be proposed 219 * @since 5438 220 */ 221 public static void applyChoosableExportFileFilters(JFileChooser fileChooser, String extension, boolean allTypes) { 222 for (ExtensionFileFilter filter: getExportExtensionFileFilters()) { 223 if (allTypes || filter.acceptName("file."+extension)) { 224 fileChooser.addChoosableFileFilter(filter); 225 } 226 } 227 fileChooser.setFileFilter(getDefaultExportExtensionFileFilter(extension)); 228 } 229 230 /** 231 * Construct an extension file filter by giving the extension to check after. 232 * @param extension The comma-separated list of file extensions 233 * @param defaultExtension The default extension 234 * @param description A short textual description of the file type 235 * @since 1169 236 */ 237 public ExtensionFileFilter(String extension, String defaultExtension, String description) { 238 this.extensions = extension; 239 this.defaultExtension = defaultExtension; 240 this.description = description; 241 } 242 243 /** 244 * Returns true if this file filter accepts the given filename. 245 * @param filename The filename to check after 246 * @return true if this file filter accepts the given filename (i.e if this filename ends with one of the extensions) 247 * @since 1169 248 */ 249 public boolean acceptName(String filename) { 250 String name = filename.toLowerCase(); 251 for (String ext : extensions.split(",")) 252 if (name.endsWith("."+ext)) 253 return true; 254 return false; 255 } 256 257 @Override 258 public boolean accept(File pathname) { 259 if (pathname.isDirectory()) 260 return true; 261 return acceptName(pathname.getName()); 262 } 263 264 @Override 265 public String getDescription() { 266 return description; 267 } 268 269 /** 270 * Replies the comma-separated list of file extensions of this file filter. 271 * @return the comma-separated list of file extensions of this file filter, as a String 272 * @since 5131 273 */ 274 public String getExtensions() { 275 return extensions; 276 } 277 278 /** 279 * Replies the default file extension of this file filter. 280 * @return the default file extension of this file filter 281 * @since 2029 282 */ 283 public String getDefaultExtension() { 284 return defaultExtension; 285 } 286 287 @Override 288 public int hashCode() { 289 final int prime = 31; 290 int result = 1; 291 result = prime * result + ((defaultExtension == null) ? 0 : defaultExtension.hashCode()); 292 result = prime * result + ((description == null) ? 0 : description.hashCode()); 293 result = prime * result + ((extensions == null) ? 0 : extensions.hashCode()); 294 return result; 295 } 296 297 @Override 298 public boolean equals(Object obj) { 299 if (this == obj) 300 return true; 301 if (obj == null) 302 return false; 303 if (getClass() != obj.getClass()) 304 return false; 305 ExtensionFileFilter other = (ExtensionFileFilter) obj; 306 if (defaultExtension == null) { 307 if (other.defaultExtension != null) 308 return false; 309 } else if (!defaultExtension.equals(other.defaultExtension)) 310 return false; 311 if (description == null) { 312 if (other.description != null) 313 return false; 314 } else if (!description.equals(other.description)) 315 return false; 316 if (extensions == null) { 317 if (other.extensions != null) 318 return false; 319 } else if (!extensions.equals(other.extensions)) 320 return false; 321 return true; 322 } 323 }