package net.apercova.io;

import java.io.IOException;
import java.io.LineNumberReader;
import java.io.Reader;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;

/**
 * Allows to iterate over a {@link LineNumberReader} while keep line
 * number tracking.
 * @author <a href="https://twitter.com/apercova" target="_blank">{@literal @}apercova</a> <a href="https://github.com/apercova" target="_blank">https://github.com/apercova</a>
 * @version 1.0 2017.08
 * @version 1.1 2017.15 Adding {@link #hasMoreLines()} and {@link #getNextLine()}
 * @since 1.0
 * 
 * <pre>
 * Use:
 * {@code
 *  IterableLineNumberReader it = new IterableLineNumberReader(reader);
 *  while (it.hasMoreLines()){
 *      String nextLine = it.getNextLine();
 *      int lineNum = it.getLineNumber();
 *      System.out.printf("#[%d]-%s%n",lineNum, nextLine);
 *  }}
 *  </pre>
 */
public class IterableLineNumberReader extends LineNumberReader implements Iterator<String>, Iterable<String>{

    protected boolean readForward;
    protected String nextLine;
    protected List<Throwable> suppressed;

    public IterableLineNumberReader(Reader in) {
        super(in);
        readForward = true;
        suppressed = new LinkedList<Throwable>();
    }

    public IterableLineNumberReader(Reader in, int sz) {
        super(in, sz);
        readForward = true;
        suppressed = new LinkedList<Throwable>();
    }

    /**
     * Exception list caused by reading errors when iterating.
     * {@link Iterator#next()} does not declare a {@code throws} statement.
     * @return Suppressed exceptions list.
     */
    public List<Throwable> getSuppressed() {
        return suppressed;
    }

    /**
     * Returns an instance of this {@link IterableLineNumberReader} as {@link Iterator}.
     * @return Iterator.
     */
    public Iterator<String> iterator() {
        return this;
    }

    /**
     * Looks up next text line within underlying reader.
     */
    protected void readNextLine(){
        try {
            nextLine = readLine();
        }catch(IOException e){
            suppressed.add(e);
            nextLine = null;
        }
    }

    /**
     * Returns {@code true} if there's more lines to be read.
     * (In other words, returns {@code true} if {@link #getNextLine()} would
     * return an element rather than throwing an exception.)
     *
     * @return {@code true} if there's more lines to read
     */
    public boolean hasNext() {
        //look forward if next line is available
        readNextLine();
        readForward = false;
        return nextLine != null;
    }

    /**
     * Returns the next line read.
     *
     * @return Value of the next line read
     * @throws NoSuchElementException if there's no more lines to be read.
     */
    public String next() {
        if(readForward){
            //read next line
            readNextLine();
        }else{
            readForward = true;
        }
        return nextLine;
    }

    /**
     * Not supported.
     * @see Iterator#remove()
     * @throws UnsupportedOperationException Not supported.
     */
    public void remove() {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns {@code true} if there's more lines to be read.
     * (In other words, returns {@code true} if {@link #getNextLine()} would
     * return an element rather than throwing an exception.)
     * Convenience alias for {@link #hasNext()}
     * @return {@code true} if there's more lines to be read
     */
    public boolean hasMoreLines() {
        return this.hasNext();
    }

    /**
     * Returns the next line read.
     * Convenience alias for {@link #next()}
     * @return Value of the next line read
     * @throws NoSuchElementException if there's no more lines to be read.
     */
    public String getNextLine() {
        return this.next();
    }

}
@@ -185,49 +185,8 @@
 ist;
-%0Aimport java.util.NoSuchElementException;
 %0A%0A/*
@@ -275,16 +275,37 @@
 racking.
+ Works with java 1.5+
 %0A * @aut
@@ -521,12 +521,12 @@
  201
-7.15
+8.01
  Add
@@ -2724,46 +2724,16 @@
 read
-%0A     * @throws NoSuchElementException
+ or null
  if 
@@ -2757,32 +2757,33 @@
 ines to be read.
+ 
 %0A     */%0A    pub
@@ -2795,25 +2795,24 @@
 tring next()
- 
 %7B%0A        if
@@ -3718,46 +3718,16 @@
 read
-%0A     * @throws NoSuchElementException
+ or null
  if 
@@ -3838,8 +3838,9 @@
     %7D%0A%0A%7D
+%0A

Update IterableLineNumberReader.java