src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/xml/SchemaParser.java

changeset 408
b0610cd08440
parent 286
f50545b5e2f1
child 637
9c07ef4934dd
equal deleted inserted replaced
405:cc682329886b 408:b0610cd08440
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any 22 * or visit www.oracle.com if you need additional information or have any
23 * questions. 23 * questions.
24 */ 24 */
25 /* 25 /*
26 * Copyright (C) 2004-2011 26 * Copyright (C) 2004-2012
27 * 27 *
28 * Permission is hereby granted, free of charge, to any person obtaining a copy 28 * Permission is hereby granted, free of charge, to any person obtaining a copy
29 * of this software and associated documentation files (the "Software"), to deal 29 * of this software and associated documentation files (the "Software"), to deal
30 * in the Software without restriction, including without limitation the rights 30 * in the Software without restriction, including without limitation the rights
31 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 31 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
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 }

mercurial