This is an automated email from the git hooks/post-receive script. New commit to branch feature/3798_new_export_API in repository nuiton-csv. See http://git.nuiton.org/nuiton-csv.git commit 0741c5563f5e4a416b8b7d01121dafda87d825be Author: Tony CHEMIT <chemit@codelutin.com> Date: Fri Dec 11 13:18:32 2015 +0100 Be able to add columns directly to the ExporterBuilder without using an ExportModel (see #3798) --- src/main/java/org/nuiton/csv/Exporter.java | 62 +++++++++++++--- src/main/java/org/nuiton/csv/ExporterBuilder.java | 86 +++++++++++++++++++--- .../java/org/nuiton/csv/ExporterConfiguration.java | 6 +- src/main/java/org/nuiton/csv/package-info.java | 16 ++-- src/test/java/org/nuiton/csv/ExporterTest.java | 54 ++++++-------- 5 files changed, 164 insertions(+), 60 deletions(-) diff --git a/src/main/java/org/nuiton/csv/Exporter.java b/src/main/java/org/nuiton/csv/Exporter.java index c869be3..c0089ae 100644 --- a/src/main/java/org/nuiton/csv/Exporter.java +++ b/src/main/java/org/nuiton/csv/Exporter.java @@ -15,6 +15,33 @@ import java.io.Writer; import java.util.Iterator; /** + * Exporter contains a configuration and is ready to export some data. + * + * <h2>Exporter construction</h2> + * + * <p>To create a new exporter, you need to use an {@link ExporterBuilder}.</p> + * <p> + * There is some useful methods such as {@link #of(ExporterConfiguration)} or {@link #of(ExportModel)} to + * obtain directly an exporter from a legacy export model or a exporter configuration. + * </p> + * <p> + * There is also other method to create a new export builder such as {@link #builder()}, {@link #builder(ExporterConfiguration)} or + * {@link #builder(ExportModel)}. Once this is done, use the {@link ExporterBuilder} API. + * </p> + * <h2>Exporter usage</h2> + * + * Once you have an exporter, use one of the method {@code exportTo...(...)} methods. + * + * You can export to + * <ul> + * <li>File</li> + * <li>String</li> + * <li>OutputStream</li> + * <li>Writer</li> + * <li>InputStream</li> + * <li>Reader</li> + * </ul> + * * Created on 09/12/15. * * @author Tony Chemit - chemit@codelutin.com @@ -23,11 +50,6 @@ import java.util.Iterator; public class Exporter<O> { /** - * Immutable exporter configuration. - */ - protected final ExporterConfiguration<O> configuration; - - /** * Creates an exporter from the given model, and using default configuration values. * * @param model model of export @@ -57,7 +79,10 @@ public class Exporter<O> { * @return the exporter builder */ public static <O> ExporterBuilder<O> builder(ExportModel<O> model) { - return new ExporterBuilder<>(model); + return Exporter + .<O>builder() + .addColumns(model.getColumnsForExport()) + .setCellSeparator(String.valueOf(model.getSeparator())); } /** @@ -72,15 +97,20 @@ public class Exporter<O> { } /** - * Creates a new exporter builder from this exporter (to reuse his configuration). + * Creates a new empty exporter builder. * * @return the exporter builder */ - public ExporterBuilder<O> builder() { - return new ExporterBuilder<>(configuration); + public static <O> ExporterBuilder<O> builder() { + return new ExporterBuilder<>(); } /** + * Immutable exporter configuration. + */ + protected final ExporterConfiguration<O> configuration; + + /** * Produces the cvs of the given {@code data} into the given {@code outputStream}. * * @param data data to export @@ -310,6 +340,15 @@ public class Exporter<O> { this.configuration = configuration; } + /** + * Creates a new exporter builder from this exporter (to reuse his configuration). + * + * @return the exporter builder + */ + public ExporterBuilder<O> toBuilder() { + return new ExporterBuilder<>(configuration); + } + protected static class ExporterAction<E> { /** @@ -452,7 +491,6 @@ public class Exporter<O> { protected void readHeader() { currentRowPosition = 0; - String cellSeparator = configuration.getCellSeparator(); StringBuilder rowBuilder = new StringBuilder(); int index = 0; @@ -471,10 +509,10 @@ public class Exporter<O> { String cellSeparator = configuration.getCellSeparator(); StringBuilder rowBuilder = new StringBuilder(); int index = 0; - for (ExportableColumn<E, Object> column : configuration.getColumns()) { + for (ExportableColumn<E, ?> column : configuration.getColumns()) { Object cell = column.getValue(row); - String formattedCell = column.formatValue(cell); + String formattedCell = ((ExportableColumn) column).formatValue(cell); Preconditions.checkNotNull(formattedCell, String.format("column for header %s (%s) returned a null value.", column.getHeaderName(), column.toString())); diff --git a/src/main/java/org/nuiton/csv/ExporterBuilder.java b/src/main/java/org/nuiton/csv/ExporterBuilder.java index 5444ef0..b02546c 100644 --- a/src/main/java/org/nuiton/csv/ExporterBuilder.java +++ b/src/main/java/org/nuiton/csv/ExporterBuilder.java @@ -24,6 +24,8 @@ public class ExporterBuilder<O> { protected final ExporterConfiguration<O> configuration; + protected final ImmutableSet.Builder<ExportableColumn<O, ?>> columnsBuilder = ImmutableSet.builder(); + /** * Set the {@link ExporterConfiguration#cellSeparator} and return the builder. * @@ -58,30 +60,96 @@ public class ExporterBuilder<O> { } /** - * Sets the {@link ExporterConfiguration#columns} and return the builder. + * Add the given columns. * - * @param columns new value for {@link ExporterConfiguration#columns}. + * @param columns columns to add to the builder * @return the builder */ - public ExporterBuilder<O> setColumns(ImmutableSet<ExportableColumn<O, Object>> columns) { - configuration.setColumns(columns); + public ExporterBuilder<O> addColumns(Iterable<ExportableColumn<O, Object>> columns) { + columnsBuilder.addAll(columns); return this; } - public Exporter<O> build() { + /** + * Add a new column for the given property name, using also the property name as the export header name. + * + * The property is exported using a String formatted. + * + * @param propertyName the property name to export + * @return the builder + */ + public ExporterBuilder<O> addColumn(String propertyName) { + return addColumn(propertyName, propertyName, Common.STRING); + } + + /** + * Add a new column for the given property name and export as the given header name. + * + * The property is obtained using a simple getter and exported using a String formatter. + * + * @param headerName the header name to use in export + * @param propertyName the property name to export + * @return the builder + */ + public ExporterBuilder<O> addColumn(String headerName, String propertyName) { + return addColumn(headerName, propertyName, Common.STRING); + } + /** + * Add a new column for the given property name and export as the given header name. + * + * The property is obtained using the given value getter and exported using a String formatter. + * + * @param headerName the header name to use in export + * @param valueGetter the value getter + * @return the builder + */ + public ExporterBuilder<O> addColumn(String headerName, ValueGetter<O, String> valueGetter) { + return addColumn(headerName, valueGetter, Common.STRING); + } + + /** + * Add a new column for the given property name and export as the given header name. + * + * The property is obtained using a simple getter and exported using the given value formatter. + * + * @param headerName the header name to use in export + * @param propertyName the property name to export + * @param valueFormatter the value formatter + * @return the builder + */ + public <T> ExporterBuilder<O> addColumn(String headerName, String propertyName, ValueFormatter<T> valueFormatter) { + return addColumn(headerName, new Common.BeanProperty<O, T>(propertyName), valueFormatter); + } + + /** + * Add a new column for the given property name and exported as the given header name. + * + * The property is obtained using the value getter and exported using the given value formatter. + * + * @param headerName the header name to use in export + * @param valueGetter the value getter + * @param valueFormatter the value formatter + * @return the builder + */ + public <T> ExporterBuilder<O> addColumn(String headerName, ValueGetter<O, T> valueGetter, ValueFormatter<T> valueFormatter) { + ExportableColumn<O, T> newColumn = Column.newExportableColumn(headerName, valueGetter, valueFormatter, false); + columnsBuilder.add(newColumn); + return this; + } + + public Exporter<O> build() { + configuration.setColumns(columnsBuilder.build()); Preconditions.checkNotNull(configuration.getColumns(), "No columns defined."); Preconditions.checkNotNull(configuration.getCellSeparator(), "No charset defined."); Preconditions.checkNotNull(configuration.getCellSeparator(), "No cellSeparator defined."); Preconditions.checkNotNull(configuration.getEndOfLineSeparator(), "No endOfLineSeparator defined."); return new Exporter<>(configuration); - } - public ExporterBuilder(ExportModel<O> model) { + public ExporterBuilder() { this.configuration = new ExporterConfiguration<>(); - setColumns(ImmutableSet.copyOf(model.getColumnsForExport())); setCharset(DEFAULT_CHARSET); setCellSeparator(DEFAULT_CELL_SEPARATOR); setEndOfLineSeparator(DEFAULT_END_OF_LINE_SEPARATOR); @@ -89,7 +157,7 @@ public class ExporterBuilder<O> { public ExporterBuilder(ExporterConfiguration<O> configuration) { this.configuration = new ExporterConfiguration<>(); - setColumns(configuration.getColumns()); + addColumns((Iterable) configuration.getColumns()); setCharset(configuration.getCharset()); setCellSeparator(configuration.getCellSeparator()); setEndOfLineSeparator(configuration.getEndOfLineSeparator()); diff --git a/src/main/java/org/nuiton/csv/ExporterConfiguration.java b/src/main/java/org/nuiton/csv/ExporterConfiguration.java index 4fea998..6d53a21 100644 --- a/src/main/java/org/nuiton/csv/ExporterConfiguration.java +++ b/src/main/java/org/nuiton/csv/ExporterConfiguration.java @@ -17,7 +17,7 @@ public class ExporterConfiguration<O> { /** * Columns export model. */ - protected ImmutableSet<ExportableColumn<O, Object>> columns; + protected ImmutableSet<ExportableColumn<O, ?>> columns; /** * Cell separator. @@ -46,7 +46,7 @@ public class ExporterConfiguration<O> { return charset; } - public ImmutableSet<ExportableColumn<O, Object>> getColumns() { + public ImmutableSet<ExportableColumn<O, ?>> getColumns() { return columns; } @@ -58,7 +58,7 @@ public class ExporterConfiguration<O> { this.charset = charset; } - public void setColumns(ImmutableSet<ExportableColumn<O, Object>> columns) { + public void setColumns(ImmutableSet<ExportableColumn<O, ?>> columns) { this.columns = columns; } diff --git a/src/main/java/org/nuiton/csv/package-info.java b/src/main/java/org/nuiton/csv/package-info.java index 19bb57c..045c1eb 100644 --- a/src/main/java/org/nuiton/csv/package-info.java +++ b/src/main/java/org/nuiton/csv/package-info.java @@ -26,12 +26,11 @@ * <h3>Exporter API (since 3.0)</h3> * <h2>Steps to export</h2> * <ul> - * <li>create export model (how objects should be tranformed)</li> - * <li>create exporter (and configure it)</li> - * <li>perform export</li> + * <li>create an exporter (and configure it)</li> + * <li>perform export using the exporter</li> * </ul> * - * <h2>Example (with default configuration values)</h2> + * <h2>Example from a legacy model (with default configuration values)</h2> * <pre> * ExportModel<O> model = ...; * Exporter<O> exporter = Exporter.of(model); @@ -39,10 +38,15 @@ * String csv = exporter.writeToString(data); * </pre> * - * <h2>Example (with customized configuration values)</h2> + * <h2>Example from scratch</h2> * <pre> * ExportModel<O> model = ...; - * Exporter<O> exporter = Exporter.build(model).setCellSeparator(",").build(); + * Exporter<O> exporter = Exporter + * .<O>builder() + * .addColum("propertyName") + * .addColum("headerName", "propertyName") + * .setCellSeparator(",") + * .build(); * Iterable<O> data = ...; * String csv = exporter.writeToString(data); * </pre> diff --git a/src/test/java/org/nuiton/csv/ExporterTest.java b/src/test/java/org/nuiton/csv/ExporterTest.java index 6c0a6cd..b7f2b7f 100644 --- a/src/test/java/org/nuiton/csv/ExporterTest.java +++ b/src/test/java/org/nuiton/csv/ExporterTest.java @@ -31,37 +31,20 @@ public class ExporterTest { public static final Charset CHARSET = Charset.forName("UTF-8"); public static final Iterable<String> RESULTS = ImmutableList.of( - "\"D~ATE\"~TITLEé~NUMBER--\n", - "\"D~ATE\"~TITLEé~NUMBER--\n" + - "01/12/2011~Batéman~1--\n", - "\"D~ATE\"~TITLEé~NUMBER--\n" + - "01/12/2011~Batéman~1--\n" + - "02/12/2011~~7--\n", - "\"D~ATE\"~TITLEé~NUMBER--\n" + - "01/12/2011~Batéman~1--\n" + - "02/12/2011~~7--\n" + - "07/12/2011~~9--\n" + - "18/12/2011~~18--\n" + - "23/12/2011~~4--\n" + "\"D~ATE\"~TITLEé~NUMBER~title~rowBeanEnum--\n", + "\"D~ATE\"~TITLEé~NUMBER~title~rowBeanEnum--\n" + + "01/12/2011~Batéman~1~Batéman~ONE--\n", + "\"D~ATE\"~TITLEé~NUMBER~title~rowBeanEnum--\n" + + "01/12/2011~Batéman~1~Batéman~ONE--\n" + + "02/12/2011~~7~~TWO--\n", + "\"D~ATE\"~TITLEé~NUMBER~title~rowBeanEnum--\n" + + "01/12/2011~Batéman~1~Batéman~ONE--\n" + + "02/12/2011~~7~~TWO--\n" + + "07/12/2011~~9~~ZERO--\n" + + "18/12/2011~~18~~ONE--\n" + + "23/12/2011~~4~~TWO--\n" ); - protected static final ExportModel<RowBean> EXPORT_MODEL = new ExportModel<RowBean>() { - - @Override - public char getSeparator() { - return 0; - } - - @Override - public Iterable<ExportableColumn<RowBean, Object>> getColumnsForExport() { - ModelBuilder<RowBean> modelBuilder = new ModelBuilder<>(); - modelBuilder.newColumnForExport("D~ATE", "date", Common.DAY); - modelBuilder.newColumnForExport("TITLEé", "title"); - modelBuilder.newColumnForExport("NUMBER", "number", Common.INTEGER); - return (Iterable) modelBuilder.getColumnsForExport(); - } - }; - protected static final Iterable<Set<RowBean>> SETS; static { @@ -88,10 +71,21 @@ public class ExporterTest { } protected static final Exporter<RowBean> EXPORTER = Exporter - .builder(EXPORT_MODEL) + .<RowBean>builder() .setCellSeparator("~") .setEndOfLineSeparator("--\n") .setCharset(CHARSET) + .addColumn("D~ATE", "date", Common.DAY) + .addColumn("TITLEé", "title") + .addColumn("NUMBER", "number", Common.INTEGER) + .addColumn("title") + .addColumn("rowBeanEnum", new ValueGetter<RowBean, String>() { + + @Override + public String get(RowBean object) throws Exception { + return object.getRowBeanEnum().name(); + } + }) .build(); @Test -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.