001 package sears.file; 002 ///////////////////////////////////////////////// 003 //This file is part of Sears project. 004 //Subtitle Editor And Re-Synch 005 //A tool to easily modify and resynch movies subtitles. 006 ///////////////////////////////////////////////// 007 //This program is free software; 008 //you can redistribute it and/or modify it under the terms 009 //of the GNU General Public License 010 //as published by the Free Software Foundation; 011 //either version 2 of the License, or (at your option) any later version. 012 ///////////////////////////////////////////////// 013 //Sears project is available under sourceforge 014 //at adress: http://sourceforge.net/projects/sears/ 015 //Copyright (C) 2005 Booba Skaya 016 //Mail: booba.skaya@gmail.com 017 ///////////////////////////////////////////////// 018 019 //some suggestions about this class: floriaen@gmail.com 020 021 import java.io.BufferedReader; 022 import java.io.File; 023 import java.io.FileInputStream; 024 import java.io.FileNotFoundException; 025 import java.io.IOException; 026 import java.io.InputStreamReader; 027 import java.io.UnsupportedEncodingException; 028 import java.util.ArrayList; 029 030 import sears.file.exception.io.FileConversionException; 031 032 /** 033 * This class must be implemented each time a <tt>java.io.File</tt> object will have to be converted to 034 * a <tt>sears.file.SubtitleFile</tt> object 035 * <br>It wrap a <tt>BufferedReader</tt> and gives method to access to it with respect of the Sears constraints 036 */ 037 public abstract class FileConversion { 038 039 protected File file; 040 private BufferedReader reader; 041 protected int lineCount; 042 043 /** 044 * Constructs a new instance 045 * @param file the file to parse 046 * @param charset the charset used to read the file 047 * @throws NullPointerException if <tt>file</tt> or/and <tt>charset</tt> are null 048 * @throws FileConversionException 049 */ 050 public FileConversion(File file, String charset) throws FileConversionException { 051 if( file == null ) { 052 throw new NullPointerException("cannot parse a null file"); 053 } 054 if( charset == null ) { 055 throw new NullPointerException("charset could not be null"); 056 } 057 this.file = file; 058 initializeReader(charset); 059 } 060 061 // ************** 062 // CORE METHODS * 063 // ************** 064 /** 065 * <br>Principal method: 066 * <br>parses <tt>file</tt> and fill the array list given in parameters with founded subtitles informations 067 * <br>If there's no subtitles found, the array list stays as it was before 068 * @param subtitleList the array of subtitles to fill 069 * @throws FileConversionException if an error occurs during the conversion 070 */ 071 public void parse(ArrayList<Subtitle> subtitleList) throws FileConversionException { 072 // while there's line to read: 073 String line = ""; 074 while( (line = readLine()) != null ) { 075 Subtitle subtitle = getSubtitle(line); 076 if( subtitle != null ) { 077 subtitleList.add(subtitle); 078 } //else line is empty line, loop 079 } 080 if( subtitleList.isEmpty() ) { 081 //throw new EmptySubtitleFileException(file); 082 throw FileConversionException.getMalformedSubtitleFileException( 083 FileConversionException.EMPTY_SUBTITLE_FILE, file); 084 } 085 } 086 087 /** 088 * Constructs and returns the <tt>Subtitle</tt> object which represents subtitles information 089 * begin at line given in parameters 090 * <br>This method is used by the non <tt>abstract</tt> {@link #parse(ArrayList)} method 091 * @param line the first line... 092 * @return the founded subtitle or null if there's no subtitle found 093 * @throws FileConversionException if an error occurs during the conversion 094 */ 095 protected abstract Subtitle getSubtitle(String line) throws FileConversionException; 096 097 098 // *********************** 099 // READER ACCESS METHODS * 100 // *********************** 101 /** 102 * Initializes the reader with the <tt>charset</tt> given in parameters 103 * @param charset if null there's no guarantee to the coherence of this method 104 * @throws FileConversionException if an error occurs during the initialisation 105 */ 106 private void initializeReader(String charset) throws FileConversionException { 107 try { 108 lineCount = 0; 109 reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), charset)); 110 } catch ( UnsupportedEncodingException e ) { 111 // fsa.unsupportedEncoding(file, charset); 112 e.printStackTrace(); 113 } catch ( FileNotFoundException e) { 114 throw FileConversionException.getAccessException( 115 FileConversionException.READ_ACCESS, file); 116 } 117 } 118 119 /** 120 * Reads and returns the next line in the buffer and increment the line count 121 * @return the next line or null if there's no more line to read 122 * @throws FileConversionException if a basic <tt>IOException</tt> occurs when 123 * attempts to read in the buffer 124 */ 125 protected String readLine() throws FileConversionException { 126 String line = null; 127 lineCount++; 128 try { 129 line = reader.readLine(); 130 } catch (IOException e) { 131 throw FileConversionException.getAccessException( 132 FileConversionException.READ_ACCESS, file); 133 } 134 return line; 135 } 136 137 /** 138 * Place the 'read head' on the next non empty line and returns it 139 * @return the next non empty line or null if there's no more line to read 140 */ 141 protected String getTheNextNonEmptyLine() throws FileConversionException { 142 String str = null; 143 try { 144 str = readLine(); 145 while( str != null && str.equals("") ){ 146 str = readLine(); 147 } 148 } catch (IOException e) { 149 throw FileConversionException.getAccessException( 150 FileConversionException.READ_ACCESS, file); 151 } 152 return str; 153 } 154 155 /** 156 * Closes the reader and reset line count 157 * @throws FileConversionException if a basic <tt>IOException</tt> occurs when 158 * attempts to close the the buffer reader 159 */ 160 protected void closeReader() throws FileConversionException { 161 if( reader != null ) { 162 try { 163 reader.close(); 164 lineCount = 0; 165 } catch (IOException e) { 166 // try to inform that error occurs when closed the file 167 //throw new ReadAccessException(file); 168 throw FileConversionException.getAccessException( 169 FileConversionException.READ_ACCESS, file); 170 } 171 } 172 } 173 174 // *************** 175 // UTILS METHODS * 176 // *************** 177 /** 178 * Tests the validity of <tt>str</tt> 179 * return true if <tt>str</tt> is not null and if it is not an empty <tt>String</tt>, false if not 180 * @throws IOException 181 */ 182 protected void ensureStringIsValid(String str) throws FileConversionException { 183 if ( str == null || str.equals("")) { 184 //throw new MalformedSubtitleFileException(file, lineCount, ""); 185 throw FileConversionException.getMalformedSubtitleFileException( 186 FileConversionException.MALFORMED_SUBTITLE_FILE, 187 file, lineCount, ""); 188 } 189 } 190 191 /** 192 * If <tt>str</tt> length is more than 100 characters, <tt>str</tt> is cut and returned 193 * @param str the string to cut 194 * @return <tt>str</str> or a sub string of this array 195 */ 196 protected static String subString(String str) { 197 if( str.length() > 100 ) { 198 str = str.substring(0, 100); 199 } 200 return str; 201 } 202 }