001    package sears.file;
002    
003    import java.io.File;
004    import java.util.ArrayList;
005    
006    import sears.file.exception.io.FileConversionException;
007    import sears.gui.MainWindow;
008    
009    /**
010     * Provides access method to file like <i>open</i> and <i>save</i>
011     * <br>An instance of this class captures error coming from the conversion of file to subtitle file
012     */
013    public class FileSystemAccess {
014    
015            private static FileSystemAccess instance;
016            private MainWindow mainWindow;
017    
018            /** (<tt>int</tt>) maximum authorized size for a subtitle file, 2 Mo */
019            public final static int MAX_SUBTITLE_FILE_SIZE = 2000000;
020    
021            /**
022             * Gives the same instance of this class
023             * <br>Only used by <tt>MainWindow</tt> class
024             * @return      an object instance of <tt>FileSystemAccess</tt> class.
025             */
026            public static FileSystemAccess getInstance() {
027                    if( instance == null ) {
028                            instance = new FileSystemAccess(MainWindow.instance);
029                    }
030                    return instance;
031            }
032    
033            /**
034             * Default constructor
035             * @param mainWindow    the extended controller
036             */
037            protected FileSystemAccess(MainWindow mainWindow) {
038                    if( mainWindow == null ) {
039                            throw new NullPointerException("main window cannot be null");
040                    }
041                    this.mainWindow = mainWindow;
042            }
043    
044            /**
045             * Tests the length of the <tt>java.io.File</tt> given in parameters
046             * @param file                                          the file to test
047             * @throws FileConversionException      if length or access to the file cause a problem 
048             * @throws NullPointerException         if <tt>file</tt> is null
049             */
050            private void ensureFileLengthCoherence(File file) throws FileConversionException {
051                    try {
052                            if( file.length() >= MAX_SUBTITLE_FILE_SIZE ) {
053                                    throw FileConversionException.getAccessException(
054                                                    FileConversionException.UNSUPPORTED_FILE_SIZE, file);
055                            }
056                    } catch( SecurityException e) {
057                            throw FileConversionException.getAccessException(
058                                            FileConversionException.READ_ACCESS, file);
059                    }
060            }
061            
062            /**
063             * Provides a way to get a <tt>SubtitleFile</tt> instance from a file
064             * @param file          the file to convert
065             * @param charset       the charset used for the conversion
066             * @return                      the <tt>SubtitleFile</tt> object created or null if an error occurs
067             */
068            public SubtitleFile openFile(File file, String charset) {
069                    return openFile(file, null, charset);
070            }
071            
072            private void fillArray(ArrayList<Subtitle> listToFill, ArrayList<Subtitle> savedList) {
073                    listToFill.clear();
074                    listToFill.addAll(savedList);
075            }
076    
077            /**
078             * Provides a way to get <tt>SubtitleFile</tt> instance from a file
079             * <br>If an error occurs an error dialog is called
080             * @param file                  the file to convert
081             * @param subtitleList  the subtitle list to fill
082             * @param charset               the charset used for the conversion
083             * @return                              the <tt>SubtitleFile</tt> object created or null if an error occurs
084             */
085            public SubtitleFile openFile(File file, ArrayList<Subtitle> subtitleList, String charset) {
086                    SubtitleFile subtitleFile = null;
087                    // save the subtitle list in case of error:
088                    ArrayList<Subtitle> savedSubtitleList = new ArrayList<Subtitle>();
089                    if( subtitleList == null ) {
090                            // subtitleList becomes an empty array
091                            subtitleList = savedSubtitleList;
092                    } else {                        
093                            savedSubtitleList.addAll(subtitleList);
094                            subtitleList.clear();
095                    }
096                    // Try to create the new subtitleFile:
097                    try {   
098                            // ensure that the file length is not bigger than the one supported by Sears
099                            ensureFileLengthCoherence(file);
100                            // try to create a new Subtitle file
101                            subtitleFile = SubtitleFile.getInstance(file, subtitleList, charset);
102                    } catch ( FileConversionException e ) {
103                            //
104                            // file conversion error occurs:
105                            // - malformed subtitle file
106                            // - read access error
107                            
108                            // return saved list
109                            fillArray(subtitleList, savedSubtitleList);
110                            charset = mainWindow.showOpenErrorDialog(e.getMessage(), e.getDetail(), e.couldBeABadEncoding());
111                            if( charset != null ) {
112                                    mainWindow.openFile(file, charset);
113                            } // else, error dialog has be closed by user, do not try to reopen file
114                    } catch ( NullPointerException e) {
115                            //
116                            // DEVELOPER:
117                            // one of the parameters is null !!
118                            
119                            // return saved list
120                            fillArray(subtitleList, savedSubtitleList);
121                            e.printStackTrace();
122                            mainWindow.showOpenErrorDialog("unknow error", e.toString(), false);
123                            
124                    } catch ( Exception e ) {
125                            //
126                            // DEVELOPER:
127                            // if an unknown error occurs, a generic dialog is show...
128                            
129                            // return saved list
130                            fillArray(subtitleList, savedSubtitleList);
131                            e.printStackTrace();
132                            mainWindow.showOpenErrorDialog("unknow error",e.toString(), false);                     
133                    }
134                    return subtitleFile;
135            }
136    
137            /**
138             * Writes the subtitle to a file and invokes an error dialog if an error occurs during the action
139             * @param file                  the file in which the subtitle must be write
140             * @param subtitleFile  the subtitle to write
141             * @param charset               the charset used to write the file, if null the subtitle's charset will be used
142             * @return                              true if action succeed, false if not
143             */
144            public boolean saveFile(File file, SubtitleFile subtitleFile, String charset) {
145                    boolean isFileSaved = false;
146                    if (subtitleFile != null) {
147                            if( charset != null ) {
148                                    subtitleFile.setCharset(charset);
149                            } // else the file will be saved with this defined charset
150                            try {                           
151                                    subtitleFile.writeToFile(file);
152                                    isFileSaved = true;
153                            } catch (FileConversionException e) {
154                                    mainWindow.showSaveErrorDialog(e.getMessage(), e.getDetail());
155                            }
156                    }               
157                    return isFileSaved;
158            }
159    }