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 /** 023 * Manages <tt>ListOfRow</tt> structure with loop iteration 024 */ 025 public class LoopIterator { 026 027 private ListOfRow listOfRow; 028 private int index; 029 030 /** 031 * Instantiate a new object 032 * @param aListOfRow the list on which iterate 033 * @throws NullPointerException if <tt>aListOfRow</tt> is null 034 */ 035 public LoopIterator(ListOfRow aListOfRow) { 036 if( aListOfRow == null ) { 037 throw new NullPointerException("cannot iterate on a null object"); 038 } 039 listOfRow = aListOfRow; 040 index = -1; 041 } 042 043 /** 044 * <p> 045 * Gets the nearest element before means: 046 * <br> gets the first smaller element before the element before the one given 047 * on parameters <br>if this element is not in the list, else it is return 048 * </p> 049 * <p> 050 * Method's algorithm uses is the <i>dichotomic</i> search 051 * </p> 052 * @param row the element 053 * @return <tt>row</tt> if it is in the list or the first smaller element before it 054 * @throws IllegalArgumentException if <tt>row</tt> is out of the bounds of the elements contained in the list 055 */ 056 public int getTheNearestElementBefore(int row) { 057 if( row < 0 ) { 058 throw new IllegalArgumentException("negative value is not a valid value for a row"); 059 } 060 // BEGIN 061 int rowBefore = -1; 062 if( !listOfRow.isEmpty() ) { 063 int currentIndex = index; 064 try { 065 int startAt = 0; 066 int stopAt = listOfRow.size() - 1; 067 int middle = 1; 068 boolean rowInTheList = false; 069 while( !rowInTheList && startAt <= stopAt ) { 070 middle = (startAt + stopAt)/2; 071 rowBefore = listOfRow.getRow(middle); 072 rowInTheList = ( rowBefore == row ); 073 if( rowBefore > row ) { 074 stopAt = middle - 1; 075 } 076 else if( rowBefore < row ) { 077 startAt = middle + 1; 078 } 079 } 080 // moves current index: 081 index = middle; 082 if( !rowInTheList ) { 083 if( rowBefore > row ) { 084 rowBefore = getPreviousElement(); 085 } 086 } 087 // listOfRow exception: 088 } catch( IndexOutOfBoundsException e ) { 089 // ensure the non modification of the state object, 090 // get back the iterator before the call of the method 091 // and return -1 which means that an error occurs 092 index = currentIndex; 093 rowBefore = -1; 094 } 095 } 096 return rowBefore; 097 } 098 099 // ensure that row is in the bounds 100 /** 101 * @param row the row 102 * @return the nearest element after 103 * @throws IllegalArgumentException if <tt>row</tt> is out of the bounds of the elements contained in the list 104 */ 105 public int getTheNearestElementAfter(int row) { 106 if( row < 0 ) { 107 throw new IllegalArgumentException("negative value is not a valid value for a row"); 108 } 109 // BEGIN 110 int rowAfter = -1; 111 if( !listOfRow.isEmpty() ) { 112 int currentIndex = index; 113 try { 114 int startAt = 0; 115 int stopAt = listOfRow.size() - 1; 116 int middle = 0; 117 boolean rowInTheList = false; 118 while( !rowInTheList && startAt <= stopAt ) { 119 middle = (startAt + stopAt)/2; 120 rowAfter = listOfRow.getRow(middle); 121 rowInTheList = (rowAfter == row); 122 if( rowAfter > row ) { 123 stopAt = middle - 1; 124 } 125 else if( rowAfter < row ) { 126 startAt = middle + 1; 127 } 128 } 129 // moves current index: 130 index = middle; 131 if( !rowInTheList ) { 132 if( rowAfter < row ) { 133 rowAfter = getNextElement(); 134 } 135 } 136 137 // listOfRow exception: 138 } catch( IndexOutOfBoundsException e ) { 139 // ensure the non modification of the state object, 140 // get back the iterator before the call of the method 141 // and return -1 which means that an error occurs 142 index = currentIndex; 143 rowAfter = -1; 144 } 145 } 146 return rowAfter; 147 } 148 149 // NEXT ROW METHOD 150 151 152 /** 153 * Returns the next positive element of the list 154 * @return the next element in the list, if the list is empty -1 is return 155 */ 156 public int getNextElement() { 157 return getNextElement(index); 158 } 159 160 /** 161 * returns the next element at index given in parameters 162 */ 163 private int getNextElement(int startIndex) { 164 index = startIndex; 165 int row = -1; 166 if( !listOfRow.isEmpty() ) { 167 row = listOfRow.getRow(getNextIndex()); 168 } 169 return row; 170 } 171 172 // PREVIOUS ROW METHODS 173 174 175 /** 176 * Returns the previous positive element of the list 177 * @return the previous element in the list, if the list is empty -1 is return 178 */ 179 public int getPreviousElement() { 180 return getPreviousElement(index); 181 } 182 183 private int getPreviousElement(int startIndex) { 184 index = startIndex; 185 int row = -1; 186 if( !listOfRow.isEmpty() ) { 187 row = listOfRow.getRow(getPreviousIndex()); 188 } 189 return row; 190 } 191 192 // INDEX MANIPULATIONS 193 // ensure that the loop iteration is respected 194 // access to the index variable must be done with this methods 195 196 /** 197 * Gets the next index, ensures that the loop iteration is done. 198 * <br> Increments the current <tt>index</tt> 199 * @return the incremented current index 200 */ 201 private int getNextIndex() { 202 if( index + 1 >= listOfRow.size() ) { 203 index = -1; 204 } 205 index++; 206 return index; 207 } 208 209 /** 210 * Gets the previous index, ensures that the loop iteration is done. 211 * <br> Decrements the current <tt>index</tt> 212 * @return the decremented current index 213 */ 214 private int getPreviousIndex() { 215 if( index - 1 < 0 ) { 216 index = listOfRow.size(); 217 } 218 index--; 219 return index; 220 } 221 222 // 223 // "SAFE" METHODS 224 // do not change iteration state 225 226 /** 227 * SAFE METHOD, do not change iteration state 228 * @return the current element 229 */ 230 public int getCurrentElement() { 231 return listOfRow.getRow(index); 232 } 233 234 /** 235 * SAFE METHOD, do not change iteration state 236 * @return the first element of the list 237 */ 238 public int getFirstElement() { 239 return listOfRow.getRow(0); 240 } 241 242 /** 243 * SAFE METHOD, do not change iteration state 244 * @return the last element of the list 245 */ 246 public int getLastElement() { 247 return listOfRow.getRow(listOfRow.size() - 1); 248 } 249 250 /** 251 * SAFE METHOD, do not change iteration state 252 * @return the index of the current element in the list 253 */ 254 public int getIndexOfTheCurrentElement() { 255 return index; 256 } 257 }