alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (SchemaParser.java)

This example Java source code file (SchemaParser.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

annotations, emptycontentstate, grammarsectionstate, location, nameclasschoicestate, override, parsednameclass, parsedpattern, patterncontainerstate, prefixmapping, sax, saxexception, state, string, stringbuffer, util

The SchemaParser.java Java example source code

/*
 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
/*
 * Copyright (C) 2004-2012
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.sun.xml.internal.rngom.parse.xml;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

import com.sun.xml.internal.rngom.ast.builder.Annotations;
import com.sun.xml.internal.rngom.ast.builder.CommentList;
import com.sun.xml.internal.rngom.ast.builder.DataPatternBuilder;
import com.sun.xml.internal.rngom.ast.builder.Div;
import com.sun.xml.internal.rngom.ast.builder.ElementAnnotationBuilder;
import com.sun.xml.internal.rngom.ast.builder.Grammar;
import com.sun.xml.internal.rngom.ast.builder.GrammarSection;
import com.sun.xml.internal.rngom.ast.builder.Include;
import com.sun.xml.internal.rngom.ast.builder.IncludedGrammar;
import com.sun.xml.internal.rngom.ast.builder.NameClassBuilder;
import com.sun.xml.internal.rngom.ast.builder.SchemaBuilder;
import com.sun.xml.internal.rngom.ast.builder.Scope;
import com.sun.xml.internal.rngom.ast.om.Location;
import com.sun.xml.internal.rngom.ast.om.ParsedElementAnnotation;
import com.sun.xml.internal.rngom.ast.om.ParsedNameClass;
import com.sun.xml.internal.rngom.ast.om.ParsedPattern;
import com.sun.xml.internal.rngom.parse.Context;
import com.sun.xml.internal.rngom.parse.IllegalSchemaException;
import com.sun.xml.internal.rngom.parse.Parseable;
import com.sun.xml.internal.rngom.util.Localizer;
import com.sun.xml.internal.rngom.util.Uri;
import com.sun.xml.internal.rngom.xml.sax.AbstractLexicalHandler;
import com.sun.xml.internal.rngom.xml.sax.XmlBaseHandler;
import com.sun.xml.internal.rngom.xml.util.Naming;
import com.sun.xml.internal.rngom.xml.util.WellKnownNamespaces;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

class SchemaParser {

    private static final String relaxngURIPrefix =
            WellKnownNamespaces.RELAX_NG.substring(0, WellKnownNamespaces.RELAX_NG.lastIndexOf('/') + 1);
    static final String relaxng10URI = WellKnownNamespaces.RELAX_NG;
    private static final Localizer localizer = new Localizer(new Localizer(Parseable.class), SchemaParser.class);
    private String relaxngURI;
    private final XMLReader xr;
    private final ErrorHandler eh;
    private final SchemaBuilder schemaBuilder;
    /**
     * The value of the {@link SchemaBuilder#getNameClassBuilder()} for the
     * {@link #schemaBuilder} object.
     */
    private final NameClassBuilder nameClassBuilder;
    private ParsedPattern startPattern;
    private Locator locator;
    private final XmlBaseHandler xmlBaseHandler = new XmlBaseHandler();
    private final ContextImpl context = new ContextImpl();
    private boolean hadError = false;
    private Hashtable patternTable;
    private Hashtable nameClassTable;

    static class PrefixMapping {

        final String prefix;
        final String uri;
        final PrefixMapping next;

        PrefixMapping(String prefix, String uri, PrefixMapping next) {
            this.prefix = prefix;
            this.uri = uri;
            this.next = next;
        }
    }

    static abstract class AbstractContext extends DtdContext implements Context {

        PrefixMapping prefixMapping;

        AbstractContext() {
            prefixMapping = new PrefixMapping("xml", WellKnownNamespaces.XML, null);
        }

        AbstractContext(AbstractContext context) {
            super(context);
            prefixMapping = context.prefixMapping;
        }

        public String resolveNamespacePrefix(String prefix) {
            for (PrefixMapping p = prefixMapping; p != null; p = p.next) {
                if (p.prefix.equals(prefix)) {
                    return p.uri;
                }
            }
            return null;
        }

        public Enumeration prefixes() {
            Vector v = new Vector();
            for (PrefixMapping p = prefixMapping; p != null; p = p.next) {
                if (!v.contains(p.prefix)) {
                    v.addElement(p.prefix);
                }
            }
            return v.elements();
        }

        public Context copy() {
            return new SavedContext(this);
        }
    }

    static class SavedContext extends AbstractContext {

        private final String baseUri;

        SavedContext(AbstractContext context) {
            super(context);
            this.baseUri = context.getBaseUri();
        }

        public String getBaseUri() {
            return baseUri;
        }
    }

    class ContextImpl extends AbstractContext {

        public String getBaseUri() {
            return xmlBaseHandler.getBaseUri();
        }
    }

    static interface CommentHandler {

        void comment(String value);
    }

    abstract class Handler implements ContentHandler, CommentHandler {

        CommentList comments;

        CommentList getComments() {
            CommentList tem = comments;
            comments = null;
            return tem;
        }

        public void comment(String value) {
            if (comments == null) {
                comments = schemaBuilder.makeCommentList();
            }
            comments.addComment(value, makeLocation());
        }

        public void processingInstruction(String target, String date) {
        }

        public void skippedEntity(String name) {
        }

        public void ignorableWhitespace(char[] ch, int start, int len) {
        }

        public void startDocument() {
        }

        public void endDocument() {
        }

        public void startPrefixMapping(String prefix, String uri) {
            context.prefixMapping = new PrefixMapping(prefix, uri, context.prefixMapping);
        }

        public void endPrefixMapping(String prefix) {
            context.prefixMapping = context.prefixMapping.next;
        }

        public void setDocumentLocator(Locator loc) {
            locator = loc;
            xmlBaseHandler.setLocator(loc);
        }
    }

    abstract class State extends Handler {

        State parent;
        String nsInherit;
        String ns;
        String datatypeLibrary;
        /**
         * The current scope, or null if there's none.
         */
        Scope scope;
        Location startLocation;
        Annotations annotations;

        void set() {
            xr.setContentHandler(this);
        }

        abstract State create();

        abstract State createChildState(String localName) throws SAXException;

        void setParent(State parent) {
            this.parent = parent;
            this.nsInherit = parent.getNs();
            this.datatypeLibrary = parent.datatypeLibrary;
            this.scope = parent.scope;
            this.startLocation = makeLocation();
            if (parent.comments != null) {
                annotations = schemaBuilder.makeAnnotations(parent.comments, getContext());
                parent.comments = null;
            } else if (parent instanceof RootState) {
                annotations = schemaBuilder.makeAnnotations(null, getContext());
            }
        }

        String getNs() {
            return ns == null ? nsInherit : ns;
        }

        boolean isRelaxNGElement(String uri) throws SAXException {
            return uri.equals(relaxngURI);
        }

        public void startElement(String namespaceURI,
                String localName,
                String qName,
                Attributes atts) throws SAXException {
            xmlBaseHandler.startElement();
            if (isRelaxNGElement(namespaceURI)) {
                State state = createChildState(localName);
                if (state == null) {
                    xr.setContentHandler(new Skipper(this));
                    return;
                }
                state.setParent(this);
                state.set();
                state.attributes(atts);
            } else {
                checkForeignElement();
                ForeignElementHandler feh = new ForeignElementHandler(this, getComments());
                feh.startElement(namespaceURI, localName, qName, atts);
                xr.setContentHandler(feh);
            }
        }

        public void endElement(String namespaceURI,
                String localName,
                String qName) throws SAXException {
            xmlBaseHandler.endElement();
            parent.set();
            end();
        }

        void setName(String name) throws SAXException {
            error("illegal_name_attribute");
        }

        void setOtherAttribute(String name, String value) throws SAXException {
            error("illegal_attribute_ignored", name);
        }

        void endAttributes() throws SAXException {
        }

        void checkForeignElement() throws SAXException {
        }

        void attributes(Attributes atts) throws SAXException {
            int len = atts.getLength();
            for (int i = 0; i < len; i++) {
                String uri = atts.getURI(i);
                if (uri.length() == 0) {
                    String name = atts.getLocalName(i);
                    if (name.equals("name")) {
                        setName(atts.getValue(i).trim());
                    } else if (name.equals("ns")) {
                        ns = atts.getValue(i);
                    } else if (name.equals("datatypeLibrary")) {
                        datatypeLibrary = atts.getValue(i);
                        checkUri(datatypeLibrary);
                        if (!datatypeLibrary.equals("")
                                && !Uri.isAbsolute(datatypeLibrary)) {
                            error("relative_datatype_library");
                        }
                        if (Uri.hasFragmentId(datatypeLibrary)) {
                            error("fragment_identifier_datatype_library");
                        }
                        datatypeLibrary = Uri.escapeDisallowedChars(datatypeLibrary);
                    } else {
                        setOtherAttribute(name, atts.getValue(i));
                    }
                } else if (uri.equals(relaxngURI)) {
                    error("qualified_attribute", atts.getLocalName(i));
                } else if (uri.equals(WellKnownNamespaces.XML)
                        && atts.getLocalName(i).equals("base")) {
                    xmlBaseHandler.xmlBaseAttribute(atts.getValue(i));
                } else {
                    if (annotations == null) {
                        annotations = schemaBuilder.makeAnnotations(null, getContext());
                    }
                    annotations.addAttribute(uri, atts.getLocalName(i), findPrefix(atts.getQName(i), uri),
                            atts.getValue(i), startLocation);
                }
            }
            endAttributes();
        }

        abstract void end() throws SAXException;

        void endChild(ParsedPattern pattern) {
            // XXX cannot happen; throw exception
        }

        void endChild(ParsedNameClass nc) {
            // XXX cannot happen; throw exception
        }

        @Override
        public void startDocument() {
        }

        @Override
        public void endDocument() {
            if (comments != null && startPattern != null) {
                startPattern = schemaBuilder.commentAfter(startPattern, comments);
                comments = null;
            }
        }

        public void characters(char[] ch, int start, int len) throws SAXException {
            for (int i = 0; i < len; i++) {
                switch (ch[start + i]) {
                    case ' ':
                    case '\r':
                    case '\n':
                    case '\t':
                        break;
                    default:
                        error("illegal_characters_ignored");
                        break;
                }
            }
        }

        boolean isPatternNamespaceURI(String s) {
            return s.equals(relaxngURI);
        }

        void endForeignChild(ParsedElementAnnotation ea) {
            if (annotations == null) {
                annotations = schemaBuilder.makeAnnotations(null, getContext());
            }
            annotations.addElement(ea);
        }

        void mergeLeadingComments() {
            if (comments != null) {
                if (annotations == null) {
                    annotations = schemaBuilder.makeAnnotations(comments, getContext());
                } else {
                    annotations.addLeadingComment(comments);
                }
                comments = null;
            }
        }
    }

    class ForeignElementHandler extends Handler {

        final State nextState;
        ElementAnnotationBuilder builder;
        final Stack builderStack = new Stack();
        StringBuffer textBuf;
        Location textLoc;

        ForeignElementHandler(State nextState, CommentList comments) {
            this.nextState = nextState;
            this.comments = comments;
        }

        public void startElement(String namespaceURI, String localName,
                String qName, Attributes atts) {
            flushText();
            if (builder != null) {
                builderStack.push(builder);
            }
            Location loc = makeLocation();
            builder = schemaBuilder.makeElementAnnotationBuilder(namespaceURI,
                    localName,
                    findPrefix(qName, namespaceURI),
                    loc,
                    getComments(),
                    getContext());
            int len = atts.getLength();
            for (int i = 0; i < len; i++) {
                String uri = atts.getURI(i);
                builder.addAttribute(uri, atts.getLocalName(i), findPrefix(atts.getQName(i), uri),
                        atts.getValue(i), loc);
            }
        }

        public void endElement(String namespaceURI, String localName,
                String qName) {
            flushText();
            if (comments != null) {
                builder.addComment(getComments());
            }
            ParsedElementAnnotation ea = builder.makeElementAnnotation();
            if (builderStack.empty()) {
                nextState.endForeignChild(ea);
                nextState.set();
            } else {
                builder = (ElementAnnotationBuilder) builderStack.pop();
                builder.addElement(ea);
            }
        }

        public void characters(char ch[], int start, int length) {
            if (textBuf == null) {
                textBuf = new StringBuffer();
            }
            textBuf.append(ch, start, length);
            if (textLoc == null) {
                textLoc = makeLocation();
            }
        }

        @Override
        public void comment(String value) {
            flushText();
            super.comment(value);
        }

        void flushText() {
            if (textBuf != null && textBuf.length() != 0) {
                builder.addText(textBuf.toString(), textLoc, getComments());
                textBuf.setLength(0);
            }
            textLoc = null;
        }
    }

    static class Skipper extends DefaultHandler implements CommentHandler {

        int level = 1;
        final State nextState;

        Skipper(State nextState) {
            this.nextState = nextState;
        }

        @Override
        public void startElement(String namespaceURI,
                String localName,
                String qName,
                Attributes atts) throws SAXException {
            ++level;
        }

        @Override
        public void endElement(String namespaceURI,
                String localName,
                String qName) throws SAXException {
            if (--level == 0) {
                nextState.set();
            }
        }

        public void comment(String value) {
        }
    }

    abstract class EmptyContentState extends State {

        State createChildState(String localName) throws SAXException {
            error("expected_empty", localName);
            return null;
        }

        abstract ParsedPattern makePattern() throws SAXException;

        void end() throws SAXException {
            if (comments != null) {
                if (annotations == null) {
                    annotations = schemaBuilder.makeAnnotations(null, getContext());
                }
                annotations.addComment(comments);
                comments = null;
            }
            parent.endChild(makePattern());
        }
    }
    static private final int INIT_CHILD_ALLOC = 5;

    abstract class PatternContainerState extends State {

        List<ParsedPattern> childPatterns;

        State createChildState(String localName) throws SAXException {
            State state = (State) patternTable.get(localName);
            if (state == null) {
                error("expected_pattern", localName);
                return null;
            }
            return state.create();
        }

        ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException {
            if (patterns.size() == 1 && anno == null) {
                return patterns.get(0);
            }
            return schemaBuilder.makeGroup(patterns, loc, anno);
        }

        @Override
        void endChild(ParsedPattern pattern) {
            if (childPatterns == null) {
                childPatterns = new ArrayList<ParsedPattern>(INIT_CHILD_ALLOC);
            }
            childPatterns.add(pattern);
        }

        @Override
        void endForeignChild(ParsedElementAnnotation ea) {
            // Harshit : Annotation handling should always be taken care of, irrespective of childPatterns being null or not.
            super.endForeignChild(ea);
            if (childPatterns != null) {
                int idx = childPatterns.size() - 1;
                childPatterns.set(idx, schemaBuilder.annotateAfter(childPatterns.get(idx), ea));
            }
        }

        void end() throws SAXException {
            if (childPatterns == null) {
                error("missing_children");
                endChild(schemaBuilder.makeErrorPattern());
            }
            if (comments != null) {
                int idx = childPatterns.size() - 1;
                childPatterns.set(idx, schemaBuilder.commentAfter(childPatterns.get(idx), comments));
                comments = null;
            }
            sendPatternToParent(buildPattern(childPatterns, startLocation, annotations));
        }

        void sendPatternToParent(ParsedPattern p) {
            parent.endChild(p);
        }
    }

    class GroupState extends PatternContainerState {

        State create() {
            return new GroupState();
        }
    }

    class ZeroOrMoreState extends PatternContainerState {

        State create() {
            return new ZeroOrMoreState();
        }

        @Override
        ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException {
            return schemaBuilder.makeZeroOrMore(super.buildPattern(patterns, loc, null), loc, anno);
        }
    }

    class OneOrMoreState extends PatternContainerState {

        State create() {
            return new OneOrMoreState();
        }

        @Override
        ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException {
            return schemaBuilder.makeOneOrMore(super.buildPattern(patterns, loc, null), loc, anno);
        }
    }

    class OptionalState extends PatternContainerState {

        State create() {
            return new OptionalState();
        }

        @Override
        ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException {
            return schemaBuilder.makeOptional(super.buildPattern(patterns, loc, null), loc, anno);
        }
    }

    class ListState extends PatternContainerState {

        State create() {
            return new ListState();
        }

        @Override
        ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException {
            return schemaBuilder.makeList(super.buildPattern(patterns, loc, null), loc, anno);
        }
    }

    class ChoiceState extends PatternContainerState {

        State create() {
            return new ChoiceState();
        }

        @Override
        ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException {
            return schemaBuilder.makeChoice(patterns, loc, anno);
        }
    }

    class InterleaveState extends PatternContainerState {

        State create() {
            return new InterleaveState();
        }

        @Override
        ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) {
            return schemaBuilder.makeInterleave(patterns, loc, anno);
        }
    }

    class MixedState extends PatternContainerState {

        State create() {
            return new MixedState();
        }

        @Override
        ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException {
            return schemaBuilder.makeMixed(super.buildPattern(patterns, loc, null), loc, anno);
        }
    }

    static interface NameClassRef {

        void setNameClass(ParsedNameClass nc);
    }

    class ElementState extends PatternContainerState implements NameClassRef {

        ParsedNameClass nameClass;
        boolean nameClassWasAttribute;
        String name;

        @Override
        void setName(String name) {
            this.name = name;
        }

        public void setNameClass(ParsedNameClass nc) {
            nameClass = nc;
        }

        @Override
        void endAttributes() throws SAXException {
            if (name != null) {
                nameClass = expandName(name, getNs(), null);
                nameClassWasAttribute = true;
            } else {
                new NameClassChildState(this, this).set();
            }
        }

        State create() {
            return new ElementState();
        }

        @Override
        ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException {
            return schemaBuilder.makeElement(nameClass, super.buildPattern(patterns, loc, null), loc, anno);
        }

        @Override
        void endForeignChild(ParsedElementAnnotation ea) {
            if (nameClassWasAttribute || childPatterns != null || nameClass == null) {
                super.endForeignChild(ea);
            } else {
                nameClass = nameClassBuilder.annotateAfter(nameClass, ea);
            }
        }
    }

    class RootState extends PatternContainerState {

        IncludedGrammar grammar;

        RootState() {
        }

        RootState(IncludedGrammar grammar, Scope scope, String ns) {
            this.grammar = grammar;
            this.scope = scope;
            this.nsInherit = ns;
            this.datatypeLibrary = "";
        }

        State create() {
            return new RootState();
        }

        @Override
        State createChildState(String localName) throws SAXException {
            if (grammar == null) {
                return super.createChildState(localName);
            }
            if (localName.equals("grammar")) {
                return new MergeGrammarState(grammar);
            }
            error("expected_grammar", localName);
            return null;
        }

        @Override
        void checkForeignElement() throws SAXException {
            error("root_bad_namespace_uri", WellKnownNamespaces.RELAX_NG);
        }

        @Override
        void endChild(ParsedPattern pattern) {
            startPattern = pattern;
        }

        @Override
        boolean isRelaxNGElement(String uri) throws SAXException {
            if (!uri.startsWith(relaxngURIPrefix)) {
                return false;
            }
            if (!uri.equals(WellKnownNamespaces.RELAX_NG)) {
                warning("wrong_uri_version",
                        WellKnownNamespaces.RELAX_NG.substring(relaxngURIPrefix.length()),
                        uri.substring(relaxngURIPrefix.length()));
            }
            relaxngURI = uri;
            return true;
        }
    }

    class NotAllowedState extends EmptyContentState {

        State create() {
            return new NotAllowedState();
        }

        ParsedPattern makePattern() {
            return schemaBuilder.makeNotAllowed(startLocation, annotations);
        }
    }

    class EmptyState extends EmptyContentState {

        State create() {
            return new EmptyState();
        }

        ParsedPattern makePattern() {
            return schemaBuilder.makeEmpty(startLocation, annotations);
        }
    }

    class TextState extends EmptyContentState {

        State create() {
            return new TextState();
        }

        ParsedPattern makePattern() {
            return schemaBuilder.makeText(startLocation, annotations);
        }
    }

    class ValueState extends EmptyContentState {

        final StringBuffer buf = new StringBuffer();
        String type;

        State create() {
            return new ValueState();
        }

        @Override
        void setOtherAttribute(String name, String value) throws SAXException {
            if (name.equals("type")) {
                type = checkNCName(value.trim());
            } else {
                super.setOtherAttribute(name, value);
            }
        }

        @Override
        public void characters(char[] ch, int start, int len) {
            buf.append(ch, start, len);
        }

        @Override
        void checkForeignElement() throws SAXException {
            error("value_contains_foreign_element");
        }

        ParsedPattern makePattern() throws SAXException {
            if (type == null) {
                return makePattern("", "token");
            } else {
                return makePattern(datatypeLibrary, type);
            }
        }

        @Override
        void end() throws SAXException {
            mergeLeadingComments();
            super.end();
        }

        ParsedPattern makePattern(String datatypeLibrary, String type) {
            return schemaBuilder.makeValue(datatypeLibrary,
                    type,
                    buf.toString(),
                    getContext(),
                    getNs(),
                    startLocation,
                    annotations);
        }
    }

    class DataState extends State {

        String type;
        ParsedPattern except = null;
        DataPatternBuilder dpb = null;

        State create() {
            return new DataState();
        }

        State createChildState(String localName) throws SAXException {
            if (localName.equals("param")) {
                if (except != null) {
                    error("param_after_except");
                }
                return new ParamState(dpb);
            }
            if (localName.equals("except")) {
                if (except != null) {
                    error("multiple_except");
                }
                return new ChoiceState();
            }
            error("expected_param_except", localName);
            return null;
        }

        @Override
        void setOtherAttribute(String name, String value) throws SAXException {
            if (name.equals("type")) {
                type = checkNCName(value.trim());
            } else {
                super.setOtherAttribute(name, value);
            }
        }

        @Override
        void endAttributes() throws SAXException {
            if (type == null) {
                error("missing_type_attribute");
            } else {
                dpb = schemaBuilder.makeDataPatternBuilder(datatypeLibrary, type, startLocation);
            }
        }

        void end() throws SAXException {
            ParsedPattern p;
            if (dpb != null) {
                if (except != null) {
                    p = dpb.makePattern(except, startLocation, annotations);
                } else {
                    p = dpb.makePattern(startLocation, annotations);
                }
            } else {
                p = schemaBuilder.makeErrorPattern();
            }
            // XXX need to capture comments
            parent.endChild(p);
        }

        @Override
        void endChild(ParsedPattern pattern) {
            except = pattern;
        }
    }

    class ParamState extends State {

        private final StringBuffer buf = new StringBuffer();
        private final DataPatternBuilder dpb;
        private String name;

        ParamState(DataPatternBuilder dpb) {
            this.dpb = dpb;
        }

        State create() {
            return new ParamState(null);
        }

        @Override
        void setName(String name) throws SAXException {
            this.name = checkNCName(name);
        }

        @Override
        void endAttributes() throws SAXException {
            if (name == null) {
                error("missing_name_attribute");
            }
        }

        State createChildState(String localName) throws SAXException {
            error("expected_empty", localName);
            return null;
        }

        @Override
        public void characters(char[] ch, int start, int len) {
            buf.append(ch, start, len);
        }

        @Override
        void checkForeignElement() throws SAXException {
            error("param_contains_foreign_element");
        }

        void end() throws SAXException {
            if (name == null) {
                return;
            }
            if (dpb == null) {
                return;
            }
            mergeLeadingComments();
            dpb.addParam(name, buf.toString(), getContext(), getNs(), startLocation, annotations);
        }
    }

    class AttributeState extends PatternContainerState implements NameClassRef {

        ParsedNameClass nameClass;
        boolean nameClassWasAttribute;
        String name;

        State create() {
            return new AttributeState();
        }

        @Override
        void setName(String name) {
            this.name = name;
        }

        public void setNameClass(ParsedNameClass nc) {
            nameClass = nc;
        }

        @Override
        void endAttributes() throws SAXException {
            if (name != null) {
                String nsUse;
                if (ns != null) {
                    nsUse = ns;
                } else {
                    nsUse = "";
                }
                nameClass = expandName(name, nsUse, null);
                nameClassWasAttribute = true;
            } else {
                new NameClassChildState(this, this).set();
            }
        }

        @Override
        void endForeignChild(ParsedElementAnnotation ea) {
            if (nameClassWasAttribute || childPatterns != null || nameClass == null) {
                super.endForeignChild(ea);
            } else {
                nameClass = nameClassBuilder.annotateAfter(nameClass, ea);
            }
        }

        @Override
        void end() throws SAXException {
            if (childPatterns == null) {
                endChild(schemaBuilder.makeText(startLocation, null));
            }
            super.end();
        }

        @Override
        ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException {
            return schemaBuilder.makeAttribute(nameClass, super.buildPattern(patterns, loc, null), loc, anno);
        }

        @Override
        State createChildState(String localName) throws SAXException {
            State tem = super.createChildState(localName);
            if (tem != null && childPatterns != null) {
                error("attribute_multi_pattern");
            }
            return tem;
        }
    }

    abstract class SinglePatternContainerState extends PatternContainerState {

        @Override
        State createChildState(String localName) throws SAXException {
            if (childPatterns == null) {
                return super.createChildState(localName);
            }
            error("too_many_children");
            return null;
        }
    }

    class GrammarSectionState extends State {

        GrammarSection section;

        GrammarSectionState() {
        }

        GrammarSectionState(GrammarSection section) {
            this.section = section;
        }

        State create() {
            return new GrammarSectionState(null);
        }

        State createChildState(String localName) throws SAXException {
            if (localName.equals("define")) {
                return new DefineState(section);
            }
            if (localName.equals("start")) {
                return new StartState(section);
            }
            if (localName.equals("include")) {
                Include include = section.makeInclude();
                if (include != null) {
                    return new IncludeState(include);
                }
            }
            if (localName.equals("div")) {
                return new DivState(section.makeDiv());
            }
            error("expected_define", localName);
            // XXX better errors
            return null;
        }

        void end() throws SAXException {
            if (comments != null) {
                section.topLevelComment(comments);
                comments = null;
            }
        }

        @Override
        void endForeignChild(ParsedElementAnnotation ea) {
            section.topLevelAnnotation(ea);
        }
    }

    class DivState extends GrammarSectionState {

        final Div div;

        DivState(Div div) {
            super(div);
            this.div = div;
        }

        @Override
        void end() throws SAXException {
            super.end();
            div.endDiv(startLocation, annotations);
        }
    }

    class IncludeState extends GrammarSectionState {

        String href;
        final Include include;

        IncludeState(Include include) {
            super(include);
            this.include = include;
        }

        @Override
        void setOtherAttribute(String name, String value) throws SAXException {
            if (name.equals("href")) {
                href = value;
                checkUri(href);
            } else {
                super.setOtherAttribute(name, value);
            }
        }

        @Override
        void endAttributes() throws SAXException {
            if (href == null) {
                error("missing_href_attribute");
            } else {
                href = resolve(href);
            }
        }

        @Override
        void end() throws SAXException {
            super.end();
            if (href != null) {
                try {
                    include.endInclude(parseable, href, getNs(), startLocation, annotations);
                } catch (IllegalSchemaException e) {
                }
            }
        }
    }

    class MergeGrammarState extends GrammarSectionState {

        final IncludedGrammar grammar;

        MergeGrammarState(IncludedGrammar grammar) {
            super(grammar);
            this.grammar = grammar;
        }

        @Override
        void end() throws SAXException {
            super.end();
            parent.endChild(grammar.endIncludedGrammar(startLocation, annotations));
        }
    }

    class GrammarState extends GrammarSectionState {

        Grammar grammar;

        @Override
        void setParent(State parent) {
            super.setParent(parent);
            grammar = schemaBuilder.makeGrammar(scope);
            section = grammar;
            scope = grammar;
        }

        @Override
        State create() {
            return new GrammarState();
        }

        @Override
        void end() throws SAXException {
            super.end();
            parent.endChild(grammar.endGrammar(startLocation, annotations));
        }
    }

    class RefState extends EmptyContentState {

        String name;

        State create() {
            return new RefState();
        }

        @Override
        void endAttributes() throws SAXException {
            if (name == null) {
                error("missing_name_attribute");
            }
        }

        @Override
        void setName(String name) throws SAXException {
            this.name = checkNCName(name);
        }

        ParsedPattern makePattern() throws SAXException {
            if (name == null) {
                return schemaBuilder.makeErrorPattern();
            }
            if (scope == null) {
                error("ref_outside_grammar", name);
                return schemaBuilder.makeErrorPattern();
            } else {
                return scope.makeRef(name, startLocation, annotations);
            }
        }
    }

    class ParentRefState extends RefState {

        @Override
        State create() {
            return new ParentRefState();
        }

        @Override
        ParsedPattern makePattern() throws SAXException {
            if (name == null) {
                return schemaBuilder.makeErrorPattern();
            }
            if (scope == null) {
                error("parent_ref_outside_grammar", name);
                return schemaBuilder.makeErrorPattern();
            } else {
                return scope.makeParentRef(name, startLocation, annotations);
            }
        }
    }

    class ExternalRefState extends EmptyContentState {

        String href;

        State create() {
            return new ExternalRefState();
        }

        @Override
        void setOtherAttribute(String name, String value) throws SAXException {
            if (name.equals("href")) {
                href = value;
                checkUri(href);
            } else {
                super.setOtherAttribute(name, value);
            }
        }

        @Override
        void endAttributes() throws SAXException {
            if (href == null) {
                error("missing_href_attribute");
            } else {
                href = resolve(href);
            }
        }

        ParsedPattern makePattern() {
            if (href != null) {
                try {
                    return schemaBuilder.makeExternalRef(parseable,
                            href,
                            getNs(),
                            scope,
                            startLocation,
                            annotations);
                } catch (IllegalSchemaException e) {
                }
            }
            return schemaBuilder.makeErrorPattern();
        }
    }

    abstract class DefinitionState extends PatternContainerState {

        GrammarSection.Combine combine = null;
        final GrammarSection section;

        DefinitionState(GrammarSection section) {
            this.section = section;
        }

        @Override
        void setOtherAttribute(String name, String value) throws SAXException {
            if (name.equals("combine")) {
                value = value.trim();
                if (value.equals("choice")) {
                    combine = GrammarSection.COMBINE_CHOICE;
                } else if (value.equals("interleave")) {
                    combine = GrammarSection.COMBINE_INTERLEAVE;
                } else {
                    error("combine_attribute_bad_value", value);
                }
            } else {
                super.setOtherAttribute(name, value);
            }
        }

        @Override
        ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException {
            return super.buildPattern(patterns, loc, null);
        }
    }

    class DefineState extends DefinitionState {

        String name;

        DefineState(GrammarSection section) {
            super(section);
        }

        State create() {
            return new DefineState(null);
        }

        @Override
        void setName(String name) throws SAXException {
            this.name = checkNCName(name);
        }

        @Override
        void endAttributes() throws SAXException {
            if (name == null) {
                error("missing_name_attribute");
            }
        }

        @Override
        void sendPatternToParent(ParsedPattern p) {
            if (name != null) {
                section.define(name, combine, p, startLocation, annotations);
            }
        }
    }

    class StartState extends DefinitionState {

        StartState(GrammarSection section) {
            super(section);
        }

        State create() {
            return new StartState(null);
        }

        @Override
        void sendPatternToParent(ParsedPattern p) {
            section.define(GrammarSection.START, combine, p, startLocation, annotations);
        }

        @Override
        State createChildState(String localName) throws SAXException {
            State tem = super.createChildState(localName);
            if (tem != null && childPatterns != null) {
                error("start_multi_pattern");
            }
            return tem;
        }
    }

    abstract class NameClassContainerState extends State {

        State createChildState(String localName) throws SAXException {
            State state = (State) nameClassTable.get(localName);
            if (state == null) {
                error("expected_name_class", localName);
                return null;
            }
            return state.create();
        }
    }

    class NameClassChildState extends NameClassContainerState {

        final State prevState;
        final NameClassRef nameClassRef;

        State create() {
            return null;
        }

        NameClassChildState(State prevState, NameClassRef nameClassRef) {
            this.prevState = prevState;
            this.nameClassRef = nameClassRef;
            setParent(prevState.parent);
            this.ns = prevState.ns;
        }

        @Override
        void endChild(ParsedNameClass nameClass) {
            nameClassRef.setNameClass(nameClass);
            prevState.set();
        }

        @Override
        void endForeignChild(ParsedElementAnnotation ea) {
            prevState.endForeignChild(ea);
        }

        void end() throws SAXException {
            nameClassRef.setNameClass(nameClassBuilder.makeErrorNameClass());
            error("missing_name_class");
            prevState.set();
            prevState.end();
        }
    }

    abstract class NameClassBaseState extends State {

        abstract ParsedNameClass makeNameClass() throws SAXException;

        void end() throws SAXException {
            parent.endChild(makeNameClass());
        }
    }

    class NameState extends NameClassBaseState {

        final StringBuffer buf = new StringBuffer();

        State createChildState(String localName) throws SAXException {
            error("expected_name", localName);
            return null;
        }

        State create() {
            return new NameState();
        }

        @Override
        public void characters(char[] ch, int start, int len) {
            buf.append(ch, start, len);
        }

        @Override
        void checkForeignElement() throws SAXException {
            error("name_contains_foreign_element");
        }

        ParsedNameClass makeNameClass() throws SAXException {
            mergeLeadingComments();
            return expandName(buf.toString().trim(), getNs(), annotations);
        }
    }
    private static final int PATTERN_CONTEXT = 0;
    private static final int ANY_NAME_CONTEXT = 1;
    private static final int NS_NAME_CONTEXT = 2;
    private SAXParseable parseable;

    class AnyNameState extends NameClassBaseState {

        ParsedNameClass except = null;

        State create() {
            return new AnyNameState();
        }

        State createChildState(String localName) throws SAXException {
            if (localName.equals("except")) {
                if (except != null) {
                    error("multiple_except");
                }
                return new NameClassChoiceState(getContext());
            }
            error("expected_except", localName);
            return null;
        }

        int getContext() {
            return ANY_NAME_CONTEXT;
        }

        ParsedNameClass makeNameClass() {
            if (except == null) {
                return makeNameClassNoExcept();
            } else {
                return makeNameClassExcept(except);
            }
        }

        ParsedNameClass makeNameClassNoExcept() {
            return nameClassBuilder.makeAnyName(startLocation, annotations);
        }

        ParsedNameClass makeNameClassExcept(ParsedNameClass except) {
            return nameClassBuilder.makeAnyName(except, startLocation, annotations);
        }

        @Override
        void endChild(ParsedNameClass nameClass) {
            except = nameClass;
        }
    }

    class NsNameState extends AnyNameState {

        @Override
        State create() {
            return new NsNameState();
        }

        @Override
        ParsedNameClass makeNameClassNoExcept() {
            return nameClassBuilder.makeNsName(getNs(), null, null);
        }

        @Override
        ParsedNameClass makeNameClassExcept(ParsedNameClass except) {
            return nameClassBuilder.makeNsName(getNs(), except, null, null);
        }

        @Override
        int getContext() {
            return NS_NAME_CONTEXT;
        }
    }

    class NameClassChoiceState extends NameClassContainerState {

        private ParsedNameClass[] nameClasses;
        private int nNameClasses;
        private int context;

        NameClassChoiceState() {
            this.context = PATTERN_CONTEXT;
        }

        NameClassChoiceState(int context) {
            this.context = context;
        }

        @Override
        void setParent(State parent) {
            super.setParent(parent);
            if (parent instanceof NameClassChoiceState) {
                this.context = ((NameClassChoiceState) parent).context;
            }
        }

        State create() {
            return new NameClassChoiceState();
        }

        @Override
        State createChildState(String localName) throws SAXException {
            if (localName.equals("anyName")) {
                if (context >= ANY_NAME_CONTEXT) {
                    error(context == ANY_NAME_CONTEXT
                            ? "any_name_except_contains_any_name"
                            : "ns_name_except_contains_any_name");
                    return null;
                }
            } else if (localName.equals("nsName")) {
                if (context == NS_NAME_CONTEXT) {
                    error("ns_name_except_contains_ns_name");
                    return null;
                }
            }
            return super.createChildState(localName);
        }

        @Override
        void endChild(ParsedNameClass nc) {
            if (nameClasses == null) {
                nameClasses = new ParsedNameClass[INIT_CHILD_ALLOC];
            } else if (nNameClasses >= nameClasses.length) {
                ParsedNameClass[] newNameClasses = new ParsedNameClass[nameClasses.length * 2];
                System.arraycopy(nameClasses, 0, newNameClasses, 0, nameClasses.length);
                nameClasses = newNameClasses;
            }
            nameClasses[nNameClasses++] = nc;
        }

        @Override
        void endForeignChild(ParsedElementAnnotation ea) {
            if (nNameClasses == 0) {
                super.endForeignChild(ea);
            } else {
                nameClasses[nNameClasses - 1] = nameClassBuilder.annotateAfter(nameClasses[nNameClasses - 1], ea);
            }
        }

        void end() throws SAXException {
            if (nNameClasses == 0) {
                error("missing_name_class");
                parent.endChild(nameClassBuilder.makeErrorNameClass());
                return;
            }
            if (comments != null) {
                nameClasses[nNameClasses - 1] = nameClassBuilder.commentAfter(nameClasses[nNameClasses - 1], comments);
                comments = null;
            }
            parent.endChild(nameClassBuilder.makeChoice(Arrays.asList(nameClasses).subList(0, nNameClasses), startLocation, annotations));
        }
    }

    private void initPatternTable() {
        patternTable = new Hashtable();
        patternTable.put("zeroOrMore", new ZeroOrMoreState());
        patternTable.put("oneOrMore", new OneOrMoreState());
        patternTable.put("optional", new OptionalState());
        patternTable.put("list", new ListState());
        patternTable.put("choice", new ChoiceState());
        patternTable.put("interleave", new InterleaveState());
        patternTable.put("group", new GroupState());
        patternTable.put("mixed", new MixedState());
        patternTable.put("element", new ElementState());
        patternTable.put("attribute", new AttributeState());
        patternTable.put("empty", new EmptyState());
        patternTable.put("text", new TextState());
        patternTable.put("value", new ValueState());
        patternTable.put("data", new DataState());
        patternTable.put("notAllowed", new NotAllowedState());
        patternTable.put("grammar", new GrammarState());
        patternTable.put("ref", new RefState());
        patternTable.put("parentRef", new ParentRefState());
        patternTable.put("externalRef", new ExternalRefState());
    }

    private void initNameClassTable() {
        nameClassTable = new Hashtable();
        nameClassTable.put("name", new NameState());
        nameClassTable.put("anyName", new AnyNameState());
        nameClassTable.put("nsName", new NsNameState());
        nameClassTable.put("choice", new NameClassChoiceState());
    }

    public ParsedPattern getParsedPattern() throws IllegalSchemaException {
        if (hadError) {
            throw new IllegalSchemaException();
        }
        return startPattern;
    }

    private void error(String key) throws SAXException {
        error(key, locator);
    }

    private void error(String key, String arg) throws SAXException {
        error(key, arg, locator);
    }

    void error(String key, String arg1, String arg2) throws SAXException {
        error(key, arg1, arg2, locator);
    }

    private void error(String key, Locator loc) throws SAXException {
        error(new SAXParseException(localizer.message(key), loc));
    }

    private void error(String key, String arg, Locator loc) throws SAXException {
        error(new SAXParseException(localizer.message(key, arg), loc));
    }

    private void error(String key, String arg1, String arg2, Locator loc)
            throws SAXException {
        error(new SAXParseException(localizer.message(key, arg1, arg2), loc));
    }

    private void error(SAXParseException e) throws SAXException {
        hadError = true;
        if (eh != null) {
            eh.error(e);
        }
    }

    void warning(String key) throws SAXException {
        warning(key, locator);
    }

    private void warning(String key, String arg) throws SAXException {
        warning(key, arg, locator);
    }

    private void warning(String key, String arg1, String arg2) throws SAXException {
        warning(key, arg1, arg2, locator);
    }

    private void warning(String key, Locator loc) throws SAXException {
        warning(new SAXParseException(localizer.message(key), loc));
    }

    private void warning(String key, String arg, Locator loc) throws SAXException {
        warning(new SAXParseException(localizer.message(key, arg), loc));
    }

    private void warning(String key, String arg1, String arg2, Locator loc)
            throws SAXException {
        warning(new SAXParseException(localizer.message(key, arg1, arg2), loc));
    }

    private void warning(SAXParseException e) throws SAXException {
        if (eh != null) {
            eh.warning(e);
        }
    }

    SchemaParser(SAXParseable parseable,
            XMLReader xr,
            ErrorHandler eh,
            SchemaBuilder schemaBuilder,
            IncludedGrammar grammar,
            Scope scope,
            String inheritedNs) throws SAXException {
        this.parseable = parseable;
        this.xr = xr;
        this.eh = eh;
        this.schemaBuilder = schemaBuilder;
        this.nameClassBuilder = schemaBuilder.getNameClassBuilder();
        if (eh != null) {
            xr.setErrorHandler(eh);
        }
        xr.setDTDHandler(context);
        if (schemaBuilder.usesComments()) {
            try {
                xr.setProperty("http://xml.org/sax/properties/lexical-handler", new LexicalHandlerImpl());
            } catch (SAXNotRecognizedException e) {
                warning("no_comment_support", xr.getClass().getName());
            } catch (SAXNotSupportedException e) {
                warning("no_comment_support", xr.getClass().getName());
            }
        }
        initPatternTable();
        initNameClassTable();
        new RootState(grammar, scope, inheritedNs).set();
    }

    private Context getContext() {
        return context;
    }

    class LexicalHandlerImpl extends AbstractLexicalHandler {

        private boolean inDtd = false;

        @Override
        public void startDTD(String s, String s1, String s2) throws SAXException {
            inDtd = true;
        }

        @Override
        public void endDTD() throws SAXException {
            inDtd = false;
        }

        @Override
        public void comment(char[] chars, int start, int length) throws SAXException {
            if (!inDtd) {
                ((CommentHandler) xr.getContentHandler()).comment(new String(chars, start, length));
            }
        }
    }

    private ParsedNameClass expandName(String name, String ns, Annotations anno) throws SAXException {
        int ic = name.indexOf(':');
        if (ic == -1) {
            return nameClassBuilder.makeName(ns, checkNCName(name), null, null, anno);
        }
        String prefix = checkNCName(name.substring(0, ic));
        String localName = checkNCName(name.substring(ic + 1));
        for (PrefixMapping tem = context.prefixMapping; tem != null; tem = tem.next) {
            if (tem.prefix.equals(prefix)) {
                return nameClassBuilder.makeName(tem.uri, localName, prefix, null, anno);
            }
        }
        error("undefined_prefix", prefix);
        return nameClassBuilder.makeName("", localName, null, null, anno);
    }

    private String findPrefix(String qName, String uri) {
        String prefix = null;
        if (qName == null || qName.equals("")) {
            for (PrefixMapping p = context.prefixMapping; p != null; p = p.next) {
                if (p.uri.equals(uri)) {
                    prefix = p.prefix;
                    break;
                }
            }
        } else {
            int off = qName.indexOf(':');
            if (off > 0) {
                prefix = qName.substring(0, off);
            }
        }
        return prefix;
    }

    private String checkNCName(String str) throws SAXException {
        if (!Naming.isNcname(str)) {
            error("invalid_ncname", str);
        }
        return str;
    }

    private String resolve(String systemId) throws SAXException {
        if (Uri.hasFragmentId(systemId)) {
            error("href_fragment_id");
        }
        systemId = Uri.escapeDisallowedChars(systemId);
        return Uri.resolve(xmlBaseHandler.getBaseUri(), systemId);
    }

    private Location makeLocation() {
        if (locator == null) {
            return null;
        }
        return schemaBuilder.makeLocation(locator.getSystemId(),
                locator.getLineNumber(),
                locator.getColumnNumber());
    }

    private void checkUri(String s) throws SAXException {
        if (!Uri.isValid(s)) {
            error("invalid_uri", s);
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java SchemaParser.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.