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.util.Collections;
22 import java.util.LinkedHashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import com.orangesignal.csv.CsvReader;
27 import com.orangesignal.csv.filters.CsvNamedValueFilter;
28
29
30
31
32
33
34
35 public class CsvColumnNameMapReader implements Closeable {
36
37
38
39
40 private CsvReader reader;
41
42
43
44
45 private List<String> columnNames;
46
47
48
49
50 private int columnCount = -1;
51
52
53
54
55 private Map<String, String> base;
56
57
58
59
60 private CsvNamedValueFilter filter;
61
62
63
64
65
66
67
68
69
70
71 public CsvColumnNameMapReader(final CsvReader reader) {
72 this(reader, null);
73 }
74
75
76
77
78
79
80
81
82 public CsvColumnNameMapReader(final CsvReader reader, final List<String> columnNames) {
83 if (reader == null) {
84 throw new IllegalArgumentException("CsvReader must not be null");
85 }
86 this.reader = reader;
87
88 if (columnNames != null) {
89 this.columnNames = Collections.unmodifiableList(columnNames);
90 }
91 }
92
93
94
95
96
97
98
99 private void ensureOpen() throws IOException {
100 if (reader == null) {
101 throw new IOException("CsvReader closed");
102 }
103 }
104
105 private void ensureHeader() throws IOException {
106 synchronized (this) {
107 if (columnNames == null) {
108 columnNames = Collections.unmodifiableList(reader.readValues());
109 if (columnNames == null) {
110
111 throw new IOException("No header is available");
112 }
113 }
114 if (columnCount == -1) {
115
116 columnCount = columnNames.size();
117 base = new LinkedHashMap<String, String>(columnCount);
118 for (final String columnName : columnNames) {
119 base.put(columnName, null);
120 }
121 }
122 }
123 }
124
125
126
127
128 @Override
129 public void close() throws IOException {
130 synchronized (this) {
131 ensureOpen();
132 reader.close();
133 reader = null;
134 columnNames = null;
135 columnCount = -1;
136 base = null;
137 }
138 }
139
140
141
142
143
144
145
146
147
148
149 public List<String> getHeader() throws IOException {
150 synchronized (this) {
151 ensureOpen();
152 ensureHeader();
153 return columnNames;
154 }
155 }
156
157
158
159
160
161
162
163 public Map<String, String> read() throws IOException {
164 synchronized (this) {
165 ensureOpen();
166 ensureHeader();
167 final List<String> values = nextValues();
168 if (values == null) {
169 return null;
170 }
171 return convert(values);
172 }
173 }
174
175
176
177
178
179
180
181 public List<String> readValues() throws IOException {
182 synchronized (this) {
183 ensureOpen();
184 ensureHeader();
185 return nextValues();
186 }
187 }
188
189
190
191
192
193
194
195
196 public Map<String, String> toMap(final List<String> values) throws IOException {
197 synchronized (this) {
198 ensureOpen();
199 ensureHeader();
200 return convert(values);
201 }
202 }
203
204 private List<String> nextValues() throws IOException {
205 List<String> values;
206 while ((values = reader.readValues()) != null) {
207 if (filter != null && !filter.accept(columnNames, values)) {
208 continue;
209 }
210 return values;
211 }
212 return null;
213 }
214
215 private Map<String, String> convert(final List<String> values) {
216 final Map<String, String> map = new LinkedHashMap<String, String>(base);
217 final int len = Math.min(columnCount, values.size());
218 for (int pos = 0; pos < len; pos++) {
219 map.put(columnNames.get(pos), values.get(pos));
220 }
221 return map;
222 }
223
224
225
226
227
228
229
230
231
232 public CsvNamedValueFilter getFilter() {
233 return filter;
234 }
235
236
237
238
239
240
241 public void setFilter(final CsvNamedValueFilter filter) {
242 synchronized (this) {
243 this.filter = filter;
244 }
245 }
246
247 }