001 ///////////////////////////////////////////////// 002 //This file is part of Sears project. 003 //Subtitle Editor And Re-Synch 004 //A tool to easily modify and resynch movies subtitles. 005 ///////////////////////////////////////////////// 006 //This program is free software; 007 //you can redistribute it and/or modify it under the terms 008 //of the GNU General Public License 009 //as published by the Free Software Foundation; 010 //either version 2 of the License, or (at your option) any later version. 011 ///////////////////////////////////////////////// 012 //Sears project is available under sourceforge 013 //at adress: http://sourceforge.net/projects/sears/ 014 //Copyright (C) 2005 Booba Skaya 015 //Mail: booba.skaya@gmail.com 016 ///////////////////////////////////////////////// 017 018 // some suggestions about this class: floriaen@gmail.com 019 020 package sears.search.data; 021 022 import java.util.ArrayList; 023 024 import sears.file.Subtitle; 025 026 /** 027 * Data structure to manage result of a search. 028 * <br><tt>CharIndexIterator</tt> performs a loop iteration 029 * 030 */ 031 public class CharIndexIterator { 032 033 private Window window; 034 private LoopIterator loopIterator; 035 private SubtitleFile subtitleFile; 036 037 ArrayList<Subtitle> subtitleList; 038 private String textForTheSearch; 039 040 /** 041 * Constructs a new <tt>CharIndexIterator</tt> object 042 * @param subtitleList the subtitle list 043 * @param str the searched string 044 * @throws IllegalArgumentException if one of the arguments id <tt>null</tt> 045 */ 046 public CharIndexIterator(ArrayList<Subtitle> subtitleList, String str) { 047 if( subtitleList == null || subtitleList.isEmpty() ) { 048 throw new IllegalArgumentException("the list of subtitles is null or empty"); 049 } 050 051 window = new Window(); 052 this.subtitleList = subtitleList; 053 subtitleFile = new SubtitleFile(subtitleList); 054 setANewTextForTheSearch(str); 055 } 056 057 /** 058 * Sets a new array of <tt>Subtitle</tT> object 059 * @param newSubtitleList the new array 060 */ 061 public void setANewSubtitleList(ArrayList<Subtitle> newSubtitleList) { 062 subtitleFile = new SubtitleFile(newSubtitleList); 063 loopIterator = subtitleFile.getAllRowWhichContainsAtLeastOneOccurrenceOfText(textForTheSearch).iterator(); 064 window = new Window(); 065 } 066 067 /** 068 * Set if needed a new text for the search 069 * @param str the new text 070 * @return true if the set is needed, false if not 071 */ 072 public boolean setANewTextForTheSearch(String str) { 073 if( !isAValidText(str) ) { 074 throw new IllegalArgumentException("the string is not valid"); 075 } 076 str = isTextChanged(str); 077 if( str != null) { 078 setTextForTheSearch(str); 079 } 080 return (str != null); 081 } 082 083 private void setTextForTheSearch(String newText) { 084 if( !isAValidText(newText) ) { 085 throw new IllegalArgumentException("the string entered is not a valid string"); 086 } 087 textForTheSearch = newText; 088 fireTextChanged(); 089 } 090 091 //private void resetWindow 092 093 private void fireTextChanged() { 094 loopIterator = subtitleFile.getAllRowWhichContainsAtLeastOneOccurrenceOfText(textForTheSearch).iterator(); 095 window = window.getEmptyClonedWindow(); 096 } 097 098 /** 099 * Tests the <code>String</code> object given in parameter. 100 * @param textToTest the <code>String</code> object to test 101 * @return <code>textToTest</code> to lower case if it is different that the text stored, <code>null</code> if not 102 */ 103 private String isTextChanged(String textToTest) { 104 textToTest = textToTest.toLowerCase(); 105 if( textForTheSearch != null && textForTheSearch.contentEquals(textToTest) ) { 106 textToTest = null; 107 } 108 return textToTest; 109 } 110 111 private boolean isAValidText(String text) { 112 return ( text != null && text.trim().length() > 0 ); 113 } 114 115 // ACCESS METHODS 116 // 117 118 /** 119 * Initializes and returns an array of two int 120 * <br>if <tt>row</tt> or <tt>index</tt> are negative, null is returned 121 * @param row the row 122 * @param index a char index 123 * @return an array of two int or null 124 */ 125 private int[] rowAndCharIndex(int row, int index) { 126 int[] rowAndCharIndex = new int[2]; 127 if( row < 0 || index < 0 ) { 128 rowAndCharIndex = null; 129 } else { 130 rowAndCharIndex[0] = row; 131 rowAndCharIndex[1] = index; 132 } 133 return rowAndCharIndex; 134 } 135 136 /** 137 * Returns the subtitle text at the index given in parameters 138 * @param index the index in the list 139 * @return a string or null if <tt>index</tt> is out of list bounds 140 */ 141 private String getSubtitleAtIndex(int index) { 142 String subtitle = null; 143 // ensure coherence with the subtitleList 144 if( index >= 0 && index < subtitleList.size() ) { 145 subtitle = subtitleList.get(index).getSubtitle(); 146 } 147 return subtitle; 148 } 149 150 /** 151 * Gets the next row and char index 152 * <br> INCOHERENCE: row < 0 or row > last row... 153 * @return an array of two positive int or null if an incoherence appears during the method 154 * 155 */ 156 public int[] getNextRowAndCharIndex() { 157 int charIndex = window.getNextCharIndex(); 158 if( charIndex == -1 ) { 159 int row = loopIterator.getNextElement(); 160 if( row != -1 ) { 161 String subtitle = getSubtitleAtIndex(row); 162 // test the coherence 163 if( subtitle != null ) { 164 // update window: 165 window.setWindowForGettingNextElement(subtitle, textForTheSearch); 166 charIndex = window.getNextCharIndex(); 167 // test the coherence of the result: 168 if( charIndex >= (subtitle.length() - textForTheSearch.length()) ) { 169 // negative charIndex cause that the #rowAndCharMethod(int,int) method 170 // returns null 171 charIndex = -1; 172 } 173 } else { 174 charIndex = -1; 175 } 176 } 177 } 178 return rowAndCharIndex(loopIterator.getCurrentElement(), charIndex); 179 } 180 181 /** 182 * Gets the row and first char index of the previous occurrence 183 * @return an array of two <tt>int</tt>, the row and the first char index of the searched text 184 * null if there's no previous occurrence (this means that there's no occurrence at all 185 */ 186 public int[] getPreviousRowAndCharIndex() { 187 int charIndex = window.getPreviousCharIndex(); 188 if( charIndex == -1 ) { 189 int row = loopIterator.getPreviousElement(); 190 if( row != -1 ) { 191 String subtitle = getSubtitleAtIndex(row); 192 // test the coherence 193 if( subtitle != null ) { 194 // update window: 195 window.setWindowForGettingPreviousElement(subtitle, textForTheSearch); 196 charIndex = window.getPreviousCharIndex(); 197 // test the coherence of the result: 198 if( charIndex >= (subtitle.length() - textForTheSearch.length()) ) { 199 // negative charIndex cause that the #rowAndCharMethod(int,int) method 200 // returns null 201 charIndex = -1; 202 } 203 } else { 204 charIndex = -1; 205 } 206 } 207 } 208 return rowAndCharIndex(loopIterator.getCurrentElement(), charIndex); 209 } 210 211 /** 212 * Gets the row and first char index of the next occurrence after <tt>row</tt> 213 * @param row the row 214 * @return an array of two <tt>int</tt>, the row and the first char index of the searched text 215 */ 216 public int[] getNextRowAndCharIndexBeginAtRow(int row) { 217 int charIndex = -1; 218 if( row >= 0 && row < subtitleList.size() ) { 219 row = loopIterator.getTheNearestElementAfter(row); 220 String subtitle = getSubtitleAtIndex(row); 221 // ensures that row is valid compared to the subtitle list 222 // row for table/index for subtitleList (same thing) 223 if( subtitle != null ) { 224 window.setWindowForGettingNextElement(subtitle, textForTheSearch); 225 charIndex = window.getNextCharIndex(); 226 // test the coherence of the result: 227 if( charIndex >= (subtitle.length() - textForTheSearch.length()) ) { 228 // negative charIndex cause that the #rowAndCharMethod(int,int) method 229 // returns null 230 charIndex = -1; 231 } 232 }// else charIndex remain equals to -1, return value will be null 233 } 234 return rowAndCharIndex(row, charIndex); 235 } 236 237 /** 238 * Gets the row and first char index of the previous occurrence after <tt>row</tt> 239 * @param row the row 240 * @return an array of two <tt>int</tt>, the row and the first char index of the searched text 241 */ 242 public int[] getPreviousRowAndCharIndexBeginAtRow(int row) { 243 int charIndex = -1; 244 if( row >= 0 && row < subtitleList.size() ) { 245 row = loopIterator.getTheNearestElementBefore(row); 246 String subtitle = getSubtitleAtIndex(row); 247 // ensures that row is valid compared to the subtitle list 248 // row for table/index for subtitleList (same thing) 249 if( subtitle != null ) { 250 window.setWindowForGettingPreviousElement(subtitle, textForTheSearch); 251 charIndex = window.getPreviousCharIndex(); 252 // test the coherence of the result: 253 if( charIndex >= (subtitle.length() - textForTheSearch.length()) ) { 254 // negative charIndex cause that the #rowAndCharMethod(int,int) method 255 // returns null 256 charIndex = -1; 257 } 258 }// else charIndex remain equals to -1, return value will be null 259 } 260 return rowAndCharIndex(row, charIndex); 261 } 262 }