001    package sears.file.exception.io;
002    
003    import java.io.File;
004    import java.io.IOException;
005    
006    import sears.file.FileSystemAccess;
007    import sears.tools.Utils;
008    
009    /**
010     * A <tt>FileConversionException</tt> is throw when an error occurs during a file access
011     * and conversion to subtitle file
012     * <br>This class provides <tt>static</tt> methods to create generic objects using
013     * the class constants.
014     * <p>
015     * Two distinct categories of constants:
016     * <br>- file access exception ( read and write access )
017     * <br>- malformed subtitle file exception
018     * </p>
019     */
020    public abstract class FileConversionException extends IOException {
021    
022            // FILE ACCESS EXCEPTION :
023            // +++++++++++++++++++++
024            //
025            /** FILE ACCESS EXCEPTION: Read access exception */
026            public static final int READ_ACCESS                             = 0;
027            /** FILE ACCESS EXCEPTION: Write access exception */
028            public static final int WRITE_ACCESS                            = 1;
029            /** FILE ACCESS EXCEPTION: unsupported file size exception */
030            public static final int UNSUPPORTED_FILE_SIZE           = 2;
031    
032            // MALFORMED SUBTITLE FILE EXCEPTION :
033            // +++++++++++++++++++++++++++++++++
034            //
035            // + NUMBER - MALFORMED SUBTITLE FILE EXCEPTION
036            /** MALFORMED SUBTITLE FILE EXCEPTION: no subtitle number exception */
037            public static final int NO_SUBTITLE_NUMBER                      = 3;
038            /** MALFORMED SUBTITLE FILE EXCEPTION: malformed subtitle number exception */
039            public static final int MALFORMED_SUBTITLE_NUMBER       = 4;
040    
041            // + TIME - MALFORMED SUBTITLE FILE EXCEPTION
042            /** MALFORMED SUBTITLE FILE EXCEPTION: no subtitle time exception */
043            public static final int NO_SUBTITLE_TIME                        = 5;
044            /** MALFORMED SUBTITLE FILE EXCEPTION: malformed subtitle time line exception */
045            public static final int MALFORMED_TIME_LINE             = 6;
046            /** MALFORMED SUBTITLE FILE EXCEPTION: malformed subtitle start time exception */
047            public static final int MALFORMED_START_TIME            = 7;
048            /** MALFORMED SUBTITLE FILE EXCEPTION: malformed subtitle end time exception */
049            public static final int MALFORMED_END_TIME                      = 8;
050    
051            // + TEXT - MALFORMED SUBTITLE FILE EXCEPTION
052            /** MALFORMED SUBTITLE FILE EXCEPTION: no subtitle text exception */
053            public static final int NO_SUBTITLE_TEXT                        = 9;
054            /** MALFORMED SUBTITLE FILE EXCEPTION: malformed subtitle text exception */
055            public static final int MALFORMED_SUBTITLE_TEXT         = 10;
056    
057            // + GENERIC MALFORMED SUBTITLE FILE EXCEPTION
058            /** MALFORMED SUBTITLE FILE EXCEPTION: generic subtitle file exception */
059            public static final int MALFORMED_SUBTITLE_FILE         = 11;
060    
061            // + SPECIAL MALFORMED SUBTITLE FILE EXCEPTION
062            /** MALFORMED SUBTITLE FILE EXCEPTION: unexpected end of file exception */
063            public static final int UNEXPECTED_END_OF_FILE          = 12;
064            /** MALFORMED SUBTITLE FILE EXCEPTION: empty subtitle file exception */
065            public static final int EMPTY_SUBTITLE_FILE                     = 13;
066    
067            /**
068             * Returns the error message
069             * @return the error message
070             */
071            public abstract String getMessage();
072    
073            /**
074             * Returns the detail error message
075             * @return the detail error message
076             */
077            public abstract String getDetail();
078    
079            /**
080             * Returns a <tt>boolean</tt> which indicates if the error could have
081             * appeared because of a bad encoding/decoding
082             * @return      true if the error could be appear because a bad encoding/decoding
083             *                      false if not
084             */
085            public abstract boolean couldBeABadEncoding();
086    
087            // returns a formatted message by analyze <tt>file</tt> parameter
088            private static String fileDetail(File file) {
089                    String detail = "";
090                    try {
091                            detail = file.getPath() + Utils.LINE_SEPARATOR;
092                    } catch( NullPointerException e ) {
093                            detail = "";
094                    }
095                    return detail;
096            }
097    
098            // READ ERROR
099            // returns a formatted error message by testing <tt>file</tt> parameter
100            private static String iOExceptionDetailWhenReading(File file) {
101                    String message = null;
102                    if( file != null ) {
103                            try {
104                                    if( file.exists() ) {
105                                            if( !file.canRead() ) {
106                                                    message = "File read access is denied";
107                                            } else {
108                                                    message = "Unknow error, the file seems to be readable";
109                                            }
110                                    } else {
111                                            message = "File does not exist";
112                                    }
113                            } catch (SecurityException e) {
114                                    message = "There's a security restriction on this file";
115                            }
116                    } else {
117                            message = "Unknow error";
118                    }
119                    return message;
120            }
121    
122            // WRITE ERROR
123            // returns a formatted error message by testing <tt>file</tt> parameter
124            private static String iOExceptionDetailWhenWriting(File file) {
125                    String message = null;
126                    if( file != null ) {
127                            try {
128                                    if( file.exists() ) {
129                                            if( !file.canWrite() ) {
130                                                    message = "File write access is denied";
131                                            } else {
132                                                    message = "Unknow error, the file seems to be writable";
133                                            }
134                                    } else {
135                                            message = "File does not exist";
136                                    }
137                            } catch (SecurityException e) {
138                                    message = "There's a security restriction on this file";
139                            }
140                    } else {
141                            message = "Unknow error";
142                    }
143                    return message;
144            }
145    
146            // LENGTH ERROR
147            // returns a formatted error message by testing <tt>file</tt> parameter
148            private static String getFileLengthMessage(File file) {
149                    String message = "";
150                    try {
151                            message = file.length() + " octets is too big"
152                            + Utils.LINE_SEPARATOR 
153                            + "SEARS do not support file bigger than " 
154                            + FileSystemAccess.MAX_SUBTITLE_FILE_SIZE + " octets";  
155                    } catch (SecurityException e) {
156                            message = "SEARS do not support file bigger than " 
157                                    + FileSystemAccess.MAX_SUBTITLE_FILE_SIZE + " octets";  
158                    } catch (NullPointerException e) {
159                            // DEVELOPPER:
160                            // ????
161                            // file is null !!!!
162                            message = "Unknow error"; 
163                    }
164                    return message;
165            }
166    
167            /**
168             * Get a new <tt>FileConversionException</tt> instance
169             * @param type  <tt>READ_ACCESS</tt>, <tt>WRITE_ACCESS</tt>, <tt>UNSUPPORTED_FILE_SIZE</tt>
170             * @param file  the file where the error is encountered
171             * @return              a new read access exception
172             */
173            public static FileConversionException getAccessException(int type, File file) {
174                    String message = "";
175                    String detail = "";
176                    switch ( type ) {
177                    case READ_ACCESS:
178                            message = "Read access error";
179                            detail  = fileDetail(file) + iOExceptionDetailWhenReading(file) + ", "
180                            + Utils.LINE_SEPARATOR + "please checks your authorisation on this file";
181                            break;
182                    case WRITE_ACCESS:
183                            message = "Write access error";
184                            detail  = fileDetail(file) + iOExceptionDetailWhenWriting(file) + ", "
185                            + Utils.LINE_SEPARATOR + "please checks your authorisation on this file";
186                            break;
187                    case UNSUPPORTED_FILE_SIZE:
188                            message = "Unsupported file size";
189                            detail  = fileDetail(file) + getFileLengthMessage(file);
190                            break;
191                    default:
192                            throw new IllegalArgumentException(type + " is not a valid identifier for an exception type");
193                    }
194                    return new Bean(message, detail, false);
195            }
196    
197            /**
198             * Get a new <tt>FileConversionException</tt> instance
199             * @param type  <tt>UNEXPECTED_END_OF_FILE</tt>, <tt>EMPTY_SUBTITLE_FILE</tt>
200             * @param file  the file on which the error occurs
201             * @return              a new malformed subtitle file exception
202             */
203            public static FileConversionException getMalformedSubtitleFileException(int type, File file) {
204                    String message = "";
205                    String detail = "";
206                    switch ( type ) {
207                    case UNEXPECTED_END_OF_FILE:
208                            message = "Subtitle file seems to be corrupted";
209                            detail  = fileDetail(file) + "unexpected end of file";
210                            break;
211                    case EMPTY_SUBTITLE_FILE:
212                            message = "file is empty";
213                            detail  = fileDetail(file) + "Sears can't read empty subtitle file";
214                            break;
215                    default:
216                            throw new IllegalArgumentException(type + " is not a valid identifier for an exception type");
217                    }
218                    return new Bean(message, detail, false);
219            }
220    
221            /**
222             * Get a new <tt>FileConversionException</tt> instance
223             * @param type                  <tt>MALFORMED_SUBTITLE_NUMBER <br>NO_SUBTITLE_TIME
224             *                                              <br>MALFORMED_TIME_LINE<br>MALFORMED_START_TIME
225             *                                              <br>MALFORMED_END_TIME<br>NO_SUBTITLE_TEXT
226             *                                              <br>MALFORMED_SUBTITLE_TEXT<br>MALFORMED_SUBTITLE_FILE</tt>
227             * @param file                  the file on which the error occurrs
228             * @param lineNumber    the line number where the error is encountered
229             * @param line                  the line where the error is encountered
230             * @return                              a new <tt>FileConversionException</tt> instance
231             */
232            public static FileConversionException getMalformedSubtitleFileException(int type, File file, int lineNumber, String line) {
233                    String message = "Subtitle file seems to be corrupted";
234                    String detail = "";
235                    switch ( type ) {
236                    case NO_SUBTITLE_NUMBER:
237                            detail = fileDetail(file) 
238                            + "no subtitle number at line " + lineNumber;   
239                            break;
240                    case MALFORMED_SUBTITLE_NUMBER:
241                            detail = fileDetail(file) 
242                            + "no subtitle number at line " + lineNumber 
243                            + Utils.LINE_SEPARATOR + line;
244                            break;
245                    case NO_SUBTITLE_TIME:
246                            detail = fileDetail(file) 
247                            + "no time at line " + lineNumber;
248                            break;
249                    case MALFORMED_TIME_LINE:
250                            detail = fileDetail(file) 
251                            + "malformed time at line " + lineNumber
252                            + Utils.LINE_SEPARATOR + line;          
253                            break;
254                    case MALFORMED_START_TIME:
255                            detail = fileDetail(file) 
256                            + "malformed start time at line " + lineNumber 
257                            + Utils.LINE_SEPARATOR + line;          
258                            break;
259                    case MALFORMED_END_TIME:
260                            detail = fileDetail(file) 
261                            + "malformed end time at line " + lineNumber 
262                            + Utils.LINE_SEPARATOR + line;
263                            break;
264                    case NO_SUBTITLE_TEXT:
265                            detail = fileDetail(file) 
266                            + "no subtitle text at line " + lineNumber;
267                            break;
268                    case MALFORMED_SUBTITLE_TEXT:
269                            detail = fileDetail(file) 
270                            + "no subtitle text at line " + lineNumber;
271                            break;
272                    case MALFORMED_SUBTITLE_FILE:
273                            detail = fileDetail(file) 
274                            + "unknow error " + Utils.LINE_SEPARATOR
275                            + "malformed subtitle file at line " + lineNumber;
276                            break;
277                    default:
278                            throw new IllegalArgumentException(type + " is not a valid identifier for an exception type");
279                    }
280                    return new Bean(message, detail, true);
281            }
282    
283            /**
284             * Get a new <tt>FileConversionException</tt> instance
285             * @param file                  the file in cause
286             * @param extension             the <tt>file</tt> extension
287             * @return                              a unsupported file format exception
288             */
289            public static FileConversionException getUnsupportedFileFormatException(File file, String extension) {
290                    return new Bean(
291                                    // MESSAGE
292                                    "unsupported file format",
293                                    // DETAIL
294                                    fileDetail(file) 
295                                    + extension + " file is not supported by Sears",
296                                    // COULD BE THE RESULT OF A BAD ENCODING
297                                    false
298                    );
299            }
300    }
301    
302    /**
303     * This class provides a way to create a basic FileConversion object
304     * <br> Used by the <tt>static</tt> methods of the abstract class that <tt>Bean</tt> extends
305     */
306    class Bean extends FileConversionException {
307    
308            private static final long serialVersionUID = 75866932870197914L;
309    
310            private String message;
311            private String detail;
312            private Boolean couldBeABadEncoding;
313    
314            /**
315             * Constructs a new object with an error message,
316             * detail for this error and a <tt>boolean</tt>
317             * to know if the error could be occur because a bad encoding/decoding
318             * @param message                               the error message
319             * @param detail                                the detail of the error
320             * @param couldBeABadEncoding   if the error may cause by a bad decoding/encoding value is true, false if not
321             */
322            public Bean(String message, String detail, boolean couldBeABadEncoding) {
323                    this.message = message;
324                    this.detail = detail;
325                    this.couldBeABadEncoding = couldBeABadEncoding;
326            }
327    
328            /*
329             * (non-Javadoc)
330             * @see sears.file.exception.io.FileConversionException#couldBeABadEncoding()
331             */
332            public boolean couldBeABadEncoding() {
333                    return couldBeABadEncoding;
334            }
335    
336            /*
337             * (non-Javadoc)
338             * @see sears.file.exception.io.FileConversionException#getDetail()
339             */
340            public String getDetail() {
341                    return detail;
342            }
343    
344            /*
345             * (non-Javadoc)
346             * @see sears.file.exception.io.FileConversionException#getMessage()
347             */
348            public String getMessage() {
349                    return message;
350            }
351    }