package ml.shifu.shifu.combo;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implement CsvFile as iterator
 * Created by zhanhu on 12/10/16.
 */
public class CsvFile implements Iterable<Map<String, String>> {
    private static Logger LOG = LoggerFactory.getLogger(CsvFile.class);

    private String filePath;
    private String delimiter;

    public CsvFile(String filePath, String delimiter) {
        this.filePath = filePath;
        this.delimiter = delimiter;
    }

    @Override
    public Iterator<Map<String, String>> iterator() {
        return new CvsFileIterator(filePath, delimiter);
    }

    public class CvsFileIterator implements Iterator<Map<String, String>> {
        private String nextLine;
        private BufferedReader reader;
        private boolean isFinished = false;
        private String[] header;
        private String delimiter;

        public CvsFileIterator(String filePath, String delimiter) {
            LOG.info("Create csv file {}, with delimiter {}", filePath, delimiter);
            this.delimiter = delimiter;
            try {
                open(filePath);
            } catch (Exception e) {
                LOG.error("Fail to open file - {}.", filePath, e);
            }
        }

        private void open(String filePath) throws IOException {
            this.reader = new BufferedReader(new FileReader(filePath));
            String headerLine = reader.readLine();
            this.header = StringUtils.split(headerLine, delimiter);
        }

        @Override
        public boolean hasNext() {
            if(nextLine != null) {
                return true;
            } else if(isFinished) {
                return false;
            } else {
                try {
                    nextLine = reader.readLine();
                } catch (IOException e) {
                    nextLine = null;
                }

                if(nextLine == null) {
                    isFinished = true;
                    IOUtils.closeQuietly(reader);
                    return false;
                }

                return true;
            }
        }

        @Override
        public Map<String, String> next() {
            if(!hasNext()) {
                return null;
            }

            String[] vars = StringUtils.split(nextLine, delimiter);
            Map<String, String> varMap = new HashMap<String, String>();
            for(int i = 0; i < this.header.length; i++) {
                varMap.put(this.header[i], vars[i]);
            }

            nextLine = null;

            return varMap;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("Remove is not supported.");
        }
    }
}

@@ -24,16 +24,199 @@
 combo;%0A%0A
+import org.apache.commons.io.IOUtils;%0Aimport org.apache.commons.lang.ArrayUtils;%0Aimport org.apache.commons.lang.StringUtils;%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A%0A
 import j
@@ -230,32 +230,32 @@
 BufferedReader;%0A
-
 import java.io.F
@@ -293,16 +293,41 @@
 eption;%0A
+import java.util.Arrays;%0A
 import j
@@ -398,148 +398,8 @@
 p;%0A%0A
-import org.apache.commons.io.IOUtils;%0Aimport org.apache.commons.lang.StringUtils;%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A%0A
 /**%0A
@@ -660,24 +660,62 @@
 g delimiter;
+%0A    private CvsFileIterator iterator;
 %0A%0A    public
@@ -826,24 +826,318 @@
  delimiter;%0A
+        this.iterator = new CvsFileIterator(filePath, delimiter);%0A    %7D%0A%0A    public int getColumnOps(String column) %7B%0A        return ArrayUtils.indexOf(this.iterator.getHeader(), column);%0A    %7D%0A%0A    public String%5B%5D getColumnNames() %7B%0A        return Arrays.copyOf(this.iterator.getHeader(), 0);%0A
     %7D%0A%0A    @
@@ -2123,16 +2123,33 @@
 ls.split
+PreserveAllTokens
 (headerL
@@ -3299,24 +3299,24 @@
  remove() %7B%0A
-
             
@@ -3389,21 +3389,102 @@
 );%0A        %7D
+%0A%0A        public String%5B%5D getHeader() %7B%0A            return this.header;%0A        %7D
 %0A    %7D%0A%7D%0A

fix the bug when split records, and expose columns for CSV file