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