View Javadoc
1   package com.opencsv.bean;
2   
3   import com.opencsv.bean.mocks.ignore.*;
4   import com.opencsv.exceptions.CsvDataTypeMismatchException;
5   import com.opencsv.exceptions.CsvException;
6   import com.opencsv.exceptions.CsvRequiredFieldEmptyException;
7   import org.apache.commons.collections4.ListValuedMap;
8   import org.apache.commons.collections4.MultiValuedMap;
9   import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
10  import org.apache.commons.lang3.StringUtils;
11  import org.junit.jupiter.api.Test;
12  
13  import java.io.StringReader;
14  import java.io.StringWriter;
15  import java.lang.reflect.Field;
16  import java.util.ArrayList;
17  import java.util.Arrays;
18  import java.util.List;
19  
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  public class IgnoreTest {
23  
24      /**
25       * Tests that the field "serialVersionUID" <em>is</em> written if the bean
26       * does not implement {@link java.io.Serializable}.
27       * <p>Also incidentally tests that beans that opencsv cannot instantiate
28       * can still be written. Yeah, I actually broke that once.</p>
29       * @throws CsvException Never
30       */
31      @Test
32      public void testSerialVersionUIDNonSerializable() throws CsvException {
33          NonSerial bean = new NonSerial(2, "3");
34          StringWriter w = new StringWriter();
35          StatefulBeanToCsv<NonSerial> btcsv = new StatefulBeanToCsvBuilder<NonSerial>(w)
36                  .withApplyQuotesToAll(false)
37                  .build();
38          btcsv.write(bean);
39          assertEquals("SERIALVERSIONUID,TESTINT,TESTSTRING\n1,2,3\n", w.toString());
40      }
41  
42      @Test
43      public void testSerialVersionUIDSerializable() throws CsvException {
44          Serial bean = new Serial(3, "4");
45          StringWriter w = new StringWriter();
46          StatefulBeanToCsv<Serial> btcsv = new StatefulBeanToCsvBuilder<Serial>(w)
47                  .withApplyQuotesToAll(false)
48                  .build();
49          btcsv.write(bean);
50          assertEquals("TESTINT,TESTSTRING\n3,4\n", w.toString());
51      }
52  
53      @Test
54      public void testInvalidInputForIgnore() throws NoSuchFieldException {
55          // Data we need for the tests
56          MultiValuedMap<Class<?>, Field> nullClass = new ArrayListValuedHashMap<>();
57          nullClass.put(null, IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored"));
58          MultiValuedMap<Class<?>, Field> nullField = new ArrayListValuedHashMap<>();
59          nullField.put(IgnoreMock.class, null);
60          MultiValuedMap<Class<?>, Field> classFieldMismatched = new ArrayListValuedHashMap<>();
61          classFieldMismatched.put(
62                  NonSerial.class,
63                  IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored"));
64  
65          // Test with all currently known mapping strategies
66          for(MappingStrategy<IgnoreMock> strategy : Arrays.asList(
67                  new HeaderColumnNameMappingStrategy<IgnoreMock>(),
68                  new ColumnPositionMappingStrategy<IgnoreMock>(),
69                  new HeaderColumnNameTranslateMappingStrategy<IgnoreMock>(),
70                  new FuzzyMappingStrategy<IgnoreMock>())) {
71              strategy.setType(IgnoreMock.class);
72  
73              // Null class
74              IllegalArgumentException e = assertThrows(
75                      IllegalArgumentException.class,
76                      () -> strategy.ignoreFields(nullClass));
77              assertNotNull(e.getMessage());
78  
79              // Null field
80              e = assertThrows(
81                      IllegalArgumentException.class,
82                      () -> strategy.ignoreFields(nullField));
83              assertNotNull(e.getMessage());
84  
85              // Field does not match class
86              e = assertThrows(
87                      IllegalArgumentException.class,
88                      () -> strategy.ignoreFields(classFieldMismatched));
89              assertNotNull(e.getMessage());
90          }
91      }
92  
93      @Test
94      public void testInvalidInputToBuilderForIgnoreOnReading() {
95          CsvToBeanBuilder<IgnoreMock> builder = new CsvToBeanBuilder<>(new StringReader(StringUtils.EMPTY));
96  
97          // Null class
98          IllegalArgumentException e = assertThrows(
99                  IllegalArgumentException.class,
100                 () -> builder.withIgnoreField(null, IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored")));
101         assertNotNull(e.getMessage());
102 
103         // Null field
104         e = assertThrows(
105                 IllegalArgumentException.class,
106                 () -> builder.withIgnoreField(IgnoreMock.class, null));
107         assertNotNull(e.getMessage());
108 
109         // Field does not match class
110         e = assertThrows(
111                 IllegalArgumentException.class,
112                 () -> builder.withIgnoreField(
113                         NonSerial.class,
114                         IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored")));
115         assertNotNull(e.getMessage());
116     }
117 
118     @Test
119     public void testInvalidInputToBuilderForIgnoreOnWriting() {
120         StringWriter w = new StringWriter();
121         StatefulBeanToCsvBuilder<IgnoreMock> builder = new StatefulBeanToCsvBuilder<>(w);
122 
123         // Null class
124         IllegalArgumentException e = assertThrows(
125                 IllegalArgumentException.class,
126                 () -> builder.withIgnoreField(null, IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored")));
127         assertNotNull(e.getMessage());
128 
129         // Null field
130         e = assertThrows(
131                 IllegalArgumentException.class,
132                 () -> builder.withIgnoreField(IgnoreMock.class, null));
133         assertNotNull(e.getMessage());
134 
135         // Field does not match class
136         e = assertThrows(
137                 IllegalArgumentException.class,
138                 () -> builder.withIgnoreField(
139                         NonSerial.class,
140                         IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored")));
141         assertNotNull(e.getMessage());
142     }
143 
144     /**
145      * Tests ignoring fields using {@link CsvIgnore} and a header name mapping
146      * strategy on reading.
147      * <p>Also incidentally tests:<ul>
148      *     <li>Ignoring with {@link CsvIgnore} combined with all forms of
149      *     header binding annotations</li>
150      * </ul></p>
151      */
152     @Test
153     public void testIgnoreWithAnnotationAndHeaderNameMappingOnReading() {
154         final MappingStrategy<IgnoreMock> strategy = new HeaderColumnNameMappingStrategy<>();
155         strategy.setType(IgnoreMock.class);
156         final String input = "bindingPrimitiveNotIgnored,bindingSplitNotIgnored,bindingJoinByNameNotIgnored,bindingJoinByNameNotIgnored,bindingPrimitiveIgnored,bindingSplitIgnored,bindingJoinByNameIgnored,bindingJoinByNameIgnored\n" +
157                 "1,2 3,4,5,6,7 8,9,10\n";
158         final CsvToBean<IgnoreMock> csvToBean = new CsvToBeanBuilder<IgnoreMock>(new StringReader(input))
159                 .withMappingStrategy(strategy)
160                 .build();
161         List<IgnoreMock> beans = csvToBean.parse();
162         List<CsvException> exceptions = csvToBean.getCapturedExceptions();
163         assertNotNull(exceptions);
164         assertTrue(exceptions.isEmpty());
165         assertNotNull(beans);
166         assertEquals(1, beans.size());
167 
168         // Test field values
169         IgnoreMock bean = beans.get(0);
170         assertEquals(1, bean.getBindingPrimitiveNotIgnored());
171         assertEquals(Arrays.asList(2, 3), bean.getBindingSplitNotIgnored());
172         assertEquals(Arrays.asList(4, 5), new ArrayList<>(bean.getBindingJoinByNameNotIgnored().values()));
173         assertEquals(0, bean.getBindingPrimitiveIgnored());
174         assertNull(bean.getBindingSplitIgnored());
175         assertNull(bean.getBindingJoinByNameIgnored());
176     }
177 
178     /**
179      * Tests ignoring fields using {@link CsvIgnore} and a column position
180      * mapping strategy on reading.
181      * <p>Also incidentally tests:<ul>
182      *     <li>Ignoring with {@link CsvIgnore} combined with all forms of
183      *     position binding annotations</li>
184      * </ul></p>
185      */
186     @Test
187     public void testIgnoreWithAnnotationAndColumnPositionMappingOnReading() {
188         final String input = "1,2 3,4,5,6,7 8,9,10\n";
189         final CsvToBean<IgnoreMock> csvToBean = new CsvToBeanBuilder<IgnoreMock>(new StringReader(input))
190                 .withType(IgnoreMock.class)
191                 .build();
192         List<IgnoreMock> beans = csvToBean.parse();
193         List<CsvException> exceptions = csvToBean.getCapturedExceptions();
194         assertNotNull(exceptions);
195         assertTrue(exceptions.isEmpty());
196         assertNotNull(beans);
197         assertEquals(1, beans.size());
198 
199         // Test field values
200         IgnoreMock bean = beans.get(0);
201         assertEquals(1, bean.getBindingPrimitiveNotIgnored());
202         assertEquals(Arrays.asList(2, 3), bean.getBindingSplitNotIgnored());
203         assertEquals(Arrays.asList(4, 5), new ArrayList<>(bean.getBindingJoinByPositionNotIgnored().values()));
204         assertEquals(0, bean.getBindingPrimitiveIgnored());
205         assertNull(bean.getBindingSplitIgnored());
206         assertNull(bean.getBindingJoinByPositionIgnored());
207     }
208 
209     /**
210      * Ignores a field using
211      * {@link CsvToBeanBuilder#withIgnoreField(Class, Field)} and a header name
212      * mapping strategy on reading.
213      * <p>Also incidentally tests:<ul>
214      *     <li>Ignoring the same field with {@link CsvIgnore} and
215      *     {@link CsvToBeanBuilder#withIgnoreField(Class, Field)}</li>
216      * </ul></p>
217      * @throws NoSuchFieldException Never
218      */
219     @Test
220     public void testIgnoreWithMethodAndHeaderNameMappingOnReading() throws NoSuchFieldException {
221         final MappingStrategy<IgnoreMock> strategy = new HeaderColumnNameMappingStrategy<>();
222         strategy.setType(IgnoreMock.class);
223         final String input = "bindingPrimitiveNotIgnored,bindingSplitNotIgnored,bindingJoinByNameNotIgnored,bindingJoinByNameNotIgnored,bindingPrimitiveIgnored,bindingSplitIgnored,bindingJoinByNameIgnored,bindingJoinByNameIgnored\n" +
224                 "1,2 3,4,5,6,7 8,9,10\n";
225         final CsvToBean<IgnoreMock> csvToBean = new CsvToBeanBuilder<IgnoreMock>(new StringReader(input))
226                 .withMappingStrategy(strategy)
227                 .withIgnoreField(IgnoreMock.class, IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored"))
228                 .withIgnoreField(IgnoreMock.class, IgnoreMock.class.getDeclaredField("bindingPrimitiveIgnored"))
229                 .build();
230         List<IgnoreMock> beans = csvToBean.parse();
231         List<CsvException> exceptions = csvToBean.getCapturedExceptions();
232         assertNotNull(exceptions);
233         assertTrue(exceptions.isEmpty());
234         assertNotNull(beans);
235         assertEquals(1, beans.size());
236 
237         // Test field values
238         IgnoreMock bean = beans.get(0);
239         assertEquals(0, bean.getBindingPrimitiveNotIgnored());
240         assertEquals(Arrays.asList(2, 3), bean.getBindingSplitNotIgnored());
241         assertEquals(Arrays.asList(4, 5), new ArrayList<>(bean.getBindingJoinByNameNotIgnored().values()));
242         assertEquals(0, bean.getBindingPrimitiveIgnored());
243         assertNull(bean.getBindingSplitIgnored());
244         assertNull(bean.getBindingJoinByNameIgnored());
245     }
246 
247     /**
248      * Ignores a field using
249      * {@link CsvToBeanBuilder#withIgnoreField(Class, Field)} and a column
250      * position mapping strategy on reading.
251      * <p>Also incidentally tests:<ul>
252      *     <li>Ignoring the same field twice</li>
253      * </ul></p>
254      * @throws NoSuchFieldException Never
255      */
256     @Test
257     public void testIgnoreWithMethodAndColumnPositionMappingOnReading() throws NoSuchFieldException {
258         final String input = "1,2 3,4,5,6,7 8,9,10\n";
259         final CsvToBean<IgnoreMock> csvToBean = new CsvToBeanBuilder<IgnoreMock>(new StringReader(input))
260                 .withType(IgnoreMock.class)
261                 .withIgnoreField(IgnoreMock.class, IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored"))
262                 .withIgnoreField(IgnoreMock.class, IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored"))
263                 .build();
264         List<IgnoreMock> beans = csvToBean.parse();
265         List<CsvException> exceptions = csvToBean.getCapturedExceptions();
266         assertNotNull(exceptions);
267         assertTrue(exceptions.isEmpty());
268         assertNotNull(beans);
269         assertEquals(1, beans.size());
270 
271         // Test field values
272         IgnoreMock bean = beans.get(0);
273         assertEquals(0, bean.getBindingPrimitiveNotIgnored());
274         assertEquals(Arrays.asList(2, 3), bean.getBindingSplitNotIgnored());
275         assertEquals(Arrays.asList(4, 5), new ArrayList<>(bean.getBindingJoinByPositionNotIgnored().values()));
276         assertEquals(0, bean.getBindingPrimitiveIgnored());
277         assertNull(bean.getBindingSplitIgnored());
278         assertNull(bean.getBindingJoinByPositionIgnored());
279     }
280 
281     /**
282      * Ignores fields on reading with all known header name bindings.
283      * <p>Also incidentally tests:<ul>
284      *     <li>Calling {@link MappingStrategy#setType(Class)} after calling
285      *     {@link MappingStrategy#ignoreFields(MultiValuedMap)}</li>
286      * </ul></p>
287      * @throws NoSuchFieldException Never
288      */
289     @Test
290     public void testIgnoreAllWithHeaderNameMappingOnReading() throws NoSuchFieldException {
291         final MappingStrategy<IgnoreMock> strategy = new HeaderColumnNameMappingStrategy<>();
292         ListValuedMap<Class<?>, Field> ignoredFields = new ArrayListValuedHashMap<>();
293         ignoredFields.put(IgnoreMock.class, IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored"));
294         ignoredFields.put(IgnoreMock.class, IgnoreMock.class.getDeclaredField("bindingSplitNotIgnored"));
295         ignoredFields.put(IgnoreMock.class, IgnoreMock.class.getDeclaredField("bindingJoinByNameNotIgnored"));
296         strategy.ignoreFields(ignoredFields);
297         strategy.setType(IgnoreMock.class);
298         final String input = "bindingPrimitiveNotIgnored,bindingSplitNotIgnored,bindingJoinByNameNotIgnored,bindingJoinByNameNotIgnored,bindingPrimitiveIgnored,bindingSplitIgnored,bindingJoinByNameIgnored,bindingJoinByNameIgnored\n" +
299                 "1,2 3,4,5,6,7 8,9,10\n";
300         final CsvToBean<IgnoreMock> csvToBean = new CsvToBeanBuilder<IgnoreMock>(new StringReader(input))
301                 .withMappingStrategy(strategy)
302                 .build();
303         List<IgnoreMock> beans = csvToBean.parse();
304         List<CsvException> exceptions = csvToBean.getCapturedExceptions();
305         assertNotNull(exceptions);
306         assertTrue(exceptions.isEmpty());
307         assertNotNull(beans);
308         assertEquals(1, beans.size());
309 
310         // Test field values
311         IgnoreMock bean = beans.get(0);
312         assertEquals(0, bean.getBindingPrimitiveNotIgnored());
313         assertNull(bean.getBindingSplitNotIgnored());
314         assertNull(bean.getBindingJoinByNameNotIgnored());
315         assertEquals(0, bean.getBindingPrimitiveIgnored());
316         assertNull(bean.getBindingSplitIgnored());
317         assertNull(bean.getBindingJoinByNameIgnored());
318     }
319 
320     /**
321      * Ignores fields on reading with all known column position bindings.
322      * <p>Also incidentally tests:<ul>
323      *     <li>Ignoring all fields with binding annotations for a preferred
324      *     mapping strategy during automatic selection does not change the
325      *     selected mapping strategy.</li>
326      *     <li>Ignoring a class/field combination not in use during mapping</li>
327      * </ul></p>
328      * @throws NoSuchFieldException Never
329      */
330     @Test
331     public void testIgnoreAllWithColumnPositionMappingOnReading() throws NoSuchFieldException {
332         final String input = "1,2 3,4,5,6,7 8,9,10\n";
333         final CsvToBean<IgnoreMock> csvToBean = new CsvToBeanBuilder<IgnoreMock>(new StringReader(input))
334                 .withType(IgnoreMock.class)
335                 .withIgnoreField(IgnoreMock.class, IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored"))
336                 .withIgnoreField(IgnoreMock.class, IgnoreMock.class.getDeclaredField("bindingSplitNotIgnored"))
337                 .withIgnoreField(IgnoreMock.class, IgnoreMock.class.getDeclaredField("bindingJoinByPositionNotIgnored"))
338                 .withIgnoreField(IgnoreRecursionMock.class, IgnoreRecursionMock.class.getDeclaredField("topLevelInteger"))
339                 .build();
340         List<IgnoreMock> beans = csvToBean.parse();
341         List<CsvException> exceptions = csvToBean.getCapturedExceptions();
342         assertNotNull(exceptions);
343         assertTrue(exceptions.isEmpty());
344         assertNotNull(beans);
345         assertEquals(1, beans.size());
346 
347         // Test field values
348         IgnoreMock bean = beans.get(0);
349         assertEquals(0, bean.getBindingPrimitiveNotIgnored());
350         assertNull(bean.getBindingSplitNotIgnored());
351         assertNull(bean.getBindingJoinByPositionNotIgnored());
352         assertEquals(0, bean.getBindingPrimitiveIgnored());
353         assertNull(bean.getBindingSplitIgnored());
354         assertNull(bean.getBindingJoinByPositionIgnored());
355     }
356 
357     @Test
358     public void testIgnoreWithRecursion() {
359         final String input = "bindingPrimitiveNotIgnored,bindingSplitNotIgnored,bindingJoinByNameNotIgnored,bindingJoinByNameNotIgnored,bindingPrimitiveIgnored,bindingSplitIgnored,bindingJoinByNameIgnored,bindingJoinByNameIgnored,topLevelInteger\n" +
360                 "1,2 3,4,5,6,7 8,9,10,11\n";
361         final CsvToBean<IgnoreRecursionMock> csvToBean = new CsvToBeanBuilder<IgnoreRecursionMock>(new StringReader(input))
362                 .withType(IgnoreRecursionMock.class)
363                 .build();
364         List<IgnoreRecursionMock> beans = csvToBean.parse();
365         List<CsvException> exceptions = csvToBean.getCapturedExceptions();
366         assertNotNull(exceptions);
367         assertTrue(exceptions.isEmpty());
368         assertNotNull(beans);
369         assertEquals(1, beans.size());
370 
371         // Test field values
372         IgnoreRecursionMock bean = beans.get(0);
373         assertEquals(11, bean.getTopLevelInteger());
374         assertNull(bean.getIgnoredRecursiveMember());
375     }
376 
377     /**
378      * Tests that ignoring fields forces a remapping, which can change
379      * bindings.
380      * <p>Also incidentally tests:<ul>
381      *     <li>Calling {@link MappingStrategy#setType(Class)} before
382      *     {@link MappingStrategy#ignoreFields(MultiValuedMap)}</li>
383      * </ul></p>
384      * @throws NoSuchFieldException Never
385      */
386     @Test
387     public void testRemappingOnIgnore() throws NoSuchFieldException {
388         String input = "int1,int2\n1,2\n";
389 
390         // First we try without ignoring anything to establish that the fuzzy
391         // mapping maps as we expect.
392         MappingStrategy<IgnoreFuzzyMock> strategy = new FuzzyMappingStrategy<>();
393         strategy.setType(IgnoreFuzzyMock.class);
394         CsvToBean<IgnoreFuzzyMock> csvToBean = new CsvToBeanBuilder<IgnoreFuzzyMock>(new StringReader(input))
395                 .withMappingStrategy(strategy)
396                 .build();
397         List<IgnoreFuzzyMock> beans = csvToBean.parse();
398         assertNotNull(beans);
399         assertEquals(1, beans.size());
400 
401         // Test individual values
402         IgnoreFuzzyMock bean = beans.get(0);
403         assertEquals(1, bean.getInt1());
404         assertEquals(2, bean.getInt2());
405         assertEquals(0, bean.getInt3());
406 
407         // Now the same thing, this time ignoring one of the fields
408         ListValuedMap<Class<?>, Field> ignoredFields = new ArrayListValuedHashMap<>();
409         ignoredFields.put(IgnoreFuzzyMock.class, IgnoreFuzzyMock.class.getDeclaredField("int1"));
410         strategy.ignoreFields(ignoredFields);
411         csvToBean = new CsvToBeanBuilder<IgnoreFuzzyMock>(new StringReader(input))
412                 .withMappingStrategy(strategy)
413                 .build();
414         beans = csvToBean.parse();
415         assertNotNull(beans);
416         assertEquals(1, beans.size());
417 
418         // Test individual values
419         bean = beans.get(0);
420         assertEquals(0, bean.getInt1());
421         assertEquals(2, bean.getInt2());
422         assertEquals(1, bean.getInt3());
423     }
424 
425     /**
426      * Tests that the mechanisms for ignoring fields also work while writing.
427      * Since the mechanism is basically decoupled from the question of reading
428      * or writing, we take a small leap of faith and say that if all of the
429      * reading tests in this class pass, all we need is one writing test to
430      * demonstrate convincingly that all combinations tested with reading also
431      * work with writing.
432      */
433     @Test
434     public void testIgnoreOnWriting() throws CsvDataTypeMismatchException, CsvRequiredFieldEmptyException, NoSuchFieldException {
435         // Prepare bean
436         IgnoreMock bean = new IgnoreMock();
437         ListValuedMap<String, Integer> stringMap = new ArrayListValuedHashMap<>();
438         stringMap.put("bindingJoinByNameIgnored", 1);
439         stringMap.put("bindingJoinByNameIgnored", 2);
440         bean.setBindingJoinByNameIgnored(stringMap);
441         stringMap = new ArrayListValuedHashMap<>();
442         stringMap.put("bindingJoinByNameNotIgnored", 3);
443         stringMap.put("bindingJoinByNameNotIgnored", 4);
444         bean.setBindingJoinByNameNotIgnored(stringMap);
445         ListValuedMap<Integer, Integer> integerMap = new ArrayListValuedHashMap<>();
446         integerMap.put(6, 5);
447         integerMap.put(7, 6);
448         bean.setBindingJoinByPositionIgnored(integerMap);
449         integerMap = new ArrayListValuedHashMap<>();
450         integerMap.put(2, 7);
451         integerMap.put(3, 8);
452         bean.setBindingJoinByPositionNotIgnored(integerMap);
453         bean.setBindingPrimitiveIgnored(9);
454         bean.setBindingPrimitiveNotIgnored(10);
455         bean.setBindingSplitIgnored(Arrays.asList(11, 12));
456         bean.setBindingSplitNotIgnored(Arrays.asList(13, 14));
457 
458         StringWriter w = new StringWriter();
459         StatefulBeanToCsv<IgnoreMock> beanToCsv = new StatefulBeanToCsvBuilder<IgnoreMock>(w)
460                 .withApplyQuotesToAll(false)
461                 .withIgnoreField(IgnoreMock.class, IgnoreMock.class.getDeclaredField("bindingPrimitiveNotIgnored"))
462                 .build();
463         beanToCsv.write(bean);
464         assertEquals(",13 14,7,8\n", w.toString());
465     }
466 }