1 /* 2 StatCvs - CVS statistics generation 3 Copyright (C) 2002 Lukasz Pekacki <lukasz@pekacki.de> 4 http://statcvs.sf.net/ 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 20 $RCSfile: LookaheadReader.java,v $ 21 $Date: 2008/04/02 11:22:15 $ 22 */ 23 package net.sf.statcvs.util; 24 25 import java.io.BufferedReader; 26 import java.io.IOException; 27 import java.io.Reader; 28 import java.util.NoSuchElementException; 29 30 /** 31 * <p>Wraps a {@link java.io.Reader} for line-by-line access. 32 * This works like {@link java.util.Iterator}: {@link #hasNextLine} 33 * returns true if another line can be read; {@link #nextLine} reads 34 * the next line and returns it. Additionally, {@link #getCurrentLine} 35 * can be used to access multiple times the line returned by 36 * <tt>nextLine()</tt>.</p> 37 * 38 * <p>At construction time, <tt>getCurrentLine()</tt> is undefined. 39 * <tt>nextLine()</tt> must be called once to read the first line.</p> 40 * 41 * @author Richard Cyganiak (richard@cyganiak.de) 42 * @version $Id: LookaheadReader.java,v 1.4 2008/04/02 11:22:15 benoitx Exp $ 43 */ 44 public class LookaheadReader { 45 private final BufferedReader reader; 46 private String currentLine = null; 47 private String nextLine = null; 48 private boolean afterEnd = false; 49 private int lineNumber = 0; 50 51 /** 52 * Creates a LookaheadReader from a source reader. 53 * @param reader a reader whose contents will be returned by the 54 * LookaheadReader 55 */ 56 public LookaheadReader(final Reader reader) { 57 this.reader = new BufferedReader(reader); 58 } 59 60 /** 61 * Returns the current line without reading a line from the source 62 * reader. Will throw an exception if {@link #nextLine} was not 63 * called before. 64 * @return The line returned by the previous call to {@link #nextLine()} 65 * @throws NoSuchElementException if {@link #nextLine} was not yet called 66 */ 67 public String getCurrentLine() { 68 if (this.currentLine == null) { 69 throw new NoSuchElementException("Call to getCurrentLine() before nextLine() was called"); 70 } 71 return this.currentLine; 72 } 73 74 /** 75 * Reads and returns a line from the source reader. The result of 76 * this call will be the new current line. Will throw an exception 77 * if trying to read from after the end of the source reader. 78 * @return The next line of the source reader 79 * @throws IOException on error while reading the source reader 80 * @throws NoSuchElementException if {@link #hasNextLine} is false 81 */ 82 public String nextLine() throws IOException { 83 if (!hasNextLine()) { 84 throw new NoSuchElementException("Call to nextLine() when hasNextLine() is false"); 85 } 86 this.currentLine = this.nextLine; 87 this.nextLine = null; 88 this.lineNumber++; 89 return this.currentLine; 90 } 91 92 /** 93 * Checks if more lines are available for reading. 94 * @return <tt>true</tt> if at least one more line can be read 95 * @throws IOException on error while reading the source reader 96 */ 97 public boolean hasNextLine() throws IOException { 98 if (this.afterEnd) { 99 return false; 100 } 101 if (this.nextLine != null) { 102 return true; 103 } 104 this.nextLine = this.reader.readLine(); 105 if (this.nextLine != null) { 106 return true; 107 } 108 this.afterEnd = true; 109 return false; 110 } 111 112 /** 113 * Returns the number of the line that would be returned by 114 * {@link #getCurrentLine}, or 0 before the first 115 * call to {@link #nextLine}. The first line has line number 1. 116 * @return the current line number 117 */ 118 public int getLineNumber() { 119 return this.lineNumber; 120 } 121 }