1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.orangesignal.csv.io;
18
19 import java.io.Closeable;
20 import java.io.IOException;
21 import java.lang.reflect.Field;
22 import java.util.Collections;
23 import java.util.List;
24
25 import com.orangesignal.csv.CsvReader;
26 import com.orangesignal.csv.bean.CsvBeanTemplate;
27 import com.orangesignal.csv.bean.FieldUtils;
28
29
30
31
32
33
34
35
36 public class CsvBeanReader<T> implements Closeable {
37
38
39
40
41 private CsvReader reader;
42
43
44
45
46 private final CsvBeanTemplate<T> template;
47
48
49
50
51 private List<String> columnNames;
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public static <T> CsvBeanReader<T> newInstance(final CsvReader reader, final Class<T> type) {
66 return new CsvBeanReader<T>(reader, type);
67 }
68
69
70
71
72
73
74
75
76
77
78 public static <T> CsvBeanReader<T> newInstance(final CsvReader reader, final CsvBeanTemplate<T> template) {
79 return new CsvBeanReader<T>(reader, template);
80 }
81
82
83
84
85
86
87
88
89
90
91
92 public CsvBeanReader(final CsvReader reader, final Class<T> type) {
93 this(reader, new CsvBeanTemplate<T>(type));
94 }
95
96
97
98
99
100
101
102
103 public CsvBeanReader(final CsvReader reader, final CsvBeanTemplate<T> template) {
104 if (reader == null) {
105 throw new IllegalArgumentException("CsvReader must not be null");
106 }
107 if (template == null) {
108 throw new IllegalArgumentException("CsvBeanTemplate must not be null");
109 }
110 this.reader = reader;
111 this.template = template;
112 }
113
114
115
116
117
118
119
120
121
122 private void ensureOpen() throws IOException {
123 if (reader == null) {
124 throw new IOException("CsvReader closed");
125 }
126 }
127
128 private void ensureHeader() throws IOException {
129 synchronized (this) {
130 if (columnNames == null) {
131 columnNames = Collections.unmodifiableList(reader.readValues());
132 if (columnNames == null) {
133
134 throw new IOException("No header is available");
135 }
136 }
137 }
138 }
139
140
141
142
143 @Override
144 public void close() throws IOException {
145 synchronized (this) {
146 ensureOpen();
147 reader.close();
148 reader = null;
149 columnNames = null;
150 }
151 }
152
153
154
155
156
157
158
159
160
161
162 public List<String> getHeader() throws IOException {
163 synchronized (this) {
164 ensureOpen();
165 ensureHeader();
166 return columnNames;
167 }
168 }
169
170
171
172
173
174
175
176 public T read() throws IOException {
177 synchronized (this) {
178 ensureOpen();
179 ensureHeader();
180 final List<String> values = nextValues();
181 if (values == null) {
182 return null;
183 }
184 return convert(values);
185 }
186 }
187
188
189
190
191
192
193
194 public List<String> readValues() throws IOException {
195 synchronized (this) {
196 ensureOpen();
197 ensureHeader();
198 return nextValues();
199 }
200 }
201
202
203
204
205
206
207
208
209 public T toBean(final List<String> values) throws IOException {
210 synchronized (this) {
211 ensureOpen();
212 ensureHeader();
213 return convert(values);
214 }
215 }
216
217 private List<String> nextValues() throws IOException {
218 List<String> values;
219 while ((values = reader.readValues()) != null) {
220 if (!template.isAccept(columnNames, values)) {
221 return values;
222 }
223 }
224 return null;
225 }
226
227 private T convert(final List<String> values) throws IOException {
228 final T bean = template.createBean();
229 final int len = Math.min(columnNames.size(), values.size());
230 for (int pos = 0; pos < len; pos++) {
231 final String name = columnNames.get(pos);
232 if (!template.isTargetName(name)) {
233 continue;
234 }
235 final Field f = FieldUtils.getField(template.getType(), name);
236 final Object o = template.stringToObject(f, values.get(pos));
237 if (o != null) {
238 FieldUtils.setFieldValue(bean, f, o);
239 }
240 }
241 return bean;
242 }
243
244
245
246
247
248
249
250
251
252
253 public CsvBeanTemplate<T> getTemplate() {
254 return template;
255 }
256
257 }