0001: package org.kohsuke.rngom.parse.xml;
0002:
0003: import java.util.Enumeration;
0004: import java.util.Hashtable;
0005: import java.util.Stack;
0006: import java.util.Vector;
0007: import java.util.List;
0008: import java.util.ArrayList;
0009: import java.util.Arrays;
0010:
0011: import org.kohsuke.rngom.ast.builder.Annotations;
0012: import org.kohsuke.rngom.ast.builder.CommentList;
0013: import org.kohsuke.rngom.ast.builder.DataPatternBuilder;
0014: import org.kohsuke.rngom.ast.builder.Div;
0015: import org.kohsuke.rngom.ast.builder.ElementAnnotationBuilder;
0016: import org.kohsuke.rngom.ast.builder.Grammar;
0017: import org.kohsuke.rngom.ast.builder.GrammarSection;
0018: import org.kohsuke.rngom.ast.builder.Include;
0019: import org.kohsuke.rngom.ast.builder.IncludedGrammar;
0020: import org.kohsuke.rngom.ast.builder.NameClassBuilder;
0021: import org.kohsuke.rngom.ast.builder.SchemaBuilder;
0022: import org.kohsuke.rngom.ast.builder.Scope;
0023: import org.kohsuke.rngom.ast.om.Location;
0024: import org.kohsuke.rngom.ast.om.ParsedElementAnnotation;
0025: import org.kohsuke.rngom.ast.om.ParsedNameClass;
0026: import org.kohsuke.rngom.ast.om.ParsedPattern;
0027: import org.kohsuke.rngom.parse.Context;
0028: import org.kohsuke.rngom.parse.IllegalSchemaException;
0029: import org.kohsuke.rngom.parse.Parseable;
0030: import org.kohsuke.rngom.util.Localizer;
0031: import org.kohsuke.rngom.util.Uri;
0032: import org.kohsuke.rngom.xml.sax.AbstractLexicalHandler;
0033: import org.kohsuke.rngom.xml.sax.XmlBaseHandler;
0034: import org.kohsuke.rngom.xml.util.Naming;
0035: import org.kohsuke.rngom.xml.util.WellKnownNamespaces;
0036: import org.xml.sax.Attributes;
0037: import org.xml.sax.ContentHandler;
0038: import org.xml.sax.ErrorHandler;
0039: import org.xml.sax.Locator;
0040: import org.xml.sax.SAXException;
0041: import org.xml.sax.SAXNotRecognizedException;
0042: import org.xml.sax.SAXNotSupportedException;
0043: import org.xml.sax.SAXParseException;
0044: import org.xml.sax.XMLReader;
0045: import org.xml.sax.helpers.DefaultHandler;
0046:
0047: class SchemaParser {
0048:
0049: private static final String relaxngURIPrefix = WellKnownNamespaces.RELAX_NG
0050: .substring(0,
0051: WellKnownNamespaces.RELAX_NG.lastIndexOf('/') + 1);
0052: static final String relaxng10URI = WellKnownNamespaces.RELAX_NG;
0053: private static final Localizer localizer = new Localizer(
0054: new Localizer(Parseable.class), SchemaParser.class);
0055:
0056: private String relaxngURI;
0057: private final XMLReader xr;
0058: private final ErrorHandler eh;
0059: private final SchemaBuilder schemaBuilder;
0060: /**
0061: * The value of the {@link SchemaBuilder#getNameClassBuilder()}
0062: * for the {@link #schemaBuilder} object.
0063: */
0064: private final NameClassBuilder nameClassBuilder;
0065: private ParsedPattern startPattern;
0066: private Locator locator;
0067: private final XmlBaseHandler xmlBaseHandler = new XmlBaseHandler();
0068: private final ContextImpl context = new ContextImpl();
0069:
0070: private boolean hadError = false;
0071:
0072: private Hashtable patternTable;
0073: private Hashtable nameClassTable;
0074:
0075: static class PrefixMapping {
0076: final String prefix;
0077: final String uri;
0078: final PrefixMapping next;
0079:
0080: PrefixMapping(String prefix, String uri, PrefixMapping next) {
0081: this .prefix = prefix;
0082: this .uri = uri;
0083: this .next = next;
0084: }
0085: }
0086:
0087: static abstract class AbstractContext extends DtdContext implements
0088: Context {
0089: PrefixMapping prefixMapping;
0090:
0091: AbstractContext() {
0092: prefixMapping = new PrefixMapping("xml",
0093: WellKnownNamespaces.XML, null);
0094: }
0095:
0096: AbstractContext(AbstractContext context) {
0097: super (context);
0098: prefixMapping = context.prefixMapping;
0099: }
0100:
0101: public String resolveNamespacePrefix(String prefix) {
0102: for (PrefixMapping p = prefixMapping; p != null; p = p.next)
0103: if (p.prefix.equals(prefix))
0104: return p.uri;
0105: return null;
0106: }
0107:
0108: public Enumeration prefixes() {
0109: Vector v = new Vector();
0110: for (PrefixMapping p = prefixMapping; p != null; p = p.next) {
0111: if (!v.contains(p.prefix))
0112: v.addElement(p.prefix);
0113: }
0114: return v.elements();
0115: }
0116:
0117: public Context copy() {
0118: return new SavedContext(this );
0119: }
0120: }
0121:
0122: static class SavedContext extends AbstractContext {
0123: private final String baseUri;
0124:
0125: SavedContext(AbstractContext context) {
0126: super (context);
0127: this .baseUri = context.getBaseUri();
0128: }
0129:
0130: public String getBaseUri() {
0131: return baseUri;
0132: }
0133: }
0134:
0135: class ContextImpl extends AbstractContext {
0136: public String getBaseUri() {
0137: return xmlBaseHandler.getBaseUri();
0138: }
0139: }
0140:
0141: static interface CommentHandler {
0142: void comment(String value);
0143: }
0144:
0145: abstract class Handler implements ContentHandler, CommentHandler {
0146: CommentList comments;
0147:
0148: CommentList getComments() {
0149: CommentList tem = comments;
0150: comments = null;
0151: return tem;
0152: }
0153:
0154: public void comment(String value) {
0155: if (comments == null)
0156: comments = schemaBuilder.makeCommentList();
0157: comments.addComment(value, makeLocation());
0158: }
0159:
0160: public void processingInstruction(String target, String date) {
0161: }
0162:
0163: public void skippedEntity(String name) {
0164: }
0165:
0166: public void ignorableWhitespace(char[] ch, int start, int len) {
0167: }
0168:
0169: public void startDocument() {
0170: }
0171:
0172: public void endDocument() {
0173: }
0174:
0175: public void startPrefixMapping(String prefix, String uri) {
0176: context.prefixMapping = new PrefixMapping(prefix, uri,
0177: context.prefixMapping);
0178: }
0179:
0180: public void endPrefixMapping(String prefix) {
0181: context.prefixMapping = context.prefixMapping.next;
0182: }
0183:
0184: public void setDocumentLocator(Locator loc) {
0185: locator = loc;
0186: xmlBaseHandler.setLocator(loc);
0187: }
0188: }
0189:
0190: abstract class State extends Handler {
0191: State parent;
0192: String nsInherit;
0193: String ns;
0194: String datatypeLibrary;
0195: /**
0196: * The current scope, or null if there's none.
0197: */
0198: Scope scope;
0199: Location startLocation;
0200: Annotations annotations;
0201:
0202: void set() {
0203: xr.setContentHandler(this );
0204: }
0205:
0206: abstract State create();
0207:
0208: abstract State createChildState(String localName)
0209: throws SAXException;
0210:
0211: void setParent(State parent) {
0212: this .parent = parent;
0213: this .nsInherit = parent.getNs();
0214: this .datatypeLibrary = parent.datatypeLibrary;
0215: this .scope = parent.scope;
0216: this .startLocation = makeLocation();
0217: if (parent.comments != null) {
0218: annotations = schemaBuilder.makeAnnotations(
0219: parent.comments, getContext());
0220: parent.comments = null;
0221: } else if (parent instanceof RootState)
0222: annotations = schemaBuilder.makeAnnotations(null,
0223: getContext());
0224: }
0225:
0226: String getNs() {
0227: return ns == null ? nsInherit : ns;
0228: }
0229:
0230: boolean isRelaxNGElement(String uri) throws SAXException {
0231: return uri.equals(relaxngURI);
0232: }
0233:
0234: public void startElement(String namespaceURI, String localName,
0235: String qName, Attributes atts) throws SAXException {
0236: xmlBaseHandler.startElement();
0237: if (isRelaxNGElement(namespaceURI)) {
0238: State state = createChildState(localName);
0239: if (state == null) {
0240: xr.setContentHandler(new Skipper(this ));
0241: return;
0242: }
0243: state.setParent(this );
0244: state.set();
0245: state.attributes(atts);
0246: } else {
0247: checkForeignElement();
0248: ForeignElementHandler feh = new ForeignElementHandler(
0249: this , getComments());
0250: feh.startElement(namespaceURI, localName, qName, atts);
0251: xr.setContentHandler(feh);
0252: }
0253: }
0254:
0255: public void endElement(String namespaceURI, String localName,
0256: String qName) throws SAXException {
0257: xmlBaseHandler.endElement();
0258: parent.set();
0259: end();
0260: }
0261:
0262: void setName(String name) throws SAXException {
0263: error("illegal_name_attribute");
0264: }
0265:
0266: void setOtherAttribute(String name, String value)
0267: throws SAXException {
0268: error("illegal_attribute_ignored", name);
0269: }
0270:
0271: void endAttributes() throws SAXException {
0272: }
0273:
0274: void checkForeignElement() throws SAXException {
0275: }
0276:
0277: void attributes(Attributes atts) throws SAXException {
0278: int len = atts.getLength();
0279: for (int i = 0; i < len; i++) {
0280: String uri = atts.getURI(i);
0281: if (uri.length() == 0) {
0282: String name = atts.getLocalName(i);
0283: if (name.equals("name"))
0284: setName(atts.getValue(i).trim());
0285: else if (name.equals("ns"))
0286: ns = atts.getValue(i);
0287: else if (name.equals("datatypeLibrary")) {
0288: datatypeLibrary = atts.getValue(i);
0289: checkUri(datatypeLibrary);
0290: if (!datatypeLibrary.equals("")
0291: && !Uri.isAbsolute(datatypeLibrary))
0292: error("relative_datatype_library");
0293: if (Uri.hasFragmentId(datatypeLibrary))
0294: error("fragment_identifier_datatype_library");
0295: datatypeLibrary = Uri
0296: .escapeDisallowedChars(datatypeLibrary);
0297: } else
0298: setOtherAttribute(name, atts.getValue(i));
0299: } else if (uri.equals(relaxngURI))
0300: error("qualified_attribute", atts.getLocalName(i));
0301: else if (uri.equals(WellKnownNamespaces.XML)
0302: && atts.getLocalName(i).equals("base"))
0303: xmlBaseHandler.xmlBaseAttribute(atts.getValue(i));
0304: else {
0305: if (annotations == null)
0306: annotations = schemaBuilder.makeAnnotations(
0307: null, getContext());
0308: annotations.addAttribute(uri, atts.getLocalName(i),
0309: findPrefix(atts.getQName(i), uri), atts
0310: .getValue(i), startLocation);
0311: }
0312: }
0313: endAttributes();
0314: }
0315:
0316: abstract void end() throws SAXException;
0317:
0318: void endChild(ParsedPattern pattern) {
0319: // XXX cannot happen; throw exception
0320: }
0321:
0322: void endChild(ParsedNameClass nc) {
0323: // XXX cannot happen; throw exception
0324: }
0325:
0326: public void startDocument() {
0327: }
0328:
0329: public void endDocument() {
0330: if (comments != null && startPattern != null) {
0331: startPattern = schemaBuilder.commentAfter(startPattern,
0332: comments);
0333: comments = null;
0334: }
0335: }
0336:
0337: public void characters(char[] ch, int start, int len)
0338: throws SAXException {
0339: for (int i = 0; i < len; i++) {
0340: switch (ch[start + i]) {
0341: case ' ':
0342: case '\r':
0343: case '\n':
0344: case '\t':
0345: break;
0346: default:
0347: error("illegal_characters_ignored");
0348: break;
0349: }
0350: }
0351: }
0352:
0353: boolean isPatternNamespaceURI(String s) {
0354: return s.equals(relaxngURI);
0355: }
0356:
0357: void endForeignChild(ParsedElementAnnotation ea) {
0358: if (annotations == null)
0359: annotations = schemaBuilder.makeAnnotations(null,
0360: getContext());
0361: annotations.addElement(ea);
0362: }
0363:
0364: void mergeLeadingComments() {
0365: if (comments != null) {
0366: if (annotations == null)
0367: annotations = schemaBuilder.makeAnnotations(
0368: comments, getContext());
0369: else
0370: annotations.addLeadingComment(comments);
0371: comments = null;
0372: }
0373: }
0374: }
0375:
0376: class ForeignElementHandler extends Handler {
0377: final State nextState;
0378: ElementAnnotationBuilder builder;
0379: final Stack builderStack = new Stack();
0380: StringBuffer textBuf;
0381: Location textLoc;
0382:
0383: ForeignElementHandler(State nextState, CommentList comments) {
0384: this .nextState = nextState;
0385: this .comments = comments;
0386: }
0387:
0388: public void startElement(String namespaceURI, String localName,
0389: String qName, Attributes atts) {
0390: flushText();
0391: if (builder != null)
0392: builderStack.push(builder);
0393: Location loc = makeLocation();
0394: builder = schemaBuilder.makeElementAnnotationBuilder(
0395: namespaceURI, localName, findPrefix(qName,
0396: namespaceURI), loc, getComments(),
0397: getContext());
0398: int len = atts.getLength();
0399: for (int i = 0; i < len; i++) {
0400: String uri = atts.getURI(i);
0401: builder.addAttribute(uri, atts.getLocalName(i),
0402: findPrefix(atts.getQName(i), uri), atts
0403: .getValue(i), loc);
0404: }
0405: }
0406:
0407: public void endElement(String namespaceURI, String localName,
0408: String qName) {
0409: flushText();
0410: if (comments != null)
0411: builder.addComment(getComments());
0412: ParsedElementAnnotation ea = builder
0413: .makeElementAnnotation();
0414: if (builderStack.empty()) {
0415: nextState.endForeignChild(ea);
0416: nextState.set();
0417: } else {
0418: builder = (ElementAnnotationBuilder) builderStack.pop();
0419: builder.addElement(ea);
0420: }
0421: }
0422:
0423: public void characters(char ch[], int start, int length) {
0424: if (textBuf == null)
0425: textBuf = new StringBuffer();
0426: textBuf.append(ch, start, length);
0427: if (textLoc == null)
0428: textLoc = makeLocation();
0429: }
0430:
0431: public void comment(String value) {
0432: flushText();
0433: super .comment(value);
0434: }
0435:
0436: void flushText() {
0437: if (textBuf != null && textBuf.length() != 0) {
0438: builder.addText(textBuf.toString(), textLoc,
0439: getComments());
0440: textBuf.setLength(0);
0441: }
0442: textLoc = null;
0443: }
0444: }
0445:
0446: class Skipper extends DefaultHandler implements CommentHandler {
0447: int level = 1;
0448: final State nextState;
0449:
0450: Skipper(State nextState) {
0451: this .nextState = nextState;
0452: }
0453:
0454: public void startElement(String namespaceURI, String localName,
0455: String qName, Attributes atts) throws SAXException {
0456: ++level;
0457: }
0458:
0459: public void endElement(String namespaceURI, String localName,
0460: String qName) throws SAXException {
0461: if (--level == 0)
0462: nextState.set();
0463: }
0464:
0465: public void comment(String value) {
0466: }
0467: }
0468:
0469: abstract class EmptyContentState extends State {
0470:
0471: State createChildState(String localName) throws SAXException {
0472: error("expected_empty", localName);
0473: return null;
0474: }
0475:
0476: abstract ParsedPattern makePattern() throws SAXException;
0477:
0478: void end() throws SAXException {
0479: if (comments != null) {
0480: if (annotations == null)
0481: annotations = schemaBuilder.makeAnnotations(null,
0482: getContext());
0483: annotations.addComment(comments);
0484: comments = null;
0485: }
0486: parent.endChild(makePattern());
0487: }
0488: }
0489:
0490: static private final int INIT_CHILD_ALLOC = 5;
0491:
0492: abstract class PatternContainerState extends State {
0493: List<ParsedPattern> childPatterns;
0494:
0495: State createChildState(String localName) throws SAXException {
0496: State state = (State) patternTable.get(localName);
0497: if (state == null) {
0498: error("expected_pattern", localName);
0499: return null;
0500: }
0501: return state.create();
0502: }
0503:
0504: ParsedPattern buildPattern(List<ParsedPattern> patterns,
0505: Location loc, Annotations anno) throws SAXException {
0506: if (patterns.size() == 1 && anno == null)
0507: return patterns.get(0);
0508: return schemaBuilder.makeGroup(patterns, loc, anno);
0509: }
0510:
0511: void endChild(ParsedPattern pattern) {
0512: if (childPatterns == null)
0513: childPatterns = new ArrayList<ParsedPattern>(
0514: INIT_CHILD_ALLOC);
0515: childPatterns.add(pattern);
0516: }
0517:
0518: void endForeignChild(ParsedElementAnnotation ea) {
0519: if (childPatterns == null)
0520: super .endForeignChild(ea);
0521: else {
0522: int idx = childPatterns.size() - 1;
0523: childPatterns.set(idx, schemaBuilder.annotateAfter(
0524: childPatterns.get(idx), ea));
0525: }
0526: }
0527:
0528: void end() throws SAXException {
0529: if (childPatterns == null) {
0530: error("missing_children");
0531: endChild(schemaBuilder.makeErrorPattern());
0532: }
0533: if (comments != null) {
0534: int idx = childPatterns.size() - 1;
0535: childPatterns.set(idx, schemaBuilder.commentAfter(
0536: childPatterns.get(idx), comments));
0537: comments = null;
0538: }
0539: sendPatternToParent(buildPattern(childPatterns,
0540: startLocation, annotations));
0541: }
0542:
0543: void sendPatternToParent(ParsedPattern p) {
0544: parent.endChild(p);
0545: }
0546: }
0547:
0548: class GroupState extends PatternContainerState {
0549: State create() {
0550: return new GroupState();
0551: }
0552: }
0553:
0554: class ZeroOrMoreState extends PatternContainerState {
0555: State create() {
0556: return new ZeroOrMoreState();
0557: }
0558:
0559: ParsedPattern buildPattern(List<ParsedPattern> patterns,
0560: Location loc, Annotations anno) throws SAXException {
0561: return schemaBuilder.makeZeroOrMore(super .buildPattern(
0562: patterns, loc, null), loc, anno);
0563: }
0564: }
0565:
0566: class OneOrMoreState extends PatternContainerState {
0567: State create() {
0568: return new OneOrMoreState();
0569: }
0570:
0571: ParsedPattern buildPattern(List<ParsedPattern> patterns,
0572: Location loc, Annotations anno) throws SAXException {
0573: return schemaBuilder.makeOneOrMore(super .buildPattern(
0574: patterns, loc, null), loc, anno);
0575: }
0576: }
0577:
0578: class OptionalState extends PatternContainerState {
0579: State create() {
0580: return new OptionalState();
0581: }
0582:
0583: ParsedPattern buildPattern(List<ParsedPattern> patterns,
0584: Location loc, Annotations anno) throws SAXException {
0585: return schemaBuilder.makeOptional(super .buildPattern(
0586: patterns, loc, null), loc, anno);
0587: }
0588: }
0589:
0590: class ListState extends PatternContainerState {
0591: State create() {
0592: return new ListState();
0593: }
0594:
0595: ParsedPattern buildPattern(List<ParsedPattern> patterns,
0596: Location loc, Annotations anno) throws SAXException {
0597: return schemaBuilder.makeList(super .buildPattern(patterns,
0598: loc, null), loc, anno);
0599: }
0600: }
0601:
0602: class ChoiceState extends PatternContainerState {
0603: State create() {
0604: return new ChoiceState();
0605: }
0606:
0607: ParsedPattern buildPattern(List<ParsedPattern> patterns,
0608: Location loc, Annotations anno) throws SAXException {
0609: return schemaBuilder.makeChoice(patterns, loc, anno);
0610: }
0611: }
0612:
0613: class InterleaveState extends PatternContainerState {
0614: State create() {
0615: return new InterleaveState();
0616: }
0617:
0618: ParsedPattern buildPattern(List<ParsedPattern> patterns,
0619: Location loc, Annotations anno) {
0620: return schemaBuilder.makeInterleave(patterns, loc, anno);
0621: }
0622: }
0623:
0624: class MixedState extends PatternContainerState {
0625: State create() {
0626: return new MixedState();
0627: }
0628:
0629: ParsedPattern buildPattern(List<ParsedPattern> patterns,
0630: Location loc, Annotations anno) throws SAXException {
0631: return schemaBuilder.makeMixed(super .buildPattern(patterns,
0632: loc, null), loc, anno);
0633: }
0634: }
0635:
0636: static interface NameClassRef {
0637: void setNameClass(ParsedNameClass nc);
0638: }
0639:
0640: class ElementState extends PatternContainerState implements
0641: NameClassRef {
0642: ParsedNameClass nameClass;
0643: boolean nameClassWasAttribute;
0644: String name;
0645:
0646: void setName(String name) {
0647: this .name = name;
0648: }
0649:
0650: public void setNameClass(ParsedNameClass nc) {
0651: nameClass = nc;
0652: }
0653:
0654: void endAttributes() throws SAXException {
0655: if (name != null) {
0656: nameClass = expandName(name, getNs(), null);
0657: nameClassWasAttribute = true;
0658: } else
0659: new NameClassChildState(this , this ).set();
0660: }
0661:
0662: State create() {
0663: return new ElementState();
0664: }
0665:
0666: ParsedPattern buildPattern(List<ParsedPattern> patterns,
0667: Location loc, Annotations anno) throws SAXException {
0668: return schemaBuilder.makeElement(nameClass, super
0669: .buildPattern(patterns, loc, null), loc, anno);
0670: }
0671:
0672: void endForeignChild(ParsedElementAnnotation ea) {
0673: if (nameClassWasAttribute || childPatterns != null
0674: || nameClass == null)
0675: super .endForeignChild(ea);
0676: else
0677: nameClass = nameClassBuilder.annotateAfter(nameClass,
0678: ea);
0679: }
0680: }
0681:
0682: class RootState extends PatternContainerState {
0683: IncludedGrammar grammar;
0684:
0685: RootState() {
0686: }
0687:
0688: RootState(IncludedGrammar grammar, Scope scope, String ns) {
0689: this .grammar = grammar;
0690: this .scope = scope;
0691: this .nsInherit = ns;
0692: this .datatypeLibrary = "";
0693: }
0694:
0695: State create() {
0696: return new RootState();
0697: }
0698:
0699: State createChildState(String localName) throws SAXException {
0700: if (grammar == null)
0701: return super .createChildState(localName);
0702: if (localName.equals("grammar"))
0703: return new MergeGrammarState(grammar);
0704: error("expected_grammar", localName);
0705: return null;
0706: }
0707:
0708: void checkForeignElement() throws SAXException {
0709: error("root_bad_namespace_uri",
0710: WellKnownNamespaces.RELAX_NG);
0711: }
0712:
0713: void endChild(ParsedPattern pattern) {
0714: startPattern = pattern;
0715: }
0716:
0717: boolean isRelaxNGElement(String uri) throws SAXException {
0718: if (!uri.startsWith(relaxngURIPrefix))
0719: return false;
0720: if (!uri.equals(WellKnownNamespaces.RELAX_NG))
0721: warning("wrong_uri_version",
0722: WellKnownNamespaces.RELAX_NG
0723: .substring(relaxngURIPrefix.length()),
0724: uri.substring(relaxngURIPrefix.length()));
0725: relaxngURI = uri;
0726: return true;
0727: }
0728:
0729: }
0730:
0731: class NotAllowedState extends EmptyContentState {
0732: State create() {
0733: return new NotAllowedState();
0734: }
0735:
0736: ParsedPattern makePattern() {
0737: return schemaBuilder.makeNotAllowed(startLocation,
0738: annotations);
0739: }
0740: }
0741:
0742: class EmptyState extends EmptyContentState {
0743: State create() {
0744: return new EmptyState();
0745: }
0746:
0747: ParsedPattern makePattern() {
0748: return schemaBuilder.makeEmpty(startLocation, annotations);
0749: }
0750: }
0751:
0752: class TextState extends EmptyContentState {
0753: State create() {
0754: return new TextState();
0755: }
0756:
0757: ParsedPattern makePattern() {
0758: return schemaBuilder.makeText(startLocation, annotations);
0759: }
0760: }
0761:
0762: class ValueState extends EmptyContentState {
0763: final StringBuffer buf = new StringBuffer();
0764: String type;
0765:
0766: State create() {
0767: return new ValueState();
0768: }
0769:
0770: void setOtherAttribute(String name, String value)
0771: throws SAXException {
0772: if (name.equals("type"))
0773: type = checkNCName(value.trim());
0774: else
0775: super .setOtherAttribute(name, value);
0776: }
0777:
0778: public void characters(char[] ch, int start, int len) {
0779: buf.append(ch, start, len);
0780: }
0781:
0782: void checkForeignElement() throws SAXException {
0783: error("value_contains_foreign_element");
0784: }
0785:
0786: ParsedPattern makePattern() throws SAXException {
0787: if (type == null)
0788: return makePattern("", "token");
0789: else
0790: return makePattern(datatypeLibrary, type);
0791: }
0792:
0793: void end() throws SAXException {
0794: mergeLeadingComments();
0795: super .end();
0796: }
0797:
0798: ParsedPattern makePattern(String datatypeLibrary, String type) {
0799: return schemaBuilder.makeValue(datatypeLibrary, type, buf
0800: .toString(), getContext(), getNs(), startLocation,
0801: annotations);
0802: }
0803:
0804: }
0805:
0806: class DataState extends State {
0807: String type;
0808: ParsedPattern except = null;
0809: DataPatternBuilder dpb = null;
0810:
0811: State create() {
0812: return new DataState();
0813: }
0814:
0815: State createChildState(String localName) throws SAXException {
0816: if (localName.equals("param")) {
0817: if (except != null)
0818: error("param_after_except");
0819: return new ParamState(dpb);
0820: }
0821: if (localName.equals("except")) {
0822: if (except != null)
0823: error("multiple_except");
0824: return new ChoiceState();
0825: }
0826: error("expected_param_except", localName);
0827: return null;
0828: }
0829:
0830: void setOtherAttribute(String name, String value)
0831: throws SAXException {
0832: if (name.equals("type"))
0833: type = checkNCName(value.trim());
0834: else
0835: super .setOtherAttribute(name, value);
0836: }
0837:
0838: void endAttributes() throws SAXException {
0839: if (type == null)
0840: error("missing_type_attribute");
0841: else
0842: dpb = schemaBuilder.makeDataPatternBuilder(
0843: datatypeLibrary, type, startLocation);
0844: }
0845:
0846: void endForeignChild(ParsedElementAnnotation ea) {
0847: dpb.annotation(ea);
0848: }
0849:
0850: void end() throws SAXException {
0851: ParsedPattern p;
0852: if (dpb != null) {
0853: if (except != null)
0854: p = dpb.makePattern(except, startLocation,
0855: annotations);
0856: else
0857: p = dpb.makePattern(startLocation, annotations);
0858: } else
0859: p = schemaBuilder.makeErrorPattern();
0860: // XXX need to capture comments
0861: parent.endChild(p);
0862: }
0863:
0864: void endChild(ParsedPattern pattern) {
0865: except = pattern;
0866: }
0867:
0868: }
0869:
0870: class ParamState extends State {
0871: private final StringBuffer buf = new StringBuffer();
0872: private final DataPatternBuilder dpb;
0873: private String name;
0874:
0875: ParamState(DataPatternBuilder dpb) {
0876: this .dpb = dpb;
0877: }
0878:
0879: State create() {
0880: return new ParamState(null);
0881: }
0882:
0883: void setName(String name) throws SAXException {
0884: this .name = checkNCName(name);
0885: }
0886:
0887: void endAttributes() throws SAXException {
0888: if (name == null)
0889: error("missing_name_attribute");
0890: }
0891:
0892: State createChildState(String localName) throws SAXException {
0893: error("expected_empty", localName);
0894: return null;
0895: }
0896:
0897: public void characters(char[] ch, int start, int len) {
0898: buf.append(ch, start, len);
0899: }
0900:
0901: void checkForeignElement() throws SAXException {
0902: error("param_contains_foreign_element");
0903: }
0904:
0905: void end() throws SAXException {
0906: if (name == null)
0907: return;
0908: if (dpb == null)
0909: return;
0910: mergeLeadingComments();
0911: dpb.addParam(name, buf.toString(), getContext(), getNs(),
0912: startLocation, annotations);
0913: }
0914: }
0915:
0916: class AttributeState extends PatternContainerState implements
0917: NameClassRef {
0918: ParsedNameClass nameClass;
0919: boolean nameClassWasAttribute;
0920: String name;
0921:
0922: State create() {
0923: return new AttributeState();
0924: }
0925:
0926: void setName(String name) {
0927: this .name = name;
0928: }
0929:
0930: public void setNameClass(ParsedNameClass nc) {
0931: nameClass = nc;
0932: }
0933:
0934: void endAttributes() throws SAXException {
0935: if (name != null) {
0936: String nsUse;
0937: if (ns != null)
0938: nsUse = ns;
0939: else
0940: nsUse = "";
0941: nameClass = expandName(name, nsUse, null);
0942: nameClassWasAttribute = true;
0943: } else
0944: new NameClassChildState(this , this ).set();
0945: }
0946:
0947: void endForeignChild(ParsedElementAnnotation ea) {
0948: if (nameClassWasAttribute || childPatterns != null
0949: || nameClass == null)
0950: super .endForeignChild(ea);
0951: else
0952: nameClass = nameClassBuilder.annotateAfter(nameClass,
0953: ea);
0954: }
0955:
0956: void end() throws SAXException {
0957: if (childPatterns == null)
0958: endChild(schemaBuilder.makeText(startLocation, null));
0959: super .end();
0960: }
0961:
0962: ParsedPattern buildPattern(List<ParsedPattern> patterns,
0963: Location loc, Annotations anno) throws SAXException {
0964: return schemaBuilder.makeAttribute(nameClass, super
0965: .buildPattern(patterns, loc, null), loc, anno);
0966: }
0967:
0968: State createChildState(String localName) throws SAXException {
0969: State tem = super .createChildState(localName);
0970: if (tem != null && childPatterns != null)
0971: error("attribute_multi_pattern");
0972: return tem;
0973: }
0974:
0975: }
0976:
0977: abstract class SinglePatternContainerState extends
0978: PatternContainerState {
0979: State createChildState(String localName) throws SAXException {
0980: if (childPatterns == null)
0981: return super .createChildState(localName);
0982: error("too_many_children");
0983: return null;
0984: }
0985: }
0986:
0987: class GrammarSectionState extends State {
0988: GrammarSection section;
0989:
0990: GrammarSectionState() {
0991: }
0992:
0993: GrammarSectionState(GrammarSection section) {
0994: this .section = section;
0995: }
0996:
0997: State create() {
0998: return new GrammarSectionState(null);
0999: }
1000:
1001: State createChildState(String localName) throws SAXException {
1002: if (localName.equals("define"))
1003: return new DefineState(section);
1004: if (localName.equals("start"))
1005: return new StartState(section);
1006: if (localName.equals("include")) {
1007: Include include = section.makeInclude();
1008: if (include != null)
1009: return new IncludeState(include);
1010: }
1011: if (localName.equals("div"))
1012: return new DivState(section.makeDiv());
1013: error("expected_define", localName);
1014: // XXX better errors
1015: return null;
1016: }
1017:
1018: void end() throws SAXException {
1019: if (comments != null) {
1020: section.topLevelComment(comments);
1021: comments = null;
1022: }
1023: }
1024:
1025: void endForeignChild(ParsedElementAnnotation ea) {
1026: section.topLevelAnnotation(ea);
1027: }
1028: }
1029:
1030: class DivState extends GrammarSectionState {
1031: final Div div;
1032:
1033: DivState(Div div) {
1034: super (div);
1035: this .div = div;
1036: }
1037:
1038: void end() throws SAXException {
1039: super .end();
1040: div.endDiv(startLocation, annotations);
1041: }
1042: }
1043:
1044: class IncludeState extends GrammarSectionState {
1045: String href;
1046: final Include include;
1047:
1048: IncludeState(Include include) {
1049: super (include);
1050: this .include = include;
1051: }
1052:
1053: void setOtherAttribute(String name, String value)
1054: throws SAXException {
1055: if (name.equals("href")) {
1056: href = value;
1057: checkUri(href);
1058: } else
1059: super .setOtherAttribute(name, value);
1060: }
1061:
1062: void endAttributes() throws SAXException {
1063: if (href == null)
1064: error("missing_href_attribute");
1065: else
1066: href = resolve(href);
1067: }
1068:
1069: void end() throws SAXException {
1070: super .end();
1071: if (href != null) {
1072: try {
1073: include.endInclude(parseable, href, getNs(),
1074: startLocation, annotations);
1075: } catch (IllegalSchemaException e) {
1076: }
1077: }
1078: }
1079: }
1080:
1081: class MergeGrammarState extends GrammarSectionState {
1082: final IncludedGrammar grammar;
1083:
1084: MergeGrammarState(IncludedGrammar grammar) {
1085: super (grammar);
1086: this .grammar = grammar;
1087: }
1088:
1089: void end() throws SAXException {
1090: super .end();
1091: parent.endChild(grammar.endIncludedGrammar(startLocation,
1092: annotations));
1093: }
1094: }
1095:
1096: class GrammarState extends GrammarSectionState {
1097: Grammar grammar;
1098:
1099: void setParent(State parent) {
1100: super .setParent(parent);
1101: grammar = schemaBuilder.makeGrammar(scope);
1102: section = grammar;
1103: scope = grammar;
1104: }
1105:
1106: State create() {
1107: return new GrammarState();
1108: }
1109:
1110: void end() throws SAXException {
1111: super .end();
1112: parent.endChild(grammar.endGrammar(startLocation,
1113: annotations));
1114: }
1115: }
1116:
1117: class RefState extends EmptyContentState {
1118: String name;
1119:
1120: State create() {
1121: return new RefState();
1122: }
1123:
1124: void endAttributes() throws SAXException {
1125: if (name == null)
1126: error("missing_name_attribute");
1127: }
1128:
1129: void setName(String name) throws SAXException {
1130: this .name = checkNCName(name);
1131: }
1132:
1133: ParsedPattern makePattern() throws SAXException {
1134: if (name == null)
1135: return schemaBuilder.makeErrorPattern();
1136: if (scope == null) {
1137: error("ref_outside_grammar", name);
1138: return schemaBuilder.makeErrorPattern();
1139: } else
1140: return scope.makeRef(name, startLocation, annotations);
1141: }
1142: }
1143:
1144: class ParentRefState extends RefState {
1145: State create() {
1146: return new ParentRefState();
1147: }
1148:
1149: ParsedPattern makePattern() throws SAXException {
1150: if (name == null)
1151: return schemaBuilder.makeErrorPattern();
1152: if (scope == null) {
1153: error("parent_ref_outside_grammar", name);
1154: return schemaBuilder.makeErrorPattern();
1155: } else
1156: return scope.makeParentRef(name, startLocation,
1157: annotations);
1158: }
1159: }
1160:
1161: class ExternalRefState extends EmptyContentState {
1162: String href;
1163: ParsedPattern includedPattern;
1164:
1165: State create() {
1166: return new ExternalRefState();
1167: }
1168:
1169: void setOtherAttribute(String name, String value)
1170: throws SAXException {
1171: if (name.equals("href")) {
1172: href = value;
1173: checkUri(href);
1174: } else
1175: super .setOtherAttribute(name, value);
1176: }
1177:
1178: void endAttributes() throws SAXException {
1179: if (href == null)
1180: error("missing_href_attribute");
1181: else
1182: href = resolve(href);
1183: }
1184:
1185: ParsedPattern makePattern() {
1186: if (href != null) {
1187: try {
1188: return schemaBuilder.makeExternalRef(parseable,
1189: href, getNs(), scope, startLocation,
1190: annotations);
1191: } catch (IllegalSchemaException e) {
1192: }
1193: }
1194: return schemaBuilder.makeErrorPattern();
1195: }
1196: }
1197:
1198: abstract class DefinitionState extends PatternContainerState {
1199: GrammarSection.Combine combine = null;
1200: final GrammarSection section;
1201:
1202: DefinitionState(GrammarSection section) {
1203: this .section = section;
1204: }
1205:
1206: void setOtherAttribute(String name, String value)
1207: throws SAXException {
1208: if (name.equals("combine")) {
1209: value = value.trim();
1210: if (value.equals("choice"))
1211: combine = GrammarSection.COMBINE_CHOICE;
1212: else if (value.equals("interleave"))
1213: combine = GrammarSection.COMBINE_INTERLEAVE;
1214: else
1215: error("combine_attribute_bad_value", value);
1216: } else
1217: super .setOtherAttribute(name, value);
1218: }
1219:
1220: ParsedPattern buildPattern(List<ParsedPattern> patterns,
1221: Location loc, Annotations anno) throws SAXException {
1222: return super .buildPattern(patterns, loc, null);
1223: }
1224: }
1225:
1226: class DefineState extends DefinitionState {
1227: String name;
1228:
1229: DefineState(GrammarSection section) {
1230: super (section);
1231: }
1232:
1233: State create() {
1234: return new DefineState(null);
1235: }
1236:
1237: void setName(String name) throws SAXException {
1238: this .name = checkNCName(name);
1239: }
1240:
1241: void endAttributes() throws SAXException {
1242: if (name == null)
1243: error("missing_name_attribute");
1244: }
1245:
1246: void sendPatternToParent(ParsedPattern p) {
1247: if (name != null)
1248: section.define(name, combine, p, startLocation,
1249: annotations);
1250: }
1251:
1252: }
1253:
1254: class StartState extends DefinitionState {
1255:
1256: StartState(GrammarSection section) {
1257: super (section);
1258: }
1259:
1260: State create() {
1261: return new StartState(null);
1262: }
1263:
1264: void sendPatternToParent(ParsedPattern p) {
1265: section.define(GrammarSection.START, combine, p,
1266: startLocation, annotations);
1267: }
1268:
1269: State createChildState(String localName) throws SAXException {
1270: State tem = super .createChildState(localName);
1271: if (tem != null && childPatterns != null)
1272: error("start_multi_pattern");
1273: return tem;
1274: }
1275:
1276: }
1277:
1278: abstract class NameClassContainerState extends State {
1279: State createChildState(String localName) throws SAXException {
1280: State state = (State) nameClassTable.get(localName);
1281: if (state == null) {
1282: error("expected_name_class", localName);
1283: return null;
1284: }
1285: return state.create();
1286: }
1287: }
1288:
1289: class NameClassChildState extends NameClassContainerState {
1290: final State prevState;
1291: final NameClassRef nameClassRef;
1292:
1293: State create() {
1294: return null;
1295: }
1296:
1297: NameClassChildState(State prevState, NameClassRef nameClassRef) {
1298: this .prevState = prevState;
1299: this .nameClassRef = nameClassRef;
1300: setParent(prevState.parent);
1301: this .ns = prevState.ns;
1302: }
1303:
1304: void endChild(ParsedNameClass nameClass) {
1305: nameClassRef.setNameClass(nameClass);
1306: prevState.set();
1307: }
1308:
1309: void endForeignChild(ParsedElementAnnotation ea) {
1310: prevState.endForeignChild(ea);
1311: }
1312:
1313: void end() throws SAXException {
1314: nameClassRef.setNameClass(nameClassBuilder
1315: .makeErrorNameClass());
1316: error("missing_name_class");
1317: prevState.set();
1318: prevState.end();
1319: }
1320: }
1321:
1322: abstract class NameClassBaseState extends State {
1323:
1324: abstract ParsedNameClass makeNameClass() throws SAXException;
1325:
1326: void end() throws SAXException {
1327: parent.endChild(makeNameClass());
1328: }
1329: }
1330:
1331: class NameState extends NameClassBaseState {
1332: final StringBuffer buf = new StringBuffer();
1333:
1334: State createChildState(String localName) throws SAXException {
1335: error("expected_name", localName);
1336: return null;
1337: }
1338:
1339: State create() {
1340: return new NameState();
1341: }
1342:
1343: public void characters(char[] ch, int start, int len) {
1344: buf.append(ch, start, len);
1345: }
1346:
1347: void checkForeignElement() throws SAXException {
1348: error("name_contains_foreign_element");
1349: }
1350:
1351: ParsedNameClass makeNameClass() throws SAXException {
1352: mergeLeadingComments();
1353: return expandName(buf.toString().trim(), getNs(),
1354: annotations);
1355: }
1356:
1357: }
1358:
1359: private static final int PATTERN_CONTEXT = 0;
1360: private static final int ANY_NAME_CONTEXT = 1;
1361: private static final int NS_NAME_CONTEXT = 2;
1362: private SAXParseable parseable;
1363:
1364: class AnyNameState extends NameClassBaseState {
1365: ParsedNameClass except = null;
1366:
1367: State create() {
1368: return new AnyNameState();
1369: }
1370:
1371: State createChildState(String localName) throws SAXException {
1372: if (localName.equals("except")) {
1373: if (except != null)
1374: error("multiple_except");
1375: return new NameClassChoiceState(getContext());
1376: }
1377: error("expected_except", localName);
1378: return null;
1379: }
1380:
1381: int getContext() {
1382: return ANY_NAME_CONTEXT;
1383: }
1384:
1385: ParsedNameClass makeNameClass() {
1386: if (except == null)
1387: return makeNameClassNoExcept();
1388: else
1389: return makeNameClassExcept(except);
1390: }
1391:
1392: ParsedNameClass makeNameClassNoExcept() {
1393: return nameClassBuilder.makeAnyName(startLocation,
1394: annotations);
1395: }
1396:
1397: ParsedNameClass makeNameClassExcept(ParsedNameClass except) {
1398: return nameClassBuilder.makeAnyName(except, startLocation,
1399: annotations);
1400: }
1401:
1402: void endChild(ParsedNameClass nameClass) {
1403: except = nameClass;
1404: }
1405:
1406: }
1407:
1408: class NsNameState extends AnyNameState {
1409: State create() {
1410: return new NsNameState();
1411: }
1412:
1413: ParsedNameClass makeNameClassNoExcept() {
1414: return nameClassBuilder.makeNsName(getNs(), null, null);
1415: }
1416:
1417: ParsedNameClass makeNameClassExcept(ParsedNameClass except) {
1418: return nameClassBuilder.makeNsName(getNs(), except, null,
1419: null);
1420: }
1421:
1422: int getContext() {
1423: return NS_NAME_CONTEXT;
1424: }
1425:
1426: }
1427:
1428: class NameClassChoiceState extends NameClassContainerState {
1429: private ParsedNameClass[] nameClasses;
1430: private int nNameClasses;
1431: private int context;
1432:
1433: NameClassChoiceState() {
1434: this .context = PATTERN_CONTEXT;
1435: }
1436:
1437: NameClassChoiceState(int context) {
1438: this .context = context;
1439: }
1440:
1441: void setParent(State parent) {
1442: super .setParent(parent);
1443: if (parent instanceof NameClassChoiceState)
1444: this .context = ((NameClassChoiceState) parent).context;
1445: }
1446:
1447: State create() {
1448: return new NameClassChoiceState();
1449: }
1450:
1451: State createChildState(String localName) throws SAXException {
1452: if (localName.equals("anyName")) {
1453: if (context >= ANY_NAME_CONTEXT) {
1454: error(context == ANY_NAME_CONTEXT ? "any_name_except_contains_any_name"
1455: : "ns_name_except_contains_any_name");
1456: return null;
1457: }
1458: } else if (localName.equals("nsName")) {
1459: if (context == NS_NAME_CONTEXT) {
1460: error("ns_name_except_contains_ns_name");
1461: return null;
1462: }
1463: }
1464: return super .createChildState(localName);
1465: }
1466:
1467: void endChild(ParsedNameClass nc) {
1468: if (nameClasses == null)
1469: nameClasses = new ParsedNameClass[INIT_CHILD_ALLOC];
1470: else if (nNameClasses >= nameClasses.length) {
1471: ParsedNameClass[] newNameClasses = new ParsedNameClass[nameClasses.length * 2];
1472: System.arraycopy(nameClasses, 0, newNameClasses, 0,
1473: nameClasses.length);
1474: nameClasses = newNameClasses;
1475: }
1476: nameClasses[nNameClasses++] = nc;
1477: }
1478:
1479: void endForeignChild(ParsedElementAnnotation ea) {
1480: if (nNameClasses == 0)
1481: super .endForeignChild(ea);
1482: else
1483: nameClasses[nNameClasses - 1] = nameClassBuilder
1484: .annotateAfter(nameClasses[nNameClasses - 1],
1485: ea);
1486: }
1487:
1488: void end() throws SAXException {
1489: if (nNameClasses == 0) {
1490: error("missing_name_class");
1491: parent.endChild(nameClassBuilder.makeErrorNameClass());
1492: return;
1493: }
1494: if (comments != null) {
1495: nameClasses[nNameClasses - 1] = nameClassBuilder
1496: .commentAfter(nameClasses[nNameClasses - 1],
1497: comments);
1498: comments = null;
1499: }
1500: parent.endChild(nameClassBuilder.makeChoice(Arrays.asList(
1501: nameClasses).subList(0, nNameClasses),
1502: startLocation, annotations));
1503: }
1504: }
1505:
1506: private void initPatternTable() {
1507: patternTable = new Hashtable();
1508: patternTable.put("zeroOrMore", new ZeroOrMoreState());
1509: patternTable.put("oneOrMore", new OneOrMoreState());
1510: patternTable.put("optional", new OptionalState());
1511: patternTable.put("list", new ListState());
1512: patternTable.put("choice", new ChoiceState());
1513: patternTable.put("interleave", new InterleaveState());
1514: patternTable.put("group", new GroupState());
1515: patternTable.put("mixed", new MixedState());
1516: patternTable.put("element", new ElementState());
1517: patternTable.put("attribute", new AttributeState());
1518: patternTable.put("empty", new EmptyState());
1519: patternTable.put("text", new TextState());
1520: patternTable.put("value", new ValueState());
1521: patternTable.put("data", new DataState());
1522: patternTable.put("notAllowed", new NotAllowedState());
1523: patternTable.put("grammar", new GrammarState());
1524: patternTable.put("ref", new RefState());
1525: patternTable.put("parentRef", new ParentRefState());
1526: patternTable.put("externalRef", new ExternalRefState());
1527: }
1528:
1529: private void initNameClassTable() {
1530: nameClassTable = new Hashtable();
1531: nameClassTable.put("name", new NameState());
1532: nameClassTable.put("anyName", new AnyNameState());
1533: nameClassTable.put("nsName", new NsNameState());
1534: nameClassTable.put("choice", new NameClassChoiceState());
1535: }
1536:
1537: public ParsedPattern getParsedPattern()
1538: throws IllegalSchemaException {
1539: if (hadError)
1540: throw new IllegalSchemaException();
1541: return startPattern;
1542: }
1543:
1544: private void error(String key) throws SAXException {
1545: error(key, locator);
1546: }
1547:
1548: private void error(String key, String arg) throws SAXException {
1549: error(key, arg, locator);
1550: }
1551:
1552: void error(String key, String arg1, String arg2)
1553: throws SAXException {
1554: error(key, arg1, arg2, locator);
1555: }
1556:
1557: private void error(String key, Locator loc) throws SAXException {
1558: error(new SAXParseException(localizer.message(key), loc));
1559: }
1560:
1561: private void error(String key, String arg, Locator loc)
1562: throws SAXException {
1563: error(new SAXParseException(localizer.message(key, arg), loc));
1564: }
1565:
1566: private void error(String key, String arg1, String arg2, Locator loc)
1567: throws SAXException {
1568: error(new SAXParseException(localizer.message(key, arg1, arg2),
1569: loc));
1570: }
1571:
1572: private void error(SAXParseException e) throws SAXException {
1573: hadError = true;
1574: if (eh != null)
1575: eh.error(e);
1576: }
1577:
1578: void warning(String key) throws SAXException {
1579: warning(key, locator);
1580: }
1581:
1582: private void warning(String key, String arg) throws SAXException {
1583: warning(key, arg, locator);
1584: }
1585:
1586: private void warning(String key, String arg1, String arg2)
1587: throws SAXException {
1588: warning(key, arg1, arg2, locator);
1589: }
1590:
1591: private void warning(String key, Locator loc) throws SAXException {
1592: warning(new SAXParseException(localizer.message(key), loc));
1593: }
1594:
1595: private void warning(String key, String arg, Locator loc)
1596: throws SAXException {
1597: warning(new SAXParseException(localizer.message(key, arg), loc));
1598: }
1599:
1600: private void warning(String key, String arg1, String arg2,
1601: Locator loc) throws SAXException {
1602: warning(new SAXParseException(localizer
1603: .message(key, arg1, arg2), loc));
1604: }
1605:
1606: private void warning(SAXParseException e) throws SAXException {
1607: if (eh != null)
1608: eh.warning(e);
1609: }
1610:
1611: SchemaParser(SAXParseable parseable, XMLReader xr, ErrorHandler eh,
1612: SchemaBuilder schemaBuilder, IncludedGrammar grammar,
1613: Scope scope, String inheritedNs) throws SAXException {
1614: this .parseable = parseable;
1615: this .xr = xr;
1616: this .eh = eh;
1617: this .schemaBuilder = schemaBuilder;
1618: this .nameClassBuilder = schemaBuilder.getNameClassBuilder();
1619: if (eh != null)
1620: xr.setErrorHandler(eh);
1621: xr.setDTDHandler(context);
1622: if (schemaBuilder.usesComments()) {
1623: try {
1624: xr
1625: .setProperty(
1626: "http://xml.org/sax/properties/lexical-handler",
1627: new LexicalHandlerImpl());
1628: } catch (SAXNotRecognizedException e) {
1629: warning("no_comment_support", xr.getClass().getName());
1630: } catch (SAXNotSupportedException e) {
1631: warning("no_comment_support", xr.getClass().getName());
1632: }
1633: }
1634: initPatternTable();
1635: initNameClassTable();
1636: new RootState(grammar, scope, inheritedNs).set();
1637: }
1638:
1639: private Context getContext() {
1640: return context;
1641: }
1642:
1643: class LexicalHandlerImpl extends AbstractLexicalHandler {
1644: private boolean inDtd = false;
1645:
1646: public void startDTD(String s, String s1, String s2)
1647: throws SAXException {
1648: inDtd = true;
1649: }
1650:
1651: public void endDTD() throws SAXException {
1652: inDtd = false;
1653: }
1654:
1655: public void comment(char[] chars, int start, int length)
1656: throws SAXException {
1657: if (!inDtd)
1658: ((CommentHandler) xr.getContentHandler())
1659: .comment(new String(chars, start, length));
1660: }
1661: }
1662:
1663: private ParsedNameClass expandName(String name, String ns,
1664: Annotations anno) throws SAXException {
1665: int ic = name.indexOf(':');
1666: if (ic == -1)
1667: return nameClassBuilder.makeName(ns, checkNCName(name),
1668: null, null, anno);
1669: String prefix = checkNCName(name.substring(0, ic));
1670: String localName = checkNCName(name.substring(ic + 1));
1671: for (PrefixMapping tem = context.prefixMapping; tem != null; tem = tem.next)
1672: if (tem.prefix.equals(prefix))
1673: return nameClassBuilder.makeName(tem.uri, localName,
1674: prefix, null, anno);
1675: error("undefined_prefix", prefix);
1676: return nameClassBuilder.makeName("", localName, null, null,
1677: anno);
1678: }
1679:
1680: private String findPrefix(String qName, String uri) {
1681: String prefix = null;
1682: if (qName == null || qName.equals("")) {
1683: for (PrefixMapping p = context.prefixMapping; p != null; p = p.next)
1684: if (p.uri.equals(uri)) {
1685: prefix = p.prefix;
1686: break;
1687: }
1688: } else {
1689: int off = qName.indexOf(':');
1690: if (off > 0)
1691: prefix = qName.substring(0, off);
1692: }
1693: return prefix;
1694: }
1695:
1696: private String checkNCName(String str) throws SAXException {
1697: if (!Naming.isNcname(str))
1698: error("invalid_ncname", str);
1699: return str;
1700: }
1701:
1702: private String resolve(String systemId) throws SAXException {
1703: if (Uri.hasFragmentId(systemId))
1704: error("href_fragment_id");
1705: systemId = Uri.escapeDisallowedChars(systemId);
1706: return Uri.resolve(xmlBaseHandler.getBaseUri(), systemId);
1707: }
1708:
1709: private Location makeLocation() {
1710: if (locator == null)
1711: return null;
1712: return schemaBuilder.makeLocation(locator.getSystemId(),
1713: locator.getLineNumber(), locator.getColumnNumber());
1714: }
1715:
1716: private void checkUri(String s) throws SAXException {
1717: if (!Uri.isValid(s))
1718: error("invalid_uri", s);
1719: }
1720: }
|