package com.janosgyerik.tools.files.csv.reading;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Pattern;

public class CsvParser {

    private static final String DEFAULT_SEPARATOR = ",";

    private abstract static class AbstractCsvParser {

        private final Pattern pattern;

        private AbstractCsvParser(String separator) {
            this.pattern = Pattern.compile("\\s*" + separator + "\\s*");
        }

        abstract String nextLine() throws IOException;

        public <T> List<T> parseLines(RowMapper<T> mapper) throws IOException {
            List<T> lines = new ArrayList<>();
            String line;
            while ((line = nextLine()) != null) {
                String[] cols = pattern.split(line.trim());
                if (mapper.isValidRow(cols)) {
                    lines.add(mapper.mapRow(cols));
                }
            }
            return lines;
        }
    }

    private static class ScannerCsvParser extends AbstractCsvParser {

        private final Scanner scanner;

        private ScannerCsvParser(Scanner scanner, String separator) {
            super(separator);
            this.scanner = scanner;
        }

        @Override
        String nextLine() {
            if (scanner.hasNextLine()) {
                return scanner.nextLine();
            }
            return null;
        }
    }

    private static class FileCsvParser extends AbstractCsvParser {

        private final BufferedReader reader;

        private FileCsvParser(File file, String separator) throws FileNotFoundException {
            super(separator);
            reader = new BufferedReader(new FileReader(file));
        }

        @Override
        String nextLine() throws IOException {
            String line = reader.readLine();
            if (line == null) {
                reader.close();
            }
            return line;
        }
    }

    private CsvParser() {
        // utility class, forbidden constructor
    }

    public static <T> List<T> objectsFromFile(String path, RowMapper<T> mapper) throws IOException {
        return objectsFromFile(path, DEFAULT_SEPARATOR, mapper);
    }

    public static <T> List<T> objectsFromFile(String path, String separator, RowMapper<T> mapper) throws IOException {
        return objectsFromFile(new File(path), separator, mapper);
    }

    public static <T> List<T> objectsFromFile(File file, RowMapper<T> mapper) throws IOException {
        return objectsFromFile(file, DEFAULT_SEPARATOR, mapper);
    }

    public static <T> List<T> objectsFromFile(File file, String separator, RowMapper<T> mapper) throws IOException {
        return new FileCsvParser(file, separator).parseLines(mapper);
    }

    public static <T> List<T> objectsFromScanner(Scanner scanner, RowMapper<T> mapper) throws IOException {
        return objectsFromScanner(scanner, DEFAULT_SEPARATOR, mapper);
    }

    public static <T> List<T> objectsFromScanner(Scanner scanner, String separator, RowMapper<T> mapper) throws IOException {
        return new ScannerCsvParser(scanner, separator).parseLines(mapper);
    }

    public static <T> List<T> objectsFromText(String text, RowMapper<T> mapper) throws IOException {
        return objectsFromText(text, DEFAULT_SEPARATOR, mapper);
    }

    public static <T> List<T> objectsFromText(String text, String separator, RowMapper<T> mapper) throws IOException {
        return objectsFromScanner(new Scanner(text), separator, mapper);
    }

}

@@ -58,17 +58,48 @@
 java.io.
-*
+File;%0Aimport java.io.IOException
 ;%0Aimport
@@ -571,24 +571,84 @@
 Exception;%0A%0A
+        abstract boolean hasNextLine() throws IOException;%0A%0A
         publ
@@ -778,21 +778,34 @@
     
-String line;%0A
+while (hasNextLine()) %7B%0A  
     
@@ -816,16 +816,17 @@
     
-while ((
+  String 
 line
@@ -842,20 +842,9 @@
 ne()
-) != null) %7B
+;
 %0A   
@@ -1362,687 +1362,187 @@
     
-String nextLine() %7B%0A            if (scanner.hasNextLine()) %7B%0A                return scanner.nextLine();%0A            %7D%0A            return null;%0A        %7D%0A    %7D%0A%0A    private static class FileCsvParser extends AbstractCsvParser %7B%0A%0A        private final BufferedReader reader;%0A%0A        private FileCsvParser(File file, String separator) throws FileNotFoundException %7B%0A            super(separator);%0A            reader = new BufferedReader(new FileReader(file));%0A        %7D%0A%0A        @Override%0A        String nextLine() throws IOException %7B%0A            String line = reader.readLine();%0A            if (line == null) %7B%0A                reader.close();%0A            %7D%0A            return l
+boolean hasNextLine() throws IOException %7B%0A            return scanner.hasNextLine();%0A        %7D%0A%0A        @Override%0A        String nextLine() %7B%0A            return scanner.nextL
 ine
+()
 ;%0A  
@@ -2310,20 +2310,23 @@
 urn new 
-File
+Scanner
 CsvParse
@@ -2327,20 +2327,33 @@
 vParser(
+new Scanner(
 file
+)
 , separa

Remove unnecessary class