1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package com.rapiddweller.platform.csv;
28
29 import com.rapiddweller.common.ArrayUtil;
30 import com.rapiddweller.common.Converter;
31 import com.rapiddweller.common.IOUtil;
32 import com.rapiddweller.common.Patterns;
33 import com.rapiddweller.common.StringUtil;
34 import com.rapiddweller.common.Tabular;
35 import com.rapiddweller.common.converter.ArrayConverter;
36 import com.rapiddweller.common.converter.ConverterChain;
37 import com.rapiddweller.format.DataContainer;
38 import com.rapiddweller.format.DataIterator;
39 import com.rapiddweller.format.csv.CSVLineIterator;
40 import com.rapiddweller.format.util.ConvertingDataIterator;
41 import com.rapiddweller.format.util.OrthogonalArrayIterator;
42 import com.rapiddweller.model.data.ComplexTypeDescriptor;
43 import com.rapiddweller.model.data.Entity;
44 import com.rapiddweller.platform.array.Array2EntityConverter;
45
46 import java.io.FileNotFoundException;
47 import java.io.IOException;
48 import java.util.ArrayList;
49 import java.util.List;
50
51
52
53
54
55
56
57
58
59
60 public class CSVEntityIterator implements DataIterator<Entity>, Tabular {
61
62 private final String uri;
63 private final char separator;
64 private final String encoding;
65 private String[] columns;
66 private final Converter<String, ?> preprocessor;
67 private boolean expectingHeader;
68 private boolean rowBased;
69
70 private DataIterator<Entity> source;
71
72 private boolean initialized;
73 private final ComplexTypeDescriptor entityDescriptor;
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public CSVEntityIterator(String uri, ComplexTypeDescriptor descriptor,
88 Converter<String, ?> preprocessor, char separator,
89 String encoding) throws FileNotFoundException {
90 if (!IOUtil.isURIAvailable(uri)) {
91 throw new FileNotFoundException("URI not found: " + uri);
92 }
93 this.uri = uri;
94 this.preprocessor = preprocessor;
95 this.separator = separator;
96 this.encoding = encoding;
97 this.entityDescriptor = descriptor;
98 this.initialized = false;
99 this.expectingHeader = true;
100 this.rowBased = (descriptor != null && descriptor.isRowBased() != null ?
101 descriptor.isRowBased() : true);
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 public static List<Entity> parseAll(String uri, char separator,
119 String encoding,
120 ComplexTypeDescriptor descriptor,
121 Converter<String, String> preprocessor,
122 Patterns patterns)
123 throws FileNotFoundException {
124 List<Entity> list = new ArrayList<>();
125 CSVEntityIterator iterator =
126 new CSVEntityIterator(uri, descriptor, preprocessor, separator,
127 encoding);
128 DataContainer<Entity> container = new DataContainer<>();
129 while ((container = iterator.next(container)) != null) {
130 list.add(container.getData());
131 }
132 return list;
133 }
134
135
136
137
138
139
140 public void setExpectingHeader(boolean expectHeader) {
141 this.expectingHeader = expectHeader;
142 }
143
144
145
146
147
148
149 public boolean isRowBased() {
150 return rowBased;
151 }
152
153
154
155
156
157
158 public void setRowBased(boolean rowBased) {
159 this.rowBased = rowBased;
160 }
161
162 @Override
163 public String[] getColumnNames() {
164 return columns;
165 }
166
167
168
169
170
171
172
173
174 public void setColumns(String[] columns) {
175 this.expectingHeader = false;
176 if (ArrayUtil.isEmpty(columns)) {
177 this.columns = null;
178 } else {
179 this.columns = columns.clone();
180 StringUtil.trimAll(this.columns);
181 }
182 }
183
184 @Override
185 public Class<Entity> getType() {
186 return Entity.class;
187 }
188
189 @Override
190 public DataContainer<Entity> next(DataContainer<Entity> container) {
191 assureInitialized();
192 return source.next(container);
193 }
194
195 @Override
196 public void close() {
197 IOUtil.close(source);
198 }
199
200
201
202 @Override
203 public String toString() {
204 return getClass().getSimpleName() + "[uri=" + uri + ", encoding=" +
205 encoding + ", separator=" + separator +
206 ", entityName=" + entityDescriptor.getName() + "]";
207 }
208
209
210
211 private void assureInitialized() {
212 if (!initialized) {
213 init();
214 initialized = true;
215 }
216 }
217
218 @SuppressWarnings({"unchecked", "rawtypes"})
219 private void init() {
220 try {
221 DataIterator<String[]> cellIterator;
222 cellIterator = new CSVLineIterator(uri, separator, true, encoding);
223 if (!rowBased) {
224 cellIterator = new OrthogonalArrayIterator<>(cellIterator);
225 }
226 if (expectingHeader) {
227 setColumns(cellIterator.next(new DataContainer<>()).getData());
228 }
229 Converter<String[], Object[]> arrayConverter =
230 new ArrayConverter(String.class, Object.class,
231 preprocessor);
232 Array2EntityConverter a2eConverter =
233 new Array2EntityConverter(entityDescriptor, columns, true);
234 Converter<String[], Entity> converter =
235 new ConverterChain<>(arrayConverter, a2eConverter);
236 this.source = new ConvertingDataIterator<>(cellIterator, converter);
237 } catch (IOException e) {
238 throw new RuntimeException("Error in processing " + uri, e);
239 }
240 }
241
242 }