1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.xmlfield.core;
17
18 import static com.google.common.collect.Iterables.toArray;
19 import static org.xmlfield.core.internal.XPathUtils.getElementNameWithSelector;
20 import static org.xmlfield.core.internal.XmlFieldUtils.getResourceNamespaces;
21 import static org.xmlfield.core.internal.XmlFieldUtils.getResourceXPath;
22
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.Writer;
26 import java.lang.reflect.InvocationHandler;
27 import java.lang.reflect.Proxy;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32
33 import javax.xml.parsers.ParserConfigurationException;
34 import javax.xml.transform.OutputKeys;
35
36 import org.xml.sax.SAXException;
37 import org.xmlfield.core.api.XmlFieldNode;
38 import org.xmlfield.core.api.XmlFieldNodeList;
39 import org.xmlfield.core.api.XmlFieldNodeModifier;
40 import org.xmlfield.core.api.XmlFieldNodeModifierFactory;
41 import org.xmlfield.core.api.XmlFieldNodeParser;
42 import org.xmlfield.core.api.XmlFieldNodeParserFactory;
43 import org.xmlfield.core.api.XmlFieldObject;
44 import org.xmlfield.core.api.XmlFieldSelector;
45 import org.xmlfield.core.api.XmlFieldSelectorFactory;
46 import org.xmlfield.core.exception.XmlFieldException;
47 import org.xmlfield.core.exception.XmlFieldParsingException;
48 import org.xmlfield.core.exception.XmlFieldXPathException;
49 import org.xmlfield.core.impl.dom.DomNodeParser;
50 import org.xmlfield.core.internal.NamespaceMap;
51 import org.xmlfield.core.internal.XPathUtils;
52 import org.xmlfield.core.internal.XmlFieldInvocationHandler;
53 import org.xmlfield.core.internal.XmlFieldUtils;
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 public class XmlField {
80
81
82
83 private static final ClassLoader classLoader = Thread.currentThread()
84 .getContextClassLoader();
85
86 private static XmlFieldNodeModifierFactory modifierFactory = XmlFieldNodeModifierFactory
87 .newInstance();
88 private static XmlFieldNodeParserFactory parserFactory = XmlFieldNodeParserFactory
89 .newInstance();
90 private static XmlFieldSelectorFactory selectorFactory = XmlFieldSelectorFactory
91 .newInstance();
92
93 private boolean getterCache = false;
94 private XmlFieldNodeModifier modifier;
95
96
97
98 private XmlFieldNodeParser parser;
99
100 private Map<String, String> parserConfiguration;
101
102
103
104 private XmlFieldSelector selector;
105
106
107
108
109
110
111
112 public XmlField() {
113 this(null);
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 public XmlField(Map<String, String> parserConfiguration) {
144 this.parserConfiguration = parserConfiguration;
145 }
146
147
148
149
150
151
152
153
154
155 public XmlFieldNodeModifier _getModifier() {
156 if (modifier == null) {
157 modifier = modifierFactory.newModifier();
158 }
159
160 return modifier;
161 }
162
163
164
165
166
167
168
169
170
171 public XmlFieldNodeParser _getParser() {
172 if (parser == null) {
173 parser = parserFactory.newParser(parserConfiguration);
174 }
175
176 return parser;
177 }
178
179
180
181
182
183
184
185
186 public XmlFieldSelector _getSelector() {
187 if (selector == null) {
188 selector = selectorFactory.newSelector();
189 }
190
191 return selector;
192 }
193
194
195
196
197
198
199
200
201
202
203 public <T> T castObject(Object o, Class<T> type) {
204 return loadProxy(XmlFieldUtils.getXmlFieldNode(o), type);
205 }
206
207
208
209
210
211
212
213
214 public Map<String, String> getParserConfiguration() {
215 return new HashMap<String, String>(parserConfiguration);
216 }
217
218 public boolean isGetterCache() {
219 return getterCache;
220 }
221
222 private <T> T loadProxy(final XmlFieldNode node, final Class<T> type) {
223
224
225 if (String.class.equals(type)) {
226 return type.cast(node.getTextContent());
227 }
228
229 final Class<?>[] types = new Class<?>[] { type, XmlFieldObject.class };
230
231 final InvocationHandler invocationHandler = new XmlFieldInvocationHandler(
232 this, node, type);
233
234 final T proxy = type.cast(Proxy.newProxyInstance(classLoader, types,
235 invocationHandler));
236
237 return proxy;
238 }
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258 public <T> T newObject(Class<T> type) throws XmlFieldParsingException {
259
260
261
262 String resourceXPath = getResourceXPath(type);
263 String tag = getElementNameWithSelector(resourceXPath);
264 NamespaceMap namespaces = getResourceNamespaces(type);
265 String xml = XmlFieldUtils.emptyTag(tag, namespaces);
266
267
268 return xmlToObject(xml, type);
269 }
270
271 public <T> T[] nodeToArray(final String resourceXPath,
272 final XmlFieldNode node, final Class<T> type)
273 throws XmlFieldXPathException {
274
275 final NamespaceMap namespaces = getResourceNamespaces(type);
276
277 final XmlFieldNodeList xmlFieldNodes = _getSelector()
278 .selectXPathToNodeList(namespaces, resourceXPath, node);
279
280 final List<T> list = new ArrayList<T>();
281 for (int i = 0; i < xmlFieldNodes.getLength(); i++) {
282 final T proxy = loadProxy(xmlFieldNodes.item(i), type);
283
284 list.add(proxy);
285 }
286 return toArray(list, type);
287 }
288
289 public <T> T[] nodeToArray(final XmlFieldNode node, final Class<T> type)
290 throws XmlFieldXPathException {
291
292 final String resourceXPath = getResourceXPath(type);
293
294 return nodeToArray(resourceXPath, node, type);
295 }
296
297
298
299
300
301
302
303
304
305
306
307
308 public Object[] nodeToExplicitArray(final String resourceXPath,
309 final XmlFieldNode node,
310 final Map<String, Class<?>> explicitCollection)
311 throws XmlFieldXPathException {
312
313
314 String toReplace = XPathUtils.getElementName(resourceXPath);
315 StringBuilder b = new StringBuilder(resourceXPath);
316 b.replace(resourceXPath.lastIndexOf(toReplace),
317 resourceXPath.lastIndexOf(toReplace) + 1, "*");
318 final String resourceXPathGlobal = b.toString();
319
320
321
322
323 final NamespaceMap namespaces = getResourceNamespaces(null);
324
325 final XmlFieldNodeList xmlFieldNodes = _getSelector()
326 .selectXPathToNodeList(namespaces, resourceXPathGlobal, node);
327
328 final List<Object> list = new ArrayList<Object>();
329
330 for (int i = 0; i < xmlFieldNodes.getLength(); i++) {
331 XmlFieldNode xmlFieldNode = xmlFieldNodes.item(i);
332 if (explicitCollection.containsKey(xmlFieldNode.getNodeName())) {
333 final Object proxy = loadProxy(xmlFieldNode,
334 explicitCollection.get(xmlFieldNode.getNodeName()));
335 list.add(proxy);
336 }
337
338 }
339
340 return toArray(list, Object.class);
341 }
342
343
344
345
346
347
348
349
350
351
352
353
354 public <T> T nodeToObject(final String resourceXPath,
355 final XmlFieldNode node, final Class<T> resourceType) {
356
357 final NamespaceMap namespaces = getResourceNamespaces(resourceType);
358
359 final XmlFieldNode subNode;
360
361 if (resourceXPath == null) {
362
363 subNode = node;
364
365 } else {
366
367 try {
368
369 subNode = _getSelector().selectXPathToNode(namespaces,
370 resourceXPath, node);
371
372 } catch (final XmlFieldXPathException e) {
373
374 throw new RuntimeException(e);
375 }
376 }
377
378 if (subNode == null || subNode.getNode() == null) {
379 return null;
380 } else {
381 return loadProxy(subNode, resourceType);
382 }
383 }
384
385
386
387
388
389
390
391
392
393
394
395
396
397 public <T> T nodeToObject(final XmlFieldNode node, final Class<T> type) {
398
399 return nodeToObject(getResourceXPath(type), node, type);
400 }
401
402 public String nodeToXml(final XmlFieldNode node)
403 throws XmlFieldParsingException {
404 return _getParser().nodeToXml(node);
405 }
406
407 public void nodeToXml(final XmlFieldNode node, Writer writer)
408 throws XmlFieldParsingException {
409 _getParser().nodeToXml(node, writer);
410 }
411
412 public XmlFieldNode objectToNode(Object o) {
413 return XmlFieldUtils.getXmlFieldNode(o);
414 }
415
416 public String objectToXml(Object o) throws XmlFieldParsingException {
417 return _getParser().nodeToXml(objectToNode(o));
418 }
419
420 public void objectToXml(Object o, Writer writer)
421 throws XmlFieldParsingException {
422 _getParser().nodeToXml(objectToNode(o), writer);
423 }
424
425
426
427
428
429
430
431
432
433
434
435 public void setGetterCache(boolean getterCache) {
436 this.getterCache = getterCache;
437 }
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455 public <T> T[] xmlToArray(String xml, Class<T> type)
456 throws XmlFieldException {
457
458 XmlFieldNode node = xmlToNode(xml);
459 T[] resultArray = nodeToArray(
460 getElementNameWithSelector(getResourceXPath(type)), node, type);
461 return resultArray;
462
463 }
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484 public XmlFieldNode xmlToNode(final InputStream xmlInputStream)
485 throws XmlFieldParsingException {
486 return _getParser().xmlToNode(xmlInputStream);
487 }
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507 public XmlFieldNode xmlToNode(final String xml)
508 throws XmlFieldParsingException {
509 return _getParser().xmlToNode(xml);
510 }
511
512
513
514
515
516
517
518 public <T> T xmlToObject(InputStream xmlContent, Class<T> type)
519 throws XmlFieldParsingException {
520 return nodeToObject(xmlToNode(xmlContent), type);
521 }
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540 public <T> T xmlToObject(String xml, Class<T> type)
541 throws XmlFieldParsingException {
542 return nodeToObject(xmlToNode(xml), type);
543 }
544 }