1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package net.sf.stax;
25
26 import java.util.List;
27 import java.util.Stack;
28 import java.util.ArrayList;
29
30 import org.xml.sax.Attributes;
31 import org.xml.sax.SAXException;
32
33 /***
34 * For-child dispatch. Use this class to handle multiple child
35 * elements of the same type. The list of values, returned by the
36 * <code>endTree(StAXContext)</code> method, is available to a
37 * parent handler via its <code>endElement(String, String, String,
38 * String, Object, StAXContext)</code> method.
39 *
40 * <p>For example, for the following (sub-)tree:
41 * <pre>
42 * >foo<
43 * >int<0>/int<
44 * >int<1>/int<
45 * >int<2>/int<
46 * >int<3>/int<
47 * >int<4>/int<
48 * >/foo<
49 * </pre>
50 * </p>
51 * <p>Use
52 * <pre>
53 * class FooHandler
54 * extends StAXContentHandlerBase
55 * {
56 * private List integerValues;
57 * private DispatchForChild dispatch = new DispatchForChild(new IntElementHandler());
58 *
59 * public void startElement(..., StAXDelegationContext dctx)
60 * {
61 * dctx.delegate(dispatch);
62 * }
63 *
64 * public void endElement(..., Object result, ...)
65 * {
66 * this.integerValues = (List) result;
67 * }
68 * }
69 * </pre>
70 * </p>
71 *
72 * @author Thomas Down
73 * @author Matthew Pocock
74 * @author Michael Heuer
75 * @version $Revision: 1.3 $ $Date: 2006/01/02 20:37:34 $
76 */
77 public final class DispatchForChild
78 extends StAXContentHandlerBase
79 {
80 /*** Wrapped handler. */
81 private final StAXContentHandler handler;
82
83 /*** Stack of frames. */
84 private final Stack frames;
85
86
87 /***
88 * Create a new for-child dispatch wrapping the specified handler.
89 *
90 * @param handler wrapped handler
91 */
92 public DispatchForChild(final StAXContentHandler handler)
93 {
94 this.handler = handler;
95 frames = new Stack();
96 }
97
98
99 /*** @see StAXContentHandlerBase */
100 public void startTree(final StAXContext ctx)
101 {
102 frames.push(new Frame());
103 }
104
105 /*** @see StAXContentHandlerBase */
106 public void startElement(final String nsURI,
107 final String localName,
108 final String qName,
109 final Attributes attrs,
110 final StAXDelegationContext dctx)
111 throws SAXException
112 {
113 Frame f = (Frame) frames.peek();
114
115 if (f.getDepth() == 1)
116 {
117 dctx.delegate(handler);
118 }
119 else
120 {
121 if (f.getDepth() > 1)
122 {
123 throw new SAXException("Too deep");
124 }
125 }
126 f.setDepth(f.getDepth() + 1);
127 }
128
129 /*** @see StAXContentHandlerBase */
130 public void endElement(final String nsURI,
131 final String localName,
132 final String qName,
133 final Object result,
134 final StAXContext ctx)
135 {
136 Frame f = (Frame) frames.peek();
137
138 f.setDepth(f.getDepth() - 1);
139 if (f.getDepth() == 1)
140 {
141 f.getResults().add(result);
142 }
143 }
144
145 /*** @see StAXContentHandlerBase */
146 public Object endTree(final StAXContext ctx)
147 {
148 Frame f = (Frame) frames.pop();
149 return f.getResults();
150 }
151
152
153 /***
154 * Memento frame class.
155 */
156 private static final class Frame
157 {
158 /*** List of results. */
159 private List results;
160
161 /*** Depth. */
162 private int depth;
163
164
165 /***
166 * Create a new empty frame.
167 */
168 public Frame()
169 {
170 results = new ArrayList();
171 depth = 0;
172 }
173
174
175 /***
176 * Return a modifiable list of results for this frame.
177 *
178 * @return a modifiable list of results for this frame
179 */
180 public List getResults()
181 {
182 return results;
183 }
184
185 /***
186 * Return the depth for this frame.
187 *
188 * @return the depth for this frame
189 */
190 public int getDepth()
191 {
192 return depth;
193 }
194
195 /***
196 * Set the depth for this frame to <code>depth</code>.
197 *
198 * @param depth depth
199 */
200 public void setDepth(final int depth)
201 {
202 this.depth = depth;
203 }
204 }
205 }