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

com.avaje.ebeaninternal.server.text.csv.TCsvReader Maven / Gradle / Ivy

There is a newer version: 2.8.1
Show newest version
/**
 * Copyright (C) 2009 Authors
 * 
 * This file is part of Ebean.
 * 
 * Ebean is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *  
 * Ebean is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Ebean; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA  
 */
package com.avaje.ebeaninternal.server.text.csv;

import java.io.Reader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.text.StringParser;
import com.avaje.ebean.text.TextException;
import com.avaje.ebean.text.csv.CsvCallback;
import com.avaje.ebean.text.csv.CsvReader;
import com.avaje.ebean.text.csv.DefaultCsvCallback;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;

/**
 * 
 * @author rbygrave
 */
public class TCsvReader implements CsvReader {

    //private static final Logger logger = Logger.getLogger(TCsvReader.class.getName());

    private final EbeanServer server;

    private final BeanDescriptor descriptor;

    private final List columnList = new ArrayList();

    private final CsvColumn ignoreColumn = new CsvColumn();

    private boolean treatEmptyStringAsNull = true;

    private boolean hasHeader;

    private int logInfoFrequency = 1000;

    /**
     * The batch size used for JDBC statement batching.
     */
    protected int persistBatchSize = 30;

    public TCsvReader(EbeanServer server, BeanDescriptor descriptor) {
        this.server = server;
        this.descriptor = descriptor;
    }

    public void setPersistBatchSize(int persistBatchSize) {
        this.persistBatchSize = persistBatchSize;
    }

    public void setHasHeader(boolean hasHeader) {
        this.hasHeader = hasHeader;
    }

    public void setLogInfoFrequency(int logInfoFrequency) {
        this.logInfoFrequency = logInfoFrequency;
    }

    public void addIgnore() {
        columnList.add(ignoreColumn);
    }

    public void addProperty(String propertyName) {
        addProperty(propertyName, null);
    }

    public void addReference(String propertyName) {
        addProperty(propertyName, null, true);
    }

    public void addProperty(String propertyName, StringParser parser) {
        addProperty(propertyName, parser, false);
    }

    public void addDateTime(String propertyName, String dateTimeFormat) {
        addDateTime(propertyName, dateTimeFormat, Locale.getDefault());
    }

    public void addDateTime(String propertyName, String dateTimeFormat, Locale locale) {

        ElPropertyValue elProp = descriptor.getElGetValue(propertyName);
        if (!elProp.isDateTimeCapable()) {
            throw new TextException("Property " + propertyName + " is not DateTime capable");
        }

        SimpleDateFormat sdf = new SimpleDateFormat(dateTimeFormat, locale);
        DateTimeParser parser = new DateTimeParser(sdf, dateTimeFormat, elProp);

        CsvColumn column = new CsvColumn(elProp, parser, false);
        columnList.add(column);
    }

    public void addProperty(String propertyName, StringParser parser, boolean reference) {

        ElPropertyValue elProp = descriptor.getElGetValue(propertyName);
        if (parser == null) {
            parser = elProp.getStringParser();
        }
        CsvColumn column = new CsvColumn(elProp, parser, reference);
        columnList.add(column);
    }

    public void process(Reader reader) throws Exception {
        DefaultCsvCallback callback = new DefaultCsvCallback(persistBatchSize, logInfoFrequency);
        process(reader, callback);
    }

    public void process(Reader reader, CsvCallback callback) throws Exception {

        if (reader == null){
            throw new NullPointerException("reader is null?");
        }
        if (callback == null){
            throw new NullPointerException("callback is null?");
        }

        CsvUtilReader utilReader = new CsvUtilReader(reader);

        callback.begin(server);

        int row = 0;

        if (hasHeader) {
            String[] line = utilReader.readNext();
            callback.readHeader(line);
        }

        try {
            do {
                ++row;
                String[] line = utilReader.readNext();
                if (line == null) {
                    --row;
                    break;
                }
                
                if (callback.processLine(row, line)) {
                    // the line content is expected to be ok for processing
                    if (line.length != columnList.size()) {
                        // we have not got the expected number of columns
                        String msg = "Error at line " + row + ". Expected [" + columnList.size() + "] columns "
                                + "but instead we have [" + line.length + "].  Line[" + Arrays.toString(line) + "]";
                        throw new TextException(msg);
                    }

                    T bean = buildBeanFromLineContent(line);

                    callback.processBean(row, line, bean);

                }
            } while (true);

            callback.end(row);


        } catch (Exception e) {
            // notify that an error occured so that any 
            // transaction can be rolled back if required 
            callback.endWithError(row, e);
            throw e;
        }
    }

    @SuppressWarnings("unchecked")
    protected T buildBeanFromLineContent(String[] line) {

        EntityBean entityBean = descriptor.createEntityBean();
        T bean = (T) entityBean;

        int columnPos = 0;
        for (; columnPos < line.length; columnPos++) {
            convertAndSetColumn(columnPos, line[columnPos], entityBean);
        }

        return bean;
    }

    protected void convertAndSetColumn(int columnPos, String strValue, Object bean) {

        if (strValue.length() == 0 && treatEmptyStringAsNull) {
            return;
        }

        CsvColumn c = columnList.get(columnPos);
        c.convertAndSet(strValue, bean);
    }

    /**
     * Processes a column in the csv content.
     */
    public static class CsvColumn {

        private final ElPropertyValue elProp;
        private final StringParser parser;
        private final boolean ignore;
        private final boolean reference;

        /**
         * Constructor for the IGNORE column.
         */
        private CsvColumn() {
            this.elProp = null;
            this.parser = null;
            this.reference = false;
            this.ignore = true;
        }

        /**
         * Construct with a property and parser.
         */
        public CsvColumn(ElPropertyValue elProp, StringParser parser, boolean reference) {
            this.elProp = elProp;
            this.parser = parser;
            this.reference = reference;
            this.ignore = false;
        }

        /**
         * Convert the string to the appropriate value and set it to the bean.
         */
        public void convertAndSet(String strValue, Object bean) {

            if (!ignore) {
                Object value = parser.parse(strValue);
                elProp.elSetValue(bean, value, true, reference);
            }
        }
    }

    /**
     * A StringParser for converting custom date/time/datetime strings into
     * appropriate java types (Date, Calendar, SQL Date, Time, Timestamp, JODA
     * etc).
     */
    private static class DateTimeParser implements StringParser {

        private final DateFormat dateFormat;
        private final ElPropertyValue elProp;
        private final String format;

        DateTimeParser(DateFormat dateFormat, String format, ElPropertyValue elProp) {
            this.dateFormat = dateFormat;
            this.elProp = elProp;
            this.format = format;
        }

        public Object parse(String value) {
            try {
                Date dt = dateFormat.parse(value);
                return elProp.parseDateTime(dt.getTime());

            } catch (ParseException e) {
                throw new TextException("Error parsing [" + value + "] using format[" + format + "]", e);
            }
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy