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

br.com.tecsinapse.dataio.importer.parser.CsvParser Maven / Gradle / Ivy

The newest version!
/*
 * Tecsinapse Data Input and Output
 *
 * License: GNU Lesser General Public License (LGPL), version 3 or later
 * See the LICENSE file in the root directory or .
 */
package br.com.tecsinapse.dataio.importer.parser;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import lombok.Getter;
import lombok.Setter;

import br.com.tecsinapse.dataio.ExporterFormatter;
import br.com.tecsinapse.dataio.annotation.TableCellMapping;
import br.com.tecsinapse.dataio.converter.Converter;
import br.com.tecsinapse.dataio.converter.group.Default;
import br.com.tecsinapse.dataio.importer.Importer;
import br.com.tecsinapse.dataio.importer.ImporterUtils;
import br.com.tecsinapse.dataio.importer.Parser;
import br.com.tecsinapse.dataio.type.FileType;
import br.com.tecsinapse.dataio.util.CsvUtil;

public class CsvParser implements Parser {

    private final Class clazz;
    @Setter
    private Class group;
    private List csvLines;
    @Setter
    private int headersRows = Importer.DEFAULT_START_ROW;
    @Getter @Setter
    private ExporterFormatter exporterFormatter = ExporterFormatter.ENGLISH;
    @Getter @Setter
    private boolean ignoreBlankLinesAtEnd = false;

    public CsvParser(Class clazz, File file, Charset charset, int afterLine, Class group) throws IOException {
        this(clazz, file, charset, group);
        this.headersRows = afterLine;
    }

    public CsvParser(Class clazz, InputStream input, Charset charset, int afterLine, Class group) throws IOException {
        this(clazz, input, charset, group);
        this.headersRows = afterLine;
    }

    public CsvParser(Class clazz, List csvLines) {
        this(clazz, csvLines, Default.class);
    }

    public CsvParser(Class clazz, File file, Charset charset) throws IOException {
        this(clazz, file, charset, Default.class);
    }

    public CsvParser(Class clazz, File file, Charset charset, Class group) throws IOException {
        this(clazz, CsvUtil.processCSV(new FileInputStream(file), charset), group);
    }

    public CsvParser(Class clazz, InputStream inputStream, Charset charset) throws IOException {
        this(clazz, inputStream, charset, Default.class);
    }

    public CsvParser(Class clazz, InputStream inputStream, Charset charset, Class group) throws IOException {
        this(clazz, CsvUtil.processCSV(inputStream, charset), group);
    }

    public CsvParser(Class clazz, List csvLines, Class group) {
        this.clazz = clazz;
        this.csvLines = csvLines;
        this.group = group;
    }

    @Override
    public int getNumberOfSheets() {
        return 1;
    }

    @Override
    public void setSheetNumber(int sheetNumber) {
        // nothing to do when is CSV
    }

    @Override
    public void setLastsheet(boolean lastsheet) {
        // nothing to do when is CSV
    }

    @Override
    public void setFirstVisibleSheet() {
        // nothing to do when is CSV
    }

    @Override
    public int getSheetNumber() {
        return 0;
    }

    @Override
    public void setSheetNumberAsFirstNotHidden() {
        // nothing to do when is CSV
    }

    @Override
    public FileType getFileType() {
        return FileType.CSV;
    }

    @Override
    public List> getLines() {
        return Collections.emptyList();
    }

    /**
     * Parser file to list of T objects
     *
     * Obs.: No read de first line.
     *
     * @return List of T object
     * @throws IllegalAccessException IllegalAccessException
     * @throws InstantiationException InstantiationException
     * @throws InvocationTargetException InvocationTargetException
     * @throws NoSuchMethodException NoSuchMethodException
     */
    @Override
    public List parse() throws IllegalAccessException, InstantiationException,
            InvocationTargetException, NoSuchMethodException {
        List list = new ArrayList<>();

        Map cellMappingByMethod = ImporterUtils.getMappedMethods(clazz, group);

        final Constructor constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        for (int i = 0; i < csvLines.size(); i++) {
            final String line = csvLines.get(i);
            if ((i + 1) <= headersRows) {
                continue;
            }

            List fields = split(line);
            T instance = constructor.newInstance();

            for (Entry methodTcm : cellMappingByMethod.entrySet()) {
                Method method = methodTcm.getKey();
                method.setAccessible(true);

                TableCellMapping tcm = methodTcm.getValue();
                String value = getValueOrEmpty(fields, tcm.columnIndex());
                Converter converter = tcm.converter().newInstance();
                Object obj = converter.apply(value);
                method.invoke(instance, obj);
            }
            list.add(instance);
        }
        return list;
    }

    private String getValueOrEmpty(List fields, int index) {
        if (fields.isEmpty() || fields.size() <= index) {
            return "";
        }
        return fields.get(index);
    }

    private List split(String line) {
        int index;
        int lastIndex = 0;

        List linhaParseadaPorAspas = new ArrayList<>();

        /*
         * Percorre a linha em busca de ;
         * depois verifica se entre 2 ; existem aspas
         * Se houver, é preciso ignorar os ; internos às aspas
         */
        while (lastIndex != -1 && lastIndex < line.length()) {
            index = line.indexOf(';', lastIndex);

            if (index == -1) {
                //ultima coluna
                linhaParseadaPorAspas.add(line.substring(lastIndex).replace(";", ""));
                break;
            } else {
                String coluna = line.substring(lastIndex, index + 1);

                if (temAspas(coluna)) {
                    index = getFinalColuna(line.substring(lastIndex), lastIndex);
                    if (index == -1) {
                        //ultima coluna
                        linhaParseadaPorAspas.add(line.substring(lastIndex).replace("\"\"", "\"").trim());
                        break;
                    }
                    coluna = substringNormalizada(line, lastIndex, index - 1);
                    linhaParseadaPorAspas.add(coluna);
                    lastIndex = index;
                } else {
                    linhaParseadaPorAspas.add(coluna.replace(";", ""));
                    lastIndex = index == -1 ? -1 : index + 1;
                }
            }
        }

        return linhaParseadaPorAspas;
    }

    private int getFinalColuna(String substring, int inicio) {
        char[] chars = substring.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '\"') {
                for (int j = i + 1; j < chars.length; j++) {
                    if (chars[j] == '\"') {
                        return getFinalColuna(substring.substring(j + 1), inicio + j + 1);
                    }
                }
            }

            if (chars[i] == ';') {
                return i + inicio + 1;
            }
        }

        return -1;
    }

    private boolean temAspas(String column) {
        return column.indexOf('"') != -1;
    }

    private String substringNormalizada(String line, int i, int f) {
        line = line.substring(i, f - 1).trim();
        if (line.startsWith("\"")) {
            line = line.substring(1);
        }
        if (line.endsWith("\"")) {
            line = line.substring(0, line.length() - 1);
        }

        return line.replace("\"\"", "\"").trim();
    }

    @Override
    public void close() {
        //nada parser é feito atualmente no construtor
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy