001 package com.thaiopensource.relaxng.impl;
002
003 import com.thaiopensource.relaxng.parse.Annotations;
004 import com.thaiopensource.relaxng.parse.BuildException;
005 import com.thaiopensource.relaxng.parse.DataPatternBuilder;
006 import com.thaiopensource.relaxng.parse.Div;
007 import com.thaiopensource.relaxng.parse.ParsedElementAnnotation;
008 import com.thaiopensource.relaxng.parse.ElementAnnotationBuilder;
009 import com.thaiopensource.relaxng.parse.Grammar;
010 import com.thaiopensource.relaxng.parse.GrammarSection;
011 import com.thaiopensource.relaxng.parse.IllegalSchemaException;
012 import com.thaiopensource.relaxng.parse.Include;
013 import com.thaiopensource.relaxng.parse.IncludedGrammar;
014 import com.thaiopensource.relaxng.parse.Location;
015 import com.thaiopensource.relaxng.parse.Parseable;
016 import com.thaiopensource.relaxng.parse.ParsedNameClass;
017 import com.thaiopensource.relaxng.parse.ParsedPattern;
018 import com.thaiopensource.relaxng.parse.SchemaBuilder;
019 import com.thaiopensource.relaxng.parse.Scope;
020 import com.thaiopensource.relaxng.parse.Context;
021 import com.thaiopensource.relaxng.parse.CommentList;
022 import com.thaiopensource.relaxng.parse.SubParser;
023 import com.thaiopensource.relaxng.parse.ParseReceiver;
024 import com.thaiopensource.relaxng.parse.ParsedPatternFuture;
025 import com.thaiopensource.validate.IncorrectSchemaException;
026 import com.thaiopensource.util.Localizer;
027 import com.thaiopensource.xml.util.Name;
028
029 import org.relaxng.datatype.Datatype;
030 import org.relaxng.datatype.DatatypeException;
031 import org.relaxng.datatype.DatatypeLibrary;
032 import org.relaxng.datatype.DatatypeLibraryFactory;
033 import org.relaxng.datatype.ValidationContext;
034 import org.relaxng.datatype.DatatypeBuilder;
035
036 import org.xml.sax.ErrorHandler;
037 import org.xml.sax.Locator;
038 import org.xml.sax.SAXException;
039 import org.xml.sax.SAXParseException;
040 import org.xml.sax.XMLReader;
041
042 import java.util.Enumeration;
043 import java.util.Hashtable;
044 import java.io.IOException;
045
046 public class SchemaBuilderImpl implements SchemaBuilder, ElementAnnotationBuilder, CommentList {
047 private final SchemaBuilderImpl parent;
048 private boolean hadError = false;
049 private final SubParser subParser;
050 private final SchemaPatternBuilder pb;
051 private final DatatypeLibraryFactory datatypeLibraryFactory;
052 private final String inheritNs;
053 private final ErrorHandler eh;
054 private final OpenIncludes openIncludes;
055 private final AttributeNameClassChecker attributeNameClassChecker = new AttributeNameClassChecker();
056 static final Localizer localizer = new Localizer(SchemaBuilderImpl.class);
057
058 static class OpenIncludes {
059 final String uri;
060 final OpenIncludes parent;
061
062 OpenIncludes(String uri, OpenIncludes parent) {
063 this.uri = uri;
064 this.parent = parent;
065 }
066 }
067
068 static public Pattern parse(Parseable parseable,
069 ErrorHandler eh,
070 DatatypeLibraryFactory datatypeLibraryFactory,
071 SchemaPatternBuilder pb,
072 boolean isAttributesPattern)
073 throws IncorrectSchemaException, IOException, SAXException {
074 try {
075 SchemaBuilderImpl sb = new SchemaBuilderImpl(parseable,
076 eh,
077 new BuiltinDatatypeLibraryFactory(datatypeLibraryFactory),
078 pb);
079 ParsedPattern pp = parseable.parse(sb, new RootScope(sb));
080 if (isAttributesPattern)
081 pp = sb.wrapAttributesPattern(pp);
082 return sb.expandPattern((Pattern)pp);
083 }
084 catch (IllegalSchemaException e) {
085 throw new IncorrectSchemaException();
086 }
087 catch (BuildException e) {
088 throw unwrapBuildException(e);
089 }
090 }
091
092
093 static public PatternFuture installHandlers(ParseReceiver parser, XMLReader xr, ErrorHandler eh, DatatypeLibraryFactory dlf,
094 SchemaPatternBuilder pb)
095 throws SAXException {
096 final SchemaBuilderImpl sb = new SchemaBuilderImpl(parser,
097 eh,
098 new BuiltinDatatypeLibraryFactory(dlf),
099 pb);
100 final ParsedPatternFuture pf = parser.installHandlers(xr, sb, new RootScope(sb));
101 return new PatternFuture() {
102 public Pattern getPattern(boolean isAttributesPattern) throws IncorrectSchemaException, SAXException, IOException {
103 try {
104 ParsedPattern pp = pf.getParsedPattern();
105 if (isAttributesPattern)
106 pp = sb.wrapAttributesPattern(pp);
107 return sb.expandPattern((Pattern)pp);
108 }
109 catch (IllegalSchemaException e) {
110 throw new IncorrectSchemaException();
111 }
112 catch (BuildException e) {
113 throw unwrapBuildException(e);
114 }
115 }
116 };
117 }
118
119 static RuntimeException unwrapBuildException(BuildException e) throws SAXException, IncorrectSchemaException, IOException {
120 Throwable t = e.getCause();
121 if (t instanceof IOException)
122 throw (IOException)t;
123 if (t instanceof RuntimeException)
124 return (RuntimeException)t;
125 if (t instanceof IllegalSchemaException)
126 throw new IncorrectSchemaException();
127 if (t instanceof SAXException)
128 throw (SAXException)t;
129 if (t instanceof Exception)
130 throw new SAXException((Exception)t);
131 throw new SAXException(t.getClass().getName() + " thrown");
132 }
133
134 private ParsedPattern wrapAttributesPattern(ParsedPattern pattern) {
135 // XXX where can we get a locator from?
136 return makeElement(makeAnyName(null, null), pattern, null, null);
137 }
138
139 private Pattern expandPattern(Pattern pattern) throws IllegalSchemaException, BuildException {
140 if (!hadError) {
141 try {
142 pattern.checkRecursion(0);
143 pattern = pattern.expand(pb);
144 pattern.checkRestrictions(Pattern.START_CONTEXT, null, null);
145 if (!hadError)
146 return pattern;
147 }
148 catch (SAXParseException e) {
149 error(e);
150 }
151 catch (SAXException e) {
152 throw new BuildException(e);
153 }
154 catch (RestrictionViolationException e) {
155 if (e.getName() != null)
156 error(e.getMessageId(), NameFormatter.format(e.getName()), e.getLocator());
157 else
158 error(e.getMessageId(), e.getLocator());
159 }
160 }
161 throw new IllegalSchemaException();
162 }
163
164 private SchemaBuilderImpl(SubParser subParser,
165 ErrorHandler eh,
166 DatatypeLibraryFactory datatypeLibraryFactory,
167 SchemaPatternBuilder pb) {
168 this.parent = null;
169 this.subParser = subParser;
170 this.eh = eh;
171 this.datatypeLibraryFactory = datatypeLibraryFactory;
172 this.pb = pb;
173 this.inheritNs = "";
174 this.openIncludes = null;
175 }
176
177 private SchemaBuilderImpl(String inheritNs,
178 String uri,
179 SchemaBuilderImpl parent) {
180 this.parent = parent;
181 this.subParser = parent.subParser;
182 this.eh = parent.eh;
183 this.datatypeLibraryFactory = parent.datatypeLibraryFactory;
184 this.pb = parent.pb;
185 this.inheritNs = parent.resolveInherit(inheritNs);
186 this.openIncludes = new OpenIncludes(uri, parent.openIncludes);
187 }
188
189 public ParsedPattern makeChoice(ParsedPattern[] patterns, int nPatterns, Location loc, Annotations anno)
190 throws BuildException {
191 if (nPatterns <= 0)
192 throw new IllegalArgumentException();
193 Pattern result = (Pattern)patterns[0];
194 for (int i = 1; i < nPatterns; i++)
195 result = pb.makeChoice(result, (Pattern)patterns[i]);
196 return result;
197 }
198
199 public ParsedPattern makeInterleave(ParsedPattern[] patterns, int nPatterns, Location loc, Annotations anno)
200 throws BuildException {
201 if (nPatterns <= 0)
202 throw new IllegalArgumentException();
203 Pattern result = (Pattern)patterns[0];
204 for (int i = 1; i < nPatterns; i++)
205 result = pb.makeInterleave(result, (Pattern)patterns[i]);
206 return result;
207 }
208
209 public ParsedPattern makeGroup(ParsedPattern[] patterns, int nPatterns, Location loc, Annotations anno)
210 throws BuildException {
211 if (nPatterns <= 0)
212 throw new IllegalArgumentException();
213 Pattern result = (Pattern)patterns[0];
214 for (int i = 1; i < nPatterns; i++)
215 result = pb.makeGroup(result, (Pattern)patterns[i]);
216 return result;
217 }
218
219 public ParsedPattern makeOneOrMore(ParsedPattern p, Location loc, Annotations anno)
220 throws BuildException {
221 return pb.makeOneOrMore((Pattern)p);
222 }
223
224 public ParsedPattern makeZeroOrMore(ParsedPattern p, Location loc, Annotations anno)
225 throws BuildException {
226 return pb.makeZeroOrMore((Pattern)p);
227 }
228
229 public ParsedPattern makeOptional(ParsedPattern p, Location loc, Annotations anno)
230 throws BuildException {
231 return pb.makeOptional((Pattern)p);
232 }
233
234 public ParsedPattern makeList(ParsedPattern p, Location loc, Annotations anno)
235 throws BuildException {
236 return pb.makeList((Pattern)p, (Locator)loc);
237 }
238
239 public ParsedPattern makeMixed(ParsedPattern p, Location loc, Annotations anno)
240 throws BuildException {
241 return pb.makeMixed((Pattern)p);
242 }
243
244 public ParsedPattern makeEmpty(Location loc, Annotations anno) {
245 return pb.makeEmpty();
246 }
247
248 public ParsedPattern makeNotAllowed(Location loc, Annotations anno) {
249 return pb.makeUnexpandedNotAllowed();
250 }
251
252 public ParsedPattern makeText(Location loc, Annotations anno) {
253 return pb.makeText();
254 }
255
256 public ParsedPattern makeErrorPattern() {
257 return pb.makeError();
258 }
259
260 public ParsedNameClass makeErrorNameClass() {
261 return new ErrorNameClass();
262 }
263
264 public ParsedPattern makeAttribute(ParsedNameClass nc, ParsedPattern p, Location loc, Annotations anno)
265 throws BuildException {
266 String messageId = attributeNameClassChecker.checkNameClass((NameClass)nc);
267 if (messageId != null)
268 error(messageId, (Locator)loc);
269 return pb.makeAttribute((NameClass)nc, (Pattern)p, (Locator)loc);
270 }
271
272 public ParsedPattern makeElement(ParsedNameClass nc, ParsedPattern p, Location loc, Annotations anno)
273 throws BuildException {
274 return pb.makeElement((NameClass)nc, (Pattern)p, (Locator)loc);
275 }
276
277 private class DummyDataPatternBuilder implements DataPatternBuilder {
278 public void addParam(String name, String value, Context context, String ns, Location loc, Annotations anno)
279 throws BuildException {
280 }
281
282 public void annotation(ParsedElementAnnotation ea)
283 throws BuildException {
284 }
285
286 public ParsedPattern makePattern(Location loc, Annotations anno)
287 throws BuildException {
288 return pb.makeError();
289 }
290
291 public ParsedPattern makePattern(ParsedPattern except, Location loc, Annotations anno)
292 throws BuildException {
293 return pb.makeError();
294 }
295 }
296
297 private class ValidationContextImpl implements ValidationContext {
298 private final ValidationContext vc;
299 private final String ns;
300
301 ValidationContextImpl(ValidationContext vc, String ns) {
302 this.vc = vc;
303 this.ns = ns.length() == 0 ? null : ns;
304 }
305
306 public String resolveNamespacePrefix(String prefix) {
307 String result = prefix.length() == 0 ? ns : vc.resolveNamespacePrefix(prefix);
308 if (result == INHERIT_NS) {
309 if (inheritNs.length() == 0)
310 return null;
311 return inheritNs;
312 }
313 return result;
314 }
315
316 public String getBaseUri() {
317 return vc.getBaseUri();
318 }
319
320 public boolean isUnparsedEntity(String entityName) {
321 return vc.isUnparsedEntity(entityName);
322 }
323
324 public boolean isNotation(String notationName) {
325 return vc.isNotation(notationName);
326 }
327 }
328
329 private class DataPatternBuilderImpl implements DataPatternBuilder {
330 private final DatatypeBuilder dtb;
331 DataPatternBuilderImpl(DatatypeBuilder dtb) {
332 this.dtb = dtb;
333 }
334
335 public void addParam(String name, String value, Context context, String ns, Location loc, Annotations anno)
336 throws BuildException {
337 try {
338 dtb.addParameter(name, value, new ValidationContextImpl(context, ns));
339 }
340 catch (DatatypeException e) {
341 String detail = e.getMessage();
342 int pos = e.getIndex();
343 String displayedParam;
344 if (pos == DatatypeException.UNKNOWN)
345 displayedParam = null;
346 else
347 displayedParam = displayParam(value, pos);
348 if (displayedParam != null) {
349 if (detail != null)
350 error("invalid_param_detail_display", detail, displayedParam, (Locator)loc);
351 else
352 error("invalid_param_display", displayedParam, (Locator)loc);
353 }
354 else if (detail != null)
355 error("invalid_param_detail", detail, (Locator)loc);
356 else
357 error("invalid_param", (Locator)loc);
358 }
359 }
360
361 public void annotation(ParsedElementAnnotation ea)
362 throws BuildException {
363 }
364
365 String displayParam(String value, int pos) {
366 if (pos < 0)
367 pos = 0;
368 else if (pos > value.length())
369 pos = value.length();
370 return localizer.message("display_param", value.substring(0, pos), value.substring(pos));
371 }
372
373 public ParsedPattern makePattern(Location loc, Annotations anno)
374 throws BuildException {
375 try {
376 return pb.makeData(dtb.createDatatype());
377 }
378 catch (DatatypeException e) {
379 String detail = e.getMessage();
380 if (detail != null)
381 error("invalid_params_detail", detail, (Locator)loc);
382 else
383 error("invalid_params", (Locator)loc);
384 return pb.makeError();
385 }
386 }
387
388 public ParsedPattern makePattern(ParsedPattern except, Location loc, Annotations anno)
389 throws BuildException {
390 try {
391 return pb.makeDataExcept(dtb.createDatatype(), (Pattern)except, (Locator)loc);
392 }
393 catch (DatatypeException e) {
394 String detail = e.getMessage();
395 if (detail != null)
396 error("invalid_params_detail", detail, (Locator)loc);
397 else
398 error("invalid_params", (Locator)loc);
399 return pb.makeError();
400 }
401 }
402 }
403
404 public DataPatternBuilder makeDataPatternBuilder(String datatypeLibrary, String type, Location loc)
405 throws BuildException {
406 DatatypeLibrary dl = datatypeLibraryFactory.createDatatypeLibrary(datatypeLibrary);
407 if (dl == null)
408 error("unrecognized_datatype_library", datatypeLibrary, (Locator)loc);
409 else {
410 try {
411 return new DataPatternBuilderImpl(dl.createDatatypeBuilder(type));
412 }
413 catch (DatatypeException e) {
414 String detail = e.getMessage();
415 if (detail != null)
416 error("unsupported_datatype_detail", datatypeLibrary, type, detail, (Locator)loc);
417 else
418 error("unrecognized_datatype", datatypeLibrary, type, (Locator)loc);
419 }
420 }
421 return new DummyDataPatternBuilder();
422 }
423
424 public ParsedPattern makeValue(String datatypeLibrary, String type, String value, Context context, String ns,
425 Location loc, Annotations anno) throws BuildException {
426 DatatypeLibrary dl = datatypeLibraryFactory.createDatatypeLibrary(datatypeLibrary);
427 if (dl == null)
428 error("unrecognized_datatype_library", datatypeLibrary, (Locator)loc);
429 else {
430 try {
431 DatatypeBuilder dtb = dl.createDatatypeBuilder(type);
432 try {
433 Datatype dt = dtb.createDatatype();
434 Object obj = dt.createValue(value, new ValidationContextImpl(context, ns));
435 if (obj != null)
436 return pb.makeValue(dt, obj);
437 error("invalid_value", value, (Locator)loc);
438 }
439 catch (DatatypeException e) {
440 String detail = e.getMessage();
441 if (detail != null)
442 error("datatype_requires_param_detail", detail, (Locator)loc);
443 else
444 error("datatype_requires_param", (Locator)loc);
445 }
446 }
447 catch (DatatypeException e) {
448 error("unrecognized_datatype", datatypeLibrary, type, (Locator)loc);
449 }
450 }
451 return pb.makeError();
452 }
453
454 static class GrammarImpl implements Grammar, Div, IncludedGrammar {
455 private final SchemaBuilderImpl sb;
456 private final Hashtable defines;
457 private final RefPattern startRef;
458 private final Scope parent;
459
460 private GrammarImpl(SchemaBuilderImpl sb, Scope parent) {
461 this.sb = sb;
462 this.parent = parent;
463 this.defines = new Hashtable();
464 this.startRef = new RefPattern(null);
465 }
466
467 protected GrammarImpl(SchemaBuilderImpl sb, GrammarImpl g) {
468 this.sb = sb;
469 parent = g.parent;
470 startRef = g.startRef;
471 defines = g.defines;
472 }
473
474 public ParsedPattern endGrammar(Location loc, Annotations anno) throws BuildException {
475 for (Enumeration en = defines.keys();
476 en.hasMoreElements();) {
477 String name = (String)en.nextElement();
478 RefPattern rp = (RefPattern)defines.get(name);
479 if (rp.getPattern() == null) {
480 sb.error("reference_to_undefined", name, rp.getRefLocator());
481 rp.setPattern(sb.pb.makeError());
482 }
483 }
484 Pattern start = startRef.getPattern();
485 if (start == null) {
486 sb.error("missing_start_element", (Locator)loc);
487 start = sb.pb.makeError();
488 }
489 return start;
490 }
491
492 public void endDiv(Location loc, Annotations anno) throws BuildException {
493 // nothing to do
494 }
495
496 public ParsedPattern endIncludedGrammar(Location loc, Annotations anno) throws BuildException {
497 return null;
498 }
499
500 public void define(String name, GrammarSection.Combine combine, ParsedPattern pattern, Location loc, Annotations anno)
501 throws BuildException {
502 define(lookup(name), combine, pattern, loc);
503 }
504
505 private void define(RefPattern rp, GrammarSection.Combine combine, ParsedPattern pattern, Location loc)
506 throws BuildException {
507 switch (rp.getReplacementStatus()) {
508 case RefPattern.REPLACEMENT_KEEP:
509 if (combine == null) {
510 if (rp.isCombineImplicit()) {
511 if (rp.getName() == null)
512 sb.error("duplicate_start", (Locator)loc);
513 else
514 sb.error("duplicate_define", rp.getName(), (Locator)loc);
515 }
516 else
517 rp.setCombineImplicit();
518 }
519 else {
520 byte combineType = (combine == COMBINE_CHOICE ? RefPattern.COMBINE_CHOICE : RefPattern.COMBINE_INTERLEAVE);
521 if (rp.getCombineType() != RefPattern.COMBINE_NONE
522 && rp.getCombineType() != combineType) {
523 if (rp.getName() == null)
524 sb.error("conflict_combine_start", (Locator)loc);
525 else
526 sb.error("conflict_combine_define", rp.getName(), (Locator)loc);
527 }
528 rp.setCombineType(combineType);
529 }
530 Pattern p = (Pattern)pattern;
531 if (rp.getPattern() == null)
532 rp.setPattern(p);
533 else if (rp.getCombineType() == RefPattern.COMBINE_INTERLEAVE)
534 rp.setPattern(sb.pb.makeInterleave(rp.getPattern(), p));
535 else
536 rp.setPattern(sb.pb.makeChoice(rp.getPattern(), p));
537 break;
538 case RefPattern.REPLACEMENT_REQUIRE:
539 rp.setReplacementStatus(RefPattern.REPLACEMENT_IGNORE);
540 break;
541 case RefPattern.REPLACEMENT_IGNORE:
542 break;
543 }
544 }
545
546 public void topLevelAnnotation(ParsedElementAnnotation ea) throws BuildException {
547 }
548
549 public void topLevelComment(CommentList comments) throws BuildException {
550 }
551
552 private RefPattern lookup(String name) {
553 if (name == START)
554 return startRef;
555 return lookup1(name);
556 }
557
558 private RefPattern lookup1(String name) {
559 RefPattern p = (RefPattern)defines.get(name);
560 if (p == null) {
561 p = new RefPattern(name);
562 defines.put(name, p);
563 }
564 return p;
565 }
566
567 public ParsedPattern makeRef(String name, Location loc, Annotations anno) throws BuildException {
568 RefPattern p = lookup1(name);
569 if (p.getRefLocator() == null && loc != null)
570 p.setRefLocator((Locator)loc);
571 return p;
572 }
573
574 public ParsedPattern makeParentRef(String name, Location loc, Annotations anno) throws BuildException {
575 if (parent == null) {
576 sb.error("parent_ref_outside_grammar", (Locator)loc);
577 return sb.makeErrorPattern();
578 }
579 return parent.makeRef(name, loc, anno);
580 }
581
582 public Div makeDiv() {
583 return this;
584 }
585
586 public Include makeInclude() {
587 return new IncludeImpl(sb, this);
588 }
589
590 }
591
592 static class RootScope implements Scope {
593 private final SchemaBuilderImpl sb;
594 RootScope(SchemaBuilderImpl sb) {
595 this.sb = sb;
596 }
597
598 public ParsedPattern makeParentRef(String name, Location loc, Annotations anno) throws BuildException {
599 sb.error("parent_ref_outside_grammar", (Locator)loc);
600 return sb.makeErrorPattern();
601 }
602 public ParsedPattern makeRef(String name, Location loc, Annotations anno) throws BuildException {
603 sb.error("ref_outside_grammar", (Locator)loc);
604 return sb.makeErrorPattern();
605 }
606
607 }
608
609 static class Override {
610 Override(RefPattern prp, Override next) {
611 this.prp = prp;
612 this.next = next;
613 }
614
615 final RefPattern prp;
616 final Override next;
617 byte replacementStatus;
618 }
619
620
621 private static class IncludeImpl implements Include, Div {
622 private final SchemaBuilderImpl sb;
623 private Override overrides;
624 private final GrammarImpl grammar;
625
626 private IncludeImpl(SchemaBuilderImpl sb, GrammarImpl grammar) {
627 this.sb = sb;
628 this.grammar = grammar;
629 }
630
631 public void define(String name, GrammarSection.Combine combine, ParsedPattern pattern, Location loc, Annotations anno)
632 throws BuildException {
633 RefPattern rp = grammar.lookup(name);
634 overrides = new Override(rp, overrides);
635 grammar.define(rp, combine, pattern, loc);
636 }
637
638 public void endDiv(Location loc, Annotations anno) throws BuildException {
639 // nothing to do
640 }
641
642 public void topLevelAnnotation(ParsedElementAnnotation ea) throws BuildException {
643 // nothing to do
644 }
645
646 public void topLevelComment(CommentList comments) throws BuildException {
647 }
648
649 public Div makeDiv() {
650 return this;
651 }
652
653 public void endInclude(String uri, String ns,
654 Location loc, Annotations anno) throws BuildException {
655 for (OpenIncludes inc = sb.openIncludes;
656 inc != null;
657 inc = inc.parent) {
658 if (inc.uri.equals(uri)) {
659 sb.error("recursive_include", uri, (Locator)loc);
660 return;
661 }
662 }
663
664 for (Override o = overrides; o != null; o = o.next) {
665 o.replacementStatus = o.prp.getReplacementStatus();
666 o.prp.setReplacementStatus(RefPattern.REPLACEMENT_REQUIRE);
667 }
668 try {
669 SchemaBuilderImpl isb = new SchemaBuilderImpl(ns, uri, sb);
670 sb.subParser.parseInclude(uri, isb, new GrammarImpl(isb, grammar));
671 for (Override o = overrides; o != null; o = o.next) {
672 if (o.prp.getReplacementStatus() == RefPattern.REPLACEMENT_REQUIRE) {
673 if (o.prp.getName() == null)
674 sb.error("missing_start_replacement", (Locator)loc);
675 else
676 sb.error("missing_define_replacement", o.prp.getName(), (Locator)loc);
677 }
678 }
679 }
680 catch (IllegalSchemaException e) {
681 sb.noteError();
682 }
683 finally {
684 for (Override o = overrides; o != null; o = o.next)
685 o.prp.setReplacementStatus(o.replacementStatus);
686 }
687 }
688
689 public Include makeInclude() {
690 return null;
691 }
692 }
693
694 public Grammar makeGrammar(Scope parent) {
695 return new GrammarImpl(this, parent);
696 }
697
698 public ParsedPattern annotate(ParsedPattern p, Annotations anno) throws BuildException {
699 return p;
700 }
701
702 public ParsedNameClass annotate(ParsedNameClass nc, Annotations anno) throws BuildException {
703 return nc;
704 }
705
706 public ParsedPattern annotateAfter(ParsedPattern p, ParsedElementAnnotation e) throws BuildException {
707 return p;
708 }
709
710 public ParsedNameClass annotateAfter(ParsedNameClass nc, ParsedElementAnnotation e) throws BuildException {
711 return nc;
712 }
713
714 public ParsedPattern commentAfter(ParsedPattern p, CommentList comments) throws BuildException {
715 return p;
716 }
717
718 public ParsedNameClass commentAfter(ParsedNameClass nc, CommentList comments) throws BuildException {
719 return nc;
720 }
721
722 public ParsedPattern makeExternalRef(String uri, String ns, Scope scope,
723 Location loc, Annotations anno)
724 throws BuildException {
725 for (OpenIncludes inc = openIncludes;
726 inc != null;
727 inc = inc.parent) {
728 if (inc.uri.equals(uri)) {
729 error("recursive_include", uri, (Locator)loc);
730 return pb.makeError();
731 }
732 }
733 try {
734 return subParser.parseExternal(uri, new SchemaBuilderImpl(ns, uri, this), scope);
735 }
736 catch (IllegalSchemaException e) {
737 noteError();
738 return pb.makeError();
739 }
740 }
741
742 public ParsedNameClass makeChoice(ParsedNameClass[] nameClasses, int nNameClasses, Location loc, Annotations anno) {
743 if (nNameClasses <= 0)
744 throw new IllegalArgumentException();
745 NameClass result = (NameClass)nameClasses[0];
746 for (int i = 1; i < nNameClasses; i++)
747 result = new ChoiceNameClass(result, (NameClass)nameClasses[i]);
748 return result;
749 }
750
751 public ParsedNameClass makeName(String ns, String localName, String prefix, Location loc, Annotations anno) {
752 return new SimpleNameClass(new Name(resolveInherit(ns), localName));
753 }
754
755 public ParsedNameClass makeNsName(String ns, Location loc, Annotations anno) {
756 return new NsNameClass(resolveInherit(ns));
757 }
758
759 public ParsedNameClass makeNsName(String ns, ParsedNameClass except, Location loc, Annotations anno) {
760 return new NsNameExceptNameClass(resolveInherit(ns), (NameClass)except);
761 }
762
763 public ParsedNameClass makeAnyName(Location loc, Annotations anno) {
764 return new AnyNameClass();
765 }
766
767 public ParsedNameClass makeAnyName(ParsedNameClass except, Location loc, Annotations anno) {
768 return new AnyNameExceptNameClass((NameClass)except);
769 }
770
771 private final String resolveInherit(String ns) {
772 if (ns == INHERIT_NS)
773 return inheritNs;
774 return ns;
775 }
776
777 private class LocatorImpl implements Locator, Location {
778 private final String systemId;
779 private final int lineNumber;
780 private final int columnNumber;
781
782 private LocatorImpl(String systemId, int lineNumber, int columnNumber) {
783 this.systemId = systemId;
784 this.lineNumber = lineNumber;
785 this.columnNumber = columnNumber;
786 }
787
788 public String getPublicId() {
789 return null;
790 }
791
792 public String getSystemId() {
793 return systemId;
794 }
795
796 public int getLineNumber() {
797 return lineNumber;
798 }
799
800 public int getColumnNumber() {
801 return columnNumber;
802 }
803 }
804
805 public Location makeLocation(String systemId, int lineNumber, int columnNumber) {
806 return new LocatorImpl(systemId, lineNumber, columnNumber);
807 }
808
809 public Annotations makeAnnotations(CommentList comments, Context context) {
810 return this;
811 }
812
813 public ElementAnnotationBuilder makeElementAnnotationBuilder(String ns, String localName, String prefix,
814 Location loc, CommentList comments, Context context) {
815 return this;
816 }
817
818 public CommentList makeCommentList() {
819 return this;
820 }
821
822 public void addComment(String value, Location loc) throws BuildException {
823 }
824
825 public void addAttribute(String ns, String localName, String prefix, String value, Location loc) {
826 // nothing needed
827 }
828
829 public void addElement(ParsedElementAnnotation ea) {
830 // nothing needed
831 }
832
833 public void addComment(CommentList comments) throws BuildException {
834 // nothing needed
835 }
836
837 public void addLeadingComment(CommentList comments) throws BuildException {
838 // nothing needed
839 }
840
841 public void addText(String value, Location loc, CommentList comments) {
842 // nothing needed
843 }
844
845 public ParsedElementAnnotation makeElementAnnotation() {
846 return null;
847 }
848
849 public boolean usesComments() {
850 return false;
851 }
852
853 private void error(SAXParseException message) throws BuildException {
854 noteError();
855 try {
856 if (eh != null)
857 eh.error(message);
858 }
859 catch (SAXException e) {
860 throw new BuildException(e);
861 }
862 }
863
864 /*
865 private void warning(SAXParseException message) throws BuildException {
866 try {
867 if (eh != null)
868 eh.warning(message);
869 }
870 catch (SAXException e) {
871 throw new BuildException(e);
872 }
873 }
874 */
875
876 private void error(String key, Locator loc) throws BuildException {
877 error(new SAXParseException(localizer.message(key), loc));
878 }
879
880 private void error(String key, String arg, Locator loc) throws BuildException {
881 error(new SAXParseException(localizer.message(key, arg), loc));
882 }
883
884 private void error(String key, String arg1, String arg2, Locator loc) throws BuildException {
885 error(new SAXParseException(localizer.message(key, arg1, arg2), loc));
886 }
887
888 private void error(String key, String arg1, String arg2, String arg3, Locator loc) throws BuildException {
889 error(new SAXParseException(localizer.message(key, new Object[]{arg1, arg2, arg3}), loc));
890 }
891 private void noteError() {
892 if (!hadError && parent != null)
893 parent.noteError();
894 hadError = true;
895 }
896 }