org.apereo.lap.services.input.handlers.csv.BaseCSVInputHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.apereo.lap.services.input.handlers.csv.BaseCSVInputHandler.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Unicon (R) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 * http://www.osedu.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *******************************************************************************/
package org.apereo.lap.services.input.handlers.csv;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apereo.lap.services.configuration.ConfigurationService;
import org.apereo.lap.services.input.BaseInputHandlerService;
import org.apereo.lap.services.input.SampleCSVInputHandlerService;
import org.apereo.lap.services.input.handlers.BaseInputHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

import au.com.bytecode.opencsv.CSVReader;

public abstract class BaseCSVInputHandler extends BaseInputHandler implements CSVInputHandler {

    private String path = null;
    private static final Logger logger = LoggerFactory.getLogger(BaseCSVInputHandler.class);
    ConfigurationService config;

    public BaseCSVInputHandler(ConfigurationService configuration, JdbcTemplate jdbcTemplate) {
        super(jdbcTemplate);
        assert configuration != null;
        this.config = configuration;
    }

    /**
     * Make the set of all known CSV handlers (this is expensive so avoid doing it more than once)
     * @param configuration current system config
     * @param jdbcTemplate temp DB jdbc template
     * @return the map of csv filename -> CSVInputHandler (in the correct order for processing and insertion)
     */
    public static Map<String, CSVInputHandler> makeCSVHandlers(ConfigurationService configuration,
            JdbcTemplate jdbcTemplate) {
        // build up the handlers
        CSVInputHandler csvih;
        Map<String, CSVInputHandler> handlers = new LinkedHashMap<>(); // maintain order
        csvih = new PersonalCSVInputHandler(configuration, jdbcTemplate);
        handlers.put(csvih.getPath(), csvih);
        csvih = new CourseCSVInputHandler(configuration, jdbcTemplate);
        handlers.put(csvih.getPath(), csvih);
        csvih = new EnrollmentCSVInputHandler(configuration, jdbcTemplate);
        handlers.put(csvih.getPath(), csvih);
        csvih = new GradeCSVInputHandler(configuration, jdbcTemplate);
        handlers.put(csvih.getPath(), csvih);
        csvih = new ActivityCSVInputHandler(configuration, jdbcTemplate);
        handlers.put(csvih.getPath(), csvih);
        return handlers;
    }

    @Override
    public SampleCSVInputHandlerService.InputType getHandledType() {
        return BaseInputHandlerService.InputType.CSV;
    }

    // general use functions

    CSVReader reader;

    /**
     * Reads a CSV file and verifies basic infor about it
     * @param minColumns min number of columns
     * @param headerStartsWith expected header value
     * @param reRead force reading the file again (otherwise it will use the existing copy)
     * @return the CSVReader
     * @throws IllegalStateException if we fail to produce the reader
     */
    CSVReader readCSV(int minColumns, String headerStartsWith, boolean reRead) {
        return readCSVResource(minColumns, headerStartsWith, reRead);
    }

    /**
     * Reads a CSV file and verifies basic infor about it
     * @param minColumns min number of columns
     * @param headerStartsWith expected header value
     * @param reRead force reading the file again (otherwise it will use the existing copy)
     * @return the CSVReader
     * @throws IllegalStateException if we fail to produce the reader
     */
    CSVReader readCSVResource(int minColumns, String headerStartsWith, boolean reRead) {
        if (this.reader == null || reRead) {
            assert minColumns > 0 : "minColumns must be > 0: " + minColumns;
            assert StringUtils.isNotBlank(headerStartsWith) : "headerStartsWith must not be blank: " + getPath();
            CSVReader fileCSV;
            try {
                Path csvPath = config.getApplicationHomeDirectory().resolve(Paths.get(getPath()));
                InputStream fileCSV_IS = Files.newInputStream(csvPath);
                fileCSV = new CSVReader(new InputStreamReader(fileCSV_IS));
                String[] check = fileCSV.readNext();
                if (check != null && check.length >= minColumns
                        && StringUtils.startsWithIgnoreCase(headerStartsWith, StringUtils.trimToEmpty(check[0]))) {
                    //logger.debug(fileName+" file and header appear valid");
                    this.reader = fileCSV;
                } else {
                    throw new IllegalStateException(getPath() + " file and header do not appear valid (no "
                            + headerStartsWith + " header or less than " + minColumns + " required columns");
                }
            } catch (Exception e) {
                throw new IllegalStateException(getPath() + " CSV is invalid: " + e);
            }
        }
        return this.reader;
    }

    /**
     * @param csvReader the csvReader used to read the file
     * @return the results of the processing (line failures are recorded but will not stop the processing)
     * @throws IllegalArgumentException if the reader cannot be read
     */
    ReadResult readCSVFileIntoDB(CSVReader csvReader) {
        ReadResult result = new ReadResult(getPath());
        String insertSQL = makeInsertSQL();
        int[] insertTypes = makeInsertSQLParams();

        int line = 1;
        String[] csvLine;
        ArrayList<String> failures = new ArrayList<>();
        try {
            while ((csvLine = csvReader.readNext()) != null) { // IOException
                line++;
                try {
                    trimStringArrayToNull(csvLine);
                    Object[] params = validateAndConvertParams(csvLine);
                    getTempDatabase().update(insertSQL, params, insertTypes);
                } catch (Exception e) {
                    String msg = getHandledType() + " line " + line + ": " + e.getMessage();
                    if (logger.isDebugEnabled())
                        logger.debug(msg, e); // to help in fixing the problem
                    failures.add(msg);
                }
            }
        } catch (IOException e) {
            throw new IllegalArgumentException("csvReader cannot read from file: " + e, e);
        }
        result.done(line, failures);
        return result;
    }

    @Override
    public String getPath() {
        return path;
    }

    @Override
    public void setPath(String path) {
        this.path = path;
    }
}