1 package com.opencsv.bean;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import com.opencsv.CSVReader;
20 import com.opencsv.ICSVParser;
21 import com.opencsv.bean.concurrent.CompleteFileReader;
22 import com.opencsv.bean.concurrent.LineExecutor;
23 import com.opencsv.bean.concurrent.ProcessCsvLine;
24 import com.opencsv.bean.concurrent.SingleLineReader;
25 import com.opencsv.bean.exceptionhandler.CsvExceptionHandler;
26 import com.opencsv.bean.exceptionhandler.ExceptionHandlerQueue;
27 import com.opencsv.bean.exceptionhandler.ExceptionHandlerThrow;
28 import com.opencsv.bean.util.OrderedObject;
29 import com.opencsv.exceptions.CsvException;
30 import com.opencsv.exceptions.CsvValidationException;
31 import org.apache.commons.lang3.ObjectUtils;
32
33 import java.io.IOException;
34 import java.util.*;
35 import java.util.concurrent.ArrayBlockingQueue;
36 import java.util.concurrent.BlockingQueue;
37 import java.util.concurrent.LinkedBlockingQueue;
38 import java.util.stream.Collectors;
39 import java.util.stream.Stream;
40 import java.util.stream.StreamSupport;
41
42
43
44
45
46
47
48
49
50
51 public class CsvToBean<T> implements Iterable<T> {
52
53
54
55
56 private final List<CsvException> capturedExceptions = new LinkedList<>();
57
58
59
60
61 private MappingStrategy<? extends T> mappingStrategy;
62
63
64
65
66 private CSVReader csvReader;
67
68
69
70
71 private CsvToBeanFilter filter = null;
72
73
74
75
76 private CsvExceptionHandler exceptionHandler = new ExceptionHandlerThrow();
77
78
79
80
81
82 private boolean orderedResults = true;
83
84
85
86
87
88 private LineExecutor<T> executor;
89
90
91
92
93 private Locale errorLocale = Locale.getDefault();
94
95
96
97
98
99 private List<BeanVerifier<T>> verifiers = Collections.<BeanVerifier<T>>emptyList();
100
101
102
103
104
105
106
107
108 private boolean ignoreEmptyLines = false;
109
110
111
112
113 public CsvToBean() {
114 }
115
116
117
118
119
120
121
122
123
124
125 public List<T> parse() throws IllegalStateException {
126 return stream().collect(Collectors.toList());
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 public Stream<T> stream() throws IllegalStateException {
143 prepareToReadInput();
144 CompleteFileReader<T> completeFileReader = new CompleteFileReader<>(
145 csvReader, filter, ignoreEmptyLines,
146 mappingStrategy, exceptionHandler, verifiers);
147 executor = new LineExecutor<T>(orderedResults, errorLocale, completeFileReader);
148 executor.prepare();
149 return StreamSupport.stream(executor, false);
150 }
151
152
153
154
155
156
157
158
159
160
161
162 public List<CsvException> getCapturedExceptions() {
163
164
165 return executor != null ? executor.getCapturedExceptions() : capturedExceptions;
166 }
167
168
169
170
171
172
173 public void setMappingStrategy(MappingStrategy<? extends T> mappingStrategy) {
174 this.mappingStrategy = mappingStrategy;
175 }
176
177
178
179
180
181
182 public void setCsvReader(CSVReader csvReader) {
183 this.csvReader = csvReader;
184 }
185
186
187
188
189
190
191
192 public void setFilter(CsvToBeanFilter filter) {
193 this.filter = filter;
194 }
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212 public void setThrowExceptions(boolean throwExceptions) {
213 if (throwExceptions) {
214 exceptionHandler = new ExceptionHandlerThrow();
215 } else {
216 exceptionHandler = new ExceptionHandlerQueue();
217 }
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233 public void setExceptionHandler(CsvExceptionHandler handler) {
234 if (handler != null) {
235 exceptionHandler = handler;
236 }
237 }
238
239
240
241
242
243
244 CsvExceptionHandler getExceptionHandler() {
245 return exceptionHandler;
246 }
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261 public void setOrderedResults(boolean orderedResults) {
262 this.orderedResults = orderedResults;
263 }
264
265
266
267
268
269
270
271
272 public void setErrorLocale(Locale errorLocale) {
273 this.errorLocale = ObjectUtils.defaultIfNull(errorLocale, Locale.getDefault());
274 if (csvReader != null) {
275 csvReader.setErrorLocale(this.errorLocale);
276 }
277 if (mappingStrategy != null) {
278 mappingStrategy.setErrorLocale(this.errorLocale);
279 }
280 }
281
282
283
284
285
286
287
288
289 public void setVerifiers(List<BeanVerifier<T>> verifiers) {
290 this.verifiers = ObjectUtils.defaultIfNull(verifiers, Collections.<BeanVerifier<T>>emptyList());
291 }
292
293 private void prepareToReadInput() throws IllegalStateException {
294
295
296 if (mappingStrategy == null || csvReader == null) {
297 throw new IllegalStateException(ResourceBundle.getBundle(ICSVParser.DEFAULT_BUNDLE_NAME, errorLocale).getString("specify.strategy.reader"));
298 }
299
300
301 try {
302 mappingStrategy.captureHeader(csvReader);
303 } catch (Exception e) {
304 throw new RuntimeException(ResourceBundle.getBundle(ICSVParser.DEFAULT_BUNDLE_NAME, errorLocale).getString("header.error"), e);
305 }
306 }
307
308
309
310
311
312
313
314
315
316
317
318
319
320 @Override
321 public Iterator<T> iterator() {
322 prepareToReadInput();
323 return new CsvToBeanIterator();
324 }
325
326
327
328
329
330
331 public void setIgnoreEmptyLines(boolean ignoreEmptyLines) {
332 this.ignoreEmptyLines = ignoreEmptyLines;
333 }
334
335
336
337
338 private class CsvToBeanIterator implements Iterator<T> {
339 private final BlockingQueue<OrderedObject<T>> resultantBeansQueue;
340 private final BlockingQueue<OrderedObject<CsvException>> thrownExceptionsQueue;
341 private final SingleLineReader lineReader = new SingleLineReader(csvReader, ignoreEmptyLines);
342 private String[] line = null;
343 private long lineProcessed = 0;
344 private T bean;
345
346 CsvToBeanIterator() {
347 resultantBeansQueue = new ArrayBlockingQueue<>(1);
348 thrownExceptionsQueue = new LinkedBlockingQueue<>();
349 readSingleLine();
350 }
351
352 private void processException() {
353
354 OrderedObject<CsvException> o = thrownExceptionsQueue.poll();
355 while (o != null && o.getElement() != null) {
356 capturedExceptions.add(o.getElement());
357 o = thrownExceptionsQueue.poll();
358 }
359 }
360
361 private void readLineWithPossibleError() throws IOException, CsvValidationException {
362
363 bean = null;
364 while (bean == null && null != (line = lineReader.readNextLine())) {
365 lineProcessed = lineReader.getLinesRead();
366
367
368 ProcessCsvLine<T> proc = new ProcessCsvLine<>(
369 lineProcessed, mappingStrategy, filter, verifiers,
370 line, resultantBeansQueue, thrownExceptionsQueue,
371 new TreeSet<>(), exceptionHandler);
372 proc.run();
373
374 if (!thrownExceptionsQueue.isEmpty()) {
375 processException();
376 } else {
377
378
379 OrderedObject<T> o = resultantBeansQueue.poll();
380 bean = o == null ? null : o.getElement();
381 }
382 }
383 if (line == null) {
384
385 bean = null;
386 }
387 }
388
389 private void readSingleLine() {
390 try {
391 readLineWithPossibleError();
392 } catch (IOException | CsvValidationException e) {
393 line = null;
394 throw new RuntimeException(String.format(ResourceBundle.getBundle(ICSVParser.DEFAULT_BUNDLE_NAME, errorLocale).getString("parsing.error"),
395 lineProcessed, Arrays.toString(line)), e);
396 }
397 }
398
399 @Override
400 public boolean hasNext() {
401 return bean != null;
402 }
403
404 @Override
405 public T next() {
406 if (bean == null) {
407 throw new NoSuchElementException();
408 }
409 T intermediateBean = bean;
410 readSingleLine();
411 return intermediateBean;
412 }
413
414 @Override
415 public void remove() {
416 throw new UnsupportedOperationException(ResourceBundle
417 .getBundle(ICSVParser.DEFAULT_BUNDLE_NAME, errorLocale)
418 .getString("read.only.iterator"));
419 }
420 }
421 }