View Javadoc
1   /*
2    * Copyright 2016 Andrew Rucker Jones.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.opencsv.bean;
17  
18  import com.opencsv.CSVReader;
19  import com.opencsv.bean.customconverter.BadIntConverter;
20  import com.opencsv.bean.mocks.*;
21  import com.opencsv.enums.CSVReaderNullFieldIndicator;
22  import com.opencsv.exceptions.*;
23  import org.apache.commons.beanutils.ConversionException;
24  import org.apache.commons.lang3.StringUtils;
25  import org.junit.jupiter.api.AfterEach;
26  import org.junit.jupiter.api.BeforeAll;
27  import org.junit.jupiter.api.BeforeEach;
28  import org.junit.jupiter.api.Test;
29  
30  import java.io.*;
31  import java.math.BigDecimal;
32  import java.math.BigInteger;
33  import java.text.ParseException;
34  import java.util.*;
35  
36  import static org.junit.jupiter.api.Assertions.*;
37  
38  /**
39   * This class tests all annotation-based mapping except
40   * {@link java.time.temporal.TemporalAccessor}-based types.
41   *
42   * @see TemporalTest
43   * @author Andrew Rucker Jones
44   */
45  public class AnnotationTest {
46  
47      private static final String UNPARSABLE = "unparsable";
48  
49      private static Locale systemLocale;
50  
51      @BeforeAll
52      public static void storeSystemLocale() {
53          systemLocale = Locale.getDefault();
54      }
55  
56      @BeforeEach
57      public void setSystemLocaleToValueNotGerman() {
58          Locale.setDefault(Locale.US);
59      }
60  
61      @AfterEach
62      public void setSystemLocaleBackToDefault() {
63          Locale.setDefault(systemLocale);
64      }
65  
66      private static GregorianCalendar createDefaultTime() {
67          return new GregorianCalendar(1978, Calendar.JANUARY, 15, 6, 32, 9);
68      }
69  
70      /**
71       * Tests mapping of all primitive types by name.
72       * <p>Also incidentally tests:
73       * <ul><li>Mapping of all wrapped primitive types by name</li>
74       * <li>Mapping field of destination class with {@link CsvBindByName} with
75       * members of same names as columns</li>
76       * <li>Mapping field of destination class with {@link CsvBindByName} with
77       * members of different names than columns</li>
78       * <li>Unmapped field using header name strategy</li>
79       * <li>Mapping required fields by {@link CsvBindByName} with complete
80       * source data</li>
81       * <li>Mapping optional fields by {@link CsvBindByName} with complete
82       * source data</li>
83       * <li>Mapping optional primitive fields by {@link CsvBindByName} with
84       * missing source data</li>
85       * <li>Mapping optional object fields by {@link CsvBindByName} with missing
86       * source data</li>
87       * <li>Mapping to primitive types with private access and no setter method
88       * with {@link CsvBindByName}</li>
89       * <li>Mapping to primitive types with private access and a public setter
90       * method with {@link CsvBindByName}</li>
91       * <li>Mapping to primitive types with private access and a private setter
92       * method with {@link CsvBindByName}</li>
93       * <li>Mapping all locale-specific fields using a different locale</li>
94       * <li>Mapping {@link java.math.BigDecimal} and
95       * {@link java.math.BigInteger} without a locale</li>
96       * <li>Mapping all the date types using the default format string and no
97       * locale</li>
98       * <li>Mapping all the date types using the default format string and a
99       * locale</li>
100      * <li>Mapping a date type using a specified format string and no
101      * locale</li>
102      * <li>Mapping a date type using a specified format string and a
103      * locale</li>
104      * <li>Using a non-existent locale</li>
105      * <li>Mapping a time before noon</li>
106      * <li>Mapping a time after noon</li>
107      * <li>Annotating a column with {@link CsvBindByName} with a column name
108      * that is not in the input</li>
109      * <li>Mapping optional date field using {@link com.opencsv.bean.CsvDate}
110      * and no source data</li>
111      * <li>Capture with a matching regular expression</li>
112      * <li>Capture without a matching regular expression</li></ul></p>
113      *
114      * @throws FileNotFoundException Never
115      */
116     @Test
117     public void testGoodDataByName() throws FileNotFoundException {
118         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
119                 new HeaderColumnNameMappingStrategy<>();
120         strat.setType(AnnotatedMockBeanFull.class);
121         FileReader fin = new FileReader("src/test/resources/testinputfullgood.csv");
122         testGoodData(strat, fin, true);
123     }
124 
125     /**
126      * "Anonymous headers" is a term someone came up with for empty headers.
127      * If empty fields are converted to {@code null}, these null headers can't
128      * break opencsv. They are not supported, but they can't cause a crash.
129      * @throws FileNotFoundException Never
130      */
131     @Test
132     public void testAnonymousHeaders() throws FileNotFoundException {
133         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
134                 new HeaderColumnNameMappingStrategy<>();
135         strat.setType(AnnotatedMockBeanFull.class);
136         FileReader fin = new FileReader("src/test/resources/testAnonymousHeaders.csv");
137         List<AnnotatedMockBeanFull> beanList = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
138                 .withSeparator(';')
139                 .withMappingStrategy(strat)
140                 .withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_SEPARATORS)
141                 .build().parse();
142         assertEquals(2, beanList.size());
143     }
144 
145     @Test
146     public void testCaptureWithNullField() throws FileNotFoundException {
147         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
148                 new HeaderColumnNameMappingStrategy<>();
149         strat.setType(AnnotatedMockBeanFull.class);
150         FileReader fin = new FileReader("src/test/resources/testinputfullgood.csv");
151         List<AnnotatedMockBeanFull> beanList = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
152                 .withSeparator(';')
153                 .withMappingStrategy(strat)
154                 .withFieldAsNull(CSVReaderNullFieldIndicator.BOTH)
155                 .build().parse();
156         assertNotNull(beanList);
157         assertEquals(2, beanList.size());
158         AnnotatedMockBeanFull bean = beanList.get(1);
159         assertNull(bean.getBoolWrapped());
160     }
161 
162     /**
163      * Tests mapping a subclass with annotations in both subclass and
164      * superclass using {@link CsvBindByName}.
165      *
166      * @throws IOException Never
167      */
168     @Test
169     public void testGoodDerivedDataByName() throws IOException {
170         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFullDerived> stratd =
171                 new HeaderColumnNameMappingStrategy<>();
172         stratd.setType(AnnotatedMockBeanFullDerived.class);
173         FileReader fin = new FileReader("src/test/resources/testinputderivedgood.csv");
174         List<AnnotatedMockBeanFull> beanList = testGoodData(stratd, fin, true);
175         AnnotatedMockBeanFullDerived bean = (AnnotatedMockBeanFullDerived) beanList.get(0);
176         assertEquals(7, bean.getIntInSubclass());
177         bean = (AnnotatedMockBeanFullDerived) beanList.get(1);
178         assertEquals(8, bean.getIntInSubclass());
179     }
180 
181     /**
182      * Tests mapping fields of all wrapped primitive destination objects by
183      * {@link com.opencsv.bean.CsvBindByPosition}.
184      * <p>Also incidentally tests:
185      * <ul><li>Unmapped field using column number strategy</li>
186      * <li>Mapping all wrappers of primitive objects by
187      * {@link com.opencsv.bean.CsvBindByPosition}</li>
188      * <li>Mapping required fields by
189      * {@link com.opencsv.bean.CsvBindByPosition} with complete source
190      * data</li>
191      * <li>Mapping optional fields by
192      * {@link com.opencsv.bean.CsvBindByPosition} with complete source
193      * data</li>
194      * <li>Mapping optional primitive fields by
195      * {@link com.opencsv.bean.CsvBindByPosition} with missing source data</li>
196      * <li>Mapping optional object fields by
197      * {@link com.opencsv.bean.CsvBindByPosition} with missing source data</li>
198      * <li>Mapping to primitive types with private access and no setter method
199      * with {@link com.opencsv.bean.CsvBindByPosition}</li>
200      * <li>Mapping to primitive types with private access and a public setter
201      * method with {@link com.opencsv.bean.CsvBindByPosition}</li>
202      * <li>Mapping to primitive types with private access and a private setter
203      * method with {@link com.opencsv.bean.CsvBindByPosition}</li>
204      * <li>Annotating a column with {@link com.opencsv.bean.CsvBindByPosition}
205      * with a column number that is not in the input</li>
206      * <li>Capture with a matching regular expression</li>
207      * <li>Capture without a matching regular expression</li></ul></p>
208      *
209      * @throws FileNotFoundException Never
210      */
211     @Test
212     public void testGoodDataByPosition() throws FileNotFoundException {
213         ColumnPositionMappingStrategy<AnnotatedMockBeanFull> strat =
214                 new ColumnPositionMappingStrategy<>();
215         strat.setType(AnnotatedMockBeanFull.class);
216         FileReader fin = new FileReader("src/test/resources/testinputposfullgood.csv");
217         testGoodData(strat, fin, true);
218     }
219 
220     /**
221      * Tests mapping a subclass with annotations in both subclass and
222      * superclass using {@link CsvBindByPosition}.
223      *
224      * Type is set by the builder
225      *
226      * @throws IOException Never
227      */
228     @Test
229     public void testGoodDerivedDataByPositionTypeWithBuilder() throws IOException {
230         ColumnPositionMappingStrategy<AnnotatedMockBeanFullDerived> stratd =
231                 new ColumnPositionMappingStrategyBuilder<AnnotatedMockBeanFullDerived>()
232                         .withType(AnnotatedMockBeanFullDerived.class)
233                         .build();
234         FileReader fin = new FileReader("src/test/resources/testinputposderivedgood.csv");
235         List<AnnotatedMockBeanFull> beanList = testGoodData(stratd, fin, true);
236         AnnotatedMockBeanFullDerived bean = (AnnotatedMockBeanFullDerived) beanList.get(0);
237         assertEquals(7, bean.getIntInSubclass());
238         bean = (AnnotatedMockBeanFullDerived) beanList.get(1);
239         assertEquals(8, bean.getIntInSubclass());
240     }
241 
242     /**
243      * Tests mapping a subclass with annotations in both subclass and
244      * superclass using {@link CsvBindByPosition}.
245      * <p>
246      * Type set with setType.
247      *
248      * @throws IOException Never
249      */
250     @Test
251     public void testGoodDerivedDataByPositionTypeWithSet() throws IOException {
252         ColumnPositionMappingStrategy<AnnotatedMockBeanFullDerived> stratd =
253                 new ColumnPositionMappingStrategyBuilder<AnnotatedMockBeanFullDerived>().build();
254         stratd.setType(AnnotatedMockBeanFullDerived.class);
255         FileReader fin = new FileReader("src/test/resources/testinputposderivedgood.csv");
256         List<AnnotatedMockBeanFull> beanList = testGoodData(stratd, fin, true);
257         AnnotatedMockBeanFullDerived bean = (AnnotatedMockBeanFullDerived) beanList.get(0);
258         assertEquals(7, bean.getIntInSubclass());
259         bean = (AnnotatedMockBeanFullDerived) beanList.get(1);
260         assertEquals(8, bean.getIntInSubclass());
261     }
262 
263     @Test
264     public void testGoodDataByNameUnordered() throws FileNotFoundException {
265         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
266                 new HeaderColumnNameMappingStrategy<>();
267         strat.setType(AnnotatedMockBeanFull.class);
268         FileReader fin = new FileReader("src/test/resources/testinputfullgood.csv");
269         testGoodData(strat, fin, false);
270         
271         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFullDerived> stratd =
272                 new HeaderColumnNameMappingStrategy<>();
273         stratd.setType(AnnotatedMockBeanFullDerived.class);
274         fin = new FileReader("src/test/resources/testinputderivedgood.csv");
275         testGoodData(stratd, fin, false);
276     }
277 
278     @Test
279     public void testGoodDataByPositionUnordered() throws FileNotFoundException {
280         ColumnPositionMappingStrategy<AnnotatedMockBeanFull> strat =
281                 new ColumnPositionMappingStrategy<>();
282         strat.setType(AnnotatedMockBeanFull.class);
283         FileReader fin = new FileReader("src/test/resources/testinputposfullgood.csv");
284         testGoodData(strat, fin, false);
285     }
286 
287     private static List<AnnotatedMockBeanFull> testGoodData(MappingStrategy<? extends AnnotatedMockBeanFull> strat, Reader fin, boolean ordered) {
288         List<AnnotatedMockBeanFull> beanList = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
289                 .withSeparator(';')
290                 .withOrderedResults(ordered)
291                 .withMappingStrategy(strat)
292                 .build().parse();
293         assertEquals(2, beanList.size());
294         if(ordered) {
295             AnnotatedMockBeanFull bean = beanList.get(0);
296             assertTrue(bean.getBoolWrapped());
297             assertFalse(bean.isBoolPrimitive());
298             assertEquals(1L, (long) bean.getByteWrappedDefaultLocale());
299             assertEquals(2L, (long) bean.getByteWrappedSetLocale());
300             assertEquals(3L, (long) bean.getBytePrimitiveDefaultLocale());
301             assertEquals(4L, (long) bean.getBytePrimitiveSetLocale());
302             assertEquals(123101.101, bean.getDoubleWrappedDefaultLocale(), 0);
303             assertEquals(123202.202, bean.getDoubleWrappedSetLocale(), 0);
304             assertEquals(123303.303, bean.getDoublePrimitiveDefaultLocale(), 0);
305             assertEquals(123404.404, bean.getDoublePrimitiveSetLocale(), 0);
306             assertEquals((float) 123101.101, bean.getFloatWrappedDefaultLocale(), 0);
307             assertEquals((float) 123202.202, bean.getFloatWrappedSetLocale(), 0);
308 
309             // There appear to be rounding errors when converting from Float to float.
310             assertEquals(123303.303, bean.getFloatPrimitiveDefaultLocale(), 0.002);
311             assertEquals(123404.404, bean.getFloatPrimitiveSetLocale(), 0.003);
312 
313             assertEquals(5000, (int) bean.getIntegerWrappedDefaultLocale());
314             assertEquals(6000, (int) bean.getIntegerWrappedSetLocale());
315             assertEquals(Integer.MAX_VALUE - 7000, bean.getIntegerPrimitiveDefaultLocale());
316             assertEquals(8000, bean.getIntegerPrimitiveSetLocale());
317             assertEquals(9000L, (long) bean.getLongWrappedDefaultLocale());
318             assertEquals(10000L, (long) bean.getLongWrappedSetLocale());
319             assertEquals(11000L, bean.getLongPrimitiveDefaultLocale());
320             assertEquals(12000L, bean.getLongPrimitiveSetLocale());
321             assertEquals((short) 13000, (short) bean.getShortWrappedDefaultLocale());
322             assertEquals((short) 14000, (short) bean.getShortWrappedSetLocale());
323             assertEquals(15000, bean.getShortPrimitiveDefaultLocale());
324             assertEquals(16000, bean.getShortPrimitiveSetLocale());
325             assertEquals('a', (char) bean.getCharacterWrapped());
326             assertEquals('b', bean.getCharacterPrimitive());
327             assertEquals(BigDecimal.valueOf(123101.101), bean.getBigdecimalDefaultLocale());
328             assertEquals(BigDecimal.valueOf(123102.102), bean.getBigdecimalSetLocale());
329             assertEquals(BigInteger.valueOf(101), bean.getBigintegerDefaultLocale());
330             assertEquals(BigInteger.valueOf(102), bean.getBigintegerSetLocale());
331             assertEquals(createDefaultTime().getTimeInMillis(), bean.getDateDefaultLocale().getTime());
332             assertEquals(createDefaultTime().getTimeInMillis(), bean.getGcalDefaultLocale().getTimeInMillis());
333             assertEquals(createDefaultTime().getTimeInMillis(), bean.getCalDefaultLocale().getTimeInMillis());
334             assertEquals(createDefaultTime().getTimeInMillis(), bean.getXmlcalDefaultLocale().toGregorianCalendar().getTimeInMillis());
335             assertEquals(createDefaultTime().getTimeInMillis(), bean.getSqltimeDefaultLocale().getTime());
336             assertEquals(createDefaultTime().getTimeInMillis(), bean.getSqltimestampDefaultLocale().getTime());
337             assertEquals(createDefaultTime().getTimeInMillis(), bean.getDateSetLocale().getTime());
338             assertEquals(createDefaultTime().getTimeInMillis(), bean.getGcalSetLocale().getTimeInMillis());
339             assertEquals(createDefaultTime().getTimeInMillis(), bean.getCalSetLocale().getTimeInMillis());
340             assertEquals(createDefaultTime().getTimeInMillis(), bean.getXmlcalSetLocale().toGregorianCalendar().getTimeInMillis());
341             assertEquals(createDefaultTime().getTimeInMillis(), bean.getSqltimeSetLocale().getTime());
342             assertEquals(createDefaultTime().getTimeInMillis(), bean.getSqltimestampSetLocale().getTime());
343             assertEquals("1978-01-15", bean.getSqldateDefaultLocale().toString());
344             assertEquals("1978-01-15", bean.getSqldateSetLocale().toString());
345             assertEquals("test string", bean.getStringClass());
346             assertEquals(new GregorianCalendar(1978, Calendar.JANUARY, 15).getTimeInMillis(), bean.getGcalFormatDefaultLocale().getTimeInMillis());
347             assertEquals(new GregorianCalendar(2018, Calendar.DECEMBER, 13).getTimeInMillis(), bean.getGcalFormatSetLocale().getTimeInMillis());
348             assertEquals(1.01, bean.getFloatBadLocale(), 0.001);
349             assertEquals(TestEnum.TEST1, bean.getTestEnum());
350             assertEquals(Currency.getInstance("EUR"), bean.getTestCurrency());
351             assertNull(bean.getColumnDoesntExist());
352             assertNull(bean.getUnmapped());
353 
354             bean = beanList.get(1);
355             assertNull(bean.getBoolWrapped());
356             assertFalse(bean.isBoolPrimitive());
357             GregorianCalendar gc = createDefaultTime();
358             gc.set(Calendar.HOUR_OF_DAY, 16);
359             assertEquals(gc.getTimeInMillis(), bean.getGcalDefaultLocale().getTimeInMillis());
360             assertNull(bean.getCalDefaultLocale());
361             assertNull(bean.getTestEnum());
362         }
363         
364         return beanList;
365     }
366 
367     /**
368      * Tests mapping fields of all wrapped primitive destination objects by
369      * {@link com.opencsv.bean.CsvCustomBindByName}.
370      * <p>Also incidentally tests:
371      * <ul><li>Mapping fields of all primitive destination types by
372      * {@link com.opencsv.bean.CsvCustomBindByName}</li>
373      * <li>Mapping fields of a complex destination object by
374      * {@link com.opencsv.bean.CsvCustomBindByName}</li>
375      * <li>Mapping fields of a complex destination object by
376      * {@link com.opencsv.bean.CsvCustomBindByName} with an assignable derived
377      * type</li>
378      * <li>Mapping fields annotated with {@link CsvBindByName} and
379      * {@link CsvCustomBindByName}</li>
380      * <li>Mapping to complex destination objects with private access and no
381      * setter method with {@link com.opencsv.bean.CsvCustomBindByName}</li>
382      * <li>Mapping to complex destination objects with private access and a
383      * public setter method with {@link CsvCustomBindByName}</li>
384      * <li>Mapping to complex destination objects with private access and a
385      * private setter method with {@link CsvCustomBindByName}</li>
386      * <li>Mapping with
387      * {@link com.opencsv.bean.customconverter.ConvertGermanToBoolean} using
388      * all available values</li>
389      * <li>Mapping with
390      * {@link com.opencsv.bean.customconverter.ConvertGermanToBoolean} using
391      * an empty input</li>
392      * <li>Mapping with
393      * {@link com.opencsv.bean.customconverter.ConvertSplitOnWhitespace} using
394      * multiple whitespace-separated values (space, tab)</li>
395      * <li>Mapping with
396      * {@link com.opencsv.bean.customconverter.ConvertSplitOnWhitespace} using
397      * a null input string</li>
398      * <li>Mapping with
399      * {@link com.opencsv.bean.customconverter.ConvertSplitOnWhitespace} using
400      * a single string with no whitespace</li>
401      * <li>Mapping with
402      * {@link com.opencsv.bean.customconverter.ConvertSplitOnWhitespace} using
403      * an input string of only whitespace characters</li></ul></p>
404      *
405      * @throws FileNotFoundException Never
406      */
407     @Test
408     public void testGoodDataCustomByName() throws FileNotFoundException {
409         HeaderColumnNameMappingStrategy<AnnotatedMockBeanCustom> strat =
410                 new HeaderColumnNameMappingStrategy<>();
411         strat.setType(AnnotatedMockBeanCustom.class);
412         FileReader fin = new FileReader("src/test/resources/testinputcustomgood.csv");
413         testGoodDataCustom(strat, fin);
414     }
415 
416     /**
417      * Tests mapping fields of all wrapped primitive destination objects by
418      * {@link com.opencsv.bean.CsvCustomBindByPosition}.
419      * <p>Also incidentally tests:
420      * <ul><li>Mapping fields of all primitive destination types by
421      * {@link com.opencsv.bean.CsvCustomBindByPosition}</li>
422      * <li>Mapping fields of a complex destination object by
423      * {@link com.opencsv.bean.CsvCustomBindByPosition}</li>
424      * <li>Mapping fields of a complex destination object by
425      * {@link com.opencsv.bean.CsvCustomBindByPosition} with an assignable
426      * derived type</li>
427      * <li>Mapping fields annotated with
428      * {@link com.opencsv.bean.CsvBindByPosition} and
429      * {@link com.opencsv.bean.CsvCustomBindByPosition}</li>
430      * <li>Mapping to complex destination objects with private access and no
431      * setter method with {@link com.opencsv.bean.CsvCustomBindByPosition}</li>
432      * <li>Mapping to complex destination objects with private access and a
433      * public setter method with
434      * {@link com.opencsv.bean.CsvCustomBindByPosition}</li>
435      * <li>Mapping to complex destination objects with private access and a
436      * private setter method with
437      * {@link com.opencsv.bean.CsvCustomBindByPosition}</li></ul></p>
438      *
439      * @throws FileNotFoundException Never
440      */
441     @Test
442     public void testGoodDataCustomByPosition() throws FileNotFoundException {
443         ColumnPositionMappingStrategy<AnnotatedMockBeanCustom> strat =
444                 new ColumnPositionMappingStrategy<>();
445         strat.setType(AnnotatedMockBeanCustom.class);
446         FileReader fin = new FileReader("src/test/resources/testinputposcustomgood.csv");
447         testGoodDataCustom(strat, fin);
448     }
449 
450     private void testGoodDataCustom(MappingStrategy<AnnotatedMockBeanCustom> strat, Reader fin) {
451         List<AnnotatedMockBeanCustom> beanList = new CsvToBeanBuilder<AnnotatedMockBeanCustom>(fin)
452                 .withMappingStrategy(strat)
453                 .withSeparator(';')
454                 .build().parse();
455 
456         AnnotatedMockBeanCustom bean = beanList.get(0);
457         assertTrue(bean.getBoolWrapped());
458         assertFalse(bean.isBoolPrimitive());
459         assertEquals(Byte.MAX_VALUE, (long) bean.getByteWrappedDefaultLocale());
460         assertEquals(Byte.MAX_VALUE, (long) bean.getByteWrappedSetLocale());
461         assertEquals(Byte.MAX_VALUE, (long) bean.getBytePrimitiveDefaultLocale());
462         assertEquals(Double.MAX_VALUE, bean.getDoubleWrappedDefaultLocale(), 0);
463         assertEquals(Double.MAX_VALUE, bean.getDoubleWrappedSetLocale(), 0);
464         assertEquals(Double.MAX_VALUE, bean.getDoublePrimitiveDefaultLocale(), 0);
465         assertEquals(Double.MAX_VALUE, bean.getDoublePrimitiveSetLocale(), 0);
466         assertEquals(Float.MAX_VALUE, bean.getFloatWrappedDefaultLocale(), 0);
467         assertEquals(Float.MAX_VALUE, bean.getFloatWrappedSetLocale(), 0);
468         assertEquals(Float.MAX_VALUE, bean.getFloatPrimitiveDefaultLocale(), 0);
469         assertEquals(Float.MAX_VALUE, bean.getFloatPrimitiveSetLocale(), 0);
470         assertEquals(Integer.MAX_VALUE, (int) bean.getIntegerWrappedDefaultLocale());
471         assertEquals(Integer.MAX_VALUE, (int) bean.getIntegerWrappedSetLocale());
472         assertEquals(Integer.MAX_VALUE, bean.getIntegerPrimitiveDefaultLocale());
473         assertEquals(Integer.MAX_VALUE, bean.getIntegerPrimitiveSetLocale());
474         assertEquals(Long.MAX_VALUE, (long) bean.getLongWrappedDefaultLocale());
475         assertEquals(Long.MAX_VALUE, (long) bean.getLongWrappedSetLocale());
476         assertEquals(Long.MAX_VALUE, bean.getLongPrimitiveDefaultLocale());
477         assertEquals(Long.MAX_VALUE, bean.getLongPrimitiveSetLocale());
478         assertEquals(Short.MAX_VALUE, (short) bean.getShortWrappedDefaultLocale());
479         assertEquals(Short.MAX_VALUE, (short) bean.getShortWrappedSetLocale());
480         assertEquals(Short.MAX_VALUE, bean.getShortPrimitiveDefaultLocale());
481         assertEquals(Short.MAX_VALUE, bean.getShortPrimitiveSetLocale());
482         assertEquals(Character.MAX_VALUE, (char) bean.getCharacterWrapped());
483         assertEquals(Character.MAX_VALUE, bean.getCharacterPrimitive());
484         assertEquals(BigDecimal.TEN, bean.getBigdecimalDefaultLocale());
485         assertEquals(BigDecimal.TEN, bean.getBigdecimalSetLocale());
486         assertEquals(BigInteger.TEN, bean.getBigintegerDefaultLocale());
487         assertEquals(BigInteger.TEN, bean.getBigintegerSetLocale());
488         assertEquals("inside custom converter", bean.getStringClass());
489         assertEquals(Arrays.asList("really", "long", "test", "string,", "yeah!"), bean.getComplexString());
490         assertTrue(bean.getComplexClass1() instanceof ComplexClassForCustomAnnotation);
491         assertFalse(bean.getComplexClass1() instanceof ComplexDerivedClassForCustomAnnotation);
492         assertEquals(1, bean.getComplexClass1().i);
493         assertEquals('a', bean.getComplexClass1().c);
494         assertEquals("long,long.string1", bean.getComplexClass1().s);
495         assertTrue(bean.getComplexClass2() instanceof ComplexClassForCustomAnnotation);
496         assertFalse(bean.getComplexClass2() instanceof ComplexDerivedClassForCustomAnnotation);
497         assertEquals(Integer.MAX_VALUE - 2, bean.getComplexClass2().i);
498         assertEquals('z', bean.getComplexClass2().c);
499         assertEquals("Inserted in setter methodlong,long.string2", bean.getComplexClass2().s);
500         assertTrue(bean.getComplexClass3() instanceof ComplexClassForCustomAnnotation);
501         assertTrue(bean.getComplexClass3() instanceof ComplexDerivedClassForCustomAnnotation);
502         assertEquals(3, bean.getComplexClass3().i);
503         assertEquals('c', bean.getComplexClass3().c);
504         assertEquals("long,long.derived.string3", bean.getComplexClass3().s);
505         assertEquals((float) 1.0, ((ComplexDerivedClassForCustomAnnotation) bean.getComplexClass3()).f, 0);
506         assertEquals("inside custom converter", bean.getRequiredWithCustom());
507 
508         bean = beanList.get(1);
509         assertEquals(Collections.singletonList("really"), bean.getComplexString());
510         assertTrue(bean.getComplexClass2() instanceof ComplexClassForCustomAnnotation);
511         assertTrue(bean.getComplexClass2() instanceof ComplexDerivedClassForCustomAnnotation);
512         assertEquals(Integer.MAX_VALUE - 5, bean.getComplexClass2().i);
513         assertEquals('z', bean.getComplexClass2().c);
514         assertEquals("Inserted in setter methodlong,long.derived.string5", bean.getComplexClass2().s);
515         assertEquals((float) 1.0, ((ComplexDerivedClassForCustomAnnotation) bean.getComplexClass2()).f, 0);
516 
517         bean = beanList.get(2);
518         assertEquals(new ArrayList<>(), bean.getComplexString());
519         assertTrue(bean.getComplexClass1() instanceof ComplexClassForCustomAnnotation);
520         assertTrue(bean.getComplexClass1() instanceof ComplexDerivedClassForCustomAnnotation);
521         assertEquals(7, bean.getComplexClass1().i);
522         assertEquals('g', bean.getComplexClass1().c);
523         assertEquals("long,long.derived.string7", bean.getComplexClass1().s);
524         assertEquals((float) 1.0, ((ComplexDerivedClassForCustomAnnotation) bean.getComplexClass1()).f, 0);
525 
526         for (AnnotatedMockBeanCustom cb : beanList.subList(1, 4)) {
527             assertTrue(cb.getBoolWrapped());
528             assertFalse(cb.isBoolPrimitive());
529             assertFalse(cb.getBoolWrappedOptional());
530             assertTrue(cb.isBoolPrimitiveOptional());
531         }
532 
533         bean = beanList.get(5);
534         assertNull(bean.getBoolWrappedOptional());
535         assertFalse(bean.isBoolPrimitiveOptional());
536         assertNull(bean.getComplexString());
537     }
538 
539     /**
540      * Tests mapping a required field with
541      * {@link com.opencsv.bean.CsvBindByName} when the source data are missing.
542      * <p>Also incidentally tests:<ul>
543      * <li>Error in input on line x</li>
544      * </ul></p>
545      *
546      * @throws FileNotFoundException Never
547      */
548     @Test
549     public void testMapRequiredByNameMissingData() throws FileNotFoundException {
550         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
551                 new HeaderColumnNameMappingStrategy<>();
552         strat.setType(AnnotatedMockBeanFull.class);
553         FileReader fin = new FileReader("src/test/resources/testinputcase7.csv");
554         auxiliaryTestMissingData(strat, fin, 2);
555     }
556 
557     @Test
558     public void testMapRequiredByPositionMissingData() throws FileNotFoundException {
559         ColumnPositionMappingStrategy<AnnotatedMockBeanFull> strat =
560                 new ColumnPositionMappingStrategy<>();
561         strat.setType(AnnotatedMockBeanFull.class);
562         FileReader fin = new FileReader("src/test/resources/testinputcase51.csv");
563         auxiliaryTestMissingData(strat, fin, 1);
564     }
565 
566     private void auxiliaryTestMissingData(MappingStrategy<AnnotatedMockBeanFull> strat, Reader fin, long expectedLineNumber) {
567         CsvToBean<AnnotatedMockBeanFull> ctb = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
568                 .withSeparator(';')
569                 .withMappingStrategy(strat)
570                 .build();
571         try {
572             ctb.parse();
573             fail("The parse should have thrown an Exception.");
574         } catch (RuntimeException e) {
575             assertTrue(e.getCause() instanceof CsvRequiredFieldEmptyException);
576             CsvRequiredFieldEmptyException csve = (CsvRequiredFieldEmptyException) e.getCause();
577             assertEquals(expectedLineNumber, csve.getLineNumber());
578             assertNotNull(csve.getLine());
579             assertEquals(AnnotatedMockBeanFull.class.getName(), csve.getBeanClass().getName());
580             assertEquals("byteWrappedSetLocale", csve.getDestinationField().getName());
581         }
582 
583     }
584 
585     @Test
586     public void testMapByNameMismatchingType() throws IOException {
587         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
588                 new HeaderColumnNameMappingStrategy<>();
589         strat.setType(AnnotatedMockBeanFull.class);
590         Reader fin = new FileReader("src/test/resources/testinputcase11.csv");
591         String englishErrorMessage = auxiliaryTestMismatchingType(strat, fin, 2);
592         
593         // Now with another locale
594         strat = new HeaderColumnNameMappingStrategy<>();
595         strat.setType(AnnotatedMockBeanFull.class);
596         strat.setErrorLocale(Locale.GERMAN); // In this test, setType(), then setErrorLocale()
597         fin = new FileReader("src/test/resources/testinputcase11.csv");
598         assertNotSame(englishErrorMessage, auxiliaryTestMismatchingType(strat, fin, 2));
599     }
600 
601     @Test
602     public void testMapByPositionMismatchingType() throws IOException {
603         ColumnPositionMappingStrategy<AnnotatedMockBeanFull> strat =
604                 new ColumnPositionMappingStrategy<>();
605         strat.setType(AnnotatedMockBeanFull.class);
606         Reader fin = new FileReader("src/test/resources/testinputcase55.csv");
607         String englishErrorMessage = auxiliaryTestMismatchingType(strat, fin, 1);
608         
609         // Now with a different locale
610         strat = new ColumnPositionMappingStrategy<>();
611         strat.setErrorLocale(Locale.GERMAN); // In this test, setErrorLocale(), then setType()
612         strat.setType(AnnotatedMockBeanFull.class);
613         fin = new FileReader("src/test/resources/testinputcase55.csv");
614         assertNotSame(englishErrorMessage, auxiliaryTestMismatchingType(strat, fin, 1));
615     }
616 
617     private String auxiliaryTestMismatchingType(MappingStrategy<AnnotatedMockBeanFull> strat, Reader fin, long expectedLineNumber) {
618         CsvToBean<AnnotatedMockBeanFull> ctb = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
619                 .withMappingStrategy(strat)
620                 .withSeparator(';')
621                 .build();
622         String errorMessage = null;
623         try {
624             ctb.parse();
625             fail("The parse should have thrown an Exception.");
626         } catch (RuntimeException e) {
627             assertTrue(e.getCause() instanceof CsvDataTypeMismatchException);
628             CsvDataTypeMismatchException csve = (CsvDataTypeMismatchException) e.getCause();
629             assertEquals(expectedLineNumber, csve.getLineNumber());
630             assertNotNull(csve.getLine());
631             assertTrue(csve.getSourceObject() instanceof String);
632             assertEquals("mismatchedtype", csve.getSourceObject());
633             assertEquals(Byte.class, csve.getDestinationClass());
634             errorMessage = csve.getLocalizedMessage();
635             assertTrue(csve.getCause() instanceof ConversionException);
636         }
637         
638         return errorMessage;
639     }
640 
641     @Test
642     public void testMapByNameUnbindableField() {
643         HeaderColumnNameMappingStrategy<UnbindableField> strat =
644                 new HeaderColumnNameMappingStrategy<>();
645         strat.setType(UnbindableField.class);
646         CSVReader read = new CSVReader(new StringReader("list\ntrue false true"));
647         auxiliaryTestUnbindableField(strat, read, 2);
648     }
649 
650     @Test
651     public void testMapByPositionUnbindableField() {
652         ColumnPositionMappingStrategy<UnbindableField> strat =
653                 new ColumnPositionMappingStrategy<>();
654         strat.setType(UnbindableField.class);
655         CSVReader read = new CSVReader(new StringReader("true false true"));
656         auxiliaryTestUnbindableField(strat, read, 1);
657     }
658 
659     private <T> void auxiliaryTestUnbindableField(MappingStrategy<T> strat, CSVReader read, long expectedLineNumber) {
660         CsvToBean<T> ctb = new CsvToBeanBuilder<T>(read).withMappingStrategy(strat).build();
661         try {
662             ctb.parse();
663             fail("The parse should have thrown an Exception.");
664         } catch (RuntimeException e) {
665             assertTrue(e.getCause() instanceof CsvDataTypeMismatchException);
666             CsvDataTypeMismatchException csve = (CsvDataTypeMismatchException) e.getCause();
667             assertEquals(expectedLineNumber, csve.getLineNumber());
668             assertNotNull(csve.getLine());
669             assertTrue(csve.getSourceObject() instanceof String);
670             assertEquals("true false true", csve.getSourceObject());
671             assertEquals(List.class, csve.getDestinationClass());
672         }
673     }
674     
675     @Test
676     public void testBadDataExceptionsCapturedUnordered() {
677         CsvToBean<DateAnnotationOnNondate> ctb = new CsvToBeanBuilder<DateAnnotationOnNondate>(new StringReader("isnotdate\n19780115T063209"))
678                 .withType(DateAnnotationOnNondate.class)
679                 .withThrowExceptions(false)
680                 .withOrderedResults(false)
681                 .build();
682         List<DateAnnotationOnNondate> beanList = ctb.parse();
683         assertNotNull(beanList);
684         assertEquals(0, beanList.size());
685         List<CsvException> exceptionList = ctb.getCapturedExceptions();
686         assertNotNull(exceptionList);
687         assertEquals(1, exceptionList.size());
688         assertTrue(exceptionList.get(0) instanceof CsvDataTypeMismatchException);
689         CsvDataTypeMismatchException innere = (CsvDataTypeMismatchException) exceptionList.get(0);
690         assertEquals(2, innere.getLineNumber());
691         assertNotNull(innere.getLine());
692         assertTrue(innere.getSourceObject() instanceof String);
693         assertEquals("19780115T063209", innere.getSourceObject());
694         assertEquals(String.class, innere.getDestinationClass());
695     }
696 
697     @Test
698     public void testMultipleExceptionsPerLine() throws FileNotFoundException {
699         ColumnPositionMappingStrategy<AnnotatedMockBeanFull> strat =
700                 new ColumnPositionMappingStrategy<>();
701         strat.setType(AnnotatedMockBeanFull.class);
702         Reader fin = new FileReader("src/test/resources/testMultipleExceptionsPerLine.csv");
703         CsvToBean<AnnotatedMockBeanFull> ctb = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
704                 .withMappingStrategy(strat)
705                 .withSeparator(';')
706                 .withThrowExceptions(false)
707                 .build();
708         ctb.parse();
709         List<CsvException> exceptionList = ctb.getCapturedExceptions();
710         assertNotNull(exceptionList);
711         assertEquals(6, exceptionList.size()); // Two lines, three mistakes per line
712         assertEquals(1, exceptionList.get(0).getLineNumber());
713         assertEquals(1, exceptionList.get(1).getLineNumber());
714         assertEquals(1, exceptionList.get(2).getLineNumber());
715         assertEquals(2, exceptionList.get(3).getLineNumber());
716         assertEquals(2, exceptionList.get(4).getLineNumber());
717         assertEquals(2, exceptionList.get(5).getLineNumber());
718     }
719 
720     @Test
721     public void testRequiredDateEmptyInput() throws IOException {
722         for(String fn : Arrays.asList(
723                 "src/test/resources/testinputcase78null.csv",
724                 "src/test/resources/testinputcase78blank.csv")) {
725             HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
726                     new HeaderColumnNameMappingStrategy<>();
727             strat.setType(AnnotatedMockBeanFull.class);
728             Reader fin = new FileReader(fn);
729             CsvToBean<AnnotatedMockBeanFull> ctb = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
730                     .withSeparator(';')
731                     .withMappingStrategy(strat)
732                     .build();
733             try {
734                 ctb.parse();
735                 fail("Expected parse to throw exception. Input filename: " + fn);
736             } catch (RuntimeException e) {
737                 assertTrue(e.getCause() instanceof CsvRequiredFieldEmptyException,
738                         "Input filename: " + fn);
739                 CsvRequiredFieldEmptyException csve = (CsvRequiredFieldEmptyException) e.getCause();
740                 assertEquals(2, csve.getLineNumber(), "Input filename: " + fn);
741                 assertNotNull(csve.getLine());
742                 assertEquals(AnnotatedMockBeanFull.class, csve.getBeanClass(),
743                         "Input filename: " + fn);
744                 assertEquals("dateDefaultLocale",
745                         csve.getDestinationField().getName(), "Input filename: " + fn);
746             }
747         }
748     }
749 
750     private void auxiliaryTestUnparseableDates(final Reader fin, final MappingStrategy<AnnotatedMockBeanFull> strat) {
751         CsvToBean<AnnotatedMockBeanFull> ctb = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
752                 .withSeparator(';')
753                 .withMappingStrategy(strat)
754                 .build();
755         try {
756             ctb.parse();
757             fail("Expected parse to throw exception.");
758         } catch (RuntimeException e) {
759             assertTrue(e.getCause() instanceof CsvDataTypeMismatchException);
760             CsvDataTypeMismatchException csve = (CsvDataTypeMismatchException) e.getCause();
761             assertEquals(2, csve.getLineNumber());
762             assertNotNull(csve.getLine());
763             assertEquals(Date.class, csve.getDestinationClass());
764             assertEquals(UNPARSABLE, csve.getSourceObject());
765             assertTrue(csve.getCause() instanceof ParseException);
766         }
767     }
768 
769     @Test
770     public void testUnparseableLocaleSpecificDate() throws IOException {
771         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
772                 new HeaderColumnNameMappingStrategy<>();
773         strat.setType(AnnotatedMockBeanFull.class);
774         Reader fin = new FileReader("src/test/resources/testinputcase82.csv");
775         auxiliaryTestUnparseableDates(fin, strat);
776     }
777 
778     @Test
779     public void testOptionalDateUnparseableInput() throws FileNotFoundException {
780         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
781                 new HeaderColumnNameMappingStrategy<>();
782         strat.setType(AnnotatedMockBeanFull.class);
783         Reader fin = new FileReader("src/test/resources/testinputcase81.csv");
784         CsvToBean<AnnotatedMockBeanFull> ctb = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
785                 .withSeparator(';')
786                 .withMappingStrategy(strat)
787                 .build();
788         try {
789             ctb.parse();
790             fail("Expected parse to throw exception.");
791         } catch (RuntimeException e) {
792             assertTrue(e.getCause() instanceof CsvDataTypeMismatchException);
793             CsvDataTypeMismatchException csve = (CsvDataTypeMismatchException) e.getCause();
794             assertEquals(2, csve.getLineNumber());
795             assertNotNull(csve.getLine());
796             assertEquals(GregorianCalendar.class, csve.getDestinationClass());
797             assertEquals(UNPARSABLE, csve.getSourceObject());
798             assertTrue(csve.getCause() instanceof ParseException);
799         }
800     }
801 
802     @Test
803     public void testUnparseableLocaleInspecificDate() throws IOException {
804         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
805                 new HeaderColumnNameMappingStrategy<>();
806         strat.setType(AnnotatedMockBeanFull.class);
807         Reader fin = new FileReader("src/test/resources/testinputcase83.csv");
808         auxiliaryTestUnparseableDates(fin, strat);
809     }
810 
811     @Test
812     public void testExceptionsSuppressed() {
813         HeaderColumnNameMappingStrategy<DateAnnotationOnNondate> strat =
814                 new HeaderColumnNameMappingStrategy<>();
815         strat.setType(DateAnnotationOnNondate.class);
816         CSVReader read = new CSVReader(new StringReader("isnotdate\n19780115T063209"));
817         CsvToBean<DateAnnotationOnNondate> ctb = new CsvToBeanBuilder<DateAnnotationOnNondate>(read)
818                 .withMappingStrategy(strat)
819                 .withThrowExceptions(false)
820                 .build();
821         ctb.parse();
822         List<CsvException> exlist = ctb.getCapturedExceptions();
823         assertEquals(1, exlist.size());
824         assertTrue(exlist.get(0) instanceof CsvDataTypeMismatchException);
825         CsvDataTypeMismatchException innere = (CsvDataTypeMismatchException) exlist.get(0);
826         assertEquals(2, innere.getLineNumber());
827         assertNotNull(innere.getLine());
828         assertTrue(innere.getSourceObject() instanceof String);
829         assertEquals("19780115T063209", innere.getSourceObject());
830         assertEquals(String.class, innere.getDestinationClass());
831     }
832 
833     @Test
834     public void testDateAnnotationOnNondateReading() {
835         HeaderColumnNameMappingStrategy<DateAnnotationOnNondate> strat =
836                 new HeaderColumnNameMappingStrategy<>();
837         strat.setType(DateAnnotationOnNondate.class);
838         CSVReader read = new CSVReader(new StringReader("isnotdate\n19780115T063209"));
839         CsvToBean<DateAnnotationOnNondate> ctb = new CsvToBeanBuilder<DateAnnotationOnNondate>(read)
840                 .withMappingStrategy(strat)
841                 .build();
842         try {
843             ctb.parse();
844             fail("Expected parse to throw exception.");
845         } catch (RuntimeException e) {
846             assertTrue(e.getCause() instanceof CsvDataTypeMismatchException);
847             CsvDataTypeMismatchException csve = (CsvDataTypeMismatchException) e.getCause();
848             assertEquals(2, csve.getLineNumber());
849             assertNotNull(csve.getLine());
850             assertTrue(csve.getSourceObject() instanceof String);
851             assertEquals("19780115T063209", csve.getSourceObject());
852             assertEquals(String.class, csve.getDestinationClass());
853         }
854     }
855 
856     @Test
857     public void testDateAnnotationOnNondateWriting() throws CsvException {
858         StringWriter w = new StringWriter();
859         try {
860             new StatefulBeanToCsvBuilder<DateAnnotationOnNondate>(w).build().write(new DateAnnotationOnNondate("test"));
861         }
862         catch(CsvDataTypeMismatchException csve) {
863             assertEquals(1, csve.getLineNumber());
864             assertTrue(csve.getSourceObject() instanceof DateAnnotationOnNondate);
865             assertEquals(String.class, csve.getDestinationClass());
866         }
867     }
868 
869     @Test
870     public void testMapByNameComplexTypeWrongType() throws FileNotFoundException {
871         HeaderColumnNameMappingStrategy<AnnotatedMockBeanCustom> strat =
872                 new HeaderColumnNameMappingStrategy<>();
873         strat.setType(AnnotatedMockBeanCustom.class);
874         Reader fin = new FileReader("src/test/resources/testinputcase16.csv");
875         auxiliaryTestWrongComplexType(strat, fin, 2);
876     }
877 
878     @Test
879     public void testMapByPositionComplexTypeWrongType() throws FileNotFoundException {
880         ColumnPositionMappingStrategy<AnnotatedMockBeanCustom> strat =
881                 new ColumnPositionMappingStrategy<>();
882         strat.setType(AnnotatedMockBeanCustom.class);
883         Reader fin = new FileReader("src/test/resources/testinputcase60.csv");
884         auxiliaryTestWrongComplexType(strat, fin, 1);
885     }
886 
887     private void auxiliaryTestWrongComplexType(MappingStrategy<AnnotatedMockBeanCustom> strat, Reader fin, long expectedLineNumber) {
888         CsvToBean<AnnotatedMockBeanCustom> ctb = new CsvToBeanBuilder<AnnotatedMockBeanCustom>(fin)
889                 .withMappingStrategy(strat)
890                 .withSeparator(';')
891                 .build();
892         try {
893             ctb.parse();
894             fail("Expected parse to throw exception.");
895         } catch (RuntimeException e) {
896             assertTrue(e.getCause() instanceof CsvDataTypeMismatchException);
897             CsvDataTypeMismatchException csve = (CsvDataTypeMismatchException) e.getCause();
898             assertEquals(expectedLineNumber, csve.getLineNumber());
899             assertNotNull(csve.getLine());
900             assertTrue(csve.getSourceObject() instanceof String);
901             assertEquals("Mismatched data type", csve.getSourceObject());
902             assertEquals(ComplexClassForCustomAnnotation.class, csve.getDestinationClass());
903             assertTrue(csve.getCause() instanceof IllegalArgumentException);
904         }
905     }
906 
907     private void auxiliaryTestCustomMismatch(Reader fin, MappingStrategy<AnnotatedMockBeanCustom> strat, int lineNumber) {
908         CsvToBean<AnnotatedMockBeanCustom> ctb = new CsvToBeanBuilder<AnnotatedMockBeanCustom>(fin)
909                 .withMappingStrategy(strat)
910                 .withSeparator(';')
911                 .build();
912         try {
913             ctb.parse();
914             fail("Expected parse to throw exception.");
915         } catch (RuntimeException e) {
916             assertTrue(e.getCause() instanceof CsvDataTypeMismatchException);
917             CsvDataTypeMismatchException csve = (CsvDataTypeMismatchException) e.getCause();
918             assertEquals(lineNumber, csve.getLineNumber());
919             assertNotNull(csve.getLine());
920             assertTrue(csve.getSourceObject() instanceof String);
921             assertEquals("invalidstring", csve.getSourceObject());
922             assertEquals(Boolean.class, csve.getDestinationClass());
923             assertTrue(csve.getCause() instanceof ConversionException);
924         }
925     }
926 
927     /**
928      * Tests mapping fields of a wrapped primitive destination object by
929      * {@link com.opencsv.bean.CsvCustomBindByPosition} with mismatching types.
930      *
931      * @throws FileNotFoundException Never
932      */
933     @Test
934     public void testCustomByPositionWrappedPrimitiveDataTypeMismatch() throws FileNotFoundException {
935         ColumnPositionMappingStrategy<AnnotatedMockBeanCustom> strat =
936                 new ColumnPositionMappingStrategy<>();
937         strat.setType(AnnotatedMockBeanCustom.class);
938 
939         FileReader fin = new FileReader("src/test/resources/testinputcase59.csv");
940         auxiliaryTestCustomMismatch(fin, strat, 1);
941     }
942 
943     /**
944      * Tests mapping fields of a wrapped primitive destination object by
945      * {@link com.opencsv.bean.CsvCustomBindByName} with mismatching types.
946      * <p>Also incidentally tests:
947      * <ul><li>Mapping with
948      * {@link com.opencsv.bean.customconverter.ConvertGermanToBoolean} using an
949      * invalid string</li></ul></p>
950      *
951      * @throws FileNotFoundException Never
952      */
953     @Test
954     public void testCustomByNameWrappedPrimitiveDataTypeMismatch() throws FileNotFoundException {
955         HeaderColumnNameMappingStrategy<AnnotatedMockBeanCustom> strat =
956                 new HeaderColumnNameMappingStrategy<>();
957         strat.setType(AnnotatedMockBeanCustom.class);
958 
959         FileReader fin = new FileReader("src/test/resources/testinputcase38.csv");
960         auxiliaryTestCustomMismatch(fin, strat, 2);
961     }
962 
963     @Test
964     public void testBadConverter() {
965         HeaderColumnNameMappingStrategy<TestCase80> strath =
966                 new HeaderColumnNameMappingStrategy<>();
967         try {
968             strath.setType(TestCase80.class);
969             fail("HeaderColumnNameMappingStrategy.setType() should have thrown an Exception.");
970         } catch (CsvBadConverterException e) {
971             assertEquals(BadIntConverter.class, e.getConverterClass());
972         }
973 
974         ColumnPositionMappingStrategy<TestCase80> stratc =
975                 new ColumnPositionMappingStrategy<>();
976         try {
977             stratc.setType(TestCase80.class);
978             fail("The parse should have thrown an Exception.");
979         } catch (CsvBadConverterException e) {
980             assertEquals(BadIntConverter.class, e.getConverterClass());
981         }
982     }
983 
984     @Test
985     public void testRequiredColumnNonexistentHeaderNameMapping() throws FileNotFoundException {
986         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
987                 new HeaderColumnNameMappingStrategy<>();
988         strat.setType(AnnotatedMockBeanFull.class);
989         FileReader fin = new FileReader("src/test/resources/testinputcase84.csv");
990         CsvToBean<AnnotatedMockBeanFull> ctb = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
991                 .withSeparator(';')
992                 .withMappingStrategy(strat)
993                 .build();
994         try {
995             ctb.parse();
996             fail("RuntimeException with inner exception CsvRequiredFieldEmpty should have been thrown because a required column is completely missing.");
997         }
998         catch(RuntimeException e) {
999             assertTrue(e.getCause() instanceof CsvRequiredFieldEmptyException);
1000             CsvRequiredFieldEmptyException csve = (CsvRequiredFieldEmptyException)e.getCause();
1001             assertEquals(AnnotatedMockBeanFull.class, csve.getBeanClass());
1002             assertEquals(-1, csve.getLineNumber());
1003             assertNotNull(csve.getLine());
1004             assertEquals("byteWrappedSetLocale", csve.getDestinationField().getName());
1005         }
1006     }
1007 
1008     private void auxiliaryTestColumnMissing(final Reader fin, final MappingStrategy<AnnotatedMockBeanFull> strat) {
1009         CsvToBean<AnnotatedMockBeanFull> ctb = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
1010                 .withSeparator(';')
1011                 .withMappingStrategy(strat)
1012                 .build();
1013         try {
1014             ctb.parse();
1015             fail("RuntimeException with inner exception CsvRequiredFieldEmpty should have been thrown because a required column is completely missing.");
1016         }
1017         catch(RuntimeException e) {
1018             assertTrue(e.getCause() instanceof CsvRequiredFieldEmptyException);
1019             CsvRequiredFieldEmptyException csve = (CsvRequiredFieldEmptyException)e.getCause();
1020             assertEquals(AnnotatedMockBeanFull.class, csve.getBeanClass());
1021             assertEquals(2, csve.getLineNumber());
1022             assertNotNull(csve.getLine());
1023             assertNull(csve.getDestinationField());
1024         }
1025     }
1026 
1027     @Test
1028     public void testRequiredColumnNonexistentColumnPositionMapping() throws FileNotFoundException {
1029         ColumnPositionMappingStrategy<AnnotatedMockBeanFull> strat =
1030                 new ColumnPositionMappingStrategy<>();
1031         strat.setType(AnnotatedMockBeanFull.class);
1032         FileReader fin = new FileReader("src/test/resources/testinputcase85.csv");
1033         auxiliaryTestColumnMissing(fin, strat);
1034     }
1035 
1036     @Test
1037     public void testPrematureEOLUsingHeaderNameMapping() throws FileNotFoundException {
1038         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
1039                 new HeaderColumnNameMappingStrategy<>();
1040         strat.setType(AnnotatedMockBeanFull.class);
1041         FileReader fin = new FileReader("src/test/resources/testinputcase86.csv");
1042         auxiliaryTestColumnMissing(fin, strat);
1043     }
1044     
1045     @Test
1046     public void testCustomConverterRequiredEmptyInput() throws FileNotFoundException {
1047         HeaderColumnNameMappingStrategy<AnnotatedMockBeanCustom> strat =
1048                 new HeaderColumnNameMappingStrategy<>();
1049         strat.setType(AnnotatedMockBeanCustom.class);
1050         FileReader fin = new FileReader("src/test/resources/testinputcase88.csv");
1051         CsvToBean<AnnotatedMockBeanCustom> ctb = new CsvToBeanBuilder<AnnotatedMockBeanCustom>(fin)
1052                 .withSeparator(';')
1053                 .withMappingStrategy(strat)
1054                 .build();
1055         try {
1056             ctb.parse();
1057             fail("Exception should have been thrown for missing required value.");
1058         }
1059         catch(RuntimeException e) {
1060             assertTrue(e.getCause() instanceof CsvRequiredFieldEmptyException);
1061             CsvRequiredFieldEmptyException csve = (CsvRequiredFieldEmptyException)e.getCause();
1062             assertEquals(AnnotatedMockBeanCustom.class, csve.getBeanClass());
1063             assertEquals(2, csve.getLineNumber());
1064             assertNotNull(csve.getLine());
1065             assertEquals("requiredWithCustom", csve.getDestinationField().getName());
1066         }
1067     }
1068     
1069     @Test
1070     public void testSetterThrowsException() {
1071         try {
1072             new CsvToBeanBuilder<>(new StringReader("map\nstring"))
1073                     .withType(SetterThrowsException.class).build().parse();
1074             fail("Exception should have been thrown");
1075         }
1076         catch(RuntimeException e) {
1077             assertNotNull(e.getCause());
1078             assertTrue(e.getCause() instanceof CsvBeanIntrospectionException);
1079             CsvBeanIntrospectionException csve = (CsvBeanIntrospectionException)e.getCause();
1080             assertEquals("map", csve.getField().getName());
1081         }
1082     }
1083 
1084     @Test
1085     public void testCaptureByNameInvalidRegex() {
1086         try {
1087             MappingStrategy<InvalidCapture> strat = new HeaderColumnNameMappingStrategy<>();
1088             strat.setType(InvalidCapture.class);
1089             fail("Exception should have been thrown.");
1090         }
1091         catch(CsvBadConverterException csve) {
1092             assertEquals(BeanFieldSingleValue.class, csve.getConverterClass());
1093             assertNotNull(csve.getCause());
1094         }
1095     }
1096 
1097     @Test
1098     public void testCaptureByPositionInvalidRegex() {
1099         try {
1100             MappingStrategy<InvalidCapture> strat = new ColumnPositionMappingStrategy<>();
1101             strat.setType(InvalidCapture.class);
1102             fail("Exception should have been thrown.");
1103         }
1104         catch(CsvBadConverterException csve) {
1105             assertEquals(BeanFieldSingleValue.class, csve.getConverterClass());
1106             assertNotNull(csve.getCause());
1107         }
1108     }
1109 
1110     @Test
1111     public void testCaptureByNameRegexWithoutCaptureGroup() {
1112         try {
1113             MappingStrategy<NoCaptureGroup> strat = new HeaderColumnNameMappingStrategy<>();
1114             strat.setType(NoCaptureGroup.class);
1115             fail("Exception should have been thrown.");
1116         }
1117         catch(CsvBadConverterException csve) {
1118             assertEquals(BeanFieldSingleValue.class, csve.getConverterClass());
1119             assertNull(csve.getCause());
1120         }
1121     }
1122 
1123     @Test
1124     public void testCaptureByPositionRegexWithoutCaptureGroup() {
1125         try {
1126             MappingStrategy<NoCaptureGroup> strat = new ColumnPositionMappingStrategy<>();
1127             strat.setType(NoCaptureGroup.class);
1128             fail("Exception should have been thrown.");
1129         }
1130         catch(CsvBadConverterException csve) {
1131             assertEquals(BeanFieldSingleValue.class, csve.getConverterClass());
1132             assertNull(csve.getCause());
1133         }
1134     }
1135 
1136     @Test
1137     public void testFormatByNameWriteInvalidFormatString() {
1138         try {
1139             MappingStrategy<InvalidFormatString> strat = new HeaderColumnNameMappingStrategy<>();
1140             strat.setType(InvalidFormatString.class);
1141             fail("Exception should have been thrown.");
1142         }
1143         catch(CsvBadConverterException csve) {
1144             assertEquals(BeanFieldSingleValue.class, csve.getConverterClass());
1145             assertNotNull(csve.getCause());
1146         }
1147     }
1148 
1149     @Test
1150     public void testFormatByPositionWriteInvalidFormatString() {
1151         try {
1152             MappingStrategy<InvalidFormatString> strat = new ColumnPositionMappingStrategy<>();
1153             strat.setType(InvalidFormatString.class);
1154             fail("Exception should have been thrown.");
1155         }
1156         catch(CsvBadConverterException csve) {
1157             assertEquals(BeanFieldSingleValue.class, csve.getConverterClass());
1158             assertNotNull(csve.getCause());
1159         }
1160     }
1161 
1162     @Test
1163     public void testWriteFormatWithHeaderNames() throws CsvException {
1164         MappingStrategy<WriteLocale> ms = new HeaderColumnNameMappingStrategy<>();
1165         ms.setType(WriteLocale.class);
1166         WriteLocale bean = new CsvToBeanBuilder<WriteLocale>(new StringReader(
1167                 "primitivePlain;numberPlain;datePlain;primitiveSplit;numberSplit;dateSplit;primitiveJoinName;primitiveJoinName;numberJoinName;numberJoinName;dateJoinName;dateJoinName;redHerring\n" +
1168                         "123.404,404;123.505,505;01/August/2019;234.505,505 234.606,606;234.707,707 234.808,808;01/Juni/2019 01/Juli/2019;345.606,606;345.707,707;345.808,808;345.909,909;01/Juli/2019;01/August/2019;456.707,707\n"))
1169                 .withSeparator(';')
1170                 .withMappingStrategy(ms)
1171                 .withType(WriteLocale.class)
1172                 .build().parse().get(0);
1173         StringWriter w = new StringWriter();
1174         new StatefulBeanToCsvBuilder<WriteLocale>(w)
1175                 .withMappingStrategy(ms)
1176                 .withApplyQuotesToAll(false)
1177                 .withSeparator(';')
1178                 .build().write(bean);
1179         // The first string is for Java < 13. The second string is for Java >= 13.
1180         assertTrue(w.toString().equals("primitivePlain;numberPlain;datePlain;primitiveSplit;numberSplit;dateSplit;primitiveJoinName;primitiveJoinName;numberJoinName;numberJoinName;dateJoinName;dateJoinName;redHerring\n" +
1181                 "123\u00A0404,404;123\u00A0505,505;01/août/2019;234\u00A0505,505 234\u00A0606,606;234\u00A0707,707 234\u00A0808,808;01/juin/2019 01/juil./2019;345\u00A0606,606;345\u00A0707,707;345\u00A0808,808;345\u00A0909,909;01/juil./2019;01/août/2019;456.707,707\n")
1182                 || w.toString().equals("primitivePlain;numberPlain;datePlain;primitiveSplit;numberSplit;dateSplit;primitiveJoinName;primitiveJoinName;numberJoinName;numberJoinName;dateJoinName;dateJoinName;redHerring\n" +
1183                 "123\u202F404,404;123505,505\u00A0;01/août/2019;234\u202F505,505 234\u202F606,606;234707,707\u00A0 234808,808\u00A0;01/juin/2019 01/juil./2019;345\u202F606,606;345\u202F707,707;345808,808\u00A0;345909,909\u00A0;01/juil./2019;01/août/2019;456.707,707\n"));
1184     }
1185 
1186     @Test
1187     public void testWriteFormatWithColumnPositions() throws CsvException {
1188         WriteLocale bean = new CsvToBeanBuilder<WriteLocale>(new StringReader(
1189                 "123.404,404;123.505,505;01/August/2019;234.505,505 234.606,606;234.707,707 234.808,808;01/Juni/2019 01/Juli/2019;345.606,606;345.707,707;345.808,808;345.909,909;01/Juli/2019;01/August/2019;456.707,707\n"))
1190                 .withSeparator(';')
1191                 .withType(WriteLocale.class)
1192                 .build().parse().get(0);
1193         StringWriter w = new StringWriter();
1194         new StatefulBeanToCsvBuilder<WriteLocale>(w)
1195                 .withApplyQuotesToAll(false)
1196                 .withSeparator(';')
1197                 .build().write(bean);
1198 
1199         // The first string is for Java < 13. The second string is for Java >= 13.
1200         assertTrue(w.toString().equals("123\u00A0404,404;123\u00A0505,505;01/août/2019;234\u00A0505,505 234\u00A0606,606;234\u00A0707,707 234\u00A0808,808;01/juin/2019 01/juil./2019;345\u00A0606,606;345\u00A0707,707;345\u00A0808,808;345\u00A0909,909;01/juil./2019;01/août/2019;456.707,707\n")
1201                 || w.toString().equals("123\u202F404,404;123505,505\u00A0;01/août/2019;234\u202F505,505 234\u202F606,606;234707,707\u00A0 234808,808\u00A0;01/juin/2019 01/juil./2019;345\u202F606,606;345\u202f707,707;345808,808\u00A0;345909,909\u00A0;01/juil./2019;01/août/2019;456.707,707\n"));
1202     }
1203 
1204     @Test
1205     public void testIllegalEnumValue() throws IOException {
1206         try {
1207             new CsvToBeanBuilder<AnnotatedMockBeanFull>(new FileReader("src/test/resources/testIllegalEnumValue.csv"))
1208                     .withType(AnnotatedMockBeanFull.class)
1209                     .withSeparator(';')
1210                     .build().parse();
1211         }
1212         catch (RuntimeException e) {
1213             assertTrue(e.getCause() instanceof CsvDataTypeMismatchException);
1214             CsvDataTypeMismatchException csve = (CsvDataTypeMismatchException) e.getCause();
1215             assertEquals(TestEnum.class, csve.getDestinationClass());
1216             assertEquals("bogusEnumValue", csve.getSourceObject());
1217             assertEquals(1L, csve.getLineNumber());
1218             assertFalse(StringUtils.isEmpty(csve.getMessage()));
1219         }
1220     }
1221 
1222     @Test
1223     public void testIllegalCurrency() throws IOException {
1224         try {
1225             new CsvToBeanBuilder<AnnotatedMockBeanFull>(new FileReader("src/test/resources/testIllegalCurrency.csv"))
1226                     .withType(AnnotatedMockBeanFull.class)
1227                     .withSeparator(';')
1228                     .build().parse();
1229         }
1230         catch (RuntimeException e) {
1231             assertTrue(e.getCause() instanceof CsvDataTypeMismatchException);
1232             CsvDataTypeMismatchException csve = (CsvDataTypeMismatchException) e.getCause();
1233             assertEquals(Currency.class, csve.getDestinationClass());
1234             assertEquals("illegalCurrency", csve.getSourceObject());
1235             assertEquals(1L, csve.getLineNumber());
1236             assertFalse(StringUtils.isEmpty(csve.getMessage()));
1237         }
1238     }
1239 
1240     /**
1241      * Checks that columns are padded or lopped off if checking is turned off.
1242      *
1243      * @throws FileNotFoundException Never
1244      */
1245     @Test
1246     public void testWrongNumberOfColumnsAllowedByName() throws FileNotFoundException {
1247         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat =
1248                 new HeaderColumnNameMappingStrategyBuilder<AnnotatedMockBeanFull>()
1249                         .withForceCorrectRecordLength(true)
1250                         .withType(AnnotatedMockBeanFull.class)
1251                         .build();
1252         FileReader fin = new FileReader("src/test/resources/testinputfullwrongcolumnnumber.csv");
1253         List<AnnotatedMockBeanFull> beanList = new CsvToBeanBuilder<AnnotatedMockBeanFull>(fin)
1254                 .withSeparator(';')
1255                 .withOrderedResults(true)
1256                 .withMappingStrategy(strat)
1257                 .build().parse();
1258         assertEquals(4, beanList.size());
1259         assertEquals(TestEnum.TEST1, beanList.get(0).getTestEnum());
1260         assertEquals(Currency.getInstance("EUR"), beanList.get(0).getTestCurrency());
1261         assertEquals(TestEnum.TEST1, beanList.get(2).getTestEnum());
1262         assertEquals(Currency.getInstance("EUR"), beanList.get(2).getTestCurrency());
1263         assertNull(beanList.get(1).getTestEnum());
1264         assertNull(beanList.get(1).getTestCurrency());
1265         assertNull(beanList.get(3).getTestEnum());
1266         assertNull(beanList.get(3).getTestCurrency());
1267     }
1268 }