branch feature/3790_export_to_reader_or_input_steam created (now 0177cc9)
This is an automated email from the git hooks/post-receive script. New change to branch feature/3790_export_to_reader_or_input_steam in repository nuiton-csv. See http://git.nuiton.org/nuiton-csv.git at 0177cc9 Add Export.exportToReaderTest and Export.exportToInputStream test methods + improve export test (See #3790) This branch includes the following new commits: new e5ad303 fix log level for tests new 6b59438 Add Export.exportToReader and Export.exportToInputStream method (See #3790) new 0177cc9 Add Export.exportToReaderTest and Export.exportToInputStream test methods + improve export test (See #3790) The 3 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit 0177cc94f2a3f8c49bac0a1ae2cd79467f81a6d2 Author: Tony CHEMIT <chemit@codelutin.com> Date: Mon Dec 7 22:46:38 2015 +0100 Add Export.exportToReaderTest and Export.exportToInputStream test methods + improve export test (See #3790) commit 6b594380db15abdcb0139de7fdd0a0ae83d2cbb2 Author: Tony CHEMIT <chemit@codelutin.com> Date: Mon Dec 7 22:46:09 2015 +0100 Add Export.exportToReader and Export.exportToInputStream method (See #3790) commit e5ad303c5c4613eaccb70d98689dd7bcf1da0360 Author: Tony CHEMIT <chemit@codelutin.com> Date: Mon Dec 7 22:44:54 2015 +0100 fix log level for tests -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/3790_export_to_reader_or_input_steam in repository nuiton-csv. See http://git.nuiton.org/nuiton-csv.git commit e5ad303c5c4613eaccb70d98689dd7bcf1da0360 Author: Tony CHEMIT <chemit@codelutin.com> Date: Mon Dec 7 22:44:54 2015 +0100 fix log level for tests --- src/test/resources/log4j.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties index 28a196d..2980548 100644 --- a/src/test/resources/log4j.properties +++ b/src/test/resources/log4j.properties @@ -28,4 +28,4 @@ log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n # package level -log4j.logger.org.nuiton.util=INFO +log4j.logger.org.nuiton.csv=INFO -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/3790_export_to_reader_or_input_steam in repository nuiton-csv. See http://git.nuiton.org/nuiton-csv.git commit 6b594380db15abdcb0139de7fdd0a0ae83d2cbb2 Author: Tony CHEMIT <chemit@codelutin.com> Date: Mon Dec 7 22:46:09 2015 +0100 Add Export.exportToReader and Export.exportToInputStream method (See #3790) --- src/main/java/org/nuiton/csv/Export.java | 288 ++++++++++++++++++++++++++++--- 1 file changed, 261 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/nuiton/csv/Export.java b/src/main/java/org/nuiton/csv/Export.java index 7d6657d..6d30ea6 100644 --- a/src/main/java/org/nuiton/csv/Export.java +++ b/src/main/java/org/nuiton/csv/Export.java @@ -21,6 +21,7 @@ */ package org.nuiton.csv; +import com.google.common.collect.ImmutableSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.util.StringUtil; @@ -29,11 +30,14 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.io.Reader; import java.io.Writer; import java.nio.charset.Charset; import java.util.Collection; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -80,6 +84,8 @@ public class Export<E> { */ protected final String separator; + protected Iterable<ExportableColumn<E, Object>> columnsForExport; + public static <E> Export<E> newExport(ExportModel<E> model, Iterable<E> data) { return new Export<E>(model, data); @@ -177,6 +183,30 @@ public class Export<E> { return exporter.toString(charset, writeHeader); } + public static <E> Reader exportToReader(ExportModel<E> model, + Iterable<E> data, + Charset charset) throws Exception { + + return exportToReader(model, data, charset, true); + } + + public static <E> Reader exportToReader(ExportModel<E> model, + Iterable<E> data, + Charset charset, + boolean writeHeader) throws Exception { + Export<E> exporter = newExport(model, data); + return exporter.newExportToReader(charset, writeHeader); + } + + public static <E> InputStream exportToInputStream(ExportModel<E> model, Iterable<E> data) { + return exportToInputStream(model, data, true); + } + + public static <E> InputStream exportToInputStream(ExportModel<E> model, Iterable<E> data, boolean writeHeader) { + Export<E> exporter = newExport(model, data); + return exporter.newExportToInputStream(writeHeader); + } + protected Export(ExportModel<E> model, Iterable<E> data) { this.model = model; this.data = data; @@ -194,24 +224,16 @@ public class Export<E> { writeHeader(writer); } - // obtain export columns - Iterable<ExportableColumn<E, Object>> columns = - model.getColumnsForExport(); - for (E row : data) { // write the row for this data - writeRow(writer, columns, row); + writeRow(writer, row); } } protected void writeHeader(Writer writer) throws IOException { - List<String> headerNames = new LinkedList<String>(); - for (ExportableColumn<E, ?> column : model.getColumnsForExport()) { - headerNames.add(column.getHeaderName()); - } - String headersLine = StringUtil.join(headerNames, separator, true); + String headersLine = getHeader(); writer.write(headersLine); writer.write('\n'); if (log.isDebugEnabled()) { @@ -222,23 +244,8 @@ public class Export<E> { } } - protected void writeRow(Writer writer, - Iterable<ExportableColumn<E, Object>> columns, - E row) throws Exception { - - List<String> formattedCells = new LinkedList<String>(); - for (ExportableColumn<E, Object> column : columns) { - Object cell = column.getValue(row); - String formattedCell = column.formatValue(cell); - if (formattedCell == null) { - throw new NullPointerException( - "column for header " + column.getHeaderName() + - " returned a null value." + column.toString()); - } - formattedCell = StringUtil.escapeCsvValue(formattedCell, separator); - formattedCells.add(formattedCell); - } - String formattedRow = StringUtil.join(formattedCells, separator, true); + protected void writeRow(Writer writer, E row) throws Exception { + String formattedRow = getRow(row); writer.write(formattedRow); writer.write('\n'); } @@ -294,4 +301,231 @@ public class Export<E> { return result; } + protected String getHeader() { + List<String> headerNames = new LinkedList<>(); + for (ExportableColumn<E, ?> column : getColumnsForExport()) { + headerNames.add(column.getHeaderName()); + } + return getFormattedRow(headerNames); + } + + protected String getRow(E row) throws Exception { + List<String> formattedCells = new LinkedList<>(); + for (ExportableColumn<E, Object> column : getColumnsForExport()) { + Object cell = column.getValue(row); + String formattedCell = column.formatValue(cell); + if (formattedCell == null) { + throw new NullPointerException( + "column for header " + column.getHeaderName() + + " returned a null value." + column.toString()); + } + formattedCell = StringUtil.escapeCsvValue(formattedCell, separator); + formattedCells.add(formattedCell); + } + return getFormattedRow(formattedCells); + } + + protected Iterable<ExportableColumn<E, Object>> getColumnsForExport() { + if (columnsForExport == null) { + columnsForExport = ImmutableSet.copyOf(model.getColumnsForExport()); + } + return columnsForExport; + } + + protected String getFormattedRow(List<String> formattedCells) { + return StringUtil.join(formattedCells, separator, true); + } + + protected Reader newExportToReader(Charset charset, boolean writeHeader) { + return new ExportToReader(charset, writeHeader); + } + + protected InputStream newExportToInputStream(boolean writeHeader) { + return new ExportToInputStream(writeHeader); + } + + /** + * Created on 07/12/15. + * + * @author Tony Chemit - chemit@codelutin.com + */ + protected class ExportToInputStream extends InputStream { + + private final ToIoContext toIoContext; + + protected ExportToInputStream(boolean writeHeader) { + this.toIoContext = new ToIoContext(data.iterator(), writeHeader); + } + + @Override + public int read() throws IOException { + + String currentRow = toIoContext.readCurrentRow(); + + int result; + if (currentRow == null) { + + // end of stream + result = -1; + + } else { + + int length = currentRow.length(); + + result = currentRow.charAt(0); + + toIoContext.resizeCurrentRow(1, length == 1); + + } + + return result; + + } + + @Override + public void close() throws IOException { + // nothing to do + } + + } + + /** + * Created on 07/12/15. + * + * @author Tony Chemit - chemit@codelutin.com + */ + protected class ExportToReader extends Reader { + + protected final Charset charset; + + private final ToIoContext toIoContext; + + protected ExportToReader(Charset charset, boolean writeHeader) { + this.charset = charset; + this.toIoContext = new ToIoContext(data.iterator(), writeHeader); + } + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + + String currentRow = toIoContext.readCurrentRow(); + + int result; + if (currentRow == null) { + + // end of stream + result = -1; + + } else { + + int length = currentRow.length(); + if (length >= len) { + + // enough in this row to fill buffer + toIoContext.fillBufferAndResizeCurrentRow(cbuf, off, len, false); + result = len; + + } else { + + // fill with that we got + toIoContext.fillBufferAndResizeCurrentRow(cbuf, off, length, true); + + currentRow = toIoContext.currentRow; + + if (currentRow == null) { + + // no more stuff + result = length; + + } else { + + // ask for the rest + result = length + read(cbuf, off + length, len - length); + + } + + } + + } + + return result; + + } + + @Override + public void close() throws IOException { + // nothing to do + } + + } + + protected class ToIoContext { + + protected final Iterator<E> dataIterator; + + protected final boolean writeHeader; + + protected String firstRow; + + protected String currentRow; + + public ToIoContext(Iterator<E> dataIterator, boolean writeHeader) { + this.dataIterator = dataIterator; + this.writeHeader = writeHeader; + } + + protected String readCurrentRow() { + + if (firstRow == null) { + if (writeHeader) { + firstRow = getHeader() + '\n'; + currentRow = firstRow; + } else { + readNextRow(dataIterator); + firstRow = currentRow; + } + } + + return currentRow; + + } + + protected void readNextRow(Iterator<E> iterator) { + + currentRow = null; + if (iterator.hasNext()) { + E row = iterator.next(); + try { + currentRow = getRow(row) + '\n'; + } catch (Exception e) { + throw new ImportRuntimeException("Could not obtain row", e); + } + } + + } + + protected void fillBufferAndResizeCurrentRow(char[] cbuf, int off, int len, boolean computeNext) { + + for (int i = 0; i < len; i++) { + char c = currentRow.charAt(i); + cbuf[i + off] = c; + } + resizeCurrentRow(len, computeNext); + + } + + protected void resizeCurrentRow(int len, boolean computeNext) { + + if (computeNext) { + readNextRow(dataIterator); + } else { + currentRow = currentRow.substring(len); + if (currentRow.isEmpty()) { + currentRow = null; + } + } + + } + + } } -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/3790_export_to_reader_or_input_steam in repository nuiton-csv. See http://git.nuiton.org/nuiton-csv.git commit 0177cc94f2a3f8c49bac0a1ae2cd79467f81a6d2 Author: Tony CHEMIT <chemit@codelutin.com> Date: Mon Dec 7 22:46:38 2015 +0100 Add Export.exportToReaderTest and Export.exportToInputStream test methods + improve export test (See #3790) --- src/test/java/org/nuiton/csv/ExportTest.java | 121 +++++++++++++++++---------- 1 file changed, 79 insertions(+), 42 deletions(-) diff --git a/src/test/java/org/nuiton/csv/ExportTest.java b/src/test/java/org/nuiton/csv/ExportTest.java index c522f9b..2d6905c 100644 --- a/src/test/java/org/nuiton/csv/ExportTest.java +++ b/src/test/java/org/nuiton/csv/ExportTest.java @@ -21,10 +21,10 @@ */ package org.nuiton.csv; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -32,10 +32,11 @@ import org.nuiton.util.DateUtil; import java.io.File; import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.Reader; import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; +import java.util.Collections; +import java.util.Iterator; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -43,53 +44,60 @@ import java.util.zip.ZipOutputStream; public class ExportTest { - private static final Log log = LogFactory.getLog(ExportTest.class); - public static final Charset CHARSET = Charset.forName("UTF-8"); - protected Set<RowBean> oneSizedSet = new HashSet<RowBean>(); - - protected Set<RowBean> twoSizedSet = new HashSet<RowBean>(); - - protected Set<RowBean> fiveSizedSet = new HashSet<RowBean>(); - - protected List<Set<RowBean>> sets; + public static final Iterable<String> RESULTS = ImmutableList.of( + "DATE;TITLE;NUMBER\n", + "DATE;TITLE;NUMBER\n" + + "01/12/2011;Batman;1\n", + "DATE;TITLE;NUMBER\n" + + "01/12/2011;Batman;1\n" + + "02/12/2011;;7\n", + "DATE;TITLE;NUMBER\n" + + "01/12/2011;Batman;1\n" + + "02/12/2011;;7\n" + + "07/12/2011;;9\n" + + "18/12/2011;;18\n" + + "23/12/2011;;4\n" + ); + + protected Iterable<Set<RowBean>> sets; protected ExportModel<RowBean> model = new RowBeanExportModel(); @Before public void setUp() { - oneSizedSet.add(new RowBean(DateUtil.createDate(1, 12, 2011), "Batman", 1, RowBeanEnum.ONE)); + ImmutableSet.Builder<RowBean> builder = ImmutableSet.builder(); + + ImmutableList.Builder<Set<RowBean>> setBuilder = ImmutableList.builder(); - twoSizedSet.addAll(oneSizedSet); - twoSizedSet.add(new RowBean(DateUtil.createDate(2, 12, 2011), "", 7, RowBeanEnum.TWO)); + setBuilder.add(Collections.<RowBean>emptySet()); - fiveSizedSet.addAll(twoSizedSet); - fiveSizedSet.add(new RowBean(DateUtil.createDate(7, 12, 2011), "", 9, RowBeanEnum.ZERO)); - fiveSizedSet.add(new RowBean(DateUtil.createDate(18, 12, 2011), "", 18, RowBeanEnum.ONE)); - fiveSizedSet.add(new RowBean(DateUtil.createDate(23, 12, 2011), "", 4, RowBeanEnum.TWO)); + builder.add(new RowBean(DateUtil.createDate(1, 12, 2011), "Batman", 1, RowBeanEnum.ONE)); + setBuilder.add(builder.build()); + + builder.add(new RowBean(DateUtil.createDate(2, 12, 2011), "", 7, RowBeanEnum.TWO)); + setBuilder.add(builder.build()); + + builder.add((new RowBean(DateUtil.createDate(7, 12, 2011), "", 9, RowBeanEnum.ZERO))); + builder.add((new RowBean(DateUtil.createDate(18, 12, 2011), "", 18, RowBeanEnum.ONE))); + builder.add((new RowBean(DateUtil.createDate(23, 12, 2011), "", 4, RowBeanEnum.TWO))); + setBuilder.add(builder.build()); + + sets = setBuilder.build(); - sets = Arrays.asList(new HashSet<RowBean>(), oneSizedSet, twoSizedSet, fiveSizedSet); } @Test public void testExportToString() throws Exception { + Iterator<String> resultIterator = RESULTS.iterator(); for (Set<RowBean> set : sets) { String csv = Export.exportToString(model, set, CHARSET); + assertExportResultEquals(resultIterator, csv); - if (log.isDebugEnabled()) { - log.debug("exported csv:\n" + csv); - } - - // 1 header line + one line per RowBean instance - int expectedLineCount = 1 + set.size(); - // number of '\n' in csv - int actualLineCount = csv.split("\n").length; - Assert.assertEquals("exported CSV must have all lines", - expectedLineCount, actualLineCount); } } @@ -101,7 +109,7 @@ public class ExportTest { public void testExportToOuputStream() throws Exception { File f = new File(FileUtils.getTempDirectory(), getClass().getName() + "-exportcsvtest.zip"); - + FileUtils.forceMkdir(f.getParentFile()); ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(f)); @@ -116,22 +124,51 @@ public class ExportTest { ZipFile zipFile = new ZipFile(f); + Iterator<String> resultIterator = RESULTS.iterator(); for (Set<RowBean> set : sets) { String csv = IOUtils.toString(zipFile.getInputStream(new ZipEntry("/export" + (set.size()) + ".csv"))); + assertExportResultEquals(resultIterator, csv); + + } + + } + + @Test + public void testExportToReader() throws Exception { - if (log.isDebugEnabled()) { - log.debug("exported csv:\n" + csv); - } + Iterator<String> resultIterator = RESULTS.iterator(); + for (Set<RowBean> set : sets) { + + Reader reader = Export.exportToReader(model, set, CHARSET); + + String csv = IOUtils.toString(reader); + assertExportResultEquals(resultIterator, csv); + + } + + } + + @Test + public void testExportToInputStream() throws Exception { + + Iterator<String> resultIterator = RESULTS.iterator(); + for (Set<RowBean> set : sets) { + + InputStream inputStream = Export.exportToInputStream(model, set); + + String csv = IOUtils.toString(inputStream); + assertExportResultEquals(resultIterator, csv); - // 1 header line + one line per RowBean instance - int expectedLineCount = 1 + set.size(); - // number of '\n' in csv - int actualLineCount = csv.split("\n").length; - Assert.assertEquals("exported CSV must have all lines", - expectedLineCount, actualLineCount); } } + protected void assertExportResultEquals(Iterator<String> resultIterator, String actual) { + + String expected = resultIterator.next(); + Assert.assertEquals(expected, actual); + + } + } -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
participants (1)
-
nuiton.org scm