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.fixedwidth;
28
29 import com.rapiddweller.benerator.InvalidGeneratorSetupException;
30 import com.rapiddweller.common.ArrayUtil;
31 import com.rapiddweller.common.Converter;
32 import com.rapiddweller.common.Escalator;
33 import com.rapiddweller.common.LoggerEscalator;
34 import com.rapiddweller.common.SystemInfo;
35 import com.rapiddweller.common.bean.ArrayPropertyExtractor;
36 import com.rapiddweller.common.converter.ArrayConverter;
37 import com.rapiddweller.common.converter.ConverterChain;
38 import com.rapiddweller.common.converter.NoOpConverter;
39 import com.rapiddweller.common.format.PadFormat;
40 import com.rapiddweller.format.DataIterator;
41 import com.rapiddweller.format.DataSource;
42 import com.rapiddweller.format.fixedwidth.FixedWidthColumnDescriptor;
43 import com.rapiddweller.format.fixedwidth.FixedWidthLineSource;
44 import com.rapiddweller.format.fixedwidth.FixedWidthRowTypeDescriptor;
45 import com.rapiddweller.format.fixedwidth.FixedWidthUtil;
46 import com.rapiddweller.format.util.ConvertingDataIterator;
47 import com.rapiddweller.model.data.ComplexTypeDescriptor;
48 import com.rapiddweller.model.data.Entity;
49 import com.rapiddweller.model.data.FileBasedEntitySource;
50 import com.rapiddweller.platform.array.Array2EntityConverter;
51
52 import java.text.ParseException;
53 import java.util.Locale;
54
55
56
57
58
59
60
61
62
63 public class FixedWidthEntitySource extends FileBasedEntitySource {
64
65 private static final Escalator escalator = new LoggerEscalator();
66
67
68
69 protected DataSource<String[]> source;
70
71
72
73 protected Converter<String[], Entity> converter;
74 private Locale locale;
75 private String encoding;
76 private String entityTypeName;
77 private ComplexTypeDescriptor entityDescriptor;
78 private FixedWidthColumnDescriptor[] descriptors;
79 private String lineFilter;
80 private final boolean initialized;
81 private final Converter<String, String> preprocessor;
82
83
84
85
86 public FixedWidthEntitySource() {
87 this(null, null, SystemInfo.getFileEncoding(), null);
88 }
89
90
91
92
93
94
95
96
97
98
99 public FixedWidthEntitySource(String uri, ComplexTypeDescriptor entityDescriptor,
100 String encoding, String lineFilter, FixedWidthColumnDescriptor... descriptors) {
101 this(uri, entityDescriptor, new NoOpConverter<>(), encoding, lineFilter, descriptors);
102 }
103
104
105
106
107
108
109
110
111
112
113
114 public FixedWidthEntitySource(String uri, ComplexTypeDescriptor entityDescriptor,
115 Converter<String, String> preprocessor, String encoding, String lineFilter,
116 FixedWidthColumnDescriptor... descriptors) {
117 super(uri);
118 this.locale = Locale.getDefault();
119 this.encoding = encoding;
120 this.entityDescriptor = entityDescriptor;
121 this.entityTypeName = (entityDescriptor != null ? entityDescriptor.getName() : null);
122 this.descriptors = descriptors;
123 this.preprocessor = preprocessor;
124 this.initialized = false;
125 this.lineFilter = lineFilter;
126 }
127
128
129
130
131
132
133
134
135 public void setLocale(Locale locale) {
136 this.locale = locale;
137 }
138
139
140
141
142
143
144 public void setEncoding(String encoding) {
145 this.encoding = encoding;
146 }
147
148
149
150
151
152
153 public String getEntity() {
154 return entityTypeName;
155 }
156
157
158
159
160
161
162 public void setEntity(String entity) {
163 this.entityTypeName = entity;
164 }
165
166
167
168
169
170
171
172
173 @Deprecated
174 public void setProperties(String properties) throws ParseException {
175 escalator.escalate("The property 'properties' of class " + getClass() + "' has been renamed to 'columns'. " +
176 "Please fix the property name in your configuration", this.getClass(), "setProperties()");
177 setColumns(properties);
178 }
179
180
181
182
183
184
185
186 public void setColumns(String columns) throws ParseException {
187 FixedWidthRowTypeDescriptor rowTypeDescriptor = FixedWidthUtil.parseBeanColumnsSpec(
188 columns, entityTypeName, null, this.locale);
189 this.descriptors = rowTypeDescriptor.getColumnDescriptors();
190 }
191
192
193
194
195
196
197
198
199 public void setLineFilter(String lineFilter) {
200 this.lineFilter = lineFilter;
201 }
202
203 @Override
204 public Class<Entity> getType() {
205 if (!initialized) {
206 init();
207 }
208 return Entity.class;
209 }
210
211 @Override
212 public DataIterator<Entity> iterator() {
213 if (!initialized) {
214 init();
215 }
216 return new ConvertingDataIterator<>(this.source.iterator(), converter);
217 }
218
219
220
221 private void init() {
222 if (this.entityDescriptor == null) {
223 this.entityDescriptor = new ComplexTypeDescriptor(entityTypeName, context.getLocalDescriptorProvider());
224 }
225 if (ArrayUtil.isEmpty(descriptors)) {
226 throw new InvalidGeneratorSetupException("Missing column descriptors. " +
227 "Use the 'columns' property of the " + getClass().getSimpleName() + " to define them.");
228 }
229 this.source = createSource();
230 this.converter = createConverter();
231 }
232
233 private DataSource<String[]> createSource() {
234 PadFormat[] formats = ArrayPropertyExtractor.convert(descriptors, "format", PadFormat.class);
235 return new FixedWidthLineSource(resolveUri(), formats, true, encoding, lineFilter);
236 }
237
238 @SuppressWarnings("unchecked")
239 private Converter<String[], Entity> createConverter() {
240 String[] featureNames = ArrayPropertyExtractor.convert(descriptors, "name", String.class);
241 Array2EntityConverterrter.html#Array2EntityConverter">Array2EntityConverter a2eConverter = new Array2EntityConverter(entityDescriptor, featureNames, true);
242 Converter<String[], String[]> aConv = new ArrayConverter<>(String.class, String.class, preprocessor);
243 return new ConverterChain<>(aConv, a2eConverter);
244 }
245
246 }