1
2
3
4
5
6
7
8
9
10
11
12
13
14 package olg.csv.bean.loader;
15
16 import java.io.File;
17 import java.io.IOException;
18 import java.lang.reflect.Method;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22
23 import javax.xml.parsers.ParserConfigurationException;
24 import javax.xml.xpath.XPathConstants;
25 import javax.xml.xpath.XPathExpressionException;
26
27 import olg.csv.base.Cell;
28 import olg.csv.bean.filter.AbstractStringFilter;
29 import olg.csv.bean.formatter.Formatter;
30 import olg.csv.bean.impl.CellProcessor;
31 import olg.csv.bean.impl.PropertyFormatter;
32 import olg.csv.bean.loader.filter.AbstractFiltreLoader;
33
34 import org.w3c.dom.Document;
35 import org.w3c.dom.Element;
36 import org.w3c.dom.NodeList;
37 import org.xml.sax.SAXException;
38
39
40
41
42
43
44
45
46
47
48 public class CellProcessorLoader<B> {
49
50
51
52 protected static final String ATTR_NAME = "name";
53
54
55
56 protected static final String ATTR_CLASS = "class";
57
58
59
60 protected static final String ATTR_RANG = "rang";
61
62
63
64 protected static final String EL_COLUMN = "column";
65
66
67
68 protected static final String EL_FORMATTER = "formatter";
69
70
71
72 protected static final String EL_FILTER = "filter";
73
74
75
76 protected static final String EL_PROPERTY = "property";
77
78
79
80 protected static final String EL_PROPERTIES = "properties";
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 public List<CellProcessor<B>> load(File file) throws LoadException {
102 if (file == null) {
103 throw new IllegalArgumentException("file argument must be not null");
104 }
105 List<CellProcessor<B>> retour = null;
106 Document doc;
107 try {
108 Util.validate(file);
109 doc = Util.openDocument(file);
110 Element element = (Element) Util.evaluerDOM(doc, "/bean-writer", XPathConstants.NODE);
111
112 if (element != null) {
113 @SuppressWarnings("unchecked")
114 Class<B> beanClass = (Class<B>) Class.forName(element.getAttribute(ATTR_CLASS));
115 if (!Util.checkBean(beanClass)) {
116 throw new LoadException(beanClass + " should be a bean class");
117 }
118 retour = load(element, EL_COLUMN, beanClass);
119
120 } else {
121 element = (Element) Util.evaluerDOM(doc, "/bean-row", XPathConstants.NODE);
122 if (element == null) {
123 throw new LoadException("Root XML Element must be bean-writer or row-bean to create a Bean Writer");
124
125 } else {
126 @SuppressWarnings("unchecked")
127 Class<B> beanClass = (Class<B>) Class.forName(element.getAttribute(ATTR_CLASS));
128 if (!Util.checkBean(beanClass)) {
129 throw new LoadException(beanClass + " should be a bean class");
130 }
131 retour = new RowBeanPropertyFormatterLoader<B>().load(element, EL_PROPERTY, beanClass);
132 }
133
134 }
135
136 } catch (ParserConfigurationException e) {
137 throw new LoadException(e);
138 } catch (SAXException e) {
139 throw new LoadException(e);
140 } catch (IOException e) {
141 throw new LoadException(e);
142 } catch (XPathExpressionException e) {
143 throw new LoadException(e);
144 } catch (ClassNotFoundException e) {
145 throw new LoadException(e);
146 }
147 return retour;
148
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 protected <E> List<CellProcessor<B>> load(Element element, String xmlListNodeName, Class<E> beanClass)
211 throws ClassNotFoundException, LoadException, XPathExpressionException {
212
213 NodeList liste = (NodeList) Util.evaluerDOM(element, xmlListNodeName, XPathConstants.NODESET);
214 List<CellProcessor<B>> cellProcessors = new ArrayList<CellProcessor<B>>();
215
216 for (int i = 0; i < liste.getLength(); i++) {
217 cellProcessors.addAll(extractColumnType((Element) liste.item(i), beanClass));
218 }
219 Collections.sort(cellProcessors);
220 return cellProcessors;
221 }
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 protected <E> List<CellProcessor<B>> extractColumnType(Element element, Class<E> beanClass) throws LoadException,
246 XPathExpressionException, ClassNotFoundException {
247 List<CellProcessor<B>> formatters = new ArrayList<CellProcessor<B>>(1);
248 String name = Util.emptyToNull(element.getAttribute(ATTR_NAME));
249 String rang = element.getAttribute(ATTR_RANG);
250
251 name = (name == null ? Cell.defaultCellName(rang) : name);
252
253
254
255 formatters.add(new CellProcessor<B>(rang, name, extractConcateReadPropertyType(
256 (Element) Util.evaluerDOM(element, EL_PROPERTIES, XPathConstants.NODE), beanClass)));
257 return formatters;
258 }
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280 private static PropertyFormatter extractConcateReadPropertyType(Element element, Class<?> beanClass)
281 throws LoadException, XPathExpressionException, ClassNotFoundException {
282
283 NodeList liste = (NodeList) Util.evaluerDOM(element, EL_PROPERTY, XPathConstants.NODESET);
284 List<PropertyFormatter> formatters = new ArrayList<PropertyFormatter>();
285 for (int i = 0; i < liste.getLength(); i++) {
286 formatters.add(extractReadPropertyType((Element) liste.item(i), beanClass));
287 }
288
289 AbstractStringFilter filtre = AbstractFiltreLoader.getInstance().getFilter(
290 (Element) Util.evaluerDOM(element, EL_FILTER, XPathConstants.NODE));
291
292 return PropertyFormatter.getConcatePropertyReader(formatters, filtre);
293
294 }
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314 private static PropertyFormatter extractReadPropertyType(Element element, Class<?> classBean) throws LoadException,
315 XPathExpressionException, ClassNotFoundException {
316 PropertyFormatter retour = null;
317 String name = element.getAttribute(ATTR_NAME);
318 Element delegateElement = (Element) Util.evaluerDOM(element, EL_PROPERTIES, XPathConstants.NODE);
319 Method method = olg.csv.bean.Util.identifyGetter(classBean, name);
320 if (method == null) {
321 throw new LoadException("Unrecognized property " + name + " from " + classBean);
322 }
323
324 if (delegateElement != null) {
325 String className = Util.emptyToNull(element.getAttribute(ATTR_CLASS));
326 Class<?> propertyClass = (className != null ? Class.forName(className) : method.getReturnType());
327
328
329
330
331
332
333 PropertyFormatter propertyFormatter = extractConcateReadPropertyType(delegateElement, propertyClass);
334 retour = PropertyFormatter.getDelegatePropertyReader(method, name, propertyFormatter);
335
336 } else {
337 AbstractStringFilter filtre = AbstractFiltreLoader.getInstance().getFilter(
338 (Element) Util.evaluerDOM(element, EL_FILTER, XPathConstants.NODE));
339 Formatter<?> formatter = AbstractFormatterLoader.getInstance().getFormatter(
340 (Element) Util.evaluerDOM(element, EL_FORMATTER, XPathConstants.NODE));
341 retour = PropertyFormatter.getPropertyReader(method, name, formatter, filtre);
342 }
343 return retour;
344
345 }
346
347
348
349
350
351
352 protected static final class RowBeanPropertyFormatterLoader<B> extends CellProcessorLoader<B> {
353
354
355
356
357
358
359
360
361
362
363
364 protected <E> void checkLoading(List<CellProcessor<E>> columnFormatters) throws LoadException {
365 int previousRank = -1;
366 int expectedRank = 0;
367 List<String> propertyNames = new ArrayList<String>();
368 for (CellProcessor<E> columnFormatter : columnFormatters) {
369 if (propertyNames.contains(columnFormatter.getPropertyFormatter().getFullName())) {
370 throw new LoadException("the property " + columnFormatter.getPropertyFormatter().getFullName()
371 + " is still mapped");
372 } else {
373 propertyNames.add(columnFormatter.getPropertyFormatter().getFullName());
374 }
375 if (columnFormatter.getRang() == expectedRank) {
376 previousRank = expectedRank++;
377 } else {
378 if (previousRank == -1) {
379 throw new LoadException("The first column is missing at rank 0");
380
381 } else {
382 throw new LoadException("A column is missing after column at rank " + previousRank);
383 }
384 }
385 }
386 }
387
388 @Override
389 protected <E> List<CellProcessor<B>> load(Element element, String xmlListNodeName, Class<E> beanClass)
390 throws ClassNotFoundException, LoadException, XPathExpressionException {
391
392 List<CellProcessor<B>> columnFormatters = super.load(element, xmlListNodeName, beanClass);
393 checkLoading(columnFormatters);
394 return columnFormatters;
395
396 }
397
398
399
400
401
402
403 @Override
404 protected <T> List<CellProcessor<B>> extractColumnType(Element element, Class<T> classBean)
405 throws LoadException, XPathExpressionException, ClassNotFoundException {
406 List<CellProcessor<B>> cellProcessors = new ArrayList<CellProcessor<B>>();
407 String name = element.getAttribute(ATTR_NAME);
408
409 Method method = olg.csv.bean.Util.identifyGetter(classBean, name);
410 if (method == null) {
411 throw new LoadException("No recognized property " + name + " of " + classBean);
412 }
413
414 NodeList liste = (NodeList) Util.evaluerDOM(element, EL_PROPERTY, XPathConstants.NODESET);
415
416 if (liste.getLength() > 0) {
417 String className = Util.emptyToNull(element.getAttribute(ATTR_CLASS));
418 Class<?> propertyClass = (Class<?>) (className != null ? Class.forName(className) : method
419 .getReturnType());
420
421
422
423
424
425
426 for (int i = 0; i < liste.getLength(); i++) {
427 List<CellProcessor<B>> delegatedProcessors = extractColumnType((Element) liste.item(i),
428 propertyClass);
429
430 for (CellProcessor<B> delegatedProcessor : delegatedProcessors) {
431 delegatedProcessor.setPropertyFormatter(PropertyFormatter.getDelegatePropertyReader(method,
432 name, delegatedProcessor.getPropertyFormatter()));
433
434 cellProcessors.add(delegatedProcessor);
435 }
436
437 }
438
439 } else {
440 Formatter<?> formatter = AbstractFormatterLoader.getInstance().getFormatter(
441 (Element) Util.evaluerDOM(element, EL_FORMATTER, XPathConstants.NODE));
442
443 String rang = ((Element) Util.evaluerDOM(element, EL_COLUMN, XPathConstants.NODE))
444 .getAttribute(ATTR_RANG);
445 String columnName = Util.emptyToNull(((Element) Util
446 .evaluerDOM(element, EL_COLUMN, XPathConstants.NODE)).getAttribute(ATTR_NAME));
447 CellProcessor<B> columnFormatter = new CellProcessor<B>(rang, columnName == null ? name : columnName,
448 PropertyFormatter.getPropertyReader(method, name, formatter, null));
449
450 cellProcessors.add(columnFormatter);
451 }
452 return cellProcessors;
453
454 }
455
456 }
457
458 }