1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.betwixt.io.read;
18
19 import java.beans.IntrospectionException;
20
21 import org.apache.commons.betwixt.AttributeDescriptor;
22 import org.apache.commons.betwixt.BindingConfiguration;
23 import org.apache.commons.betwixt.ElementDescriptor;
24 import org.apache.commons.betwixt.Options;
25 import org.apache.commons.betwixt.XMLBeanInfo;
26 import org.apache.commons.betwixt.XMLIntrospector;
27 import org.apache.commons.betwixt.expression.Context;
28 import org.apache.commons.betwixt.expression.Updater;
29 import org.apache.commons.betwixt.registry.PolymorphicReferenceResolver;
30 import org.apache.commons.betwixt.strategy.ActionMappingStrategy;
31 import org.apache.commons.collections.ArrayStack;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.xml.sax.Attributes;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class ReadContext extends Context {
54 ;
55
56 private ClassLoader classLoader;
57
58 private ReadConfiguration readConfiguration;
59
60 private ArrayStack elementMappingStack = new ArrayStack();
61
62 private ArrayStack actionMappingStack = new ArrayStack();
63
64 private ArrayStack objectStack = new ArrayStack();
65
66 private ArrayStack descriptorStack = new ArrayStack();
67
68 private ArrayStack updaterStack = new ArrayStack();
69
70 private Class rootClass;
71
72 private XMLIntrospector xmlIntrospector;
73
74
75
76
77
78
79
80 public ReadContext(Context context, ReadConfiguration readConfiguration) {
81 super(context);
82 this.readConfiguration = readConfiguration;
83 }
84
85
86
87
88
89
90 public ReadContext(
91 BindingConfiguration bindingConfiguration,
92 ReadConfiguration readConfiguration) {
93 this(
94 LogFactory.getLog(ReadContext.class),
95 bindingConfiguration,
96 readConfiguration);
97 }
98
99
100
101
102
103
104
105 public ReadContext(
106 Log log,
107 BindingConfiguration bindingConfiguration,
108 ReadConfiguration readConfiguration) {
109 super(null, log, bindingConfiguration);
110 this.readConfiguration = readConfiguration;
111 }
112
113
114
115
116
117
118 public ReadContext(ReadContext readContext) {
119 super(readContext);
120 classLoader = readContext.classLoader;
121 readConfiguration = readContext.readConfiguration;
122 }
123
124
125
126
127
128
129
130 public void putBean(String id, Object bean) {
131 getIdMappingStrategy().setReference(this, bean, id);
132 }
133
134
135
136
137
138
139
140 public Object getBean(String id) {
141 return getIdMappingStrategy().getReferenced(this, id);
142 }
143
144
145
146
147 public void clearBeans() {
148 getIdMappingStrategy().reset();
149 }
150
151
152
153
154
155 public ClassLoader getClassLoader() {
156 return classLoader;
157 }
158
159
160
161
162
163 public void setClassLoader(ClassLoader classLoader) {
164 this.classLoader = classLoader;
165 }
166
167
168
169
170
171
172 public BeanCreationChain getBeanCreationChain() {
173 return readConfiguration.getBeanCreationChain();
174 }
175
176
177
178
179
180
181 public ActionMappingStrategy getActionMappingStrategy() {
182 return readConfiguration.getActionMappingStrategy();
183 }
184
185
186
187
188
189
190
191
192
193 public String popElement() {
194
195
196 if (!descriptorStack.isEmpty()) {
197 descriptorStack.pop();
198 }
199
200 if (!updaterStack.isEmpty()) {
201 updaterStack.pop();
202 }
203
204 popOptions();
205
206 Object top = null;
207 if (!elementMappingStack.isEmpty()) {
208 top = elementMappingStack.pop();
209 if (top != null) {
210 if (!(top instanceof String)) {
211 return popElement();
212 }
213 }
214 }
215
216 return (String) top;
217 }
218
219
220
221
222
223
224 public String getCurrentElement() {
225 String result = null;
226 int stackSize = elementMappingStack.size();
227 int i = 0;
228 while ( i < stackSize ) {
229 Object mappedElement = elementMappingStack.peek(i);
230 if (mappedElement instanceof String) {
231 result = (String) mappedElement;
232 break;
233 }
234 ++i;
235 }
236 return result;
237 }
238
239
240
241
242
243
244
245 public Class getLastMappedClass() {
246 Class lastMapped = null;
247 for (int i = 0, size = elementMappingStack.size();
248 i < size;
249 i++) {
250 Object entry = elementMappingStack.peek(i);
251 if (entry instanceof Class) {
252 lastMapped = (Class) entry;
253 break;
254 }
255 }
256 return lastMapped;
257 }
258
259 private ElementDescriptor getParentDescriptor() throws IntrospectionException {
260 ElementDescriptor result = null;
261 if (descriptorStack.size() > 1) {
262 result = (ElementDescriptor) descriptorStack.peek(1);
263 }
264 return result;
265 }
266
267
268
269
270
271
272
273
274 public void pushElement(String elementName) throws Exception {
275
276 elementMappingStack.push(elementName);
277
278
279 ElementDescriptor nextDescriptor = null;
280 if (elementMappingStack.size() == 1 && rootClass != null) {
281 markClassMap(rootClass);
282 XMLBeanInfo rootClassInfo
283 = getXMLIntrospector().introspect(rootClass);
284 nextDescriptor = rootClassInfo.getElementDescriptor();
285 } else {
286 ElementDescriptor currentDescriptor = getCurrentDescriptor();
287 if (currentDescriptor != null) {
288 nextDescriptor = currentDescriptor.getElementDescriptor(elementName);
289 }
290 }
291 Updater updater = null;
292 Options options = null;
293 if (nextDescriptor != null) {
294 updater = nextDescriptor.getUpdater();
295 options = nextDescriptor.getOptions();
296 }
297 updaterStack.push(updater);
298 descriptorStack.push(nextDescriptor);
299 pushOptions(options);
300 }
301
302
303
304
305
306
307
308 public void markClassMap(Class mappedClazz) throws IntrospectionException {
309 if (mappedClazz.isArray()) {
310 mappedClazz = mappedClazz.getComponentType();
311 }
312 elementMappingStack.push(mappedClazz);
313
314 XMLBeanInfo mappedClassInfo = getXMLIntrospector().introspect(mappedClazz);
315 ElementDescriptor mappedElementDescriptor = mappedClassInfo.getElementDescriptor();
316 descriptorStack.push(mappedElementDescriptor);
317
318 Updater updater = mappedElementDescriptor.getUpdater();
319 updaterStack.push(updater);
320 }
321
322
323
324
325
326 public MappingAction popMappingAction() {
327 return (MappingAction) actionMappingStack.pop();
328 }
329
330
331
332
333
334 public void pushMappingAction(MappingAction mappingAction) {
335 actionMappingStack.push(mappingAction);
336 }
337
338
339
340
341
342 public MappingAction currentMappingAction() {
343 if (actionMappingStack.size() == 0)
344 {
345 return null;
346 }
347 return (MappingAction) actionMappingStack.peek();
348 }
349
350 public Object getBean() {
351 return objectStack.peek();
352 }
353
354 public void setBean(Object bean) {
355
356
357
358 }
359
360
361
362
363
364
365 public Object popBean() {
366 return objectStack.pop();
367 }
368
369
370
371
372
373 public void pushBean(Object bean) {
374 objectStack.push(bean);
375 }
376
377
378
379
380
381
382 public XMLIntrospector getXMLIntrospector() {
383
384
385 if (xmlIntrospector == null) {
386 xmlIntrospector = new XMLIntrospector();
387 }
388 return xmlIntrospector;
389 }
390
391
392
393
394
395
396 public void setXMLIntrospector(XMLIntrospector xmlIntrospector) {
397 this.xmlIntrospector = xmlIntrospector;
398 }
399
400 public Class getRootClass() {
401 return rootClass;
402 }
403
404 public void setRootClass(Class rootClass) {
405 this.rootClass = rootClass;
406 }
407
408
409
410
411
412
413
414
415 public ElementDescriptor getCurrentDescriptor() throws Exception {
416 ElementDescriptor result = null;
417 if (!descriptorStack.empty()) {
418 result = (ElementDescriptor) descriptorStack.peek();
419 }
420 return result;
421 }
422
423
424
425
426
427
428
429 public void populateAttributes(
430 AttributeDescriptor[] attributeDescriptors,
431 Attributes attributes) {
432
433 Log log = getLog();
434 if (attributeDescriptors != null) {
435 for (int i = 0, size = attributeDescriptors.length;
436 i < size;
437 i++) {
438 AttributeDescriptor attributeDescriptor =
439 attributeDescriptors[i];
440
441
442
443
444
445 String value =
446 attributes.getValue(
447 attributeDescriptor.getURI(),
448 attributeDescriptor.getLocalName());
449
450 if (value == null) {
451 value =
452 attributes.getValue(
453 attributeDescriptor.getQualifiedName());
454 }
455
456 if (log.isTraceEnabled()) {
457 log.trace("Attr URL:" + attributeDescriptor.getURI());
458 log.trace(
459 "Attr LocalName:" + attributeDescriptor.getLocalName());
460 log.trace(value);
461 }
462
463 Updater updater = attributeDescriptor.getUpdater();
464 log.trace(updater);
465 if (updater != null && value != null) {
466 updater.update(this, value);
467 }
468 }
469 }
470 }
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487 public void pushUpdater(Updater updater) {
488 updaterStack.push(updater);
489 }
490
491
492
493
494
495
496
497
498
499
500 public Updater popUpdater() {
501 return (Updater) updaterStack.pop();
502 }
503
504
505
506
507
508
509
510
511
512
513
514
515 public Updater getCurrentUpdater() {
516
517
518
519
520
521 Updater result = null;
522 if (!updaterStack.empty()) {
523 result = (Updater) updaterStack.peek();
524 if ( result == null && updaterStack.size() >1 ) {
525 result = (Updater) updaterStack.peek(1);
526 }
527 }
528 return result;
529 }
530
531
532
533
534
535
536
537
538 public Class resolvePolymorphicType(ElementMapping mapping) {
539 Class result = null;
540 Log log = getLog();
541 try {
542 ElementDescriptor currentDescriptor = getCurrentDescriptor();
543 if (currentDescriptor != null) {
544 if (currentDescriptor.isPolymorphic()) {
545 PolymorphicReferenceResolver resolver = getXMLIntrospector().getPolymorphicReferenceResolver();
546 result = resolver.resolveType(mapping, this);
547 if (result == null) {
548
549 ElementDescriptor parent = getParentDescriptor();
550 if (parent != null) {
551 ElementDescriptor[] descriptors = parent.getElementDescriptors();
552 ElementDescriptor originalDescriptor = mapping.getDescriptor();
553 boolean resolved = false;
554 for (int i=0; i<descriptors.length;i++) {
555 ElementDescriptor descriptor = descriptors[i];
556 if (descriptor.isPolymorphic()) {
557 mapping.setDescriptor(descriptor);
558 result = resolver.resolveType(mapping, this);
559 if (result != null) {
560 resolved = true;
561 descriptorStack.pop();
562 popOptions();
563 descriptorStack.push(descriptor);
564 pushOptions(descriptor.getOptions());
565 Updater originalUpdater = originalDescriptor.getUpdater();
566 Updater newUpdater = descriptor.getUpdater();
567 substituteUpdater(originalUpdater, newUpdater);
568 break;
569 }
570 }
571 }
572 if (resolved) {
573 log.debug("Resolved polymorphic type");
574 } else {
575 log.debug("Failed to resolve polymorphic type");
576 mapping.setDescriptor(originalDescriptor);
577 }
578 }
579 }
580 }
581 }
582 } catch (Exception e) {
583 log.info("Failed to resolved polymorphic type");
584 log.debug(mapping, e);
585 }
586 return result;
587 }
588
589
590
591
592
593
594 private void substituteUpdater(Updater originalUpdater, Updater newUpdater) {
595
596
597 if (!updaterStack.isEmpty()) {
598 Updater updater = (Updater) updaterStack.pop();
599 if (originalUpdater == null && updater == null) {
600 updaterStack.push(newUpdater);
601 } else if (originalUpdater.equals(updater)) {
602 updaterStack.push(newUpdater);
603 } else {
604 substituteUpdater(originalUpdater, newUpdater);
605 updaterStack.push(updater);
606 }
607 }
608 }
609
610 }