All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.poiji.bind.mapping.CsvLineReader Maven / Gradle / Ivy

package com.poiji.bind.mapping;

import com.poiji.option.PoijiOptions;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

public final class CsvLineReader {

    private final ReadMappedFields readMappedFields;
    private final PoijiOptions options;
    private final Collection usedColumns;
    private int row = 0;
    private int internalCount = 1;

    public CsvLineReader(final Class entity, final PoijiOptions options) {
        this.readMappedFields = new ReadMappedFields(entity, options).parseEntity();
        this.options = options;
        this.usedColumns = new HashSet<>();
    }

    public T readLine(final String line) {
        final T result;
        if (isHeaderRow()){
            result = parseColumnNames(line);
        } else if (isContentRow()){
            result = parseContentRow(line);
        } else {
            result = null;
        }
        row++;
        return result;
    }

    private boolean isContentRow() {
        return row > options.skip() + options.getHeaderStart() + options.getHeaderCount() - 1 && (options.getLimit() == 0 || internalCount <= options.getLimit());
    }

    private boolean isHeaderRow() {
        int headerStart = options.getHeaderStart();
        int headerCount = options.getHeaderCount();
        this.internalCount = headerStart + headerCount;
        return row >= headerStart && row < headerStart + headerCount;
    }

    private T parseContentRow(final String line) {
        final String[] values = parseLine(line);
        final int lastValuedColumn = lastValuedColumn(values);
        if (lastValuedColumn >= 0) {
            final Data data = readMappedFields.createInstanceData();
            for (int column = 0; column <= lastValuedColumn; column++) {
                if (usedColumns.contains(column) || readMappedFields.orderedFields.containsKey(column)) {
                    readMappedFields.setCellInData(row, column, unwrap(values[column]), data);
                }
            }
            internalCount++;
            return (T) readMappedFields.createNewInstance(data);
        } else {
            internalCount++;
            return null;
        }
    }

    private T parseColumnNames(final String line) {
        final String[] columnNames = parseLine(line);
        for (int i = 0; i < columnNames.length; i++) {
            final String columnName = unwrap(columnNames[i]);
            if (!columnName.isEmpty()){
                readMappedFields.parseColumnName(i, columnName);
                usedColumns.add(i);
            }
        }
        readMappedFields.validateMandatoryNameColumns();
        return null;
    }

    private String[] parseLine(final String line) {
        final char[] chars = line.toCharArray();
        State state = State.BEGIN;
        final ArrayList words = new ArrayList<>();
        StringBuilder word = new StringBuilder();
        final char delimiter = options.getCsvDelimiter();
        for (char aChar : chars) {
            if (state == State.BEGIN && word.length() == 0 && aChar == '\"') {
                state = State.MIDDLE;
            } else if ((state == State.MIDDLE || (state == State.BEGIN && word.length() > 0)) && aChar == '\"') {
                state = State.QUOTE;
            } else if (state == State.QUOTE && aChar == '\"') {
                state = State.BEGIN;
                word.append('\"');
            } else if ((state == State.QUOTE || state == State.BEGIN) && aChar == delimiter) {
                words.add(word.toString());
                word = new StringBuilder();
                state = State.BEGIN;
            } else {
                word.append(aChar);
            }
        }
        if (word.length() > 0) {
            words.add(word.toString());
        }
        final String[] result = new String[words.size()];
        words.toArray(result);
        return result;
    }

    private enum State {
        BEGIN, MIDDLE, QUOTE
    }

    private int lastValuedColumn(final String[] values) {
        for (int i = values.length - 1; i >= 0; i--) {
            if (!values[i].isEmpty()) {
                return i;
            }
        }
        return -1;
    }

    private String unwrap(final String value) {
        if (!value.isEmpty() && value.charAt(0) == '"' && value.charAt(value.length() - 1) == '"'){
            return value.substring(1, value.length() - 1);
        } else {
            return value;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy