org.opentestsystem.delivery.testreg.rest.FilePreviewHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.opentestsystem.delivery.testreg.rest.FilePreviewHelper.java

Source

/*******************************************************************************
 * Educational Online Test Delivery System
 * Copyright (c) 2013 American Institutes for Research
 *
 * Distributed under the AIR Open Source License, Version 1.0
 * See accompanying file AIR-License-1_0.txt or at
 * http://www.smarterapp.org/documents/American_Institutes_for_Research_Open_Source_Software_License.pdf
 ******************************************************************************/

package org.opentestsystem.delivery.testreg.rest;

import static java.util.Arrays.asList;
import static java.util.Arrays.copyOf;
import static org.opentestsystem.delivery.testreg.upload.parser.ParserTextUtils.padEmptyIfNoColumnAtEnd;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.opentestsystem.delivery.testreg.upload.ExcelUtils;
import org.opentestsystem.delivery.testreg.upload.ExcelUtils.ExcelRowMapper;
import org.opentestsystem.delivery.testreg.upload.ExcelUtils.ExcelWorksheetProcessor;
import org.opentestsystem.delivery.testreg.upload.TextFileUtils;
import org.opentestsystem.delivery.testreg.upload.TextFileUtils.LineMapper;
import org.opentestsystem.shared.exception.LocalizedException;

/**
 * Helper class for extracting content of a file for preview.
 */
public final class FilePreviewHelper {

    // Regular expression ensures that a split occurs only at commas which are followed by an even (or zero) number of quotes
    private static final String REGEX_DELIMITER = "(\\t)|(,)(?=([^\"]*\"[^\"]*\")*[^\"]*$)";

    private static final int HEADER_ROW = 0;

    private FilePreviewHelper() {
        // utility classes need not be instantiated
    }

    /**
     * Extracts rows from the file for preview.
     *
     * @param instream
     *        input stream
     * @param fileName
     *        name of the uploaded file
     * @param noOfRowsToExtract
     *        number of rows to extract including header row
     * @return List<FilePreview> list of file preview. Each sheet is translated into a file preview.
     * @throws IOException
     */
    public static List<FilePreview> extractDataForPreview(final InputStream instream, final String formatType,
            final String fileName, final int noOfRowsToExtract) {
        if (instream == null) {
            throw new LocalizedException("file.preview.error");
        }
        try {
            switch (FileType.findByFilename(fileName)) {
            case CSV:
            case TXT:
                return getPreviewDataFromText(instream, formatType, fileName, noOfRowsToExtract);
            case XLS:
            case XLSX:
                return getPreviewDataFromExcel(instream, formatType, fileName, noOfRowsToExtract);
            default:
                throw new LocalizedException("file.invalid.filetype");
            }
        } catch (final Exception e) {
            throw new LocalizedException("file.preview.error", new String[] { e.getMessage() });
        }
    }

    /**
     * Extracts preview data from CSV or TXT files.
     *
     * @param instream
     *        input stream
     * @param fileName
     *        name of the uploaded file
     * @param noOfRowsToExtract
     *        number of rows to extract including header row
     * @return List<FilePreview> list of file preview.
     * @throws IOException
     */
    private static List<FilePreview> getPreviewDataFromText(final InputStream instream, final String formatType,
            final String fileName, final int noOfRowsToExtract) throws Exception {
        final TextFileUtils textFileUtils = new TextFileUtils();

        final List<List<String>> rowData = new ArrayList<List<String>>();
        textFileUtils.processTextFile(instream, formatType, new LineMapper() {
            @Override
            public boolean mapLine(final String line, final int lineNumber, final String formatType) {
                List<String> rowDataTemp = new ArrayList<String>();
                if (lineNumber < noOfRowsToExtract) {
                    final String[] columnValues = line.split(REGEX_DELIMITER);
                    rowDataTemp = Arrays.asList(columnValues);
                    List<String> col = new ArrayList<String>();
                    for (String s : rowDataTemp) {
                        col.add(removeExtraneousQuotes(s));
                    }
                    rowData.add(col);
                    return true;
                } else {
                    return false; // Exit Condition
                }
            }
        });

        final List<FilePreview> previewData = new ArrayList<FilePreview>();
        if (!rowData.isEmpty()) {
            final FilePreview preview = new FilePreview();
            preview.setSheetName(rowData.get(0).get(0));
            preview.setRowData(rowData);
            previewData.add(preview);
        }
        return previewData;
    }

    /**
     * Extracts preview data from EXCEL format files.
     *
     * @param instream
     *        input stream
     * @param fileName
     *        name of the uploaded file
     * @param noOfRowsToExtract
     *        number of rows to extract including header row
     * @return List<FilePreview> list of file preview. Each sheet is translated into a file preview.
     * @throws IOException
     */
    private static List<FilePreview> getPreviewDataFromExcel(final InputStream instream, final String formatType,
            final String fileName, final int noOfRowsToExtract) throws Exception {

        final ExcelUtils excelUtils = new ExcelUtils();
        final List<FilePreview> previewData = new ArrayList<FilePreview>();
        excelUtils.processExcelFile(instream, new ExcelWorksheetProcessor() {

            // Sheet Processing
            @Override
            public void process(final Sheet sheet) {
                final FilePreview preview = new FilePreview();
                final List<List<String>> rowData = new ArrayList<List<String>>();
                final boolean skipHeader = false;

                // Row Processing
                excelUtils.iterateRows(sheet, new ExcelRowMapper() {
                    int numberOfHeaders;

                    @Override
                    public boolean mapRow(final Row row) {
                        if (row == null) {
                            rowData.add(null);
                            return true;
                        }
                        final String[] columnsText = excelUtils.getCellTextValuesWithNullAsBlank(row);

                        if (StringUtils.isBlank(preview.getSheetName())) { // Sheet Name - FormatType
                            preview.setSheetName(formatType);
                        }

                        if (row.getRowNum() < noOfRowsToExtract) {

                            if (row.getRowNum() == HEADER_ROW) {
                                this.numberOfHeaders = columnsText.length;
                            }
                            rowData.add(asList(copyOf(padEmptyIfNoColumnAtEnd(this.numberOfHeaders, columnsText),
                                    this.numberOfHeaders, String[].class)));
                            return true;

                        } else {
                            return false; // Break Mapping the row

                        }
                    }
                }, skipHeader, true);

                // Populate Preview
                preview.setRowData(rowData);
                previewData.add(preview);
            }
        });

        return previewData;
    }

    /**
    * Formats string which contains double quotes or double quotes Fields with embedded commas/double quotes.
     *
     * @param string 
     *          
     * @return formatted string
     * 
     */
    public static String removeExtraneousQuotes(String string) {
        // IF string contains a quote and not equal to null and length greater than 0 THEN
        if (string != null && string.length() > 0 && string.contains("\"")) {
            // IF string starts with a triple or single quote THEN
            if (string.startsWith("\"\"\"") || string.startsWith("\"")) {
                // eliminate the initial quote
                string = string.substring(1);
            }
            // IF string ends with a triple or single quote THEN
            if (string.endsWith("\"\"\"") || string.endsWith("\"")) {
                // eliminate the trailing quote
                string = string.substring(0, string.length() - 1);
            }
            // Replace all (quote, followed by zero-or-more spaces, followed by quote, followed by zero-or-more spaces)  by a single quote.
            string = string.replaceAll("\"\\s*\"\\s*", "\"");
            return string;
        } else {
            // return the string unchanged
            return string;
        }
    }

}