1
2
3
4
5
6
7
8 package net.sf.jour.rt.view.config.impl.runtime;
9
10 import java.util.Iterator;
11
12 import javax.xml.bind.ValidationEvent;
13
14 import org.xml.sax.Attributes;
15 import org.xml.sax.Locator;
16 import org.xml.sax.SAXException;
17
18 import com.sun.xml.bind.JAXBAssertionError;
19 import com.sun.xml.bind.unmarshaller.Tracer;
20
21 /***
22 * Splits the unmarshalling events to bracnhes to support
23 * XML Schema's <all> and RELAX NG's <interleave>
24 *
25 * <p>
26 * This class will be extended by the generated code.
27 *
28 * @optionalRuntime
29 *
30 * @author
31 * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
32 */
33 public abstract class InterleaveDispatcher implements UnmarshallingEventHandler {
34
35 /*** Parent context. */
36 private final UnmarshallingContext parent;
37
38 /*** Branches of an interleave. */
39 protected final Site[] sites;
40
41 /*** Set to true while all the branches are joining. */
42 private boolean isJoining;
43
44 /*** Counts the depth of the element nesting. */
45 private int nestLevel = 0;
46
47 /*** When nestLevel>0, all the events shall be sent to this branch. */
48 private Site currentSite;
49
50
51 protected InterleaveDispatcher( UnmarshallingContext context, int size ) {
52 this.parent = context;
53 sites = new Site[size];
54 for( int i=0; i<size; i++ )
55 sites[i] = new Site();
56 }
57
58 protected void init( UnmarshallingEventHandler[] handlers ) {
59 for( int i=0; i<handlers.length; i++ )
60 sites[i].pushContentHandler(handlers[i],0);
61 }
62
63
64
65 /***
66 * Returns the branch number that consumes the given element,
67 * or -1 if the name is not recognized.
68 */
69 protected abstract int getBranchForElement( String uri, String local );
70
71 /***
72 * Returns the branch number that consumes the given attribute,
73 * or -1 if the name is not recognized.
74 */
75 protected abstract int getBranchForAttribute( String uri, String local );
76
77 /***
78 * Returns the branch number that consumes the text events,
79 * or -1 if no branch is expected to consume it.
80 */
81 protected abstract int getBranchForText();
82
83
84
85
86
87 public Object owner() {
88 if( nestLevel>0 )
89 return currentSite.getCurrentHandler().owner();
90 else
91 throw new JAXBAssertionError();
92 }
93
94 public void enterElement(String uri, String local, String qname, Attributes atts) throws SAXException {
95 if( nestLevel++==0 ) {
96 int idx = getBranchForElement(uri, local);
97 if(idx==-1) {
98
99 joinByEnterElement(null, uri, local, qname, atts);
100 return;
101 }
102 currentSite = sites[idx];
103 }
104
105 currentSite.getCurrentHandler().enterElement(uri, local, qname, atts);
106 }
107 private void joinByEnterElement( Site source, String uri, String local, String qname, Attributes atts ) throws SAXException {
108 if(isJoining) return;
109 isJoining = true;
110
111
112
113
114 for( int i=0; i<sites.length; i++ )
115 if( sites[i]!=source )
116 sites[i].getCurrentHandler().enterElement(uri, local, qname, atts);
117
118
119 parent.popContentHandler();
120 parent.getCurrentHandler().enterElement(uri,local,qname,atts);
121 }
122
123
124 public void leaveElement(String uri, String local, String qname) throws SAXException {
125 if( nestLevel==0 )
126 joinByLeaveElement(null,uri,local,qname);
127 else {
128 currentSite.getCurrentHandler().leaveElement(uri,local,qname);
129
130
131
132 nestLevel--;
133 }
134 }
135 private void joinByLeaveElement(Site source,String uri, String local, String qname) throws SAXException {
136 if(isJoining) return;
137 isJoining = true;
138
139
140
141
142 for( int i=0; i<sites.length; i++ )
143 if( sites[i]!=source )
144 sites[i].getCurrentHandler().leaveElement(uri,local,qname);
145
146
147 parent.popContentHandler();
148 parent.getCurrentHandler().leaveElement(uri,local,qname);
149 }
150
151
152 public void text(String s) throws SAXException {
153 if( nestLevel==0 ) {
154 int idx = getBranchForText();
155 if(idx==-1) {
156 if( s.trim().length()==0 ) {
157
158 } else {
159 joinByText(null,s);
160 }
161 return;
162 }
163 currentSite = sites[idx];
164 }
165
166 currentSite.getCurrentHandler().text(s);
167 }
168 private void joinByText(Site source, String s) throws SAXException {
169 if(isJoining) return;
170 isJoining = true;
171
172
173
174
175 for( int i=0; i<sites.length; i++ )
176 if( sites[i]!=source )
177 sites[i].getCurrentHandler().text(s);
178
179
180 parent.popContentHandler();
181 parent.getCurrentHandler().text(s);
182 }
183
184
185 public void enterAttribute(String uri, String local, String qname) throws SAXException {
186 if( nestLevel++==0 ) {
187 int idx = getBranchForAttribute(uri, local);
188 if(idx==-1) {
189
190 joinByEnterAttribute(null, uri, local, qname);
191 return;
192 }
193 currentSite = sites[idx];
194 }
195
196 currentSite.getCurrentHandler().enterAttribute(uri, local, qname);
197 }
198 private void joinByEnterAttribute( Site source, String uri, String local, String qname ) throws SAXException {
199 if(isJoining) return;
200 isJoining = true;
201
202
203
204
205 for( int i=0; i<sites.length; i++ )
206 if( sites[i]!=source )
207 sites[i].getCurrentHandler().enterAttribute(uri, local, qname);
208
209
210 parent.popContentHandler();
211 parent.getCurrentHandler().enterAttribute(uri,local,qname);
212 }
213
214
215 public void leaveAttribute(String uri, String local, String qname) throws SAXException {
216 if( nestLevel==0 )
217 joinByLeaveAttribute(null,uri,local,qname);
218 else {
219 nestLevel--;
220 currentSite.getCurrentHandler().leaveAttribute(uri,local,qname);
221 }
222 }
223 private void joinByLeaveAttribute(Site source,String uri, String local, String qname) throws SAXException {
224 if(isJoining) return;
225 isJoining = true;
226
227
228
229
230 for( int i=0; i<sites.length; i++ )
231 if( sites[i]!=source )
232 sites[i].getCurrentHandler().leaveAttribute(uri,local,qname);
233
234
235 parent.popContentHandler();
236 parent.getCurrentHandler().leaveAttribute(uri,local,qname);
237 }
238
239 public void leaveChild(int nextState) throws SAXException {
240
241
242 throw new JAXBAssertionError();
243 }
244
245
246 /*** triggers join. */
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268 /***
269 * This implementation will be passed to branches as
270 * the {@link UnmarshallingContext} implementation.
271 *
272 * Used to maintain separate handler stacks for each branch.
273 *
274 * As an {@link UnmarshallingEventHandler}, this object
275 * triggers join.
276 */
277 private class Site implements UnmarshallingContext, UnmarshallingEventHandler {
278
279
280 private UnmarshallingEventHandler[] handlers = new UnmarshallingEventHandler[8];
281 private int[] mementos = new int[8];
282 private int handlerLen=0;
283
284 private Site() {
285 pushContentHandler(this, 0);
286 }
287
288 public void pushContentHandler( UnmarshallingEventHandler handler, int memento ) {
289 if(handlerLen==handlers.length) {
290
291 UnmarshallingEventHandler[] h = new UnmarshallingEventHandler[handlerLen*2];
292 int[] m = new int[handlerLen*2];
293 System.arraycopy(handlers,0,h,0,handlerLen);
294 System.arraycopy(mementos,0,m,0,handlerLen);
295 handlers = h;
296 mementos = m;
297 }
298 handlers[handlerLen] = handler;
299 mementos[handlerLen] = memento;
300 handlerLen++;
301 }
302
303 public void popContentHandler() throws SAXException {
304 handlerLen--;
305 handlers[handlerLen]=null;
306 getCurrentHandler().leaveChild(mementos[handlerLen]);
307 }
308
309 public UnmarshallingEventHandler getCurrentHandler() {
310 return handlers[handlerLen-1];
311 }
312
313
314
315 public Object owner() { return null; }
316 public void enterElement(String uri, String local, String qname, Attributes atts) throws SAXException {
317 joinByEnterElement(this,uri,local,qname,atts);
318 }
319 public void leaveElement(String uri, String local, String qname) throws SAXException {
320 joinByLeaveElement(this,uri,local,qname);
321 }
322 public void enterAttribute(String uri, String local, String qname) throws SAXException {
323 joinByEnterAttribute(this,uri,local,qname);
324 }
325 public void leaveAttribute(String uri, String local, String qname) throws SAXException {
326 joinByLeaveAttribute(this,uri,local,qname);
327 }
328 public void text(String s) throws SAXException {
329 joinByText(this,s);
330 }
331 public void leaveChild(int nextState) throws SAXException {
332 }
333
334
335
336
337 public void addPatcher(Runnable job) {
338 parent.addPatcher(job);
339 }
340
341 public String addToIdTable(String id) {
342 return parent.addToIdTable(id);
343 }
344
345 public void consumeAttribute(int idx) throws SAXException {
346 parent.consumeAttribute(idx);
347 }
348
349 public String eatAttribute(int idx) throws SAXException {
350 return parent.eatAttribute(idx);
351 }
352
353 public int getAttribute(String uri, String name) {
354 return parent.getAttribute(uri, name);
355 }
356
357 public String getBaseUri() {
358 return parent.getBaseUri();
359 }
360
361 public GrammarInfo getGrammarInfo() {
362 return parent.getGrammarInfo();
363 }
364
365 public Locator getLocator() {
366 return parent.getLocator();
367 }
368
369 public String getNamespaceURI(String prefix) {
370 return parent.getNamespaceURI(prefix);
371 }
372
373 public Object getObjectFromId(String id) {
374 return parent.getObjectFromId(id);
375 }
376
377 public String getPrefix(String namespaceURI) {
378 return parent.getPrefix(namespaceURI);
379 }
380
381 public Iterator getPrefixes(String namespaceURI) {
382 return parent.getPrefixes(namespaceURI);
383 }
384
385 public Tracer getTracer() {
386 return parent.getTracer();
387 }
388
389 public Attributes getUnconsumedAttributes() {
390 return parent.getUnconsumedAttributes();
391 }
392
393 public void handleEvent(ValidationEvent event, boolean canRecover) throws SAXException {
394 parent.handleEvent(event,canRecover);
395 }
396
397 public boolean isNotation(String arg0) {
398 return parent.isNotation(arg0);
399 }
400
401 public boolean isUnparsedEntity(String arg0) {
402 return parent.isUnparsedEntity(arg0);
403 }
404
405 public void popAttributes() {
406 parent.popAttributes();
407 }
408
409 public void pushAttributes(Attributes atts,boolean collectTextFlag) {
410 parent.pushAttributes(atts,collectTextFlag);
411 }
412
413 public String resolveNamespacePrefix(String prefix) {
414 return parent.resolveNamespacePrefix(prefix);
415 }
416
417 public String[] getNewlyDeclaredPrefixes() {
418 return parent.getNewlyDeclaredPrefixes();
419 }
420
421 public String[] getAllDeclaredPrefixes() {
422 return parent.getAllDeclaredPrefixes();
423 }
424
425 }
426 }