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