89 import org.xml.sax.XMLReader; |
89 import org.xml.sax.XMLReader; |
90 import org.xml.sax.helpers.DefaultHandler; |
90 import org.xml.sax.helpers.DefaultHandler; |
91 |
91 |
92 class SchemaParser { |
92 class SchemaParser { |
93 |
93 |
94 private static final String relaxngURIPrefix = |
94 private static final String relaxngURIPrefix = |
95 WellKnownNamespaces.RELAX_NG.substring(0, WellKnownNamespaces.RELAX_NG.lastIndexOf('/') + 1); |
95 WellKnownNamespaces.RELAX_NG.substring(0, WellKnownNamespaces.RELAX_NG.lastIndexOf('/') + 1); |
96 static final String relaxng10URI = WellKnownNamespaces.RELAX_NG; |
96 static final String relaxng10URI = WellKnownNamespaces.RELAX_NG; |
97 private static final Localizer localizer = new Localizer(new Localizer(Parseable.class),SchemaParser.class); |
97 private static final Localizer localizer = new Localizer(new Localizer(Parseable.class), SchemaParser.class); |
98 |
98 private String relaxngURI; |
99 private String relaxngURI; |
99 private final XMLReader xr; |
100 private final XMLReader xr; |
100 private final ErrorHandler eh; |
101 private final ErrorHandler eh; |
101 private final SchemaBuilder schemaBuilder; |
102 private final SchemaBuilder schemaBuilder; |
|
103 /** |
|
104 * The value of the {@link SchemaBuilder#getNameClassBuilder()} |
|
105 * for the {@link #schemaBuilder} object. |
|
106 */ |
|
107 private final NameClassBuilder nameClassBuilder; |
|
108 private ParsedPattern startPattern; |
|
109 private Locator locator; |
|
110 private final XmlBaseHandler xmlBaseHandler = new XmlBaseHandler(); |
|
111 private final ContextImpl context = new ContextImpl(); |
|
112 |
|
113 private boolean hadError = false; |
|
114 |
|
115 private Hashtable patternTable; |
|
116 private Hashtable nameClassTable; |
|
117 |
|
118 static class PrefixMapping { |
|
119 final String prefix; |
|
120 final String uri; |
|
121 final PrefixMapping next; |
|
122 |
|
123 PrefixMapping(String prefix, String uri, PrefixMapping next) { |
|
124 this.prefix = prefix; |
|
125 this.uri = uri; |
|
126 this.next = next; |
|
127 } |
|
128 } |
|
129 |
|
130 static abstract class AbstractContext extends DtdContext implements Context { |
|
131 PrefixMapping prefixMapping; |
|
132 |
|
133 AbstractContext() { |
|
134 prefixMapping = new PrefixMapping("xml", WellKnownNamespaces.XML, null); |
|
135 } |
|
136 |
|
137 AbstractContext(AbstractContext context) { |
|
138 super(context); |
|
139 prefixMapping = context.prefixMapping; |
|
140 } |
|
141 |
|
142 public String resolveNamespacePrefix(String prefix) { |
|
143 for (PrefixMapping p = prefixMapping; p != null; p = p.next) |
|
144 if (p.prefix.equals(prefix)) |
|
145 return p.uri; |
|
146 return null; |
|
147 } |
|
148 |
|
149 public Enumeration prefixes() { |
|
150 Vector v = new Vector(); |
|
151 for (PrefixMapping p = prefixMapping; p != null; p = p.next) { |
|
152 if (!v.contains(p.prefix)) |
|
153 v.addElement(p.prefix); |
|
154 } |
|
155 return v.elements(); |
|
156 } |
|
157 |
|
158 public Context copy() { |
|
159 return new SavedContext(this); |
|
160 } |
|
161 } |
|
162 |
|
163 static class SavedContext extends AbstractContext { |
|
164 private final String baseUri; |
|
165 SavedContext(AbstractContext context) { |
|
166 super(context); |
|
167 this.baseUri = context.getBaseUri(); |
|
168 } |
|
169 |
|
170 public String getBaseUri() { |
|
171 return baseUri; |
|
172 } |
|
173 } |
|
174 |
|
175 class ContextImpl extends AbstractContext { |
|
176 public String getBaseUri() { |
|
177 return xmlBaseHandler.getBaseUri(); |
|
178 } |
|
179 } |
|
180 |
|
181 static interface CommentHandler { |
|
182 void comment(String value); |
|
183 } |
|
184 |
|
185 abstract class Handler implements ContentHandler, CommentHandler { |
|
186 CommentList comments; |
|
187 |
|
188 CommentList getComments() { |
|
189 CommentList tem = comments; |
|
190 comments = null; |
|
191 return tem; |
|
192 } |
|
193 |
|
194 public void comment(String value) { |
|
195 if (comments == null) |
|
196 comments = schemaBuilder.makeCommentList(); |
|
197 comments.addComment(value, makeLocation()); |
|
198 } |
|
199 public void processingInstruction(String target, String date) { } |
|
200 public void skippedEntity(String name) { } |
|
201 public void ignorableWhitespace(char[] ch, int start, int len) { } |
|
202 public void startDocument() { } |
|
203 public void endDocument() { } |
|
204 public void startPrefixMapping(String prefix, String uri) { |
|
205 context.prefixMapping = new PrefixMapping(prefix, uri, context.prefixMapping); |
|
206 } |
|
207 |
|
208 public void endPrefixMapping(String prefix) { |
|
209 context.prefixMapping = context.prefixMapping.next; |
|
210 } |
|
211 |
|
212 public void setDocumentLocator(Locator loc) { |
|
213 locator = loc; |
|
214 xmlBaseHandler.setLocator(loc); |
|
215 } |
|
216 } |
|
217 |
|
218 abstract class State extends Handler { |
|
219 State parent; |
|
220 String nsInherit; |
|
221 String ns; |
|
222 String datatypeLibrary; |
|
223 /** |
102 /** |
224 * The current scope, or null if there's none. |
103 * The value of the {@link SchemaBuilder#getNameClassBuilder()} for the |
|
104 * {@link #schemaBuilder} object. |
225 */ |
105 */ |
226 Scope scope; |
106 private final NameClassBuilder nameClassBuilder; |
227 Location startLocation; |
107 private ParsedPattern startPattern; |
228 Annotations annotations; |
108 private Locator locator; |
229 |
109 private final XmlBaseHandler xmlBaseHandler = new XmlBaseHandler(); |
230 void set() { |
110 private final ContextImpl context = new ContextImpl(); |
231 xr.setContentHandler(this); |
111 private boolean hadError = false; |
232 } |
112 private Hashtable patternTable; |
233 |
113 private Hashtable nameClassTable; |
234 abstract State create(); |
114 |
235 abstract State createChildState(String localName) throws SAXException; |
115 static class PrefixMapping { |
236 |
116 |
237 |
117 final String prefix; |
238 void setParent(State parent) { |
118 final String uri; |
239 this.parent = parent; |
119 final PrefixMapping next; |
240 this.nsInherit = parent.getNs(); |
120 |
241 this.datatypeLibrary = parent.datatypeLibrary; |
121 PrefixMapping(String prefix, String uri, PrefixMapping next) { |
242 this.scope = parent.scope; |
122 this.prefix = prefix; |
243 this.startLocation = makeLocation(); |
123 this.uri = uri; |
244 if (parent.comments != null) { |
124 this.next = next; |
245 annotations = schemaBuilder.makeAnnotations(parent.comments, getContext()); |
125 } |
246 parent.comments = null; |
126 } |
247 } |
127 |
248 else if (parent instanceof RootState) |
128 static abstract class AbstractContext extends DtdContext implements Context { |
249 annotations = schemaBuilder.makeAnnotations(null, getContext()); |
129 |
250 } |
130 PrefixMapping prefixMapping; |
251 |
131 |
252 String getNs() { |
132 AbstractContext() { |
253 return ns == null ? nsInherit : ns; |
133 prefixMapping = new PrefixMapping("xml", WellKnownNamespaces.XML, null); |
254 } |
134 } |
255 |
135 |
256 boolean isRelaxNGElement(String uri) throws SAXException { |
136 AbstractContext(AbstractContext context) { |
257 return uri.equals(relaxngURI); |
137 super(context); |
258 } |
138 prefixMapping = context.prefixMapping; |
259 |
139 } |
260 public void startElement(String namespaceURI, |
140 |
261 String localName, |
141 public String resolveNamespacePrefix(String prefix) { |
262 String qName, |
142 for (PrefixMapping p = prefixMapping; p != null; p = p.next) { |
263 Attributes atts) throws SAXException { |
143 if (p.prefix.equals(prefix)) { |
264 xmlBaseHandler.startElement(); |
144 return p.uri; |
265 if (isRelaxNGElement(namespaceURI)) { |
145 } |
266 State state = createChildState(localName); |
146 } |
267 if (state == null) { |
147 return null; |
268 xr.setContentHandler(new Skipper(this)); |
148 } |
269 return; |
149 |
270 } |
150 public Enumeration prefixes() { |
271 state.setParent(this); |
151 Vector v = new Vector(); |
272 state.set(); |
152 for (PrefixMapping p = prefixMapping; p != null; p = p.next) { |
273 state.attributes(atts); |
153 if (!v.contains(p.prefix)) { |
274 } |
154 v.addElement(p.prefix); |
275 else { |
155 } |
276 checkForeignElement(); |
156 } |
277 ForeignElementHandler feh = new ForeignElementHandler(this, getComments()); |
157 return v.elements(); |
278 feh.startElement(namespaceURI, localName, qName, atts); |
158 } |
279 xr.setContentHandler(feh); |
159 |
280 } |
160 public Context copy() { |
281 } |
161 return new SavedContext(this); |
282 |
162 } |
283 public void endElement(String namespaceURI, |
163 } |
284 String localName, |
164 |
285 String qName) throws SAXException { |
165 static class SavedContext extends AbstractContext { |
286 xmlBaseHandler.endElement(); |
166 |
287 parent.set(); |
167 private final String baseUri; |
288 end(); |
168 |
289 } |
169 SavedContext(AbstractContext context) { |
290 |
170 super(context); |
291 void setName(String name) throws SAXException { |
171 this.baseUri = context.getBaseUri(); |
292 error("illegal_name_attribute"); |
172 } |
293 } |
173 |
294 |
174 public String getBaseUri() { |
295 void setOtherAttribute(String name, String value) throws SAXException { |
175 return baseUri; |
296 error("illegal_attribute_ignored", name); |
176 } |
297 } |
177 } |
298 |
178 |
299 void endAttributes() throws SAXException { |
179 class ContextImpl extends AbstractContext { |
300 } |
180 |
301 |
181 public String getBaseUri() { |
302 void checkForeignElement() throws SAXException { |
182 return xmlBaseHandler.getBaseUri(); |
303 } |
183 } |
304 |
184 } |
305 void attributes(Attributes atts) throws SAXException { |
185 |
306 int len = atts.getLength(); |
186 static interface CommentHandler { |
307 for (int i = 0; i < len; i++) { |
187 |
308 String uri = atts.getURI(i); |
188 void comment(String value); |
309 if (uri.length() == 0) { |
189 } |
310 String name = atts.getLocalName(i); |
190 |
311 if (name.equals("name")) |
191 abstract class Handler implements ContentHandler, CommentHandler { |
312 setName(atts.getValue(i).trim()); |
192 |
313 else if (name.equals("ns")) |
193 CommentList comments; |
314 ns = atts.getValue(i); |
194 |
315 else if (name.equals("datatypeLibrary")) { |
195 CommentList getComments() { |
316 datatypeLibrary = atts.getValue(i); |
196 CommentList tem = comments; |
317 checkUri(datatypeLibrary); |
197 comments = null; |
318 if (!datatypeLibrary.equals("") |
198 return tem; |
319 && !Uri.isAbsolute(datatypeLibrary)) |
199 } |
320 error("relative_datatype_library"); |
200 |
321 if (Uri.hasFragmentId(datatypeLibrary)) |
201 public void comment(String value) { |
322 error("fragment_identifier_datatype_library"); |
202 if (comments == null) { |
323 datatypeLibrary = Uri.escapeDisallowedChars(datatypeLibrary); |
203 comments = schemaBuilder.makeCommentList(); |
324 } |
204 } |
325 else |
205 comments.addComment(value, makeLocation()); |
326 setOtherAttribute(name, atts.getValue(i)); |
206 } |
327 } |
207 |
328 else if (uri.equals(relaxngURI)) |
208 public void processingInstruction(String target, String date) { |
329 error("qualified_attribute", atts.getLocalName(i)); |
209 } |
330 else if (uri.equals(WellKnownNamespaces.XML) |
210 |
331 && atts.getLocalName(i).equals("base")) |
211 public void skippedEntity(String name) { |
332 xmlBaseHandler.xmlBaseAttribute(atts.getValue(i)); |
212 } |
333 else { |
213 |
334 if (annotations == null) |
214 public void ignorableWhitespace(char[] ch, int start, int len) { |
335 annotations = schemaBuilder.makeAnnotations(null, getContext()); |
215 } |
336 annotations.addAttribute(uri, atts.getLocalName(i), findPrefix(atts.getQName(i), uri), |
216 |
337 atts.getValue(i), startLocation); |
217 public void startDocument() { |
338 } |
218 } |
339 } |
219 |
340 endAttributes(); |
220 public void endDocument() { |
341 } |
221 } |
342 |
222 |
343 abstract void end() throws SAXException; |
223 public void startPrefixMapping(String prefix, String uri) { |
344 |
224 context.prefixMapping = new PrefixMapping(prefix, uri, context.prefixMapping); |
345 void endChild(ParsedPattern pattern) { |
225 } |
346 // XXX cannot happen; throw exception |
226 |
347 } |
227 public void endPrefixMapping(String prefix) { |
348 |
228 context.prefixMapping = context.prefixMapping.next; |
349 void endChild(ParsedNameClass nc) { |
229 } |
350 // XXX cannot happen; throw exception |
230 |
351 } |
231 public void setDocumentLocator(Locator loc) { |
352 |
232 locator = loc; |
353 public void startDocument() { } |
233 xmlBaseHandler.setLocator(loc); |
354 public void endDocument() { |
234 } |
355 if (comments != null && startPattern != null) { |
235 } |
356 startPattern = schemaBuilder.commentAfter(startPattern, comments); |
236 |
357 comments = null; |
237 abstract class State extends Handler { |
358 } |
238 |
359 } |
239 State parent; |
360 |
240 String nsInherit; |
361 public void characters(char[] ch, int start, int len) throws SAXException { |
241 String ns; |
362 for (int i = 0; i < len; i++) { |
242 String datatypeLibrary; |
363 switch(ch[start + i]) { |
243 /** |
364 case ' ': |
244 * The current scope, or null if there's none. |
365 case '\r': |
245 */ |
366 case '\n': |
246 Scope scope; |
367 case '\t': |
247 Location startLocation; |
368 break; |
248 Annotations annotations; |
369 default: |
249 |
370 error("illegal_characters_ignored"); |
250 void set() { |
371 break; |
251 xr.setContentHandler(this); |
372 } |
252 } |
373 } |
253 |
374 } |
254 abstract State create(); |
375 |
255 |
376 boolean isPatternNamespaceURI(String s) { |
256 abstract State createChildState(String localName) throws SAXException; |
377 return s.equals(relaxngURI); |
257 |
378 } |
258 void setParent(State parent) { |
379 |
259 this.parent = parent; |
380 void endForeignChild(ParsedElementAnnotation ea) { |
260 this.nsInherit = parent.getNs(); |
381 if (annotations == null) |
261 this.datatypeLibrary = parent.datatypeLibrary; |
382 annotations = schemaBuilder.makeAnnotations(null, getContext()); |
262 this.scope = parent.scope; |
383 annotations.addElement(ea); |
263 this.startLocation = makeLocation(); |
384 } |
264 if (parent.comments != null) { |
385 |
265 annotations = schemaBuilder.makeAnnotations(parent.comments, getContext()); |
386 void mergeLeadingComments() { |
266 parent.comments = null; |
387 if (comments != null) { |
267 } else if (parent instanceof RootState) { |
388 if (annotations == null) |
268 annotations = schemaBuilder.makeAnnotations(null, getContext()); |
389 annotations = schemaBuilder.makeAnnotations(comments, getContext()); |
269 } |
390 else |
270 } |
391 annotations.addLeadingComment(comments); |
271 |
392 comments = null; |
272 String getNs() { |
393 } |
273 return ns == null ? nsInherit : ns; |
394 } |
274 } |
395 } |
275 |
396 |
276 boolean isRelaxNGElement(String uri) throws SAXException { |
397 class ForeignElementHandler extends Handler { |
277 return uri.equals(relaxngURI); |
398 final State nextState; |
278 } |
399 ElementAnnotationBuilder builder; |
279 |
400 final Stack builderStack = new Stack(); |
280 public void startElement(String namespaceURI, |
401 StringBuffer textBuf; |
281 String localName, |
402 Location textLoc; |
282 String qName, |
403 |
283 Attributes atts) throws SAXException { |
404 ForeignElementHandler(State nextState, CommentList comments) { |
284 xmlBaseHandler.startElement(); |
405 this.nextState = nextState; |
285 if (isRelaxNGElement(namespaceURI)) { |
406 this.comments = comments; |
286 State state = createChildState(localName); |
407 } |
287 if (state == null) { |
408 |
288 xr.setContentHandler(new Skipper(this)); |
409 public void startElement(String namespaceURI, String localName, |
289 return; |
410 String qName, Attributes atts) { |
290 } |
411 flushText(); |
291 state.setParent(this); |
412 if (builder != null) |
292 state.set(); |
413 builderStack.push(builder); |
293 state.attributes(atts); |
414 Location loc = makeLocation(); |
294 } else { |
415 builder = schemaBuilder.makeElementAnnotationBuilder(namespaceURI, |
295 checkForeignElement(); |
416 localName, |
296 ForeignElementHandler feh = new ForeignElementHandler(this, getComments()); |
417 findPrefix(qName, namespaceURI), |
297 feh.startElement(namespaceURI, localName, qName, atts); |
418 loc, |
298 xr.setContentHandler(feh); |
419 getComments(), |
299 } |
420 getContext()); |
300 } |
421 int len = atts.getLength(); |
301 |
422 for (int i = 0; i < len; i++) { |
302 public void endElement(String namespaceURI, |
423 String uri = atts.getURI(i); |
303 String localName, |
424 builder.addAttribute(uri, atts.getLocalName(i), findPrefix(atts.getQName(i), uri), |
304 String qName) throws SAXException { |
425 atts.getValue(i), loc); |
305 xmlBaseHandler.endElement(); |
426 } |
306 parent.set(); |
427 } |
307 end(); |
428 |
308 } |
429 public void endElement(String namespaceURI, String localName, |
309 |
430 String qName) { |
310 void setName(String name) throws SAXException { |
431 flushText(); |
311 error("illegal_name_attribute"); |
432 if (comments != null) |
312 } |
433 builder.addComment(getComments()); |
313 |
434 ParsedElementAnnotation ea = builder.makeElementAnnotation(); |
314 void setOtherAttribute(String name, String value) throws SAXException { |
435 if (builderStack.empty()) { |
315 error("illegal_attribute_ignored", name); |
436 nextState.endForeignChild(ea); |
316 } |
437 nextState.set(); |
317 |
438 } |
318 void endAttributes() throws SAXException { |
439 else { |
319 } |
440 builder = (ElementAnnotationBuilder)builderStack.pop(); |
320 |
441 builder.addElement(ea); |
321 void checkForeignElement() throws SAXException { |
442 } |
322 } |
443 } |
323 |
444 |
324 void attributes(Attributes atts) throws SAXException { |
445 public void characters(char ch[], int start, int length) { |
325 int len = atts.getLength(); |
446 if (textBuf == null) |
326 for (int i = 0; i < len; i++) { |
447 textBuf = new StringBuffer(); |
327 String uri = atts.getURI(i); |
448 textBuf.append(ch, start, length); |
328 if (uri.length() == 0) { |
449 if (textLoc == null) |
329 String name = atts.getLocalName(i); |
450 textLoc = makeLocation(); |
330 if (name.equals("name")) { |
451 } |
331 setName(atts.getValue(i).trim()); |
452 |
332 } else if (name.equals("ns")) { |
453 public void comment(String value) { |
333 ns = atts.getValue(i); |
454 flushText(); |
334 } else if (name.equals("datatypeLibrary")) { |
455 super.comment(value); |
335 datatypeLibrary = atts.getValue(i); |
456 } |
336 checkUri(datatypeLibrary); |
457 |
337 if (!datatypeLibrary.equals("") |
458 void flushText() { |
338 && !Uri.isAbsolute(datatypeLibrary)) { |
459 if (textBuf != null && textBuf.length() != 0) { |
339 error("relative_datatype_library"); |
460 builder.addText(textBuf.toString(), textLoc, getComments()); |
340 } |
461 textBuf.setLength(0); |
341 if (Uri.hasFragmentId(datatypeLibrary)) { |
462 } |
342 error("fragment_identifier_datatype_library"); |
463 textLoc = null; |
343 } |
464 } |
344 datatypeLibrary = Uri.escapeDisallowedChars(datatypeLibrary); |
465 } |
345 } else { |
466 |
346 setOtherAttribute(name, atts.getValue(i)); |
467 class Skipper extends DefaultHandler implements CommentHandler { |
347 } |
468 int level = 1; |
348 } else if (uri.equals(relaxngURI)) { |
469 final State nextState; |
349 error("qualified_attribute", atts.getLocalName(i)); |
470 |
350 } else if (uri.equals(WellKnownNamespaces.XML) |
471 Skipper(State nextState) { |
351 && atts.getLocalName(i).equals("base")) { |
472 this.nextState = nextState; |
352 xmlBaseHandler.xmlBaseAttribute(atts.getValue(i)); |
473 } |
353 } else { |
474 |
354 if (annotations == null) { |
475 public void startElement(String namespaceURI, |
355 annotations = schemaBuilder.makeAnnotations(null, getContext()); |
476 String localName, |
356 } |
477 String qName, |
357 annotations.addAttribute(uri, atts.getLocalName(i), findPrefix(atts.getQName(i), uri), |
478 Attributes atts) throws SAXException { |
358 atts.getValue(i), startLocation); |
479 ++level; |
359 } |
480 } |
360 } |
481 |
361 endAttributes(); |
482 public void endElement(String namespaceURI, |
362 } |
483 String localName, |
363 |
484 String qName) throws SAXException { |
364 abstract void end() throws SAXException; |
485 if (--level == 0) |
365 |
486 nextState.set(); |
366 void endChild(ParsedPattern pattern) { |
487 } |
367 // XXX cannot happen; throw exception |
488 |
368 } |
489 public void comment(String value) { |
369 |
490 } |
370 void endChild(ParsedNameClass nc) { |
491 } |
371 // XXX cannot happen; throw exception |
492 |
372 } |
493 abstract class EmptyContentState extends State { |
373 |
494 |
374 @Override |
495 State createChildState(String localName) throws SAXException { |
375 public void startDocument() { |
496 error("expected_empty", localName); |
376 } |
497 return null; |
377 |
498 } |
378 @Override |
499 |
379 public void endDocument() { |
500 abstract ParsedPattern makePattern() throws SAXException; |
380 if (comments != null && startPattern != null) { |
501 |
381 startPattern = schemaBuilder.commentAfter(startPattern, comments); |
502 void end() throws SAXException { |
382 comments = null; |
503 if (comments != null) { |
383 } |
504 if (annotations == null) |
384 } |
505 annotations = schemaBuilder.makeAnnotations(null, getContext()); |
385 |
506 annotations.addComment(comments); |
386 public void characters(char[] ch, int start, int len) throws SAXException { |
507 comments = null; |
387 for (int i = 0; i < len; i++) { |
508 } |
388 switch (ch[start + i]) { |
509 parent.endChild(makePattern()); |
389 case ' ': |
510 } |
390 case '\r': |
511 } |
391 case '\n': |
512 |
392 case '\t': |
513 static private final int INIT_CHILD_ALLOC = 5; |
393 break; |
514 |
394 default: |
515 abstract class PatternContainerState extends State { |
395 error("illegal_characters_ignored"); |
516 List<ParsedPattern> childPatterns; |
396 break; |
517 |
397 } |
518 State createChildState(String localName) throws SAXException { |
398 } |
519 State state = (State)patternTable.get(localName); |
399 } |
520 if (state == null) { |
400 |
521 error("expected_pattern", localName); |
401 boolean isPatternNamespaceURI(String s) { |
522 return null; |
402 return s.equals(relaxngURI); |
523 } |
403 } |
524 return state.create(); |
404 |
525 } |
405 void endForeignChild(ParsedElementAnnotation ea) { |
526 |
406 if (annotations == null) { |
527 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
407 annotations = schemaBuilder.makeAnnotations(null, getContext()); |
528 if (patterns.size() == 1 && anno == null) |
408 } |
529 return patterns.get(0); |
409 annotations.addElement(ea); |
530 return schemaBuilder.makeGroup(patterns, loc, anno); |
410 } |
531 } |
411 |
532 |
412 void mergeLeadingComments() { |
533 void endChild(ParsedPattern pattern) { |
413 if (comments != null) { |
534 if (childPatterns == null) |
414 if (annotations == null) { |
535 childPatterns = new ArrayList<ParsedPattern>(INIT_CHILD_ALLOC); |
415 annotations = schemaBuilder.makeAnnotations(comments, getContext()); |
536 childPatterns.add(pattern); |
416 } else { |
537 } |
417 annotations.addLeadingComment(comments); |
538 |
418 } |
539 void endForeignChild(ParsedElementAnnotation ea) { |
419 comments = null; |
540 if (childPatterns == null) |
420 } |
541 super.endForeignChild(ea); |
421 } |
542 else { |
422 } |
543 int idx = childPatterns.size()-1; |
423 |
544 childPatterns.set(idx, schemaBuilder.annotateAfter(childPatterns.get(idx), ea)); |
424 class ForeignElementHandler extends Handler { |
545 } |
425 |
546 } |
426 final State nextState; |
547 |
427 ElementAnnotationBuilder builder; |
548 void end() throws SAXException { |
428 final Stack builderStack = new Stack(); |
549 if (childPatterns == null) { |
429 StringBuffer textBuf; |
550 error("missing_children"); |
430 Location textLoc; |
551 endChild(schemaBuilder.makeErrorPattern()); |
431 |
552 } |
432 ForeignElementHandler(State nextState, CommentList comments) { |
553 if (comments != null) { |
433 this.nextState = nextState; |
554 int idx = childPatterns.size()-1; |
434 this.comments = comments; |
555 childPatterns.set(idx,schemaBuilder.commentAfter(childPatterns.get(idx), comments)); |
435 } |
556 comments = null; |
436 |
557 } |
437 public void startElement(String namespaceURI, String localName, |
558 sendPatternToParent(buildPattern(childPatterns, startLocation, annotations)); |
438 String qName, Attributes atts) { |
559 } |
439 flushText(); |
560 |
440 if (builder != null) { |
561 void sendPatternToParent(ParsedPattern p) { |
441 builderStack.push(builder); |
562 parent.endChild(p); |
442 } |
563 } |
443 Location loc = makeLocation(); |
564 } |
444 builder = schemaBuilder.makeElementAnnotationBuilder(namespaceURI, |
565 |
445 localName, |
566 class GroupState extends PatternContainerState { |
446 findPrefix(qName, namespaceURI), |
567 State create() { |
447 loc, |
568 return new GroupState(); |
448 getComments(), |
569 } |
449 getContext()); |
570 } |
450 int len = atts.getLength(); |
571 |
451 for (int i = 0; i < len; i++) { |
572 class ZeroOrMoreState extends PatternContainerState { |
452 String uri = atts.getURI(i); |
573 State create() { |
453 builder.addAttribute(uri, atts.getLocalName(i), findPrefix(atts.getQName(i), uri), |
574 return new ZeroOrMoreState(); |
454 atts.getValue(i), loc); |
575 } |
455 } |
576 |
456 } |
577 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
457 |
578 return schemaBuilder.makeZeroOrMore(super.buildPattern(patterns, loc, null), loc, anno); |
458 public void endElement(String namespaceURI, String localName, |
579 } |
459 String qName) { |
580 } |
460 flushText(); |
581 |
461 if (comments != null) { |
582 class OneOrMoreState extends PatternContainerState { |
462 builder.addComment(getComments()); |
583 State create() { |
463 } |
584 return new OneOrMoreState(); |
464 ParsedElementAnnotation ea = builder.makeElementAnnotation(); |
585 } |
465 if (builderStack.empty()) { |
586 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
466 nextState.endForeignChild(ea); |
587 return schemaBuilder.makeOneOrMore(super.buildPattern(patterns, loc, null), loc, anno); |
467 nextState.set(); |
588 } |
468 } else { |
589 } |
469 builder = (ElementAnnotationBuilder) builderStack.pop(); |
590 |
470 builder.addElement(ea); |
591 class OptionalState extends PatternContainerState { |
471 } |
592 State create() { |
472 } |
593 return new OptionalState(); |
473 |
594 } |
474 public void characters(char ch[], int start, int length) { |
595 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
475 if (textBuf == null) { |
596 return schemaBuilder.makeOptional(super.buildPattern(patterns, loc, null), loc, anno); |
476 textBuf = new StringBuffer(); |
597 } |
477 } |
598 } |
478 textBuf.append(ch, start, length); |
599 |
479 if (textLoc == null) { |
600 class ListState extends PatternContainerState { |
480 textLoc = makeLocation(); |
601 State create() { |
481 } |
602 return new ListState(); |
482 } |
603 } |
483 |
604 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
484 @Override |
605 return schemaBuilder.makeList(super.buildPattern(patterns, loc, null), loc, anno); |
485 public void comment(String value) { |
606 } |
486 flushText(); |
607 } |
487 super.comment(value); |
608 |
488 } |
609 class ChoiceState extends PatternContainerState { |
489 |
610 State create() { |
490 void flushText() { |
611 return new ChoiceState(); |
491 if (textBuf != null && textBuf.length() != 0) { |
612 } |
492 builder.addText(textBuf.toString(), textLoc, getComments()); |
613 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
493 textBuf.setLength(0); |
614 return schemaBuilder.makeChoice(patterns, loc, anno); |
494 } |
615 } |
495 textLoc = null; |
616 } |
496 } |
617 |
497 } |
618 class InterleaveState extends PatternContainerState { |
498 |
619 State create() { |
499 static class Skipper extends DefaultHandler implements CommentHandler { |
620 return new InterleaveState(); |
500 |
621 } |
501 int level = 1; |
622 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) { |
502 final State nextState; |
623 return schemaBuilder.makeInterleave(patterns, loc, anno); |
503 |
624 } |
504 Skipper(State nextState) { |
625 } |
505 this.nextState = nextState; |
626 |
506 } |
627 class MixedState extends PatternContainerState { |
507 |
628 State create() { |
508 @Override |
629 return new MixedState(); |
509 public void startElement(String namespaceURI, |
630 } |
510 String localName, |
631 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
511 String qName, |
632 return schemaBuilder.makeMixed(super.buildPattern(patterns, loc, null), loc, anno); |
512 Attributes atts) throws SAXException { |
633 } |
513 ++level; |
634 } |
514 } |
635 |
515 |
636 static interface NameClassRef { |
516 @Override |
637 void setNameClass(ParsedNameClass nc); |
517 public void endElement(String namespaceURI, |
638 } |
518 String localName, |
639 |
519 String qName) throws SAXException { |
640 class ElementState extends PatternContainerState implements NameClassRef { |
520 if (--level == 0) { |
641 ParsedNameClass nameClass; |
521 nextState.set(); |
642 boolean nameClassWasAttribute; |
522 } |
643 String name; |
523 } |
644 |
524 |
645 void setName(String name) { |
525 public void comment(String value) { |
646 this.name = name; |
526 } |
647 } |
527 } |
648 |
528 |
649 public void setNameClass(ParsedNameClass nc) { |
529 abstract class EmptyContentState extends State { |
650 nameClass = nc; |
530 |
651 } |
531 State createChildState(String localName) throws SAXException { |
652 |
532 error("expected_empty", localName); |
653 void endAttributes() throws SAXException { |
533 return null; |
654 if (name != null) { |
534 } |
655 nameClass = expandName(name, getNs(), null); |
535 |
656 nameClassWasAttribute = true; |
536 abstract ParsedPattern makePattern() throws SAXException; |
657 } |
537 |
658 else |
538 void end() throws SAXException { |
659 new NameClassChildState(this, this).set(); |
539 if (comments != null) { |
660 } |
540 if (annotations == null) { |
661 |
541 annotations = schemaBuilder.makeAnnotations(null, getContext()); |
662 State create() { |
542 } |
663 return new ElementState(); |
543 annotations.addComment(comments); |
664 } |
544 comments = null; |
665 |
545 } |
666 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
546 parent.endChild(makePattern()); |
667 return schemaBuilder.makeElement(nameClass, super.buildPattern(patterns, loc, null), loc, anno); |
547 } |
668 } |
548 } |
669 |
549 static private final int INIT_CHILD_ALLOC = 5; |
670 void endForeignChild(ParsedElementAnnotation ea) { |
550 |
671 if (nameClassWasAttribute || childPatterns!=null || nameClass == null) |
551 abstract class PatternContainerState extends State { |
672 super.endForeignChild(ea); |
552 |
673 else |
553 List<ParsedPattern> childPatterns; |
674 nameClass = nameClassBuilder.annotateAfter(nameClass, ea); |
554 |
675 } |
555 State createChildState(String localName) throws SAXException { |
676 } |
556 State state = (State) patternTable.get(localName); |
677 |
557 if (state == null) { |
678 class RootState extends PatternContainerState { |
558 error("expected_pattern", localName); |
679 IncludedGrammar grammar; |
559 return null; |
680 |
560 } |
681 RootState() { |
561 return state.create(); |
682 } |
562 } |
683 |
563 |
684 RootState(IncludedGrammar grammar, Scope scope, String ns) { |
564 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
685 this.grammar = grammar; |
565 if (patterns.size() == 1 && anno == null) { |
686 this.scope = scope; |
566 return patterns.get(0); |
687 this.nsInherit = ns; |
567 } |
688 this.datatypeLibrary = ""; |
568 return schemaBuilder.makeGroup(patterns, loc, anno); |
689 } |
569 } |
690 |
570 |
691 State create() { |
571 @Override |
692 return new RootState(); |
572 void endChild(ParsedPattern pattern) { |
693 } |
573 if (childPatterns == null) { |
694 |
574 childPatterns = new ArrayList<ParsedPattern>(INIT_CHILD_ALLOC); |
695 State createChildState(String localName) throws SAXException { |
575 } |
696 if (grammar == null) |
576 childPatterns.add(pattern); |
697 return super.createChildState(localName); |
577 } |
698 if (localName.equals("grammar")) |
578 |
699 return new MergeGrammarState(grammar); |
579 @Override |
700 error("expected_grammar", localName); |
580 void endForeignChild(ParsedElementAnnotation ea) { |
701 return null; |
581 // Harshit : Annotation handling should always be taken care of, irrespective of childPatterns being null or not. |
702 } |
582 super.endForeignChild(ea); |
703 |
583 if (childPatterns != null) { |
704 void checkForeignElement() throws SAXException { |
584 int idx = childPatterns.size() - 1; |
705 error("root_bad_namespace_uri", WellKnownNamespaces.RELAX_NG); |
585 childPatterns.set(idx, schemaBuilder.annotateAfter(childPatterns.get(idx), ea)); |
706 } |
586 } |
707 |
587 } |
708 void endChild(ParsedPattern pattern) { |
588 |
709 startPattern = pattern; |
589 void end() throws SAXException { |
710 } |
590 if (childPatterns == null) { |
711 |
591 error("missing_children"); |
712 boolean isRelaxNGElement(String uri) throws SAXException { |
592 endChild(schemaBuilder.makeErrorPattern()); |
713 if (!uri.startsWith(relaxngURIPrefix)) |
593 } |
714 return false; |
594 if (comments != null) { |
715 if (!uri.equals(WellKnownNamespaces.RELAX_NG)) |
595 int idx = childPatterns.size() - 1; |
716 warning("wrong_uri_version", |
596 childPatterns.set(idx, schemaBuilder.commentAfter(childPatterns.get(idx), comments)); |
717 WellKnownNamespaces.RELAX_NG.substring(relaxngURIPrefix.length()), |
597 comments = null; |
718 uri.substring(relaxngURIPrefix.length())); |
598 } |
719 relaxngURI = uri; |
599 sendPatternToParent(buildPattern(childPatterns, startLocation, annotations)); |
720 return true; |
600 } |
721 } |
601 |
722 |
602 void sendPatternToParent(ParsedPattern p) { |
723 } |
603 parent.endChild(p); |
724 |
604 } |
725 class NotAllowedState extends EmptyContentState { |
605 } |
726 State create() { |
606 |
727 return new NotAllowedState(); |
607 class GroupState extends PatternContainerState { |
728 } |
608 |
729 |
609 State create() { |
730 ParsedPattern makePattern() { |
610 return new GroupState(); |
731 return schemaBuilder.makeNotAllowed(startLocation, annotations); |
611 } |
732 } |
612 } |
733 } |
613 |
734 |
614 class ZeroOrMoreState extends PatternContainerState { |
735 class EmptyState extends EmptyContentState { |
615 |
736 State create() { |
616 State create() { |
737 return new EmptyState(); |
617 return new ZeroOrMoreState(); |
738 } |
618 } |
739 |
619 |
740 ParsedPattern makePattern() { |
620 @Override |
741 return schemaBuilder.makeEmpty(startLocation, annotations); |
621 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
742 } |
622 return schemaBuilder.makeZeroOrMore(super.buildPattern(patterns, loc, null), loc, anno); |
743 } |
623 } |
744 |
624 } |
745 class TextState extends EmptyContentState { |
625 |
746 State create() { |
626 class OneOrMoreState extends PatternContainerState { |
747 return new TextState(); |
627 |
748 } |
628 State create() { |
749 |
629 return new OneOrMoreState(); |
750 ParsedPattern makePattern() { |
630 } |
751 return schemaBuilder.makeText(startLocation, annotations); |
631 |
752 } |
632 @Override |
753 } |
633 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
754 |
634 return schemaBuilder.makeOneOrMore(super.buildPattern(patterns, loc, null), loc, anno); |
755 class ValueState extends EmptyContentState { |
635 } |
756 final StringBuffer buf = new StringBuffer(); |
636 } |
757 String type; |
637 |
758 |
638 class OptionalState extends PatternContainerState { |
759 State create() { |
639 |
760 return new ValueState(); |
640 State create() { |
761 } |
641 return new OptionalState(); |
762 |
642 } |
763 void setOtherAttribute(String name, String value) throws SAXException { |
643 |
764 if (name.equals("type")) |
644 @Override |
765 type = checkNCName(value.trim()); |
645 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
766 else |
646 return schemaBuilder.makeOptional(super.buildPattern(patterns, loc, null), loc, anno); |
767 super.setOtherAttribute(name, value); |
647 } |
768 } |
648 } |
769 |
649 |
770 public void characters(char[] ch, int start, int len) { |
650 class ListState extends PatternContainerState { |
771 buf.append(ch, start, len); |
651 |
772 } |
652 State create() { |
773 |
653 return new ListState(); |
774 void checkForeignElement() throws SAXException { |
654 } |
775 error("value_contains_foreign_element"); |
655 |
776 } |
656 @Override |
777 |
657 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
778 ParsedPattern makePattern() throws SAXException { |
658 return schemaBuilder.makeList(super.buildPattern(patterns, loc, null), loc, anno); |
779 if (type == null) |
659 } |
780 return makePattern("", "token"); |
660 } |
781 else |
661 |
782 return makePattern(datatypeLibrary, type); |
662 class ChoiceState extends PatternContainerState { |
783 } |
663 |
784 |
664 State create() { |
785 void end() throws SAXException { |
665 return new ChoiceState(); |
786 mergeLeadingComments(); |
666 } |
787 super.end(); |
667 |
788 } |
668 @Override |
789 |
669 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
790 ParsedPattern makePattern(String datatypeLibrary, String type) { |
670 return schemaBuilder.makeChoice(patterns, loc, anno); |
791 return schemaBuilder.makeValue(datatypeLibrary, |
671 } |
792 type, |
672 } |
793 buf.toString(), |
673 |
794 getContext(), |
674 class InterleaveState extends PatternContainerState { |
795 getNs(), |
675 |
796 startLocation, |
676 State create() { |
797 annotations); |
677 return new InterleaveState(); |
798 } |
678 } |
799 |
679 |
800 } |
680 @Override |
801 |
681 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) { |
802 class DataState extends State { |
682 return schemaBuilder.makeInterleave(patterns, loc, anno); |
803 String type; |
683 } |
804 ParsedPattern except = null; |
684 } |
805 DataPatternBuilder dpb = null; |
685 |
806 |
686 class MixedState extends PatternContainerState { |
807 State create() { |
687 |
808 return new DataState(); |
688 State create() { |
809 } |
689 return new MixedState(); |
810 |
690 } |
811 State createChildState(String localName) throws SAXException { |
691 |
812 if (localName.equals("param")) { |
692 @Override |
813 if (except != null) |
693 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
814 error("param_after_except"); |
694 return schemaBuilder.makeMixed(super.buildPattern(patterns, loc, null), loc, anno); |
815 return new ParamState(dpb); |
695 } |
816 } |
696 } |
817 if (localName.equals("except")) { |
697 |
818 if (except != null) |
698 static interface NameClassRef { |
819 error("multiple_except"); |
699 |
820 return new ChoiceState(); |
700 void setNameClass(ParsedNameClass nc); |
821 } |
701 } |
822 error("expected_param_except", localName); |
702 |
823 return null; |
703 class ElementState extends PatternContainerState implements NameClassRef { |
824 } |
704 |
825 |
705 ParsedNameClass nameClass; |
826 void setOtherAttribute(String name, String value) throws SAXException { |
706 boolean nameClassWasAttribute; |
827 if (name.equals("type")) |
707 String name; |
828 type = checkNCName(value.trim()); |
708 |
829 else |
709 @Override |
830 super.setOtherAttribute(name, value); |
710 void setName(String name) { |
831 } |
711 this.name = name; |
832 |
712 } |
833 void endAttributes() throws SAXException { |
713 |
834 if (type == null) |
714 public void setNameClass(ParsedNameClass nc) { |
835 error("missing_type_attribute"); |
715 nameClass = nc; |
836 else |
716 } |
837 dpb = schemaBuilder.makeDataPatternBuilder(datatypeLibrary, type, startLocation); |
717 |
838 } |
718 @Override |
839 |
719 void endAttributes() throws SAXException { |
840 void endForeignChild(ParsedElementAnnotation ea) { |
720 if (name != null) { |
841 dpb.annotation(ea); |
721 nameClass = expandName(name, getNs(), null); |
842 } |
722 nameClassWasAttribute = true; |
843 |
723 } else { |
844 void end() throws SAXException { |
724 new NameClassChildState(this, this).set(); |
845 ParsedPattern p; |
725 } |
846 if (dpb != null) { |
726 } |
847 if (except != null) |
727 |
848 p = dpb.makePattern(except, startLocation, annotations); |
728 State create() { |
849 else |
729 return new ElementState(); |
850 p = dpb.makePattern(startLocation, annotations); |
730 } |
851 } |
731 |
852 else |
732 @Override |
853 p = schemaBuilder.makeErrorPattern(); |
733 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
854 // XXX need to capture comments |
734 return schemaBuilder.makeElement(nameClass, super.buildPattern(patterns, loc, null), loc, anno); |
855 parent.endChild(p); |
735 } |
856 } |
736 |
857 |
737 @Override |
858 void endChild(ParsedPattern pattern) { |
738 void endForeignChild(ParsedElementAnnotation ea) { |
859 except = pattern; |
739 if (nameClassWasAttribute || childPatterns != null || nameClass == null) { |
860 } |
740 super.endForeignChild(ea); |
861 |
741 } else { |
862 } |
742 nameClass = nameClassBuilder.annotateAfter(nameClass, ea); |
863 |
743 } |
864 class ParamState extends State { |
744 } |
865 private final StringBuffer buf = new StringBuffer(); |
745 } |
866 private final DataPatternBuilder dpb; |
746 |
867 private String name; |
747 class RootState extends PatternContainerState { |
868 |
748 |
869 ParamState(DataPatternBuilder dpb) { |
749 IncludedGrammar grammar; |
870 this.dpb = dpb; |
750 |
871 } |
751 RootState() { |
872 |
752 } |
873 State create() { |
753 |
874 return new ParamState(null); |
754 RootState(IncludedGrammar grammar, Scope scope, String ns) { |
875 } |
755 this.grammar = grammar; |
876 |
756 this.scope = scope; |
877 void setName(String name) throws SAXException { |
757 this.nsInherit = ns; |
878 this.name = checkNCName(name); |
758 this.datatypeLibrary = ""; |
879 } |
759 } |
880 |
760 |
881 void endAttributes() throws SAXException { |
761 State create() { |
882 if (name == null) |
762 return new RootState(); |
883 error("missing_name_attribute"); |
763 } |
884 } |
764 |
885 |
765 @Override |
886 State createChildState(String localName) throws SAXException { |
766 State createChildState(String localName) throws SAXException { |
887 error("expected_empty", localName); |
767 if (grammar == null) { |
888 return null; |
768 return super.createChildState(localName); |
889 } |
769 } |
890 |
770 if (localName.equals("grammar")) { |
891 public void characters(char[] ch, int start, int len) { |
771 return new MergeGrammarState(grammar); |
892 buf.append(ch, start, len); |
772 } |
893 } |
773 error("expected_grammar", localName); |
894 |
774 return null; |
895 void checkForeignElement() throws SAXException { |
775 } |
896 error("param_contains_foreign_element"); |
776 |
897 } |
777 @Override |
898 |
778 void checkForeignElement() throws SAXException { |
899 void end() throws SAXException { |
779 error("root_bad_namespace_uri", WellKnownNamespaces.RELAX_NG); |
900 if (name == null) |
780 } |
901 return; |
781 |
902 if (dpb == null) |
782 @Override |
903 return; |
783 void endChild(ParsedPattern pattern) { |
904 mergeLeadingComments(); |
784 startPattern = pattern; |
905 dpb.addParam(name, buf.toString(), getContext(), getNs(), startLocation, annotations); |
785 } |
906 } |
786 |
907 } |
787 @Override |
908 |
788 boolean isRelaxNGElement(String uri) throws SAXException { |
909 class AttributeState extends PatternContainerState implements NameClassRef { |
789 if (!uri.startsWith(relaxngURIPrefix)) { |
910 ParsedNameClass nameClass; |
790 return false; |
911 boolean nameClassWasAttribute; |
791 } |
912 String name; |
792 if (!uri.equals(WellKnownNamespaces.RELAX_NG)) { |
913 |
793 warning("wrong_uri_version", |
914 State create() { |
794 WellKnownNamespaces.RELAX_NG.substring(relaxngURIPrefix.length()), |
915 return new AttributeState(); |
795 uri.substring(relaxngURIPrefix.length())); |
916 } |
796 } |
917 |
797 relaxngURI = uri; |
918 void setName(String name) { |
798 return true; |
919 this.name = name; |
799 } |
920 } |
800 } |
921 |
801 |
922 public void setNameClass(ParsedNameClass nc) { |
802 class NotAllowedState extends EmptyContentState { |
923 nameClass = nc; |
803 |
924 } |
804 State create() { |
925 |
805 return new NotAllowedState(); |
926 void endAttributes() throws SAXException { |
806 } |
927 if (name != null) { |
807 |
928 String nsUse; |
808 ParsedPattern makePattern() { |
929 if (ns != null) |
809 return schemaBuilder.makeNotAllowed(startLocation, annotations); |
930 nsUse = ns; |
810 } |
931 else |
811 } |
932 nsUse = ""; |
812 |
933 nameClass = expandName(name, nsUse, null); |
813 class EmptyState extends EmptyContentState { |
934 nameClassWasAttribute = true; |
814 |
935 } |
815 State create() { |
936 else |
816 return new EmptyState(); |
937 new NameClassChildState(this, this).set(); |
817 } |
938 } |
818 |
939 |
819 ParsedPattern makePattern() { |
940 void endForeignChild(ParsedElementAnnotation ea) { |
820 return schemaBuilder.makeEmpty(startLocation, annotations); |
941 if (nameClassWasAttribute || childPatterns!=null || nameClass == null) |
821 } |
942 super.endForeignChild(ea); |
822 } |
943 else |
823 |
944 nameClass = nameClassBuilder.annotateAfter(nameClass, ea); |
824 class TextState extends EmptyContentState { |
945 } |
825 |
946 |
826 State create() { |
947 void end() throws SAXException { |
827 return new TextState(); |
948 if (childPatterns == null) |
828 } |
949 endChild(schemaBuilder.makeText(startLocation, null)); |
829 |
950 super.end(); |
830 ParsedPattern makePattern() { |
951 } |
831 return schemaBuilder.makeText(startLocation, annotations); |
952 |
832 } |
953 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
833 } |
954 return schemaBuilder.makeAttribute(nameClass, super.buildPattern(patterns, loc, null), loc, anno); |
834 |
955 } |
835 class ValueState extends EmptyContentState { |
956 |
836 |
957 State createChildState(String localName) throws SAXException { |
837 final StringBuffer buf = new StringBuffer(); |
958 State tem = super.createChildState(localName); |
838 String type; |
959 if (tem != null && childPatterns!=null) |
839 |
960 error("attribute_multi_pattern"); |
840 State create() { |
961 return tem; |
841 return new ValueState(); |
962 } |
842 } |
963 |
843 |
964 } |
844 @Override |
965 |
845 void setOtherAttribute(String name, String value) throws SAXException { |
966 abstract class SinglePatternContainerState extends PatternContainerState { |
846 if (name.equals("type")) { |
967 State createChildState(String localName) throws SAXException { |
847 type = checkNCName(value.trim()); |
968 if (childPatterns==null) |
848 } else { |
969 return super.createChildState(localName); |
849 super.setOtherAttribute(name, value); |
970 error("too_many_children"); |
850 } |
971 return null; |
851 } |
972 } |
852 |
973 } |
853 @Override |
974 |
854 public void characters(char[] ch, int start, int len) { |
975 class GrammarSectionState extends State { |
855 buf.append(ch, start, len); |
976 GrammarSection section; |
856 } |
977 |
857 |
978 GrammarSectionState() { } |
858 @Override |
979 |
859 void checkForeignElement() throws SAXException { |
980 GrammarSectionState(GrammarSection section) { |
860 error("value_contains_foreign_element"); |
981 this.section = section; |
861 } |
982 } |
862 |
983 |
863 ParsedPattern makePattern() throws SAXException { |
984 State create() { |
864 if (type == null) { |
985 return new GrammarSectionState(null); |
865 return makePattern("", "token"); |
986 } |
866 } else { |
987 |
867 return makePattern(datatypeLibrary, type); |
988 State createChildState(String localName) throws SAXException { |
868 } |
989 if (localName.equals("define")) |
869 } |
990 return new DefineState(section); |
870 |
991 if (localName.equals("start")) |
871 @Override |
992 return new StartState(section); |
872 void end() throws SAXException { |
993 if (localName.equals("include")) { |
873 mergeLeadingComments(); |
994 Include include = section.makeInclude(); |
874 super.end(); |
995 if (include != null) |
875 } |
996 return new IncludeState(include); |
876 |
997 } |
877 ParsedPattern makePattern(String datatypeLibrary, String type) { |
998 if (localName.equals("div")) |
878 return schemaBuilder.makeValue(datatypeLibrary, |
999 return new DivState(section.makeDiv()); |
879 type, |
1000 error("expected_define", localName); |
880 buf.toString(), |
1001 // XXX better errors |
881 getContext(), |
1002 return null; |
882 getNs(), |
1003 } |
883 startLocation, |
1004 |
884 annotations); |
1005 void end() throws SAXException { |
885 } |
1006 if (comments != null) { |
886 } |
1007 section.topLevelComment(comments); |
887 |
1008 comments = null; |
888 class DataState extends State { |
1009 } |
889 |
1010 } |
890 String type; |
1011 |
891 ParsedPattern except = null; |
1012 void endForeignChild(ParsedElementAnnotation ea) { |
892 DataPatternBuilder dpb = null; |
1013 section.topLevelAnnotation(ea); |
893 |
1014 } |
894 State create() { |
1015 } |
895 return new DataState(); |
1016 |
896 } |
1017 class DivState extends GrammarSectionState { |
897 |
1018 final Div div; |
898 State createChildState(String localName) throws SAXException { |
1019 DivState(Div div) { |
899 if (localName.equals("param")) { |
1020 super(div); |
900 if (except != null) { |
1021 this.div = div; |
901 error("param_after_except"); |
1022 } |
902 } |
1023 |
903 return new ParamState(dpb); |
1024 void end() throws SAXException { |
904 } |
1025 super.end(); |
905 if (localName.equals("except")) { |
1026 div.endDiv(startLocation, annotations); |
906 if (except != null) { |
1027 } |
907 error("multiple_except"); |
1028 } |
908 } |
1029 |
909 return new ChoiceState(); |
1030 class IncludeState extends GrammarSectionState { |
910 } |
1031 String href; |
911 error("expected_param_except", localName); |
1032 final Include include; |
912 return null; |
1033 |
913 } |
1034 IncludeState(Include include) { |
914 |
1035 super(include); |
915 @Override |
1036 this.include = include; |
916 void setOtherAttribute(String name, String value) throws SAXException { |
1037 } |
917 if (name.equals("type")) { |
1038 |
918 type = checkNCName(value.trim()); |
1039 void setOtherAttribute(String name, String value) throws SAXException { |
919 } else { |
1040 if (name.equals("href")) { |
920 super.setOtherAttribute(name, value); |
1041 href = value; |
921 } |
1042 checkUri(href); |
922 } |
1043 } |
923 |
1044 else |
924 @Override |
1045 super.setOtherAttribute(name, value); |
925 void endAttributes() throws SAXException { |
1046 } |
926 if (type == null) { |
1047 |
927 error("missing_type_attribute"); |
1048 void endAttributes() throws SAXException { |
928 } else { |
1049 if (href == null) |
929 dpb = schemaBuilder.makeDataPatternBuilder(datatypeLibrary, type, startLocation); |
1050 error("missing_href_attribute"); |
930 } |
1051 else |
931 } |
1052 href = resolve(href); |
932 |
1053 } |
933 void end() throws SAXException { |
1054 |
934 ParsedPattern p; |
1055 void end() throws SAXException { |
935 if (dpb != null) { |
1056 super.end(); |
936 if (except != null) { |
1057 if (href != null) { |
937 p = dpb.makePattern(except, startLocation, annotations); |
1058 try { |
938 } else { |
1059 include.endInclude(parseable, href, getNs(), startLocation, annotations); |
939 p = dpb.makePattern(startLocation, annotations); |
1060 } |
940 } |
1061 catch (IllegalSchemaException e) { |
941 } else { |
1062 } |
942 p = schemaBuilder.makeErrorPattern(); |
1063 } |
943 } |
1064 } |
944 // XXX need to capture comments |
1065 } |
945 parent.endChild(p); |
1066 |
946 } |
1067 class MergeGrammarState extends GrammarSectionState { |
947 |
1068 final IncludedGrammar grammar; |
948 @Override |
1069 MergeGrammarState(IncludedGrammar grammar) { |
949 void endChild(ParsedPattern pattern) { |
1070 super(grammar); |
950 except = pattern; |
1071 this.grammar = grammar; |
951 } |
1072 } |
952 } |
1073 |
953 |
1074 void end() throws SAXException { |
954 class ParamState extends State { |
1075 super.end(); |
955 |
1076 parent.endChild(grammar.endIncludedGrammar(startLocation, annotations)); |
956 private final StringBuffer buf = new StringBuffer(); |
1077 } |
957 private final DataPatternBuilder dpb; |
1078 } |
958 private String name; |
1079 |
959 |
1080 class GrammarState extends GrammarSectionState { |
960 ParamState(DataPatternBuilder dpb) { |
1081 Grammar grammar; |
961 this.dpb = dpb; |
1082 |
962 } |
1083 void setParent(State parent) { |
963 |
1084 super.setParent(parent); |
964 State create() { |
1085 grammar = schemaBuilder.makeGrammar(scope); |
965 return new ParamState(null); |
1086 section = grammar; |
966 } |
1087 scope = grammar; |
967 |
1088 } |
968 @Override |
1089 |
969 void setName(String name) throws SAXException { |
1090 State create() { |
970 this.name = checkNCName(name); |
1091 return new GrammarState(); |
971 } |
1092 } |
972 |
1093 |
973 @Override |
1094 void end() throws SAXException { |
974 void endAttributes() throws SAXException { |
1095 super.end(); |
975 if (name == null) { |
1096 parent.endChild(grammar.endGrammar(startLocation, annotations)); |
976 error("missing_name_attribute"); |
1097 } |
977 } |
1098 } |
978 } |
1099 |
979 |
1100 class RefState extends EmptyContentState { |
980 State createChildState(String localName) throws SAXException { |
1101 String name; |
981 error("expected_empty", localName); |
1102 |
982 return null; |
1103 State create() { |
983 } |
1104 return new RefState(); |
984 |
1105 } |
985 @Override |
1106 |
986 public void characters(char[] ch, int start, int len) { |
1107 |
987 buf.append(ch, start, len); |
1108 void endAttributes() throws SAXException { |
988 } |
1109 if (name == null) |
989 |
1110 error("missing_name_attribute"); |
990 @Override |
1111 } |
991 void checkForeignElement() throws SAXException { |
1112 |
992 error("param_contains_foreign_element"); |
1113 void setName(String name) throws SAXException { |
993 } |
1114 this.name = checkNCName(name); |
994 |
1115 } |
995 void end() throws SAXException { |
1116 |
996 if (name == null) { |
1117 ParsedPattern makePattern() throws SAXException { |
997 return; |
1118 if (name == null) |
998 } |
1119 return schemaBuilder.makeErrorPattern(); |
999 if (dpb == null) { |
1120 if(scope==null) { |
1000 return; |
1121 error("ref_outside_grammar",name); |
1001 } |
1122 return schemaBuilder.makeErrorPattern(); |
1002 mergeLeadingComments(); |
1123 } else |
1003 dpb.addParam(name, buf.toString(), getContext(), getNs(), startLocation, annotations); |
1124 return scope.makeRef(name, startLocation, annotations); |
1004 } |
1125 } |
1005 } |
1126 } |
1006 |
1127 |
1007 class AttributeState extends PatternContainerState implements NameClassRef { |
1128 class ParentRefState extends RefState { |
1008 |
1129 State create() { |
1009 ParsedNameClass nameClass; |
1130 return new ParentRefState(); |
1010 boolean nameClassWasAttribute; |
1131 } |
1011 String name; |
1132 |
1012 |
1133 ParsedPattern makePattern() throws SAXException { |
1013 State create() { |
1134 if (name == null) |
1014 return new AttributeState(); |
1135 return schemaBuilder.makeErrorPattern(); |
1015 } |
1136 if(scope==null) { |
1016 |
1137 error("parent_ref_outside_grammar",name); |
1017 @Override |
1138 return schemaBuilder.makeErrorPattern(); |
1018 void setName(String name) { |
1139 } else |
1019 this.name = name; |
1140 return scope.makeParentRef(name, startLocation, annotations); |
1020 } |
1141 } |
1021 |
1142 } |
1022 public void setNameClass(ParsedNameClass nc) { |
1143 |
1023 nameClass = nc; |
1144 class ExternalRefState extends EmptyContentState { |
1024 } |
1145 String href; |
1025 |
1146 ParsedPattern includedPattern; |
1026 @Override |
1147 |
1027 void endAttributes() throws SAXException { |
1148 State create() { |
1028 if (name != null) { |
1149 return new ExternalRefState(); |
1029 String nsUse; |
1150 } |
1030 if (ns != null) { |
1151 |
1031 nsUse = ns; |
1152 void setOtherAttribute(String name, String value) throws SAXException { |
1032 } else { |
1153 if (name.equals("href")) { |
1033 nsUse = ""; |
1154 href = value; |
1034 } |
1155 checkUri(href); |
1035 nameClass = expandName(name, nsUse, null); |
1156 } |
1036 nameClassWasAttribute = true; |
1157 else |
1037 } else { |
1158 super.setOtherAttribute(name, value); |
1038 new NameClassChildState(this, this).set(); |
1159 } |
1039 } |
1160 |
1040 } |
1161 void endAttributes() throws SAXException { |
1041 |
1162 if (href == null) |
1042 @Override |
1163 error("missing_href_attribute"); |
1043 void endForeignChild(ParsedElementAnnotation ea) { |
1164 else |
1044 if (nameClassWasAttribute || childPatterns != null || nameClass == null) { |
1165 href = resolve(href); |
1045 super.endForeignChild(ea); |
1166 } |
1046 } else { |
1167 |
1047 nameClass = nameClassBuilder.annotateAfter(nameClass, ea); |
1168 ParsedPattern makePattern() { |
1048 } |
1169 if (href != null) { |
1049 } |
1170 try { |
1050 |
1171 return schemaBuilder.makeExternalRef(parseable, |
1051 @Override |
1172 href, |
1052 void end() throws SAXException { |
1173 getNs(), |
1053 if (childPatterns == null) { |
1174 scope, |
1054 endChild(schemaBuilder.makeText(startLocation, null)); |
1175 startLocation, |
1055 } |
1176 annotations); |
1056 super.end(); |
1177 } |
1057 } |
1178 catch (IllegalSchemaException e) { } |
1058 |
1179 } |
1059 @Override |
1180 return schemaBuilder.makeErrorPattern(); |
1060 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
1181 } |
1061 return schemaBuilder.makeAttribute(nameClass, super.buildPattern(patterns, loc, null), loc, anno); |
1182 } |
1062 } |
1183 |
1063 |
1184 abstract class DefinitionState extends PatternContainerState { |
1064 @Override |
1185 GrammarSection.Combine combine = null; |
1065 State createChildState(String localName) throws SAXException { |
1186 final GrammarSection section; |
1066 State tem = super.createChildState(localName); |
1187 |
1067 if (tem != null && childPatterns != null) { |
1188 DefinitionState(GrammarSection section) { |
1068 error("attribute_multi_pattern"); |
1189 this.section = section; |
1069 } |
1190 } |
1070 return tem; |
1191 |
1071 } |
1192 void setOtherAttribute(String name, String value) throws SAXException { |
1072 } |
1193 if (name.equals("combine")) { |
1073 |
1194 value = value.trim(); |
1074 abstract class SinglePatternContainerState extends PatternContainerState { |
1195 if (value.equals("choice")) |
1075 |
1196 combine = GrammarSection.COMBINE_CHOICE; |
1076 @Override |
1197 else if (value.equals("interleave")) |
1077 State createChildState(String localName) throws SAXException { |
1198 combine = GrammarSection.COMBINE_INTERLEAVE; |
1078 if (childPatterns == null) { |
1199 else |
1079 return super.createChildState(localName); |
1200 error("combine_attribute_bad_value", value); |
1080 } |
1201 } |
1081 error("too_many_children"); |
1202 else |
1082 return null; |
1203 super.setOtherAttribute(name, value); |
1083 } |
1204 } |
1084 } |
1205 |
1085 |
1206 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
1086 class GrammarSectionState extends State { |
1207 return super.buildPattern(patterns, loc, null); |
1087 |
1208 } |
1088 GrammarSection section; |
1209 } |
1089 |
1210 |
1090 GrammarSectionState() { |
1211 class DefineState extends DefinitionState { |
1091 } |
1212 String name; |
1092 |
1213 |
1093 GrammarSectionState(GrammarSection section) { |
1214 DefineState(GrammarSection section) { |
1094 this.section = section; |
1215 super(section); |
1095 } |
1216 } |
1096 |
1217 |
1097 State create() { |
1218 State create() { |
1098 return new GrammarSectionState(null); |
1219 return new DefineState(null); |
1099 } |
1220 } |
1100 |
1221 |
1101 State createChildState(String localName) throws SAXException { |
1222 void setName(String name) throws SAXException { |
1102 if (localName.equals("define")) { |
1223 this.name = checkNCName(name); |
1103 return new DefineState(section); |
1224 } |
1104 } |
1225 |
1105 if (localName.equals("start")) { |
1226 void endAttributes() throws SAXException { |
1106 return new StartState(section); |
1227 if (name == null) |
1107 } |
1228 error("missing_name_attribute"); |
1108 if (localName.equals("include")) { |
1229 } |
1109 Include include = section.makeInclude(); |
1230 |
1110 if (include != null) { |
1231 void sendPatternToParent(ParsedPattern p) { |
1111 return new IncludeState(include); |
1232 if (name != null) |
1112 } |
1233 section.define(name, combine, p, startLocation, annotations); |
1113 } |
1234 } |
1114 if (localName.equals("div")) { |
1235 |
1115 return new DivState(section.makeDiv()); |
1236 } |
1116 } |
1237 |
1117 error("expected_define", localName); |
1238 class StartState extends DefinitionState { |
1118 // XXX better errors |
1239 |
1119 return null; |
1240 StartState(GrammarSection section) { |
1120 } |
1241 super(section); |
1121 |
1242 } |
1122 void end() throws SAXException { |
1243 |
1123 if (comments != null) { |
1244 State create() { |
1124 section.topLevelComment(comments); |
1245 return new StartState(null); |
1125 comments = null; |
1246 } |
1126 } |
1247 |
1127 } |
1248 void sendPatternToParent(ParsedPattern p) { |
1128 |
1249 section.define(GrammarSection.START, combine, p, startLocation, annotations); |
1129 @Override |
1250 } |
1130 void endForeignChild(ParsedElementAnnotation ea) { |
1251 |
1131 section.topLevelAnnotation(ea); |
1252 State createChildState(String localName) throws SAXException { |
1132 } |
1253 State tem = super.createChildState(localName); |
1133 } |
1254 if (tem != null && childPatterns!=null) |
1134 |
1255 error("start_multi_pattern"); |
1135 class DivState extends GrammarSectionState { |
1256 return tem; |
1136 |
1257 } |
1137 final Div div; |
1258 |
1138 |
1259 } |
1139 DivState(Div div) { |
1260 |
1140 super(div); |
1261 abstract class NameClassContainerState extends State { |
1141 this.div = div; |
1262 State createChildState(String localName) throws SAXException { |
1142 } |
1263 State state = (State)nameClassTable.get(localName); |
1143 |
1264 if (state == null) { |
1144 @Override |
1265 error("expected_name_class", localName); |
1145 void end() throws SAXException { |
1266 return null; |
1146 super.end(); |
1267 } |
1147 div.endDiv(startLocation, annotations); |
1268 return state.create(); |
1148 } |
1269 } |
1149 } |
1270 } |
1150 |
1271 |
1151 class IncludeState extends GrammarSectionState { |
1272 class NameClassChildState extends NameClassContainerState { |
1152 |
1273 final State prevState; |
1153 String href; |
1274 final NameClassRef nameClassRef; |
1154 final Include include; |
1275 |
1155 |
1276 State create() { |
1156 IncludeState(Include include) { |
1277 return null; |
1157 super(include); |
1278 } |
1158 this.include = include; |
1279 |
1159 } |
1280 NameClassChildState(State prevState, NameClassRef nameClassRef) { |
1160 |
1281 this.prevState = prevState; |
1161 @Override |
1282 this.nameClassRef = nameClassRef; |
1162 void setOtherAttribute(String name, String value) throws SAXException { |
1283 setParent(prevState.parent); |
1163 if (name.equals("href")) { |
1284 this.ns = prevState.ns; |
1164 href = value; |
1285 } |
1165 checkUri(href); |
1286 |
1166 } else { |
1287 void endChild(ParsedNameClass nameClass) { |
1167 super.setOtherAttribute(name, value); |
1288 nameClassRef.setNameClass(nameClass); |
1168 } |
1289 prevState.set(); |
1169 } |
1290 } |
1170 |
1291 |
1171 @Override |
1292 void endForeignChild(ParsedElementAnnotation ea) { |
1172 void endAttributes() throws SAXException { |
1293 prevState.endForeignChild(ea); |
1173 if (href == null) { |
1294 } |
1174 error("missing_href_attribute"); |
1295 |
1175 } else { |
1296 void end() throws SAXException { |
1176 href = resolve(href); |
1297 nameClassRef.setNameClass(nameClassBuilder.makeErrorNameClass()); |
1177 } |
1298 error("missing_name_class"); |
1178 } |
1299 prevState.set(); |
1179 |
1300 prevState.end(); |
1180 @Override |
1301 } |
1181 void end() throws SAXException { |
1302 } |
1182 super.end(); |
1303 |
1183 if (href != null) { |
1304 abstract class NameClassBaseState extends State { |
1184 try { |
1305 |
1185 include.endInclude(parseable, href, getNs(), startLocation, annotations); |
1306 abstract ParsedNameClass makeNameClass() throws SAXException; |
1186 } catch (IllegalSchemaException e) { |
1307 |
1187 } |
1308 void end() throws SAXException { |
1188 } |
1309 parent.endChild(makeNameClass()); |
1189 } |
1310 } |
1190 } |
1311 } |
1191 |
1312 |
1192 class MergeGrammarState extends GrammarSectionState { |
1313 class NameState extends NameClassBaseState { |
1193 |
1314 final StringBuffer buf = new StringBuffer(); |
1194 final IncludedGrammar grammar; |
1315 |
1195 |
1316 State createChildState(String localName) throws SAXException { |
1196 MergeGrammarState(IncludedGrammar grammar) { |
1317 error("expected_name", localName); |
1197 super(grammar); |
1318 return null; |
1198 this.grammar = grammar; |
1319 } |
1199 } |
1320 |
1200 |
1321 State create() { |
1201 @Override |
1322 return new NameState(); |
1202 void end() throws SAXException { |
1323 } |
1203 super.end(); |
1324 |
1204 parent.endChild(grammar.endIncludedGrammar(startLocation, annotations)); |
1325 public void characters(char[] ch, int start, int len) { |
1205 } |
1326 buf.append(ch, start, len); |
1206 } |
1327 } |
1207 |
1328 |
1208 class GrammarState extends GrammarSectionState { |
1329 void checkForeignElement() throws SAXException { |
1209 |
1330 error("name_contains_foreign_element"); |
1210 Grammar grammar; |
1331 } |
1211 |
1332 |
1212 @Override |
1333 ParsedNameClass makeNameClass() throws SAXException { |
1213 void setParent(State parent) { |
1334 mergeLeadingComments(); |
1214 super.setParent(parent); |
1335 return expandName(buf.toString().trim(), getNs(), annotations); |
1215 grammar = schemaBuilder.makeGrammar(scope); |
1336 } |
1216 section = grammar; |
1337 |
1217 scope = grammar; |
1338 } |
1218 } |
1339 |
1219 |
1340 private static final int PATTERN_CONTEXT = 0; |
1220 @Override |
1341 private static final int ANY_NAME_CONTEXT = 1; |
1221 State create() { |
1342 private static final int NS_NAME_CONTEXT = 2; |
1222 return new GrammarState(); |
1343 private SAXParseable parseable; |
1223 } |
1344 |
1224 |
1345 class AnyNameState extends NameClassBaseState { |
1225 @Override |
1346 ParsedNameClass except = null; |
1226 void end() throws SAXException { |
1347 |
1227 super.end(); |
1348 State create() { |
1228 parent.endChild(grammar.endGrammar(startLocation, annotations)); |
1349 return new AnyNameState(); |
1229 } |
1350 } |
1230 } |
1351 |
1231 |
1352 State createChildState(String localName) throws SAXException { |
1232 class RefState extends EmptyContentState { |
1353 if (localName.equals("except")) { |
1233 |
1354 if (except != null) |
1234 String name; |
1355 error("multiple_except"); |
1235 |
1356 return new NameClassChoiceState(getContext()); |
1236 State create() { |
1357 } |
1237 return new RefState(); |
1358 error("expected_except", localName); |
1238 } |
1359 return null; |
1239 |
1360 } |
1240 @Override |
1361 |
1241 void endAttributes() throws SAXException { |
1362 int getContext() { |
1242 if (name == null) { |
1363 return ANY_NAME_CONTEXT; |
1243 error("missing_name_attribute"); |
1364 } |
1244 } |
1365 |
1245 } |
1366 ParsedNameClass makeNameClass() { |
1246 |
1367 if (except == null) |
1247 @Override |
1368 return makeNameClassNoExcept(); |
1248 void setName(String name) throws SAXException { |
1369 else |
1249 this.name = checkNCName(name); |
1370 return makeNameClassExcept(except); |
1250 } |
1371 } |
1251 |
1372 |
1252 ParsedPattern makePattern() throws SAXException { |
1373 ParsedNameClass makeNameClassNoExcept() { |
1253 if (name == null) { |
1374 return nameClassBuilder.makeAnyName(startLocation, annotations); |
1254 return schemaBuilder.makeErrorPattern(); |
1375 } |
1255 } |
1376 |
1256 if (scope == null) { |
1377 ParsedNameClass makeNameClassExcept(ParsedNameClass except) { |
1257 error("ref_outside_grammar", name); |
1378 return nameClassBuilder.makeAnyName(except, startLocation, annotations); |
1258 return schemaBuilder.makeErrorPattern(); |
1379 } |
1259 } else { |
1380 |
1260 return scope.makeRef(name, startLocation, annotations); |
1381 void endChild(ParsedNameClass nameClass) { |
1261 } |
1382 except = nameClass; |
1262 } |
1383 } |
1263 } |
1384 |
1264 |
1385 } |
1265 class ParentRefState extends RefState { |
1386 |
1266 |
1387 class NsNameState extends AnyNameState { |
1267 @Override |
1388 State create() { |
1268 State create() { |
1389 return new NsNameState(); |
1269 return new ParentRefState(); |
1390 } |
1270 } |
1391 |
1271 |
1392 ParsedNameClass makeNameClassNoExcept() { |
1272 @Override |
1393 return nameClassBuilder.makeNsName(getNs(), null, null); |
1273 ParsedPattern makePattern() throws SAXException { |
1394 } |
1274 if (name == null) { |
1395 |
1275 return schemaBuilder.makeErrorPattern(); |
1396 ParsedNameClass makeNameClassExcept(ParsedNameClass except) { |
1276 } |
1397 return nameClassBuilder.makeNsName(getNs(), except, null, null); |
1277 if (scope == null) { |
1398 } |
1278 error("parent_ref_outside_grammar", name); |
1399 |
1279 return schemaBuilder.makeErrorPattern(); |
1400 int getContext() { |
1280 } else { |
1401 return NS_NAME_CONTEXT; |
1281 return scope.makeParentRef(name, startLocation, annotations); |
1402 } |
1282 } |
1403 |
1283 } |
1404 } |
1284 } |
1405 |
1285 |
1406 class NameClassChoiceState extends NameClassContainerState { |
1286 class ExternalRefState extends EmptyContentState { |
1407 private ParsedNameClass[] nameClasses; |
1287 |
1408 private int nNameClasses; |
1288 String href; |
1409 private int context; |
1289 |
1410 |
1290 State create() { |
1411 NameClassChoiceState() { |
1291 return new ExternalRefState(); |
1412 this.context = PATTERN_CONTEXT; |
1292 } |
1413 } |
1293 |
1414 |
1294 @Override |
1415 NameClassChoiceState(int context) { |
1295 void setOtherAttribute(String name, String value) throws SAXException { |
1416 this.context = context; |
1296 if (name.equals("href")) { |
1417 } |
1297 href = value; |
1418 |
1298 checkUri(href); |
1419 void setParent(State parent) { |
1299 } else { |
1420 super.setParent(parent); |
1300 super.setOtherAttribute(name, value); |
1421 if (parent instanceof NameClassChoiceState) |
1301 } |
1422 this.context = ((NameClassChoiceState)parent).context; |
1302 } |
1423 } |
1303 |
1424 |
1304 @Override |
1425 State create() { |
1305 void endAttributes() throws SAXException { |
1426 return new NameClassChoiceState(); |
1306 if (href == null) { |
1427 } |
1307 error("missing_href_attribute"); |
1428 |
1308 } else { |
1429 State createChildState(String localName) throws SAXException { |
1309 href = resolve(href); |
1430 if (localName.equals("anyName")) { |
1310 } |
1431 if (context >= ANY_NAME_CONTEXT) { |
1311 } |
1432 error(context == ANY_NAME_CONTEXT |
1312 |
1433 ? "any_name_except_contains_any_name" |
1313 ParsedPattern makePattern() { |
1434 : "ns_name_except_contains_any_name"); |
1314 if (href != null) { |
1435 return null; |
1315 try { |
1436 } |
1316 return schemaBuilder.makeExternalRef(parseable, |
1437 } |
1317 href, |
1438 else if (localName.equals("nsName")) { |
1318 getNs(), |
1439 if (context == NS_NAME_CONTEXT) { |
1319 scope, |
1440 error("ns_name_except_contains_ns_name"); |
1320 startLocation, |
1441 return null; |
1321 annotations); |
1442 } |
1322 } catch (IllegalSchemaException e) { |
1443 } |
1323 } |
1444 return super.createChildState(localName); |
1324 } |
1445 } |
1325 return schemaBuilder.makeErrorPattern(); |
1446 |
1326 } |
1447 void endChild(ParsedNameClass nc) { |
1327 } |
1448 if (nameClasses == null) |
1328 |
1449 nameClasses = new ParsedNameClass[INIT_CHILD_ALLOC]; |
1329 abstract class DefinitionState extends PatternContainerState { |
1450 else if (nNameClasses >= nameClasses.length) { |
1330 |
1451 ParsedNameClass[] newNameClasses = new ParsedNameClass[nameClasses.length * 2]; |
1331 GrammarSection.Combine combine = null; |
1452 System.arraycopy(nameClasses, 0, newNameClasses, 0, nameClasses.length); |
1332 final GrammarSection section; |
1453 nameClasses = newNameClasses; |
1333 |
1454 } |
1334 DefinitionState(GrammarSection section) { |
1455 nameClasses[nNameClasses++] = nc; |
1335 this.section = section; |
1456 } |
1336 } |
1457 |
1337 |
1458 void endForeignChild(ParsedElementAnnotation ea) { |
1338 @Override |
1459 if (nNameClasses == 0) |
1339 void setOtherAttribute(String name, String value) throws SAXException { |
1460 super.endForeignChild(ea); |
1340 if (name.equals("combine")) { |
1461 else |
1341 value = value.trim(); |
1462 nameClasses[nNameClasses - 1] = nameClassBuilder.annotateAfter(nameClasses[nNameClasses - 1], ea); |
1342 if (value.equals("choice")) { |
1463 } |
1343 combine = GrammarSection.COMBINE_CHOICE; |
1464 |
1344 } else if (value.equals("interleave")) { |
1465 void end() throws SAXException { |
1345 combine = GrammarSection.COMBINE_INTERLEAVE; |
1466 if (nNameClasses == 0) { |
1346 } else { |
1467 error("missing_name_class"); |
1347 error("combine_attribute_bad_value", value); |
1468 parent.endChild(nameClassBuilder.makeErrorNameClass()); |
1348 } |
1469 return; |
1349 } else { |
1470 } |
1350 super.setOtherAttribute(name, value); |
1471 if (comments != null) { |
1351 } |
1472 nameClasses[nNameClasses - 1] = nameClassBuilder.commentAfter(nameClasses[nNameClasses - 1], comments); |
1352 } |
1473 comments = null; |
1353 |
1474 } |
1354 @Override |
1475 parent.endChild(nameClassBuilder.makeChoice(Arrays.asList(nameClasses).subList(0,nNameClasses), startLocation, annotations)); |
1355 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { |
1476 } |
1356 return super.buildPattern(patterns, loc, null); |
1477 } |
1357 } |
1478 |
1358 } |
1479 private void initPatternTable() { |
1359 |
1480 patternTable = new Hashtable(); |
1360 class DefineState extends DefinitionState { |
1481 patternTable.put("zeroOrMore", new ZeroOrMoreState()); |
1361 |
1482 patternTable.put("oneOrMore", new OneOrMoreState()); |
1362 String name; |
1483 patternTable.put("optional", new OptionalState()); |
1363 |
1484 patternTable.put("list", new ListState()); |
1364 DefineState(GrammarSection section) { |
1485 patternTable.put("choice", new ChoiceState()); |
1365 super(section); |
1486 patternTable.put("interleave", new InterleaveState()); |
1366 } |
1487 patternTable.put("group", new GroupState()); |
1367 |
1488 patternTable.put("mixed", new MixedState()); |
1368 State create() { |
1489 patternTable.put("element", new ElementState()); |
1369 return new DefineState(null); |
1490 patternTable.put("attribute", new AttributeState()); |
1370 } |
1491 patternTable.put("empty", new EmptyState()); |
1371 |
1492 patternTable.put("text", new TextState()); |
1372 @Override |
1493 patternTable.put("value", new ValueState()); |
1373 void setName(String name) throws SAXException { |
1494 patternTable.put("data", new DataState()); |
1374 this.name = checkNCName(name); |
1495 patternTable.put("notAllowed", new NotAllowedState()); |
1375 } |
1496 patternTable.put("grammar", new GrammarState()); |
1376 |
1497 patternTable.put("ref", new RefState()); |
1377 @Override |
1498 patternTable.put("parentRef", new ParentRefState()); |
1378 void endAttributes() throws SAXException { |
1499 patternTable.put("externalRef", new ExternalRefState()); |
1379 if (name == null) { |
1500 } |
1380 error("missing_name_attribute"); |
1501 |
1381 } |
1502 private void initNameClassTable() { |
1382 } |
1503 nameClassTable = new Hashtable(); |
1383 |
1504 nameClassTable.put("name", new NameState()); |
1384 @Override |
1505 nameClassTable.put("anyName", new AnyNameState()); |
1385 void sendPatternToParent(ParsedPattern p) { |
1506 nameClassTable.put("nsName", new NsNameState()); |
1386 if (name != null) { |
1507 nameClassTable.put("choice", new NameClassChoiceState()); |
1387 section.define(name, combine, p, startLocation, annotations); |
1508 } |
1388 } |
1509 |
1389 } |
1510 public ParsedPattern getParsedPattern() throws IllegalSchemaException { |
1390 } |
1511 if (hadError) |
1391 |
1512 throw new IllegalSchemaException(); |
1392 class StartState extends DefinitionState { |
1513 return startPattern; |
1393 |
1514 } |
1394 StartState(GrammarSection section) { |
1515 |
1395 super(section); |
1516 private void error(String key) throws SAXException { |
1396 } |
1517 error(key, locator); |
1397 |
1518 } |
1398 State create() { |
1519 |
1399 return new StartState(null); |
1520 private void error(String key, String arg) throws SAXException { |
1400 } |
1521 error(key, arg, locator); |
1401 |
1522 } |
1402 @Override |
1523 |
1403 void sendPatternToParent(ParsedPattern p) { |
1524 void error(String key, String arg1, String arg2) throws SAXException { |
1404 section.define(GrammarSection.START, combine, p, startLocation, annotations); |
1525 error(key, arg1, arg2, locator); |
1405 } |
1526 } |
1406 |
1527 |
1407 @Override |
1528 private void error(String key, Locator loc) throws SAXException { |
1408 State createChildState(String localName) throws SAXException { |
1529 error(new SAXParseException(localizer.message(key), loc)); |
1409 State tem = super.createChildState(localName); |
1530 } |
1410 if (tem != null && childPatterns != null) { |
1531 |
1411 error("start_multi_pattern"); |
1532 private void error(String key, String arg, Locator loc) throws SAXException { |
1412 } |
1533 error(new SAXParseException(localizer.message(key, arg), loc)); |
1413 return tem; |
1534 } |
1414 } |
1535 |
1415 } |
1536 private void error(String key, String arg1, String arg2, Locator loc) |
1416 |
1537 throws SAXException { |
1417 abstract class NameClassContainerState extends State { |
1538 error(new SAXParseException(localizer.message(key, arg1, arg2), loc)); |
1418 |
1539 } |
1419 State createChildState(String localName) throws SAXException { |
1540 |
1420 State state = (State) nameClassTable.get(localName); |
1541 private void error(SAXParseException e) throws SAXException { |
1421 if (state == null) { |
1542 hadError = true; |
1422 error("expected_name_class", localName); |
1543 if (eh != null) |
1423 return null; |
1544 eh.error(e); |
1424 } |
1545 } |
1425 return state.create(); |
1546 |
1426 } |
1547 void warning(String key) throws SAXException { |
1427 } |
1548 warning(key, locator); |
1428 |
1549 } |
1429 class NameClassChildState extends NameClassContainerState { |
1550 |
1430 |
1551 private void warning(String key, String arg) throws SAXException { |
1431 final State prevState; |
1552 warning(key, arg, locator); |
1432 final NameClassRef nameClassRef; |
1553 } |
1433 |
1554 |
1434 State create() { |
1555 private void warning(String key, String arg1, String arg2) throws SAXException { |
1435 return null; |
1556 warning(key, arg1, arg2, locator); |
1436 } |
1557 } |
1437 |
1558 |
1438 NameClassChildState(State prevState, NameClassRef nameClassRef) { |
1559 private void warning(String key, Locator loc) throws SAXException { |
1439 this.prevState = prevState; |
1560 warning(new SAXParseException(localizer.message(key), loc)); |
1440 this.nameClassRef = nameClassRef; |
1561 } |
1441 setParent(prevState.parent); |
1562 |
1442 this.ns = prevState.ns; |
1563 private void warning(String key, String arg, Locator loc) throws SAXException { |
1443 } |
1564 warning(new SAXParseException(localizer.message(key, arg), loc)); |
1444 |
1565 } |
1445 @Override |
1566 |
1446 void endChild(ParsedNameClass nameClass) { |
1567 private void warning(String key, String arg1, String arg2, Locator loc) |
1447 nameClassRef.setNameClass(nameClass); |
1568 throws SAXException { |
1448 prevState.set(); |
1569 warning(new SAXParseException(localizer.message(key, arg1, arg2), loc)); |
1449 } |
1570 } |
1450 |
1571 |
1451 @Override |
1572 private void warning(SAXParseException e) throws SAXException { |
1452 void endForeignChild(ParsedElementAnnotation ea) { |
1573 if (eh != null) |
1453 prevState.endForeignChild(ea); |
1574 eh.warning(e); |
1454 } |
1575 } |
1455 |
1576 |
1456 void end() throws SAXException { |
1577 SchemaParser(SAXParseable parseable, |
1457 nameClassRef.setNameClass(nameClassBuilder.makeErrorNameClass()); |
1578 XMLReader xr, |
1458 error("missing_name_class"); |
1579 ErrorHandler eh, |
1459 prevState.set(); |
1580 SchemaBuilder schemaBuilder, |
1460 prevState.end(); |
1581 IncludedGrammar grammar, |
1461 } |
1582 Scope scope, |
1462 } |
1583 String inheritedNs) throws SAXException { |
1463 |
1584 this.parseable = parseable; |
1464 abstract class NameClassBaseState extends State { |
1585 this.xr = xr; |
1465 |
1586 this.eh = eh; |
1466 abstract ParsedNameClass makeNameClass() throws SAXException; |
1587 this.schemaBuilder = schemaBuilder; |
1467 |
1588 this.nameClassBuilder = schemaBuilder.getNameClassBuilder(); |
1468 void end() throws SAXException { |
1589 if (eh != null) |
1469 parent.endChild(makeNameClass()); |
1590 xr.setErrorHandler(eh); |
1470 } |
1591 xr.setDTDHandler(context); |
1471 } |
1592 if (schemaBuilder.usesComments()) { |
1472 |
1593 try { |
1473 class NameState extends NameClassBaseState { |
1594 xr.setProperty("http://xml.org/sax/properties/lexical-handler", new LexicalHandlerImpl()); |
1474 |
1595 } |
1475 final StringBuffer buf = new StringBuffer(); |
1596 catch (SAXNotRecognizedException e) { |
1476 |
1597 warning("no_comment_support", xr.getClass().getName()); |
1477 State createChildState(String localName) throws SAXException { |
1598 } |
1478 error("expected_name", localName); |
1599 catch (SAXNotSupportedException e) { |
1479 return null; |
1600 warning("no_comment_support", xr.getClass().getName()); |
1480 } |
1601 } |
1481 |
1602 } |
1482 State create() { |
1603 initPatternTable(); |
1483 return new NameState(); |
1604 initNameClassTable(); |
1484 } |
1605 new RootState(grammar, scope, inheritedNs).set(); |
1485 |
1606 } |
1486 @Override |
1607 |
1487 public void characters(char[] ch, int start, int len) { |
1608 |
1488 buf.append(ch, start, len); |
1609 private Context getContext() { |
1489 } |
1610 return context; |
1490 |
1611 } |
1491 @Override |
1612 |
1492 void checkForeignElement() throws SAXException { |
1613 class LexicalHandlerImpl extends AbstractLexicalHandler { |
1493 error("name_contains_foreign_element"); |
1614 private boolean inDtd = false; |
1494 } |
1615 |
1495 |
1616 public void startDTD(String s, String s1, String s2) throws SAXException { |
1496 ParsedNameClass makeNameClass() throws SAXException { |
1617 inDtd = true; |
1497 mergeLeadingComments(); |
1618 } |
1498 return expandName(buf.toString().trim(), getNs(), annotations); |
1619 |
1499 } |
1620 public void endDTD() throws SAXException { |
1500 } |
1621 inDtd = false; |
1501 private static final int PATTERN_CONTEXT = 0; |
1622 } |
1502 private static final int ANY_NAME_CONTEXT = 1; |
1623 |
1503 private static final int NS_NAME_CONTEXT = 2; |
1624 public void comment(char[] chars, int start, int length) throws SAXException { |
1504 private SAXParseable parseable; |
1625 if (!inDtd) |
1505 |
1626 ((CommentHandler)xr.getContentHandler()).comment(new String(chars, start, length)); |
1506 class AnyNameState extends NameClassBaseState { |
1627 } |
1507 |
1628 } |
1508 ParsedNameClass except = null; |
1629 |
1509 |
1630 private ParsedNameClass expandName(String name, String ns, Annotations anno) throws SAXException { |
1510 State create() { |
1631 int ic = name.indexOf(':'); |
1511 return new AnyNameState(); |
1632 if (ic == -1) |
1512 } |
1633 return nameClassBuilder.makeName(ns, checkNCName(name), null, null, anno); |
1513 |
1634 String prefix = checkNCName(name.substring(0, ic)); |
1514 State createChildState(String localName) throws SAXException { |
1635 String localName = checkNCName(name.substring(ic + 1)); |
1515 if (localName.equals("except")) { |
1636 for (PrefixMapping tem = context.prefixMapping; tem != null; tem = tem.next) |
1516 if (except != null) { |
1637 if (tem.prefix.equals(prefix)) |
1517 error("multiple_except"); |
1638 return nameClassBuilder.makeName(tem.uri, localName, prefix, null, anno); |
1518 } |
1639 error("undefined_prefix", prefix); |
1519 return new NameClassChoiceState(getContext()); |
1640 return nameClassBuilder.makeName("", localName, null, null, anno); |
1520 } |
1641 } |
1521 error("expected_except", localName); |
1642 |
1522 return null; |
1643 private String findPrefix(String qName, String uri) { |
1523 } |
1644 String prefix = null; |
1524 |
1645 if (qName == null || qName.equals("")) { |
1525 int getContext() { |
1646 for (PrefixMapping p = context.prefixMapping; p != null; p = p.next) |
1526 return ANY_NAME_CONTEXT; |
1647 if (p.uri.equals(uri)) { |
1527 } |
1648 prefix = p.prefix; |
1528 |
1649 break; |
1529 ParsedNameClass makeNameClass() { |
1650 } |
1530 if (except == null) { |
1651 } |
1531 return makeNameClassNoExcept(); |
1652 else { |
1532 } else { |
1653 int off = qName.indexOf(':'); |
1533 return makeNameClassExcept(except); |
1654 if (off > 0) |
1534 } |
1655 prefix = qName.substring(0, off); |
1535 } |
1656 } |
1536 |
1657 return prefix; |
1537 ParsedNameClass makeNameClassNoExcept() { |
1658 } |
1538 return nameClassBuilder.makeAnyName(startLocation, annotations); |
1659 private String checkNCName(String str) throws SAXException { |
1539 } |
1660 if (!Naming.isNcname(str)) |
1540 |
1661 error("invalid_ncname", str); |
1541 ParsedNameClass makeNameClassExcept(ParsedNameClass except) { |
1662 return str; |
1542 return nameClassBuilder.makeAnyName(except, startLocation, annotations); |
1663 } |
1543 } |
1664 |
1544 |
1665 private String resolve(String systemId) throws SAXException { |
1545 @Override |
1666 if (Uri.hasFragmentId(systemId)) |
1546 void endChild(ParsedNameClass nameClass) { |
1667 error("href_fragment_id"); |
1547 except = nameClass; |
1668 systemId = Uri.escapeDisallowedChars(systemId); |
1548 } |
1669 return Uri.resolve(xmlBaseHandler.getBaseUri(), systemId); |
1549 } |
1670 } |
1550 |
1671 |
1551 class NsNameState extends AnyNameState { |
1672 private Location makeLocation() { |
1552 |
1673 if (locator == null) |
1553 @Override |
1674 return null; |
1554 State create() { |
1675 return schemaBuilder.makeLocation(locator.getSystemId(), |
1555 return new NsNameState(); |
1676 locator.getLineNumber(), |
1556 } |
1677 locator.getColumnNumber()); |
1557 |
1678 } |
1558 @Override |
1679 |
1559 ParsedNameClass makeNameClassNoExcept() { |
1680 private void checkUri(String s) throws SAXException { |
1560 return nameClassBuilder.makeNsName(getNs(), null, null); |
1681 if (!Uri.isValid(s)) |
1561 } |
1682 error("invalid_uri", s); |
1562 |
1683 } |
1563 @Override |
|
1564 ParsedNameClass makeNameClassExcept(ParsedNameClass except) { |
|
1565 return nameClassBuilder.makeNsName(getNs(), except, null, null); |
|
1566 } |
|
1567 |
|
1568 @Override |
|
1569 int getContext() { |
|
1570 return NS_NAME_CONTEXT; |
|
1571 } |
|
1572 } |
|
1573 |
|
1574 class NameClassChoiceState extends NameClassContainerState { |
|
1575 |
|
1576 private ParsedNameClass[] nameClasses; |
|
1577 private int nNameClasses; |
|
1578 private int context; |
|
1579 |
|
1580 NameClassChoiceState() { |
|
1581 this.context = PATTERN_CONTEXT; |
|
1582 } |
|
1583 |
|
1584 NameClassChoiceState(int context) { |
|
1585 this.context = context; |
|
1586 } |
|
1587 |
|
1588 @Override |
|
1589 void setParent(State parent) { |
|
1590 super.setParent(parent); |
|
1591 if (parent instanceof NameClassChoiceState) { |
|
1592 this.context = ((NameClassChoiceState) parent).context; |
|
1593 } |
|
1594 } |
|
1595 |
|
1596 State create() { |
|
1597 return new NameClassChoiceState(); |
|
1598 } |
|
1599 |
|
1600 @Override |
|
1601 State createChildState(String localName) throws SAXException { |
|
1602 if (localName.equals("anyName")) { |
|
1603 if (context >= ANY_NAME_CONTEXT) { |
|
1604 error(context == ANY_NAME_CONTEXT |
|
1605 ? "any_name_except_contains_any_name" |
|
1606 : "ns_name_except_contains_any_name"); |
|
1607 return null; |
|
1608 } |
|
1609 } else if (localName.equals("nsName")) { |
|
1610 if (context == NS_NAME_CONTEXT) { |
|
1611 error("ns_name_except_contains_ns_name"); |
|
1612 return null; |
|
1613 } |
|
1614 } |
|
1615 return super.createChildState(localName); |
|
1616 } |
|
1617 |
|
1618 @Override |
|
1619 void endChild(ParsedNameClass nc) { |
|
1620 if (nameClasses == null) { |
|
1621 nameClasses = new ParsedNameClass[INIT_CHILD_ALLOC]; |
|
1622 } else if (nNameClasses >= nameClasses.length) { |
|
1623 ParsedNameClass[] newNameClasses = new ParsedNameClass[nameClasses.length * 2]; |
|
1624 System.arraycopy(nameClasses, 0, newNameClasses, 0, nameClasses.length); |
|
1625 nameClasses = newNameClasses; |
|
1626 } |
|
1627 nameClasses[nNameClasses++] = nc; |
|
1628 } |
|
1629 |
|
1630 @Override |
|
1631 void endForeignChild(ParsedElementAnnotation ea) { |
|
1632 if (nNameClasses == 0) { |
|
1633 super.endForeignChild(ea); |
|
1634 } else { |
|
1635 nameClasses[nNameClasses - 1] = nameClassBuilder.annotateAfter(nameClasses[nNameClasses - 1], ea); |
|
1636 } |
|
1637 } |
|
1638 |
|
1639 void end() throws SAXException { |
|
1640 if (nNameClasses == 0) { |
|
1641 error("missing_name_class"); |
|
1642 parent.endChild(nameClassBuilder.makeErrorNameClass()); |
|
1643 return; |
|
1644 } |
|
1645 if (comments != null) { |
|
1646 nameClasses[nNameClasses - 1] = nameClassBuilder.commentAfter(nameClasses[nNameClasses - 1], comments); |
|
1647 comments = null; |
|
1648 } |
|
1649 parent.endChild(nameClassBuilder.makeChoice(Arrays.asList(nameClasses).subList(0, nNameClasses), startLocation, annotations)); |
|
1650 } |
|
1651 } |
|
1652 |
|
1653 private void initPatternTable() { |
|
1654 patternTable = new Hashtable(); |
|
1655 patternTable.put("zeroOrMore", new ZeroOrMoreState()); |
|
1656 patternTable.put("oneOrMore", new OneOrMoreState()); |
|
1657 patternTable.put("optional", new OptionalState()); |
|
1658 patternTable.put("list", new ListState()); |
|
1659 patternTable.put("choice", new ChoiceState()); |
|
1660 patternTable.put("interleave", new InterleaveState()); |
|
1661 patternTable.put("group", new GroupState()); |
|
1662 patternTable.put("mixed", new MixedState()); |
|
1663 patternTable.put("element", new ElementState()); |
|
1664 patternTable.put("attribute", new AttributeState()); |
|
1665 patternTable.put("empty", new EmptyState()); |
|
1666 patternTable.put("text", new TextState()); |
|
1667 patternTable.put("value", new ValueState()); |
|
1668 patternTable.put("data", new DataState()); |
|
1669 patternTable.put("notAllowed", new NotAllowedState()); |
|
1670 patternTable.put("grammar", new GrammarState()); |
|
1671 patternTable.put("ref", new RefState()); |
|
1672 patternTable.put("parentRef", new ParentRefState()); |
|
1673 patternTable.put("externalRef", new ExternalRefState()); |
|
1674 } |
|
1675 |
|
1676 private void initNameClassTable() { |
|
1677 nameClassTable = new Hashtable(); |
|
1678 nameClassTable.put("name", new NameState()); |
|
1679 nameClassTable.put("anyName", new AnyNameState()); |
|
1680 nameClassTable.put("nsName", new NsNameState()); |
|
1681 nameClassTable.put("choice", new NameClassChoiceState()); |
|
1682 } |
|
1683 |
|
1684 public ParsedPattern getParsedPattern() throws IllegalSchemaException { |
|
1685 if (hadError) { |
|
1686 throw new IllegalSchemaException(); |
|
1687 } |
|
1688 return startPattern; |
|
1689 } |
|
1690 |
|
1691 private void error(String key) throws SAXException { |
|
1692 error(key, locator); |
|
1693 } |
|
1694 |
|
1695 private void error(String key, String arg) throws SAXException { |
|
1696 error(key, arg, locator); |
|
1697 } |
|
1698 |
|
1699 void error(String key, String arg1, String arg2) throws SAXException { |
|
1700 error(key, arg1, arg2, locator); |
|
1701 } |
|
1702 |
|
1703 private void error(String key, Locator loc) throws SAXException { |
|
1704 error(new SAXParseException(localizer.message(key), loc)); |
|
1705 } |
|
1706 |
|
1707 private void error(String key, String arg, Locator loc) throws SAXException { |
|
1708 error(new SAXParseException(localizer.message(key, arg), loc)); |
|
1709 } |
|
1710 |
|
1711 private void error(String key, String arg1, String arg2, Locator loc) |
|
1712 throws SAXException { |
|
1713 error(new SAXParseException(localizer.message(key, arg1, arg2), loc)); |
|
1714 } |
|
1715 |
|
1716 private void error(SAXParseException e) throws SAXException { |
|
1717 hadError = true; |
|
1718 if (eh != null) { |
|
1719 eh.error(e); |
|
1720 } |
|
1721 } |
|
1722 |
|
1723 void warning(String key) throws SAXException { |
|
1724 warning(key, locator); |
|
1725 } |
|
1726 |
|
1727 private void warning(String key, String arg) throws SAXException { |
|
1728 warning(key, arg, locator); |
|
1729 } |
|
1730 |
|
1731 private void warning(String key, String arg1, String arg2) throws SAXException { |
|
1732 warning(key, arg1, arg2, locator); |
|
1733 } |
|
1734 |
|
1735 private void warning(String key, Locator loc) throws SAXException { |
|
1736 warning(new SAXParseException(localizer.message(key), loc)); |
|
1737 } |
|
1738 |
|
1739 private void warning(String key, String arg, Locator loc) throws SAXException { |
|
1740 warning(new SAXParseException(localizer.message(key, arg), loc)); |
|
1741 } |
|
1742 |
|
1743 private void warning(String key, String arg1, String arg2, Locator loc) |
|
1744 throws SAXException { |
|
1745 warning(new SAXParseException(localizer.message(key, arg1, arg2), loc)); |
|
1746 } |
|
1747 |
|
1748 private void warning(SAXParseException e) throws SAXException { |
|
1749 if (eh != null) { |
|
1750 eh.warning(e); |
|
1751 } |
|
1752 } |
|
1753 |
|
1754 SchemaParser(SAXParseable parseable, |
|
1755 XMLReader xr, |
|
1756 ErrorHandler eh, |
|
1757 SchemaBuilder schemaBuilder, |
|
1758 IncludedGrammar grammar, |
|
1759 Scope scope, |
|
1760 String inheritedNs) throws SAXException { |
|
1761 this.parseable = parseable; |
|
1762 this.xr = xr; |
|
1763 this.eh = eh; |
|
1764 this.schemaBuilder = schemaBuilder; |
|
1765 this.nameClassBuilder = schemaBuilder.getNameClassBuilder(); |
|
1766 if (eh != null) { |
|
1767 xr.setErrorHandler(eh); |
|
1768 } |
|
1769 xr.setDTDHandler(context); |
|
1770 if (schemaBuilder.usesComments()) { |
|
1771 try { |
|
1772 xr.setProperty("http://xml.org/sax/properties/lexical-handler", new LexicalHandlerImpl()); |
|
1773 } catch (SAXNotRecognizedException e) { |
|
1774 warning("no_comment_support", xr.getClass().getName()); |
|
1775 } catch (SAXNotSupportedException e) { |
|
1776 warning("no_comment_support", xr.getClass().getName()); |
|
1777 } |
|
1778 } |
|
1779 initPatternTable(); |
|
1780 initNameClassTable(); |
|
1781 new RootState(grammar, scope, inheritedNs).set(); |
|
1782 } |
|
1783 |
|
1784 private Context getContext() { |
|
1785 return context; |
|
1786 } |
|
1787 |
|
1788 class LexicalHandlerImpl extends AbstractLexicalHandler { |
|
1789 |
|
1790 private boolean inDtd = false; |
|
1791 |
|
1792 @Override |
|
1793 public void startDTD(String s, String s1, String s2) throws SAXException { |
|
1794 inDtd = true; |
|
1795 } |
|
1796 |
|
1797 @Override |
|
1798 public void endDTD() throws SAXException { |
|
1799 inDtd = false; |
|
1800 } |
|
1801 |
|
1802 @Override |
|
1803 public void comment(char[] chars, int start, int length) throws SAXException { |
|
1804 if (!inDtd) { |
|
1805 ((CommentHandler) xr.getContentHandler()).comment(new String(chars, start, length)); |
|
1806 } |
|
1807 } |
|
1808 } |
|
1809 |
|
1810 private ParsedNameClass expandName(String name, String ns, Annotations anno) throws SAXException { |
|
1811 int ic = name.indexOf(':'); |
|
1812 if (ic == -1) { |
|
1813 return nameClassBuilder.makeName(ns, checkNCName(name), null, null, anno); |
|
1814 } |
|
1815 String prefix = checkNCName(name.substring(0, ic)); |
|
1816 String localName = checkNCName(name.substring(ic + 1)); |
|
1817 for (PrefixMapping tem = context.prefixMapping; tem != null; tem = tem.next) { |
|
1818 if (tem.prefix.equals(prefix)) { |
|
1819 return nameClassBuilder.makeName(tem.uri, localName, prefix, null, anno); |
|
1820 } |
|
1821 } |
|
1822 error("undefined_prefix", prefix); |
|
1823 return nameClassBuilder.makeName("", localName, null, null, anno); |
|
1824 } |
|
1825 |
|
1826 private String findPrefix(String qName, String uri) { |
|
1827 String prefix = null; |
|
1828 if (qName == null || qName.equals("")) { |
|
1829 for (PrefixMapping p = context.prefixMapping; p != null; p = p.next) { |
|
1830 if (p.uri.equals(uri)) { |
|
1831 prefix = p.prefix; |
|
1832 break; |
|
1833 } |
|
1834 } |
|
1835 } else { |
|
1836 int off = qName.indexOf(':'); |
|
1837 if (off > 0) { |
|
1838 prefix = qName.substring(0, off); |
|
1839 } |
|
1840 } |
|
1841 return prefix; |
|
1842 } |
|
1843 |
|
1844 private String checkNCName(String str) throws SAXException { |
|
1845 if (!Naming.isNcname(str)) { |
|
1846 error("invalid_ncname", str); |
|
1847 } |
|
1848 return str; |
|
1849 } |
|
1850 |
|
1851 private String resolve(String systemId) throws SAXException { |
|
1852 if (Uri.hasFragmentId(systemId)) { |
|
1853 error("href_fragment_id"); |
|
1854 } |
|
1855 systemId = Uri.escapeDisallowedChars(systemId); |
|
1856 return Uri.resolve(xmlBaseHandler.getBaseUri(), systemId); |
|
1857 } |
|
1858 |
|
1859 private Location makeLocation() { |
|
1860 if (locator == null) { |
|
1861 return null; |
|
1862 } |
|
1863 return schemaBuilder.makeLocation(locator.getSystemId(), |
|
1864 locator.getLineNumber(), |
|
1865 locator.getColumnNumber()); |
|
1866 } |
|
1867 |
|
1868 private void checkUri(String s) throws SAXException { |
|
1869 if (!Uri.isValid(s)) { |
|
1870 error("invalid_uri", s); |
|
1871 } |
|
1872 } |
1684 } |
1873 } |