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 import java.util.Map;
25
26 import com.orangesignal.csv.CsvReader;
27 import com.orangesignal.csv.bean.CsvColumnPositionMappingBeanTemplate;
28 import com.orangesignal.csv.bean.FieldUtils;
29
30
31
32
33
34
35
36 public class CsvColumnPositionMappingBeanReader<T> implements Closeable {
37
38
39
40
41 private CsvReader reader;
42
43
44
45
46 private final CsvColumnPositionMappingBeanTemplate<T> template;
47
48
49
50
51 private List<String> columnNames;
52
53 private Field[] fields;
54 private Map<String, Object[]> fieldColumnsMap;
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public static <T> CsvColumnPositionMappingBeanReader<T> newInstance(final CsvReader reader, final Class<T> type) {
69 return new CsvColumnPositionMappingBeanReader<T>(reader, type);
70 }
71
72
73
74
75
76
77
78
79
80
81 public static <T> CsvColumnPositionMappingBeanReader<T> newInstance(final CsvReader reader, final CsvColumnPositionMappingBeanTemplate<T> template) {
82 return new CsvColumnPositionMappingBeanReader<T>(reader, template);
83 }
84
85
86
87
88
89
90
91
92
93
94
95 public CsvColumnPositionMappingBeanReader(final CsvReader reader, final Class<T> type) {
96 this(reader, new CsvColumnPositionMappingBeanTemplate<T>(type));
97 }
98
99
100
101
102
103
104
105
106 public CsvColumnPositionMappingBeanReader(final CsvReader reader, final CsvColumnPositionMappingBeanTemplate<T> template) {
107 if (reader == null) {
108 throw new IllegalArgumentException("CsvReader must not be null");
109 }
110 if (template == null) {
111 throw new IllegalArgumentException("CsvColumnPositionMappingBeanTemplate must not be null");
112 }
113 this.reader = reader;
114 this.template = template;
115 }
116
117
118
119
120
121
122
123 private void ensureOpen() throws IOException {
124 if (reader == null) {
125 throw new IOException("CsvReader closed");
126 }
127 }
128
129 private void ensureHeader() throws IOException {
130 synchronized (this) {
131 if (columnNames == null) {
132
133 if (template.getMaxColumnPosition() == -1) {
134 final List<String> names = reader.readValues();
135 if (names == null) {
136
137 throw new IOException("No header is available");
138 }
139 for (final String name : names) {
140 template.column(name);
141 }
142 }
143 columnNames = Collections.unmodifiableList(template.createColumnNames());
144 fields = template.getType().getDeclaredFields();
145 fieldColumnsMap = template.createFieldAndColumnsMap();
146 }
147 }
148 }
149
150
151
152
153 @Override
154 public void close() throws IOException {
155 synchronized (this) {
156 ensureOpen();
157 reader.close();
158 reader = null;
159 columnNames = null;
160 fields = null;
161 fieldColumnsMap = null;
162 }
163 }
164
165
166
167
168
169
170
171
172
173
174 public List<String> getHeader() throws IOException {
175 synchronized (this) {
176 ensureOpen();
177 ensureHeader();
178 return columnNames;
179 }
180 }
181
182
183
184
185
186
187
188 public T read() throws IOException {
189 synchronized (this) {
190 ensureOpen();
191 ensureHeader();
192 final List<String> values = nextValues();
193 if (values == null) {
194 return null;
195 }
196 return convert(values);
197 }
198 }
199
200
201
202
203
204
205
206 public List<String> readValues() throws IOException {
207 synchronized (this) {
208 ensureOpen();
209 ensureHeader();
210 return nextValues();
211 }
212 }
213
214
215
216
217
218
219
220
221 public T toBean(final List<String> values) throws IOException {
222 synchronized (this) {
223 ensureOpen();
224 ensureHeader();
225 return convert(values);
226 }
227 }
228
229 private List<String> nextValues() throws IOException {
230 List<String> values;
231 while ((values = reader.readValues()) != null) {
232 if (template.isAccept(values)) {
233 continue;
234 }
235 return values;
236 }
237 return null;
238 }
239
240 @SuppressWarnings("null")
241 private T convert(final List<String> values) throws IOException {
242 final T bean = template.createBean();
243 for (final Field f : fields) {
244 final Object[] columns = fieldColumnsMap.get(f.getName());
245 final int count = columns == null ? 0 : columns.length;
246
247 Object o = null;
248 if (count == 1) {
249 final int pos = (Integer) columns[0];
250 if (pos >= 0) {
251 o = template.stringToObject(f, values.get(pos));
252 }
253 } else if (count > 1) {
254 final StringBuilder sb = new StringBuilder();
255 for (final Object column : columns) {
256 final int pos = (Integer) column;
257 if (pos >= 0) {
258 final String s = values.get(pos);
259 if (s != null) {
260 sb.append(s);
261 }
262 }
263 }
264 o = template.stringToObject(f, sb.toString());
265 }
266 if (o != null) {
267 FieldUtils.setFieldValue(bean, f, o);
268 }
269 }
270 return bean;
271 }
272
273
274
275
276
277
278
279
280
281
282 public CsvColumnPositionMappingBeanTemplate<T> getTemplate() {
283 return template;
284 }
285
286 }