View Javadoc
1   package integrationTest.Bug252;
2   
3   import com.opencsv.bean.*;
4   import com.opencsv.exceptions.CsvDataTypeMismatchException;
5   import com.opencsv.exceptions.CsvRequiredFieldEmptyException;
6   import org.apache.commons.lang3.StringUtils;
7   import org.junit.jupiter.api.Test;
8   
9   import java.io.StringWriter;
10  import java.io.Writer;
11  import java.lang.annotation.ElementType;
12  import java.lang.annotation.Retention;
13  import java.lang.annotation.RetentionPolicy;
14  import java.lang.annotation.Target;
15  import java.math.BigDecimal;
16  import java.text.DecimalFormat;
17  import java.text.NumberFormat;
18  import java.util.ArrayList;
19  import java.util.List;
20  import java.util.Locale;
21  
22  import static org.junit.jupiter.api.Assertions.assertEquals;
23  
24  class MiniCaseCsvTest {
25  
26      @Test
27      void testExportByName() {
28          // given
29          final CsvNameExporter csvExporter = new CsvNameExporter();
30          final ExportRow exportRow = new ExportRowName();
31          exportRow.setNumber(new BigDecimal("1.23456789"));
32  
33          final List<ExportRow> exportRowList = new ArrayList<>();
34          exportRowList.add(exportRow);
35  
36          // when
37          final String export = csvExporter.export(exportRowList, ExportRowName.class);
38          // then
39          final String secondLine = export.split("\n")[1];
40          assertEquals("1.2", secondLine);
41      }
42  
43      @Test
44      void testExportByPosition() {
45          // given
46          final CsvExporter csvExporter = new CsvExporter();
47          final ExportRow exportRow = new ExportRowPosition();
48          exportRow.setNumber(new BigDecimal("1.23456789"));
49  
50          final List<ExportRow> exportRowList = new ArrayList<>();
51          exportRowList.add(exportRow);
52  
53          // when
54          final String export = csvExporter.export(exportRowList, ExportRowPosition.class);
55          // then
56          final String secondLine = export.split("\n")[1];
57          assertEquals("1.2", secondLine);
58      }
59  
60      class CsvExporter<T extends ExportRow> {
61          public String export(final List<T> rows, final Class<T> clazz) {
62  
63              final Writer writer = new StringWriter();
64              final ColumnPositionMappingStrategy<T> strategy = new ColumnPositionMappingStrategy<T>() {
65                  @Override
66                  public String[] generateHeader(final T row) {
67                      return new String[]{"number"};
68                  }
69              };
70  
71              strategy.setType(clazz);
72              strategy.setColumnMapping("number");
73  
74              final StatefulBeanToCsv<T> beanToCsv = new StatefulBeanToCsvBuilder<T>(writer)
75                      .withMappingStrategy(strategy)
76                      .withQuotechar('"')
77                      .withSeparator(',')
78                      .withLineEnd("\n")
79                      .withApplyQuotesToAll(false)
80                      .withOrderedResults(true)
81                      .build();
82  
83              try {
84                  beanToCsv.write(rows);
85                  return writer.toString();
86              } catch (final CsvDataTypeMismatchException | CsvRequiredFieldEmptyException e) {
87                  throw new RuntimeException("Error while exporting to csv", e);
88              }
89          }
90  
91      }
92  
93      class CsvNameExporter<T extends ExportRow> {
94          public String export(final List<T> rows, final Class<T> clazz) {
95  
96              final Writer writer = new StringWriter();
97              final HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<T>();
98  
99              strategy.setType(clazz);
100 
101             final StatefulBeanToCsv<T> beanToCsv = new StatefulBeanToCsvBuilder<T>(writer)
102                     .withMappingStrategy(strategy)
103                     .withQuotechar('"')
104                     .withSeparator(',')
105                     .withLineEnd("\n")
106                     .withApplyQuotesToAll(false)
107                     .withOrderedResults(true)
108                     .build();
109 
110             try {
111                 beanToCsv.write(rows);
112                 return writer.toString();
113             } catch (final CsvDataTypeMismatchException | CsvRequiredFieldEmptyException e) {
114                 throw new RuntimeException("Error while exporting to csv", e);
115             }
116         }
117 
118     }
119 
120     interface ExportRow {
121         void setNumber(BigDecimal bigDecimal);
122     }
123 
124     public static class ExportRowName implements ExportRow {
125 
126         @CsvCustomBindByName(column = "number", converter = BigDecimalFormatterTest.class)
127         @CsvBigDecimalFormat(format = "20.1")
128         private BigDecimal number;
129 
130         @Override
131         public void setNumber(final BigDecimal bigDecimal) {
132             this.number = bigDecimal;
133         }
134 
135         public BigDecimal getNumber() {
136             return number;
137         }
138     }
139 
140     public static class ExportRowPosition implements ExportRow {
141 
142         @CsvCustomBindByPosition(position = 0, converter = BigDecimalFormatterTest.class)
143         @CsvBigDecimalFormat(format = "20.1")
144         private BigDecimal number;
145 
146         @Override
147         public void setNumber(final BigDecimal bigDecimal) {
148             this.number = bigDecimal;
149         }
150 
151         public BigDecimal getNumber() {
152             return number;
153         }
154 
155     }
156 
157     public static class BigDecimalFormatterTest<T, I> extends AbstractBeanField<T, I> {
158 
159         public BigDecimalFormatterTest() {
160         }
161 
162         @Override
163         protected Object convert(final String value) {
164             throw new UnsupportedOperationException("Only writing of CSV files is possible");
165         }
166 
167         @Override
168         protected String convertToWrite(final Object value) {
169             if (value == null) {
170                 return "";
171             } else {
172                 final CsvBigDecimalFormat annotation = field.getAnnotation(CsvBigDecimalFormat.class);
173                 final NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US);
174                 if (annotation != null) {
175                     ((DecimalFormat) numberFormat).applyPattern(parseFormat(annotation.format()));
176                 }
177                 return numberFormat.format(value);
178             }
179         }
180 
181         private String parseFormat(final String format) {
182             final String[] split = format.split("\\.");
183             if (split.length == 2) {
184                 final int digits = Integer.parseInt(split[0]);
185                 final int decimalPlaces = Integer.parseInt(split[1]);
186                 return StringUtils.repeat("#", digits) + "." + StringUtils.repeat("#", decimalPlaces);
187             } else {
188                 final int digits = Integer.parseInt(split[0]);
189                 return StringUtils.repeat("#", digits);
190             }
191         }
192     }
193 
194     @Retention(RetentionPolicy.RUNTIME)
195     @Target(ElementType.FIELD)
196     public @interface CsvBigDecimalFormat {
197 
198         String format();
199 
200     }
201 
202 }