Java tutorial
/******************************************************************************* * 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; } } }