001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.nbio.genome.parsers.gff; 022 023import org.biojava.nbio.genome.App; 024import org.slf4j.Logger; 025import org.slf4j.LoggerFactory; 026 027import java.util.Iterator; 028import java.util.NoSuchElementException; 029 030/** 031 * Move a sliding window over a Location. 032 * Window size and increment can be specified. 033 * If the increment is negative, the iteration starts 034 * at end of Location and moves toward beginning. 035 * 036 * @author Hanno Hinsch 037 */ 038public class LocIterator implements Iterator<Location> { 039 private static final Logger logger = LoggerFactory.getLogger(App.class); 040 041 Location mBounds; 042 int mPosition; 043 int mWindowSize; 044 int mIncrement; 045 046 @SuppressWarnings("unused") 047 private LocIterator() {}; 048 049 /** 050 * Construct an iterator that slides a window over a Location. 051 * 052 * @param bounds The location over which to iterate. 053 * @param windowSize The size of the moving window. 054 * @param increment The increment by which to move the window at each iteration. 055 * If increment is positive, the iteration starts at the beginning of the bounding location 056 * and moves toward the end; if the increment is negative, the iteration starts at the end and moves 057 * toward the begnning. 058 */ 059 public LocIterator( Location bounds, int windowSize, int increment ) 060 { 061 mWindowSize= windowSize; 062 mIncrement= increment; 063 mBounds= bounds; 064 065 if( windowSize <= 0 ) 066 { 067 throw new IllegalArgumentException( "Window size must be positive." ); 068 } 069 070 if( increment == 0 ) 071 { 072 throw new IllegalArgumentException( "Increment must be non-zero." ); 073 } 074 075 mPosition= 0; 076 077 } 078 079 080 081 /** 082 * Check if next window of specified size is available. 083 * 084 * @param windowSize Size of window. May be smaller or larger than default window size. 085 * @param increment The increment by which to move the window at each iteration. Note that this 086 * method does not actually change the position. However, it checks the sign of the increment parameter to determine 087 * the direction of the iteration. 088 * @return True if window of specified size is available. 089 * @throws IllegalArgumentException Window size parameter was not positive. 090 */ 091 public boolean hasNext( int windowSize, int increment ) 092 { 093 if( windowSize <= 0 ) 094 { 095 throw new IllegalArgumentException( "Window size must be positive." ); 096 } 097 098 try 099 { 100 if( increment > 0 ) 101 { 102 return windowSize == mBounds.suffix( mPosition ).prefix( windowSize ).length(); 103 } 104 else 105 { 106 if( mPosition == 0 ) 107 { 108 return windowSize == mBounds.suffix( - windowSize ).length(); 109 } 110 else 111 { 112 return windowSize == mBounds.prefix( mPosition ).suffix( - windowSize ).length(); 113 } 114 } 115 } 116 catch( Exception e ) 117 { 118 return false; 119 } 120 } 121 122 /** 123 * Check if next window of default size is available. 124 * 125 * @return True if window of default size is available. The default size 126 * is the size specified in the LocIterator constructor. 127 */ 128 @Override 129 public boolean hasNext() 130 { 131 return hasNext( mWindowSize, mIncrement ); 132 } 133 134 /** 135 * Get portion of bounding location that has not yet been retrieved by next() method. 136 * 137 * @return The location not yet retrieved. 138 */ 139 public Location remainder() 140 { 141 Location remainder= null; 142 143 if( mPosition == 0 ) 144 { 145 remainder= mBounds; 146 } 147 else 148 { 149 if( mIncrement > 0 ) 150 { 151 remainder = mBounds.suffix( mPosition ); 152 } 153 else 154 { 155 remainder = mBounds.prefix( mPosition ); 156 } 157 } 158 159 return remainder; 160 161 } 162 163 /** 164 * Get next window of default size, then increment position by default amount. Both 165 * defaults are specified in the LocIterator constructor. 166 * 167 * @return Location of next window. 168 * @throws IndexOutOfBoundsException The next window was not within the bounding location. 169 */ 170 @Override 171 public Location next() 172 { 173 if(!hasNext()){ 174 throw new NoSuchElementException(); 175 } 176 return next( mWindowSize, mIncrement ); 177 } 178 179 /** 180 * Get next window of specified size, then increment position by specified amount. 181 * 182 * @return Location of next window. 183 * @param windowSize Size of window to get. 184 * @param increment Amount by which to shift position. If increment is positive, the position is shifted 185 * toward the end of the bounding location; if increment is negative, the position is shifted toward 186 * the beginning of the bounding location. 187 * @throws IndexOutOfBoundsException The next window was not within the bounding location. 188 * @throws IllegalArgumentException The increment was zero, or windowSize was not positive. 189 */ 190 public Location next( int windowSize, int increment ) 191 { 192 if( windowSize <= 0 ) 193 { 194 throw new IllegalArgumentException( "Window size must be positive." ); 195 } 196 197 if( increment == 0 ) 198 { 199 throw new IllegalArgumentException( "Increment must be non-zero." ); 200 } 201 202 Location r; 203 204 try 205 { 206 if( increment > 0 ) 207 { 208 r= mBounds.suffix( mPosition ).prefix( windowSize ); 209 } 210 else 211 { 212 if( mPosition == 0 ) 213 { 214 r= mBounds.suffix( - windowSize ); 215 } 216 else 217 { 218 r= mBounds.prefix( mPosition ).suffix( - windowSize ); 219 } 220 } 221 222 mPosition+= increment; 223 224 } 225 catch( Exception e ) 226 { 227 throw new IndexOutOfBoundsException( e.toString() ); 228 } 229 230 return r; 231 } 232 233 /** 234 * Get string representation of iterator. 235 * 236 * @return Description of internal state. 237 */ 238 @Override 239 public String toString() 240 { 241 return "bounds=" + mBounds.toString() + "; pos=" + mPosition + "; winsize=" + mWindowSize + "; inc=" + mIncrement; 242 } 243 244 /** 245 * Unsupported. 246 * 247 * @throws UnsupportedOperationException 248 */ 249 @Override 250 public void remove() 251 { 252 throw new UnsupportedOperationException(); 253 } 254 255 /** 256 * @deprecated 257 */ 258 @Deprecated 259 public static void main(String[] args ) 260 { 261 262 Location r= new Location( 10, 21 ); 263 264 logger.info( "10 to 21, 1 by 1" ); 265 for( Location t: r.window( 1, 1 )) { logger.info( t.toString() ); } 266 267 logger.info( "10 to 21, 3 by 3" ); 268 for( Location t: r.window( 3, 3 )) { logger.info( t.toString() ); } 269 270 logger.info( "10 to 21, 3 by 1" ); 271 for( Location t: r.window( 3, 1 )) { logger.info( t.toString() ); } 272 273 logger.info( "10 to 21, 11 by 1" ); 274 for( Location t: r.window( 11, 1 )) { logger.info( t.toString() ); } 275 276 logger.info( "10 to 21, 12 by 1" ); 277 for( Location t: r.window( 12, 1 )) { logger.info( t.toString() ); } 278 279 logger.info( "10 to 21, 1 by -1" ); 280 for( Location t: r.window( 1, -1 )) { logger.info( t.toString() ); } 281 282 logger.info( "10 to 21, 3 by -3" ); 283 for( Location t: r.window( 3, -3 )) { logger.info( t.toString() ); } 284 285 logger.info( "10 to 21, 3 by -1" ); 286 for( Location t: r.window( 3, -1 )) { logger.info( t.toString() ); } 287 288 logger.info( "10 to 21, 1 by 1" ); 289 for( Location t: r.window( 1, 1 )) { logger.info( t.toString() ); } 290 291 logger.info( "10 to 21, 3 by 3" ); 292 for( Location t: r.window( 3, 3 )) { logger.info( t.toString() ); } 293 294 logger.info( "10 to 21, 3 by 1" ); 295 for( Location t: r.window( 3, 1 )) { logger.info( t.toString() ); } 296 297 logger.info( "10 to 21, 11 by 1" ); 298 for( Location t: r.window( 11, 1 )) { logger.info( t.toString() ); } 299 300 logger.info( "10 to 21, 12 by 1" ); 301 for( Location t: r.window( 12, 1 )) { logger.info( t.toString() ); } 302 303 logger.info( "10 to 21, 1 by -1" ); 304 for( Location t: r.window( 1, -1 )) { logger.info( t.toString() ); } 305 306 //reverse strand 307 r= r.opposite(); 308 logger.info( "reverse strand" ); 309 310 logger.info( "10 to 21, 1 by 1" ); 311 for( Location t: r.window( 1, 1 )) { logger.info( t.toString() ); } 312 313 logger.info( "10 to 21, 3 by 3" ); 314 for( Location t: r.window( 3, 3 )) { logger.info( t.toString() ); } 315 316 logger.info( "10 to 21, 3 by 1" ); 317 for( Location t: r.window( 3, 1 )) { logger.info( t.toString() ); } 318 319 logger.info( "10 to 21, 11 by 1" ); 320 for( Location t: r.window( 11, 1 )) { logger.info( t.toString() ); } 321 322 logger.info( "10 to 21, 12 by 1" ); 323 for( Location t: r.window( 12, 1 )) { logger.info( t.toString() ); } 324 325 logger.info( "10 to 21, 1 by -1" ); 326 for( Location t: r.window( 1, -1 )) { logger.info( t.toString() ); } 327 328 logger.info( "10 to 21, 3 by -3" ); 329 for( Location t: r.window( 3, -3 )) { logger.info( t.toString() ); } 330 331 logger.info( "10 to 21, 3 by -1" ); 332 for( Location t: r.window( 3, -1 )) { logger.info( t.toString() ); } 333 334 logger.info( "10 to 21, 1 by 1" ); 335 for( Location t: r.window( 1, 1 )) { logger.info( t.toString() ); } 336 337 logger.info( "10 to 21, 3 by 3" ); 338 for( Location t: r.window( 3, 3 )) { logger.info( t.toString() ); } 339 340 logger.info( "10 to 21, 3 by 1" ); 341 for( Location t: r.window( 3, 1 )) { logger.info( t.toString() ); } 342 343 logger.info( "10 to 21, 11 by 1" ); 344 for( Location t: r.window( 11, 1 )) { logger.info( t.toString() ); } 345 346 logger.info( "10 to 21, 12 by 1" ); 347 for( Location t: r.window( 12, 1 )) { logger.info( t.toString() ); } 348 349 logger.info( "10 to 21, 1 by -1" ); 350 for( Location t: r.window( 1, -1 )) { logger.info( t.toString() ); } 351 352 logger.info( "10 to 21, 1 by 1 (+2)" ); 353 LocIterator i= r.iterator(); 354 int chunk= 1; 355 while( i.hasNext( 1, chunk ) ) 356 { 357 Location t= i.next( 1, chunk ); 358 logger.info( t.toString() ); 359 chunk+= 2; 360 } 361 362 //FIXME test remainder() 363 364 logger.info("JavaGene.LocIterator Passed."); 365 } 366 367}