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