001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.io;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.io.BufferedInputStream;
007    import java.io.File;
008    import java.io.IOException;
009    import java.io.InputStream;
010    import java.util.List;
011    import java.util.zip.GZIPInputStream;
012    
013    import javax.swing.JOptionPane;
014    
015    import org.apache.tools.bzip2.CBZip2InputStream;
016    import org.openstreetmap.josm.Main;
017    import org.openstreetmap.josm.actions.ExtensionFileFilter;
018    import org.openstreetmap.josm.gui.HelpAwareOptionPane;
019    import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
020    import org.openstreetmap.josm.gui.layer.Layer;
021    import org.openstreetmap.josm.gui.progress.ProgressMonitor;
022    
023    public abstract class FileImporter implements Comparable<FileImporter>, LayerChangeListener {
024    
025        public final ExtensionFileFilter filter;
026        
027        private boolean enabled;
028    
029        public FileImporter(ExtensionFileFilter filter) {
030            this.filter = filter;
031            this.enabled = true;
032        }
033    
034        public boolean acceptFile(File pathname) {
035            return filter.acceptName(pathname.getName());
036        }
037    
038        /**
039         * A batch importer is a file importer that prefers to read multiple files at the same time.
040         */
041        public boolean isBatchImporter() {
042            return false;
043        }
044    
045        /**
046         * Needs to be implemented if isBatchImporter() returns false.
047         */
048        public void importData(File file, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
049            throw new IOException(tr("Could not import ''{0}''.", file.getName()));
050        }
051    
052        /**
053         * Needs to be implemented if isBatchImporter() returns true.
054         */
055        public void importData(List<File> files, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
056            throw new IOException(tr("Could not import files."));
057        }
058    
059        /**
060         * Wrapper to give meaningful output if things go wrong.
061         * @return true if data import was successful
062         */
063        public boolean importDataHandleExceptions(File f, ProgressMonitor progressMonitor) {
064            try {
065                System.out.println("Open file: " + f.getAbsolutePath() + " (" + f.length() + " bytes)");
066                importData(f, progressMonitor);
067                return true;
068            } catch (Exception e) {
069                e.printStackTrace();
070                HelpAwareOptionPane.showMessageDialogInEDT(
071                        Main.parent,
072                        tr("<html>Could not read file ''{0}''.<br>Error is:<br>{1}</html>", f.getName(), e.getMessage()),
073                        tr("Error"),
074                        JOptionPane.ERROR_MESSAGE, null
075                );
076                return false;
077            }
078        }
079        public boolean importDataHandleExceptions(List<File> files, ProgressMonitor progressMonitor) {
080            try {
081                System.out.println("Open "+files.size()+" files");
082                importData(files, progressMonitor);
083                return true;
084            } catch (Exception e) {
085                e.printStackTrace();
086                HelpAwareOptionPane.showMessageDialogInEDT(
087                        Main.parent,
088                        tr("<html>Could not read files.<br>Error is:<br>{0}</html>", e.getMessage()),
089                        tr("Error"),
090                        JOptionPane.ERROR_MESSAGE, null
091                );
092                return false;
093            }
094        }
095    
096        /**
097         * If multiple files (with multiple file formats) are selected,
098         * they are opened in the order of their priorities.
099         * Highest priority comes first.
100         */
101        public double getPriority() {
102            return 0;
103        }
104    
105        public int compareTo(FileImporter other) {
106            return (new Double(this.getPriority())).compareTo(other.getPriority());
107        }
108        
109        public static CBZip2InputStream getBZip2InputStream(InputStream in) throws IOException {
110            if (in == null) {
111                return null;
112            }
113            BufferedInputStream bis = new BufferedInputStream(in);
114            int b = bis.read();
115            if (b != 'B')
116                throw new IOException(tr("Invalid bz2 file."));
117            b = bis.read();
118            if (b != 'Z')
119                throw new IOException(tr("Invalid bz2 file."));
120            return new CBZip2InputStream(bis);
121        }
122    
123        public static GZIPInputStream getGZipInputStream(InputStream in) throws IOException {
124            if (in == null) {
125                return null;
126            }
127            return new GZIPInputStream(in);
128        }
129    
130        /**
131         * Returns the enabled state of this {@code FileImporter}. When enabled, it is listed and usable in "File->Open" dialog. 
132         * @return true if this {@code FileImporter} is enabled
133         * @since 5459
134         */
135        public final boolean isEnabled() {
136            return enabled;
137        }
138    
139        /**
140         * Sets the enabled state of the {@code FileImporter}. When enabled, it is listed and usable in "File->Open" dialog.
141         * @param enabled true to enable this {@code FileImporter}, false to disable it
142         * @since 5459
143         */
144        public final void setEnabled(boolean enabled) {
145            this.enabled = enabled;
146        }
147    
148        @Override
149        public void activeLayerChange(Layer oldLayer, Layer newLayer) {
150            // To be overriden by subclasses if their enabled state depends of the active layer nature
151        }
152    
153        @Override
154        public void layerAdded(Layer newLayer) {
155            // To be overriden by subclasses if needed
156        }
157    
158        @Override
159        public void layerRemoved(Layer oldLayer) {
160            // To be overriden by subclasses if needed
161        }
162    }