1 package com.opencsv.bean;
2
3 import com.opencsv.bean.mocks.recurse.*;
4 import com.opencsv.exceptions.*;
5 import org.apache.commons.lang3.StringUtils;
6 import org.junit.jupiter.api.Test;
7
8 import java.io.StringReader;
9 import java.io.StringWriter;
10 import java.util.List;
11
12 import static org.junit.jupiter.api.Assertions.*;
13
14 public class RecursionTest {
15
16 private static final String HEADER = "intLevelZero,stringLevelOne,charLevelTwo,floatLevelThree,booleanLevelThree,shortLevelThree\n";
17 private static final String DATA = "10,11,c,4.0,true,32\n";
18
19 private RecursionMockLevelZero oneGoodMock() {
20 RecursionMockLevelZero bean = new RecursionMockLevelZero();
21 bean.setIntLevelZero(10);
22 RecursionMockLevelOne l1 = new RecursionMockLevelOne();
23 l1.setStringLevelOne("11");
24 bean.setLevelOne(l1);
25 RecursionMockLevelTwo l2 = new RecursionMockLevelTwo();
26 l2.setCharLevelTwo('c');
27 l1.setLevelTwo(l2);
28 l2.procureTheThirdLevelPointZero().setFloatLevelThree(4.0f);
29 RecursionMockLevelThreePointOne l3point1 = new RecursionMockLevelThreePointOne();
30 l3point1.setBooleanLevelThree(true);
31 l2.setLevelThreePointOne(l3point1);
32 RecursionMockLevelThreePointTwo l3point2 = new RecursionMockLevelThreePointTwo();
33 l3point2.setShortLevelThree((short)32);
34 l2.setLevelThreePointTwo(l3point2);
35 return bean;
36 }
37
38 private RecursionMockLevelZeroNoAnnotations oneGoodMockNoAnnotations() {
39 RecursionMockLevelZeroNoAnnotations bean = new RecursionMockLevelZeroNoAnnotations();
40 bean.setIntLevelZero(10);
41 RecursionMockLevelOneNoAnnotations l1 = new RecursionMockLevelOneNoAnnotations();
42 l1.setStringLevelOne("11");
43 bean.setLevelOne(l1);
44 RecursionMockLevelTwoNoAnnotations l2 = new RecursionMockLevelTwoNoAnnotations();
45 l2.setCharLevelTwo('c');
46 l1.setLevelTwo(l2);
47 l2.procureTheThirdLevelPointZero().setFloatLevelThree(4.0f);
48 RecursionMockLevelThreePointOneNoAnnotations l3point1 = new RecursionMockLevelThreePointOneNoAnnotations();
49 l3point1.setBooleanLevelThree(true);
50 l2.setLevelThreePointOne(l3point1);
51 RecursionMockLevelThreePointTwoNoAnnotations l3point2 = new RecursionMockLevelThreePointTwoNoAnnotations();
52 l3point2.setShortLevelThree((short)32);
53 l2.setLevelThreePointTwo(l3point2);
54 return bean;
55 }
56
57 private void checkReadingResults(List<RecursionMockLevelZero> beans) {
58 assertNotNull(beans);
59 assertEquals(1, beans.size());
60
61 RecursionMockLevelZero b0 = beans.get(0);
62 assertEquals(10, b0.getIntLevelZero());
63
64 RecursionMockLevelOne b1 = b0.getLevelOne();
65 assertEquals("11", b1.getStringLevelOne());
66
67 RecursionMockLevelTwo b2 = b1.getLevelTwo();
68 assertEquals('c', b2.getCharLevelTwo());
69
70 RecursionMockLevelThreePointZero b3point0 = b2.procureTheThirdLevelPointZero();
71 assertEquals(4.0f, b3point0.getFloatLevelThree());
72
73 RecursionMockLevelThreePointOne b3point1 = b2.getLevelThreePointOne();
74 assertTrue(b3point1.isBooleanLevelThree());
75
76 RecursionMockLevelThreePointTwo b3point2 = b2.getLevelThreePointTwo();
77 assertEquals((short)32, b3point2.getShortLevelThree());
78 }
79
80 private void checkReadingResultsNoAnnotations(List<RecursionMockLevelZeroNoAnnotations> beans) {
81 assertNotNull(beans);
82 assertEquals(1, beans.size());
83
84 RecursionMockLevelZeroNoAnnotations b0 = beans.get(0);
85 assertEquals(10, b0.getIntLevelZero());
86
87 RecursionMockLevelOneNoAnnotations b1 = b0.getLevelOne();
88 assertEquals("11", b1.getStringLevelOne());
89
90 RecursionMockLevelTwoNoAnnotations b2 = b1.getLevelTwo();
91 assertEquals('c', b2.getCharLevelTwo());
92
93 RecursionMockLevelThreePointZeroNoAnnotations b3point0 = b2.procureTheThirdLevelPointZero();
94 assertEquals(4.0f, b3point0.getFloatLevelThree());
95
96 RecursionMockLevelThreePointOneNoAnnotations b3point1 = b2.getLevelThreePointOne();
97 assertTrue(b3point1.isBooleanLevelThree());
98
99 RecursionMockLevelThreePointTwoNoAnnotations b3point2 = b2.getLevelThreePointTwo();
100 assertEquals((short)32, b3point2.getShortLevelThree());
101 }
102
103 @Test
104 public void testPrimitives() {
105
106
107 try {
108 new CsvToBeanBuilder<BooleanRecurse>(new StringReader(StringUtils.EMPTY))
109 .withType(BooleanRecurse.class)
110 .build();
111 fail("Exception should have been thrown.");
112 }
113 catch(CsvRecursionException e) {
114 assertFalse(StringUtils.isBlank(e.getMessage()));
115 assertEquals(Boolean.TYPE, e.getOffendingType());
116 }
117
118
119 try {
120 new CsvToBeanBuilder<ByteRecurse>(new StringReader(StringUtils.EMPTY))
121 .withType(ByteRecurse.class)
122 .build();
123 fail("Exception should have been thrown.");
124 }
125 catch(CsvRecursionException e) {
126 assertFalse(StringUtils.isBlank(e.getMessage()));
127 assertEquals(Byte.TYPE, e.getOffendingType());
128 }
129
130
131 try {
132 new CsvToBeanBuilder<CharacterRecurse>(new StringReader(StringUtils.EMPTY))
133 .withType(CharacterRecurse.class)
134 .build();
135 fail("Exception should have been thrown.");
136 }
137 catch(CsvRecursionException e) {
138 assertFalse(StringUtils.isBlank(e.getMessage()));
139 assertEquals(Character.TYPE, e.getOffendingType());
140 }
141
142
143 try {
144 new CsvToBeanBuilder<DoubleRecurse>(new StringReader(StringUtils.EMPTY))
145 .withType(DoubleRecurse.class)
146 .build();
147 fail("Exception should have been thrown.");
148 }
149 catch(CsvRecursionException e) {
150 assertFalse(StringUtils.isBlank(e.getMessage()));
151 assertEquals(Double.TYPE, e.getOffendingType());
152 }
153
154
155 try {
156 new CsvToBeanBuilder<FloatRecurse>(new StringReader(StringUtils.EMPTY))
157 .withType(FloatRecurse.class)
158 .build();
159 fail("Exception should have been thrown.");
160 }
161 catch(CsvRecursionException e) {
162 assertFalse(StringUtils.isBlank(e.getMessage()));
163 assertEquals(Float.TYPE, e.getOffendingType());
164 }
165
166
167 try {
168 new CsvToBeanBuilder<IntegerRecurse>(new StringReader(StringUtils.EMPTY))
169 .withType(IntegerRecurse.class)
170 .build();
171 fail("Exception should have been thrown.");
172 }
173 catch(CsvRecursionException e) {
174 assertFalse(StringUtils.isBlank(e.getMessage()));
175 assertEquals(Integer.TYPE, e.getOffendingType());
176 }
177
178
179 try {
180 new CsvToBeanBuilder<LongRecurse>(new StringReader(StringUtils.EMPTY))
181 .withType(LongRecurse.class)
182 .build();
183 fail("Exception should have been thrown.");
184 }
185 catch(CsvRecursionException e) {
186 assertFalse(StringUtils.isBlank(e.getMessage()));
187 assertEquals(Long.TYPE, e.getOffendingType());
188 }
189
190
191 try {
192 new CsvToBeanBuilder<ShortRecurse>(new StringReader(StringUtils.EMPTY))
193 .withType(ShortRecurse.class)
194 .build();
195 fail("Exception should have been thrown.");
196 }
197 catch(CsvRecursionException e) {
198 assertFalse(StringUtils.isBlank(e.getMessage()));
199 assertEquals(Short.TYPE, e.getOffendingType());
200 }
201 }
202
203 @Test
204 public void testDuplicateRecursion() {
205 try {
206 new CsvToBeanBuilder<DuplicateRecurse>(new StringReader(StringUtils.EMPTY))
207 .withType(DuplicateRecurse.class)
208 .build();
209 fail("Exception should have been thrown.");
210 }
211 catch(CsvRecursionException e) {
212 assertFalse(StringUtils.isBlank(e.getMessage()));
213 assertEquals(RecursionMockLevelZero.class, e.getOffendingType());
214 }
215 }
216
217 @Test
218 public void testBindAndRecurse() {
219 try {
220 new CsvToBeanBuilder<BindAndRecurse>(new StringReader(StringUtils.EMPTY))
221 .withType(BindAndRecurse.class)
222 .build();
223 fail("Exception should have been thrown.");
224 }
225 catch(CsvRecursionException e) {
226 assertFalse(StringUtils.isBlank(e.getMessage()));
227 assertEquals(RecursionMockLevelZero.class, e.getOffendingType());
228 }
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242
243 @Test
244 public void testReadingHeaderNames() {
245 MappingStrategy<RecursionMockLevelZero> strategy = new HeaderColumnNameMappingStrategy<>();
246 strategy.setType(RecursionMockLevelZero.class);
247 CsvToBean<RecursionMockLevelZero> csvToBean =
248 new CsvToBeanBuilder<RecursionMockLevelZero>(new StringReader(
249 HEADER + DATA))
250 .withMappingStrategy(strategy)
251 .build();
252 List<RecursionMockLevelZero> beans = csvToBean.parse();
253 List<CsvException> exceptions = csvToBean.getCapturedExceptions();
254 assertNotNull(exceptions);
255 assertTrue(exceptions.isEmpty());
256 checkReadingResults(beans);
257 }
258
259 @Test
260 public void testReadingHeaderNamesNoAnnotations() {
261 CsvToBean<RecursionMockLevelZeroNoAnnotations> csvToBean =
262 new CsvToBeanBuilder<RecursionMockLevelZeroNoAnnotations>(new StringReader(
263 HEADER + DATA))
264 .withType(RecursionMockLevelZeroNoAnnotations.class)
265 .build();
266 List<RecursionMockLevelZeroNoAnnotations> beans = csvToBean.parse();
267 List<CsvException> exceptions = csvToBean.getCapturedExceptions();
268 assertNotNull(exceptions);
269 assertTrue(exceptions.isEmpty());
270 checkReadingResultsNoAnnotations(beans);
271 }
272
273 @Test
274 public void testReadingColumnPositions() {
275 CsvToBean<RecursionMockLevelZero> csvToBean =
276 new CsvToBeanBuilder<RecursionMockLevelZero>(new StringReader(DATA))
277 .withType(RecursionMockLevelZero.class)
278 .build();
279 List<RecursionMockLevelZero> beans = csvToBean.parse();
280 List<CsvException> exceptions = csvToBean.getCapturedExceptions();
281 assertNotNull(exceptions);
282 assertTrue(exceptions.isEmpty());
283 checkReadingResults(beans);
284 }
285
286 @Test
287 public void testEmbeddedBeanNoNullaryConstructor() {
288 try {
289 CsvToBean<EmbeddedBeanNoNullaryConstructor> csvToBean = new CsvToBeanBuilder<EmbeddedBeanNoNullaryConstructor>(new StringReader(DATA))
290 .withType(EmbeddedBeanNoNullaryConstructor.class)
291 .build();
292 csvToBean.parse();
293 fail("Exception should have been thrown.");
294 } catch (RuntimeException e) {
295 assertFalse(StringUtils.isBlank(e.getMessage()));
296 assertTrue(e.getCause() instanceof CsvBeanIntrospectionException);
297 CsvBeanIntrospectionException csve = (CsvBeanIntrospectionException)e.getCause();
298 assertFalse(StringUtils.isBlank(csve.getMessage()));
299 assertNull(csve.getField());
300 assertNull(csve.getBean());
301 assertNotNull(csve.getCause());
302 }
303 }
304
305 @Test
306 public void testWritingHeaderNames() throws CsvDataTypeMismatchException, CsvRequiredFieldEmptyException {
307 StringWriter w = new StringWriter();
308 MappingStrategy<RecursionMockLevelZero> strategy = new HeaderColumnNameMappingStrategy<>();
309 strategy.setType(RecursionMockLevelZero.class);
310 StatefulBeanToCsv<RecursionMockLevelZero> b2c = new StatefulBeanToCsvBuilder<RecursionMockLevelZero>(w)
311 .withMappingStrategy(strategy)
312 .withApplyQuotesToAll(false)
313 .build();
314 b2c.write(oneGoodMock());
315 assertEquals("BOOLEANLEVELTHREE,CHARLEVELTWO,FLOATLEVELTHREE,INTLEVELZERO,SHORTLEVELTHREE,STRINGLEVELONE\n" +
316 "true,c,4.0,10,32,11\n", w.toString());
317 }
318
319 @Test
320 public void testWritingHeaderNamesNoAnnotations() throws CsvDataTypeMismatchException, CsvRequiredFieldEmptyException {
321 StringWriter w = new StringWriter();
322 StatefulBeanToCsv<RecursionMockLevelZeroNoAnnotations> b2c = new StatefulBeanToCsvBuilder<RecursionMockLevelZeroNoAnnotations>(w)
323 .withApplyQuotesToAll(false)
324 .build();
325 b2c.write(oneGoodMockNoAnnotations());
326 assertEquals("BOOLEANLEVELTHREE,CHARLEVELTWO,FLOATLEVELTHREE,INTLEVELZERO,SHORTLEVELTHREE,STRINGLEVELONE\n" +
327 "true,c,4.0,10,32,11\n", w.toString());
328 }
329
330 @Test
331 public void testWritingColumnPositions() throws CsvDataTypeMismatchException, CsvRequiredFieldEmptyException {
332 StringWriter w = new StringWriter();
333 StatefulBeanToCsv<RecursionMockLevelZero> b2c = new StatefulBeanToCsvBuilder<RecursionMockLevelZero>(w)
334 .withApplyQuotesToAll(false)
335 .build();
336 b2c.write(oneGoodMock());
337 assertEquals(DATA, w.toString());
338 }
339
340 @Test
341 public void testNullMemberVariableOptional() throws CsvDataTypeMismatchException, CsvRequiredFieldEmptyException {
342 StringWriter w = new StringWriter();
343 StatefulBeanToCsv<RecursionMockLevelZero> b2c = new StatefulBeanToCsvBuilder<RecursionMockLevelZero>(w)
344 .withApplyQuotesToAll(false)
345 .build();
346 RecursionMockLevelZero bean = oneGoodMock();
347 bean.getLevelOne().setLevelTwo(null);
348 b2c.write(bean);
349 assertEquals("10,11,,,,\n", w.toString());
350 }
351
352 @Test
353 public void testNullMemberVariableRequired() throws CsvDataTypeMismatchException {
354 StringWriter w = new StringWriter();
355 StatefulBeanToCsv<RecursionMockLevelZero> b2c = new StatefulBeanToCsvBuilder<RecursionMockLevelZero>(w)
356 .withApplyQuotesToAll(false)
357 .build();
358 RecursionMockLevelZero bean = oneGoodMock();
359 bean.setLevelOne(null);
360 try {
361 b2c.write(bean);
362 fail("Exception should have been thrown.");
363 } catch (CsvRequiredFieldEmptyException e) {
364 assertEquals(RecursionMockLevelOne.class, e.getBeanClass());
365 assertNotNull(e.getDestinationFields());
366 assertFalse(e.getDestinationFields().isEmpty());
367 assertEquals("stringLevelOne", e.getDestinationFields().get(0).getName());
368 }
369 }
370 }