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.util.ArrayList;
20 import java.util.List;
21
22 import org.apache.commons.betwixt.ElementDescriptor;
23 import org.apache.commons.betwixt.expression.Context;
24 import org.apache.commons.betwixt.expression.Updater;
25 import org.xml.sax.Attributes;
26
27 /***
28 * <p>Acts to bind an array property.
29 * Note that this is intended to be used to map
30 * properties with a setter taking an array
31 * but which do not have an adder.</p>
32 * <p>
33 * <strong>Note</strong> this implementation has state
34 * and therefore cannot be used concurrently (in simultaneous readings).
35 * </p>
36 * @author <a href='http://jakarta.apache.org/'>Jakarta Commons Team</a>
37 * @version $Revision: 155402 $
38 */
39 public class ArrayBindAction extends MappingAction.Base {
40
41
42 /***
43 * Factory method creates implementations to map arrays.
44 * @param elementDescriptor <code>ElementDescriptor</code> to be mapped,
45 * not null
46 * @return <code>MappingAction</code>, not null
47 */
48 public static final MappingAction createMappingAction(ElementDescriptor elementDescriptor) {
49 MappingAction result = new ArrayBindAction();
50 if (elementDescriptor.getSingularPropertyType() != null &&
51 !elementDescriptor.getSingularPropertyType().isArray()) {
52 result = BeanBindAction.INSTANCE;
53 }
54 return result;
55 }
56
57 private BeanMapping beanMapping = new BeanMapping();
58 private Updater originalUpdater;
59
60 /***
61 * Mapping arrays requires the addition of a temporary object
62 * (an <code>ArrayList</code>) into the stack together with an
63 * updater for that object.
64 *
65 */
66 public MappingAction begin(
67 String namespace,
68 String name,
69 Attributes attributes,
70 ReadContext context)
71 throws Exception {
72
73 context.pushBean(new ArrayList());
74 return this;
75 }
76
77 /***
78 * Pops the <code>ArrayList</code> and the updater from
79 * their stacks. The original updater is called with the
80 * result of the convertion.
81 */
82 public void end(ReadContext context) throws Exception {
83 if (originalUpdater != null) {
84
85 List values = (List) context.popBean();
86 originalUpdater.update(context, values);
87 }
88 }
89
90 /*** Construct a delegating implmentation that wraps the real bean creator */
91 public MappingAction next(
92 String namespace,
93 String name,
94 Attributes attributes,
95 ReadContext context)
96 throws Exception {
97 originalUpdater = context.getCurrentUpdater();
98 MappingAction nextBindAction = BeanBindAction.INSTANCE;
99 beanMapping.setDelegate(nextBindAction);
100 return beanMapping;
101 }
102
103
104
105 /*** Updates a list by adding the new value */
106 private static class ListUpdater implements Updater {
107 /*** Singleton */
108 private static final ListUpdater INSTANCE = new ListUpdater();
109
110 /*** Update by adding the new value to the list */
111 public void update(Context context, Object newValue) {
112 List values = (List) context.getBean();
113 values.add(newValue);
114 }
115
116 }
117
118 private static class BeanMapping extends MappingAction.Base {
119 private MappingAction delegate;
120
121 BeanMapping() {}
122
123
124 /***
125 * Gets the action to which the bean binding is delegated.
126 * @return <code>MappingAction</code> delegate, not null
127 */
128 MappingAction getDelegate() {
129 return delegate;
130 }
131
132 /***
133 * Sets the action to which the bean binding is delegated.
134 * @param action< code>MappingAction</code> delegate, not null
135 */
136 void setDelegate(MappingAction action) {
137 delegate = action;
138 }
139
140 /*** Push updater and then delegate */
141 public MappingAction begin(
142 String namespace,
143 String name,
144 Attributes attributes,
145 ReadContext context)
146 throws Exception {
147 context.pushUpdater(ListUpdater.INSTANCE);
148 delegate = delegate.begin(namespace, name, attributes, context);
149 return this;
150 }
151
152 /*** Delegate to delegate (Doh!) */
153 public void body(String text, ReadContext context) throws Exception {
154 delegate.body(text, context);
155 }
156
157 /*** Call delegate then pop <code>Updater</code> */
158 public void end(ReadContext context) throws Exception {
159 delegate.end(context);
160 Updater updater = context.popUpdater();
161 }
162
163 /*** Use delegate to create next action */
164 public MappingAction next(
165 String namespace,
166 String name,
167 Attributes attributes,
168 ReadContext context)
169 throws Exception {
170 return delegate.next(namespace, name, attributes, context);
171 }
172
173
174 }
175 }