/* * Copyright (c) 2014 Red Hat, Inc. and/or its affiliates. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cheng Fang - Initial API and implementation */ package org.jberet.support.io; import java.io.File; import java.util.Properties; import java.util.concurrent.TimeUnit; import javax.batch.operations.JobOperator; import javax.batch.runtime.BatchRuntime; import javax.batch.runtime.BatchStatus; import org.jberet.runtime.JobExecutionImpl; import org.junit.After; import org.junit.Assert; import org.junit.Test; //these tests do not verify expected or forbidden data in the resulting excel files. //open the generated excel files to manually verify. For example, // cd $TMPDIR // open testMoviesBeanTypeFullTemplateHeader.xlsx public final class ExcelWriterTest { private final JobOperator jobOperator = BatchRuntime.getJobOperator(); static final String writerTestJobName = "org.jberet.support.io.ExcelWriterTest"; static final String moviesSheetName = "Movies 2012"; static final String templateResource = "person-movies-company.xltx"; static final String moviesTemplateSheetName = "Movies"; static final String moviesTemplateHeaderRow = "0"; static final String moviesTemplateNoHeaderSheetName = "Movies No Header"; static final String streamingWriterTestJobName = "org.jberet.support.io.ExcelStreamingWriterTest.xml"; static final String companyListCsv = "companylist.csv"; static final String companyListTemplateSheetName = "Company List"; static final String companyListTemplateHeaderRow = "0"; static final String companyListCsvNameMapping = "symbol, name, lastSale, marketCap, address, ipoYear, sector, industry, summaryQuote, null"; static final String companyListCsvCellProcessors = "null;" + "null;" + "StrReplace('n/a', '0'), ParseDouble;" + "StrReplace('n/a', '0'), ParseDouble;" + "null;" + "null;" + "null;" + "null;" + "null;" + "null"; static final String ibmStockTradeCsv = "IBM_unadjusted.txt"; static final String ibmStockTradeSheetName = "IBM Stock Minute Date (1998 - 2014)"; static final String ibmStockTradeNameMapping = "date,time,open,high,low,close,volume"; static final String ibmStockTradeHeader = "Date,Time,Open,High,Low,Close,Volume"; static final String ibmStockTradeCellProcessors = "ParseDate('MM/dd/yyyy');" + "null; ParseDouble; ParseDouble; ParseDouble; ParseDouble; ParseDouble"; private String csvNameMapping; private String csvCellProcessors; private String csvHeaderless; @After public void after() { this.csvCellProcessors = null; this.csvNameMapping = null; this.csvHeaderless = null; } @Test public void testMoviesBeanTypeFull() throws Exception { testReadWrite0(writerTestJobName, JsonItemReaderTest.movieJson, "testMoviesBeanTypeFull.xlsx", MovieTest.header, null, null, null, Movie.class, moviesSheetName); } @Test public void testMoviesBeanTypeFullStreaming() throws Exception { this.csvCellProcessors = MovieTest.cellProcessors; testReadWrite0(streamingWriterTestJobName, MovieTest.moviesCsv, "testMoviesBeanTypeFullStreaming.xlsx", MovieTest.header, null, null, null, Movie.class, moviesSheetName); } //verifies an existing excel file can be used as a template for populating data into a new excel file. //the template contains format (set font color to blue) that should be applied to the generated output excel file. //the header is also configured in template file, so no need to explicitly specify header property in job.xml. @Test public void testMoviesBeanTypeFullTemplate() throws Exception { testReadWrite0(writerTestJobName, JsonItemReaderTest.movieJson, "testMoviesBeanTypeFullTemplate.xlsx", null, templateResource, moviesTemplateSheetName, moviesTemplateHeaderRow, Movie.class, moviesSheetName); } @Test public void testMoviesBeanTypeFullTemplateStreaming() throws Exception { this.csvCellProcessors = MovieTest.cellProcessors; testReadWrite0(streamingWriterTestJobName, MovieTest.moviesCsv, "testMoviesBeanTypeFullTemplateStreaming.xlsx", null, templateResource, moviesTemplateSheetName, moviesTemplateHeaderRow, Movie.class, moviesSheetName); } //similar to the above test, but passing in external header //the template sheet has no header, and font color for all rows is configured magenta @Test public void testMoviesBeanTypeFullTemplateHeader() throws Exception { testReadWrite0(writerTestJobName, JsonItemReaderTest.movieJson, "testMoviesBeanTypeFullTemplateHeader.xlsx", MovieTest.header, templateResource, moviesTemplateNoHeaderSheetName, null, Movie.class, moviesSheetName); } @Test public void testMoviesBeanTypeFullTemplateHeaderStreaming() throws Exception { this.csvCellProcessors = MovieTest.cellProcessors; testReadWrite0(streamingWriterTestJobName, MovieTest.moviesCsv, "testMoviesBeanTypeFullTemplateHeaderStreaming.xlsx", MovieTest.header, templateResource, moviesTemplateNoHeaderSheetName, null, Movie.class, moviesSheetName); } //verifies reading large csv data set and writing excel with ExcelStreamingItemWriter. @Test public void testCompanyListBeanTypeFullStreaming() throws Exception { this.csvCellProcessors = companyListCsvCellProcessors; this.csvNameMapping = companyListCsvNameMapping; testReadWrite0(streamingWriterTestJobName, companyListCsv, "testCompanyListBeanTypeFullStreaming.xlsx", null, templateResource, companyListTemplateSheetName, companyListTemplateHeaderRow, Company.class, companyListTemplateSheetName); } //verifies reading very large csv data set (IBM_unadjusted.txt, 51,058,469) and writing excel (size 34,232,654). //when running with ExcelUserModelItemWriter, failed with java.lang.OutOfMemoryError: GC overhead limit exceeded //when running with ExcelStreamingItemWriter, passed after 19 seconds @Test public void testIBMStockTradeBeanTypeFullStreaming() throws Exception { this.csvCellProcessors = ibmStockTradeCellProcessors; this.csvNameMapping = ibmStockTradeNameMapping; this.csvHeaderless = Boolean.TRUE.toString(); testReadWrite0(streamingWriterTestJobName, ibmStockTradeCsv, "testIBMStockTradeBeanTypeFullStreaming.xlsx", ibmStockTradeHeader, null, null, null, StockTrade.class, ibmStockTradeSheetName); } void testReadWrite0(final String jobName, final String resource, final String writeResource, final String header, final String templateResource, final String templateSheetName, final String templateHeaderRow, final Class<?> beanType, final String sheetName) throws Exception { final Properties params = CsvItemReaderWriterTest.createParams(CsvProperties.BEAN_TYPE_KEY, beanType.getName()); final File writeResourceFile = new File(CsvItemReaderWriterTest.tmpdir, writeResource); params.setProperty("writeResource", writeResourceFile.getPath()); params.setProperty("resource", resource); if (header != null) { params.setProperty("header", header); } if (sheetName != null) { params.setProperty("sheetName", sheetName); } if (templateResource != null) { params.setProperty("templateResource", templateResource); } if (templateSheetName != null) { params.setProperty("templateSheetName", templateSheetName); } if (templateHeaderRow != null) { params.setProperty("templateHeaderRow", templateHeaderRow); } if (this.csvCellProcessors != null) { params.setProperty(CsvProperties.CELL_PROCESSORS_KEY, this.csvCellProcessors); } if (this.csvNameMapping != null) { params.setProperty(CsvProperties.NAME_MAPPING_KEY, this.csvNameMapping); } if (this.csvHeaderless != null) { params.setProperty(CsvProperties.HEADERLESS_KEY, this.csvHeaderless); } final long jobExecutionId = jobOperator.start(jobName, params); final JobExecutionImpl jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(CsvItemReaderWriterTest.waitTimeoutMinutes, TimeUnit.MINUTES); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getBatchStatus()); } }