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