325N/A/*
325N/A * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
325N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
325N/A *
325N/A * This code is free software; you can redistribute it and/or modify it
325N/A * under the terms of the GNU General Public License version 2 only, as
325N/A * published by the Free Software Foundation. Oracle designates this
325N/A * particular file as subject to the "Classpath" exception as provided
325N/A * by Oracle in the LICENSE file that accompanied this code.
325N/A *
325N/A * This code is distributed in the hope that it will be useful, but WITHOUT
325N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
325N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
325N/A * version 2 for more details (a copy is included in the LICENSE file that
325N/A * accompanied this code).
325N/A *
325N/A * You should have received a copy of the GNU General Public License version
325N/A * 2 along with this work; if not, write to the Free Software Foundation,
325N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
325N/A *
325N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
325N/A * or visit www.oracle.com if you need additional information or have any
325N/A * questions.
325N/A */
325N/A/*
325N/A * Copyright (C) 2004-2011
325N/A *
325N/A * Permission is hereby granted, free of charge, to any person obtaining a copy
325N/A * of this software and associated documentation files (the "Software"), to deal
325N/A * in the Software without restriction, including without limitation the rights
325N/A * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
325N/A * copies of the Software, and to permit persons to whom the Software is
325N/A * furnished to do so, subject to the following conditions:
325N/A *
325N/A * The above copyright notice and this permission notice shall be included in
325N/A * all copies or substantial portions of the Software.
325N/A *
325N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
325N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
325N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
325N/A * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
325N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
325N/A * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
325N/A * THE SOFTWARE.
325N/A */
325N/Apackage com.sun.xml.internal.rngom.binary;
325N/A
325N/Aimport java.util.Enumeration;
325N/Aimport java.util.Hashtable;
325N/Aimport java.util.List;
325N/A
325N/Aimport com.sun.xml.internal.rngom.ast.builder.Annotations;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.BuildException;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.CommentList;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.DataPatternBuilder;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.Div;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.ElementAnnotationBuilder;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.Grammar;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.GrammarSection;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.Include;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.IncludedGrammar;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.NameClassBuilder;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.SchemaBuilder;
325N/Aimport com.sun.xml.internal.rngom.ast.builder.Scope;
325N/Aimport com.sun.xml.internal.rngom.ast.om.Location;
325N/Aimport com.sun.xml.internal.rngom.ast.om.ParsedElementAnnotation;
325N/Aimport com.sun.xml.internal.rngom.ast.om.ParsedNameClass;
325N/Aimport com.sun.xml.internal.rngom.ast.om.ParsedPattern;
325N/Aimport com.sun.xml.internal.rngom.ast.util.LocatorImpl;
325N/Aimport com.sun.xml.internal.rngom.dt.builtin.BuiltinDatatypeLibraryFactory;
325N/Aimport com.sun.xml.internal.rngom.dt.CascadingDatatypeLibraryFactory;
325N/Aimport com.sun.xml.internal.rngom.nc.NameClass;
325N/Aimport com.sun.xml.internal.rngom.nc.NameClassBuilderImpl;
325N/Aimport com.sun.xml.internal.rngom.parse.Context;
325N/Aimport com.sun.xml.internal.rngom.parse.IllegalSchemaException;
325N/Aimport com.sun.xml.internal.rngom.parse.Parseable;
325N/Aimport com.sun.xml.internal.rngom.util.Localizer;
325N/Aimport org.relaxng.datatype.Datatype;
325N/Aimport org.relaxng.datatype.DatatypeBuilder;
325N/Aimport org.relaxng.datatype.DatatypeException;
325N/Aimport org.relaxng.datatype.DatatypeLibrary;
325N/Aimport org.relaxng.datatype.DatatypeLibraryFactory;
325N/Aimport org.relaxng.datatype.ValidationContext;
325N/Aimport org.relaxng.datatype.helpers.DatatypeLibraryLoader;
325N/Aimport org.xml.sax.ErrorHandler;
325N/Aimport org.xml.sax.Locator;
325N/Aimport org.xml.sax.SAXException;
325N/Aimport org.xml.sax.SAXParseException;
325N/A
325N/Apublic class SchemaBuilderImpl implements SchemaBuilder, ElementAnnotationBuilder, CommentList {
325N/A private final SchemaBuilderImpl parent;
325N/A private boolean hadError = false;
325N/A private final SchemaPatternBuilder pb;
325N/A private final DatatypeLibraryFactory datatypeLibraryFactory;
325N/A private final String inheritNs;
325N/A private final ErrorHandler eh;
325N/A private final OpenIncludes openIncludes;
325N/A private final NameClassBuilder ncb =new NameClassBuilderImpl();
325N/A static final Localizer localizer = new Localizer(SchemaBuilderImpl.class);
325N/A
325N/A static class OpenIncludes {
325N/A final String uri;
325N/A final OpenIncludes parent;
325N/A
325N/A OpenIncludes(String uri, OpenIncludes parent) {
325N/A this.uri = uri;
325N/A this.parent = parent;
325N/A }
325N/A }
325N/A
325N/A public ParsedPattern expandPattern(ParsedPattern _pattern)
325N/A throws BuildException, IllegalSchemaException {
325N/A Pattern pattern = (Pattern) _pattern;
325N/A if (!hadError) {
325N/A try {
325N/A pattern.checkRecursion(0);
325N/A pattern = pattern.expand(pb);
325N/A pattern.checkRestrictions(Pattern.START_CONTEXT, null, null);
325N/A if (!hadError) return pattern;
325N/A } catch (SAXParseException e) {
325N/A error(e);
325N/A } catch (SAXException e) {
325N/A throw new BuildException(e);
325N/A } catch (RestrictionViolationException e) {
325N/A if (e.getName() != null)
325N/A error(e.getMessageId(), e.getName().toString(), e
325N/A .getLocator());
325N/A else
325N/A error(e.getMessageId(), e.getLocator());
325N/A }
325N/A }
325N/A throw new IllegalSchemaException();
325N/A }
325N/A
325N/A /**
325N/A *
325N/A * @param eh
325N/A * Error handler to receive errors while building the schema.
325N/A */
325N/A public SchemaBuilderImpl(ErrorHandler eh) {
325N/A this(eh,
325N/A new CascadingDatatypeLibraryFactory(new DatatypeLibraryLoader(),
325N/A new BuiltinDatatypeLibraryFactory(new DatatypeLibraryLoader())),
325N/A new SchemaPatternBuilder());
325N/A }
325N/A
325N/A /**
325N/A *
325N/A * @param eh
325N/A * Error handler to receive errors while building the schema.
325N/A * @param datatypeLibraryFactory
325N/A * This is consulted to locate datatype libraries.
325N/A * @param pb
325N/A * Used to build patterns.
325N/A */
325N/A public SchemaBuilderImpl(ErrorHandler eh,
325N/A DatatypeLibraryFactory datatypeLibraryFactory,
325N/A SchemaPatternBuilder pb) {
325N/A this.parent = null;
325N/A this.eh = eh;
325N/A this.datatypeLibraryFactory = datatypeLibraryFactory;
325N/A this.pb = pb;
325N/A this.inheritNs = "";
325N/A this.openIncludes = null;
325N/A }
325N/A
325N/A private SchemaBuilderImpl(String inheritNs,
325N/A String uri,
325N/A SchemaBuilderImpl parent) {
325N/A this.parent = parent;
325N/A this.eh = parent.eh;
325N/A this.datatypeLibraryFactory = parent.datatypeLibraryFactory;
325N/A this.pb = parent.pb;
325N/A this.inheritNs = inheritNs;
325N/A this.openIncludes = new OpenIncludes(uri, parent.openIncludes);
325N/A }
325N/A
325N/A public NameClassBuilder getNameClassBuilder() {
325N/A return ncb;
325N/A }
325N/A
325N/A public ParsedPattern makeChoice(List patterns, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A if (patterns.isEmpty())
325N/A throw new IllegalArgumentException();
325N/A Pattern result = (Pattern)patterns.get(0);
325N/A for (int i = 1; i < patterns.size(); i++)
325N/A result = pb.makeChoice(result, (Pattern)patterns.get(i));
325N/A return result;
325N/A }
325N/A
325N/A public ParsedPattern makeInterleave(List patterns, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A if (patterns.isEmpty())
325N/A throw new IllegalArgumentException();
325N/A Pattern result = (Pattern)patterns.get(0);
325N/A for (int i = 1; i < patterns.size(); i++)
325N/A result = pb.makeInterleave(result, (Pattern)patterns.get(i));
325N/A return result;
325N/A }
325N/A
325N/A public ParsedPattern makeGroup(List patterns, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A if (patterns.isEmpty())
325N/A throw new IllegalArgumentException();
325N/A Pattern result = (Pattern)patterns.get(0);
325N/A for (int i = 1; i < patterns.size(); i++)
325N/A result = pb.makeGroup(result, (Pattern)patterns.get(i));
325N/A return result;
325N/A }
325N/A
325N/A public ParsedPattern makeOneOrMore(ParsedPattern p, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A return pb.makeOneOrMore((Pattern)p);
325N/A }
325N/A
325N/A public ParsedPattern makeZeroOrMore(ParsedPattern p, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A return pb.makeZeroOrMore((Pattern)p);
325N/A }
325N/A
325N/A public ParsedPattern makeOptional(ParsedPattern p, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A return pb.makeOptional((Pattern)p);
325N/A }
325N/A
325N/A public ParsedPattern makeList(ParsedPattern p, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A return pb.makeList((Pattern)p, (Locator)loc);
325N/A }
325N/A
325N/A public ParsedPattern makeMixed(ParsedPattern p, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A return pb.makeMixed((Pattern)p);
325N/A }
325N/A
325N/A public ParsedPattern makeEmpty(Location loc, Annotations anno) {
325N/A return pb.makeEmpty();
325N/A }
325N/A
325N/A public ParsedPattern makeNotAllowed(Location loc, Annotations anno) {
325N/A return pb.makeUnexpandedNotAllowed();
325N/A }
325N/A
325N/A public ParsedPattern makeText(Location loc, Annotations anno) {
325N/A return pb.makeText();
325N/A }
325N/A
325N/A public ParsedPattern makeErrorPattern() {
325N/A return pb.makeError();
325N/A }
325N/A
325N/A// public ParsedNameClass makeErrorNameClass() {
325N/A// return new ErrorNameClass();
325N/A// }
325N/A
325N/A public ParsedPattern makeAttribute(ParsedNameClass nc, ParsedPattern p, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A return pb.makeAttribute((NameClass)nc, (Pattern)p, (Locator)loc);
325N/A }
325N/A
325N/A public ParsedPattern makeElement(ParsedNameClass nc, ParsedPattern p, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A return pb.makeElement((NameClass)nc, (Pattern)p, (Locator)loc);
325N/A }
325N/A
325N/A private class DummyDataPatternBuilder implements DataPatternBuilder {
325N/A public void addParam(String name, String value, Context context, String ns, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A }
325N/A
325N/A public ParsedPattern makePattern(Location loc, Annotations anno)
325N/A throws BuildException {
325N/A return pb.makeError();
325N/A }
325N/A
325N/A public ParsedPattern makePattern(ParsedPattern except, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A return pb.makeError();
325N/A }
325N/A
325N/A public void annotation(ParsedElementAnnotation ea) {
325N/A }
325N/A }
325N/A
325N/A private class ValidationContextImpl implements ValidationContext {
325N/A private ValidationContext vc;
325N/A private String ns;
325N/A
325N/A ValidationContextImpl(ValidationContext vc, String ns) {
325N/A this.vc = vc;
325N/A this.ns = ns.length() == 0 ? null : ns;
325N/A }
325N/A
325N/A public String resolveNamespacePrefix(String prefix) {
325N/A return prefix.length() == 0 ? ns : vc.resolveNamespacePrefix(prefix);
325N/A }
325N/A
325N/A public String getBaseUri() {
325N/A return vc.getBaseUri();
325N/A }
325N/A
325N/A public boolean isUnparsedEntity(String entityName) {
325N/A return vc.isUnparsedEntity(entityName);
325N/A }
325N/A
325N/A public boolean isNotation(String notationName) {
325N/A return vc.isNotation(notationName);
325N/A }
325N/A }
325N/A
325N/A private class DataPatternBuilderImpl implements DataPatternBuilder {
325N/A private DatatypeBuilder dtb;
325N/A DataPatternBuilderImpl(DatatypeBuilder dtb) {
325N/A this.dtb = dtb;
325N/A }
325N/A
325N/A public void addParam(String name, String value, Context context, String ns, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A try {
325N/A dtb.addParameter(name, value, new ValidationContextImpl(context, ns));
325N/A }
325N/A catch (DatatypeException e) {
325N/A String detail = e.getMessage();
325N/A int pos = e.getIndex();
325N/A String displayedParam;
325N/A if (pos == DatatypeException.UNKNOWN)
325N/A displayedParam = null;
325N/A else
325N/A displayedParam = displayParam(value, pos);
325N/A if (displayedParam != null) {
325N/A if (detail != null)
325N/A error("invalid_param_detail_display", detail, displayedParam, (Locator)loc);
325N/A else
325N/A error("invalid_param_display", displayedParam, (Locator)loc);
325N/A }
325N/A else if (detail != null)
325N/A error("invalid_param_detail", detail, (Locator)loc);
325N/A else
325N/A error("invalid_param", (Locator)loc);
325N/A }
325N/A }
325N/A
325N/A String displayParam(String value, int pos) {
325N/A if (pos < 0)
325N/A pos = 0;
325N/A else if (pos > value.length())
325N/A pos = value.length();
325N/A return localizer.message("display_param", value.substring(0, pos), value.substring(pos));
325N/A }
325N/A
325N/A public ParsedPattern makePattern(Location loc, Annotations anno)
325N/A throws BuildException {
325N/A try {
325N/A return pb.makeData(dtb.createDatatype());
325N/A }
325N/A catch (DatatypeException e) {
325N/A String detail = e.getMessage();
325N/A if (detail != null)
325N/A error("invalid_params_detail", detail, (Locator)loc);
325N/A else
325N/A error("invalid_params", (Locator)loc);
325N/A return pb.makeError();
325N/A }
325N/A }
325N/A
325N/A public ParsedPattern makePattern(ParsedPattern except, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A try {
325N/A return pb.makeDataExcept(dtb.createDatatype(), (Pattern)except, (Locator)loc);
325N/A }
325N/A catch (DatatypeException e) {
325N/A String detail = e.getMessage();
325N/A if (detail != null)
325N/A error("invalid_params_detail", detail, (Locator)loc);
325N/A else
325N/A error("invalid_params", (Locator)loc);
325N/A return pb.makeError();
325N/A }
325N/A }
325N/A
325N/A public void annotation(ParsedElementAnnotation ea) {
325N/A }
325N/A }
325N/A
325N/A public DataPatternBuilder makeDataPatternBuilder(String datatypeLibrary, String type, Location loc)
325N/A throws BuildException {
325N/A DatatypeLibrary dl = datatypeLibraryFactory.createDatatypeLibrary(datatypeLibrary);
325N/A if (dl == null)
325N/A error("unrecognized_datatype_library", datatypeLibrary, (Locator)loc);
325N/A else {
325N/A try {
325N/A return new DataPatternBuilderImpl(dl.createDatatypeBuilder(type));
325N/A }
325N/A catch (DatatypeException e) {
325N/A String detail = e.getMessage();
325N/A if (detail != null)
325N/A error("unsupported_datatype_detail", datatypeLibrary, type, detail, (Locator)loc);
325N/A else
325N/A error("unrecognized_datatype", datatypeLibrary, type, (Locator)loc);
325N/A }
325N/A }
325N/A return new DummyDataPatternBuilder();
325N/A }
325N/A
325N/A public ParsedPattern makeValue(String datatypeLibrary, String type, String value, Context context, String ns,
325N/A Location loc, Annotations anno) throws BuildException {
325N/A DatatypeLibrary dl = datatypeLibraryFactory.createDatatypeLibrary(datatypeLibrary);
325N/A if (dl == null)
325N/A error("unrecognized_datatype_library", datatypeLibrary, (Locator)loc);
325N/A else {
325N/A try {
325N/A DatatypeBuilder dtb = dl.createDatatypeBuilder(type);
325N/A try {
325N/A Datatype dt = dtb.createDatatype();
325N/A Object obj = dt.createValue(value, new ValidationContextImpl(context, ns));
325N/A if (obj != null)
325N/A return pb.makeValue(dt, obj);
325N/A error("invalid_value", value, (Locator)loc);
325N/A }
325N/A catch (DatatypeException e) {
325N/A String detail = e.getMessage();
325N/A if (detail != null)
325N/A error("datatype_requires_param_detail", detail, (Locator)loc);
325N/A else
325N/A error("datatype_requires_param", (Locator)loc);
325N/A }
325N/A }
325N/A catch (DatatypeException e) {
325N/A error("unrecognized_datatype", datatypeLibrary, type, (Locator)loc);
325N/A }
325N/A }
325N/A return pb.makeError();
325N/A }
325N/A
325N/A static class GrammarImpl implements Grammar, Div, IncludedGrammar {
325N/A private final SchemaBuilderImpl sb;
325N/A private final Hashtable defines;
325N/A private final RefPattern startRef;
325N/A private final Scope parent;
325N/A
325N/A private GrammarImpl(SchemaBuilderImpl sb, Scope parent) {
325N/A this.sb = sb;
325N/A this.parent = parent;
325N/A this.defines = new Hashtable();
325N/A this.startRef = new RefPattern(null);
325N/A }
325N/A
325N/A protected GrammarImpl(SchemaBuilderImpl sb, GrammarImpl g) {
325N/A this.sb = sb;
325N/A parent = g.parent;
325N/A startRef = g.startRef;
325N/A defines = g.defines;
325N/A }
325N/A
325N/A public ParsedPattern endGrammar(Location loc, Annotations anno) throws BuildException {
325N/A for (Enumeration e = defines.keys();
325N/A e.hasMoreElements();) {
325N/A String name = (String)e.nextElement();
325N/A RefPattern rp = (RefPattern)defines.get(name);
325N/A if (rp.getPattern() == null) {
325N/A sb.error("reference_to_undefined", name, rp.getRefLocator());
325N/A rp.setPattern(sb.pb.makeError());
325N/A }
325N/A }
325N/A Pattern start = startRef.getPattern();
325N/A if (start == null) {
325N/A sb.error("missing_start_element", (Locator)loc);
325N/A start = sb.pb.makeError();
325N/A }
325N/A return start;
325N/A }
325N/A
325N/A public void endDiv(Location loc, Annotations anno) throws BuildException {
325N/A // nothing to do
325N/A }
325N/A
325N/A public ParsedPattern endIncludedGrammar(Location loc, Annotations anno) throws BuildException {
325N/A return null;
325N/A }
325N/A
325N/A public void define(String name, GrammarSection.Combine combine, ParsedPattern pattern, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A define(lookup(name), combine, pattern, loc);
325N/A }
325N/A
325N/A private void define(RefPattern rp, GrammarSection.Combine combine, ParsedPattern pattern, Location loc)
325N/A throws BuildException {
325N/A switch (rp.getReplacementStatus()) {
325N/A case RefPattern.REPLACEMENT_KEEP:
325N/A if (combine == null) {
325N/A if (rp.isCombineImplicit()) {
325N/A if (rp.getName() == null)
325N/A sb.error("duplicate_start", (Locator)loc);
325N/A else
325N/A sb.error("duplicate_define", rp.getName(), (Locator)loc);
325N/A }
325N/A else
325N/A rp.setCombineImplicit();
325N/A }
325N/A else {
325N/A byte combineType = (combine == COMBINE_CHOICE ? RefPattern.COMBINE_CHOICE : RefPattern.COMBINE_INTERLEAVE);
325N/A if (rp.getCombineType() != RefPattern.COMBINE_NONE
325N/A && rp.getCombineType() != combineType) {
325N/A if (rp.getName() == null)
325N/A sb.error("conflict_combine_start", (Locator)loc);
325N/A else
325N/A sb.error("conflict_combine_define", rp.getName(), (Locator)loc);
325N/A }
325N/A rp.setCombineType(combineType);
325N/A }
325N/A Pattern p = (Pattern)pattern;
325N/A if (rp.getPattern() == null)
325N/A rp.setPattern(p);
325N/A else if (rp.getCombineType() == RefPattern.COMBINE_INTERLEAVE)
325N/A rp.setPattern(sb.pb.makeInterleave(rp.getPattern(), p));
325N/A else
325N/A rp.setPattern(sb.pb.makeChoice(rp.getPattern(), p));
325N/A break;
325N/A case RefPattern.REPLACEMENT_REQUIRE:
325N/A rp.setReplacementStatus(RefPattern.REPLACEMENT_IGNORE);
325N/A break;
325N/A case RefPattern.REPLACEMENT_IGNORE:
325N/A break;
325N/A }
325N/A }
325N/A
325N/A public void topLevelAnnotation(ParsedElementAnnotation ea) throws BuildException {
325N/A }
325N/A
325N/A public void topLevelComment(CommentList comments) throws BuildException {
325N/A }
325N/A
325N/A private RefPattern lookup(String name) {
325N/A if (name == START)
325N/A return startRef;
325N/A return lookup1(name);
325N/A }
325N/A
325N/A private RefPattern lookup1(String name) {
325N/A RefPattern p = (RefPattern)defines.get(name);
325N/A if (p == null) {
325N/A p = new RefPattern(name);
325N/A defines.put(name, p);
325N/A }
325N/A return p;
325N/A }
325N/A
325N/A public ParsedPattern makeRef(String name, Location loc, Annotations anno) throws BuildException {
325N/A RefPattern p = lookup1(name);
325N/A if (p.getRefLocator() == null && loc != null)
325N/A p.setRefLocator((Locator)loc);
325N/A return p;
325N/A }
325N/A
325N/A public ParsedPattern makeParentRef(String name, Location loc, Annotations anno) throws BuildException {
325N/A // TODO: do this check by the caller
325N/A if (parent == null) {
325N/A sb.error("parent_ref_outside_grammar", (Locator)loc);
325N/A return sb.makeErrorPattern();
325N/A }
325N/A return parent.makeRef(name, loc, anno);
325N/A }
325N/A
325N/A public Div makeDiv() {
325N/A return this;
325N/A }
325N/A
325N/A public Include makeInclude() {
325N/A return new IncludeImpl(sb, this);
325N/A }
325N/A
325N/A }
325N/A
325N/A
325N/A static class Override {
325N/A Override(RefPattern prp, Override next) {
325N/A this.prp = prp;
325N/A this.next = next;
325N/A }
325N/A
325N/A RefPattern prp;
325N/A Override next;
325N/A byte replacementStatus;
325N/A }
325N/A
325N/A
325N/A private static class IncludeImpl implements Include, Div {
325N/A private SchemaBuilderImpl sb;
325N/A private Override overrides;
325N/A private GrammarImpl grammar;
325N/A
325N/A private IncludeImpl(SchemaBuilderImpl sb, GrammarImpl grammar) {
325N/A this.sb = sb;
325N/A this.grammar = grammar;
325N/A }
325N/A
325N/A public void define(String name, GrammarSection.Combine combine, ParsedPattern pattern, Location loc, Annotations anno)
325N/A throws BuildException {
325N/A RefPattern rp = grammar.lookup(name);
325N/A overrides = new Override(rp, overrides);
325N/A grammar.define(rp, combine, pattern, loc);
325N/A }
325N/A
325N/A public void endDiv(Location loc, Annotations anno) throws BuildException {
325N/A // nothing to do
325N/A }
325N/A
325N/A public void topLevelAnnotation(ParsedElementAnnotation ea) throws BuildException {
325N/A // nothing to do
325N/A }
325N/A
325N/A public void topLevelComment(CommentList comments) throws BuildException {
325N/A }
325N/A
325N/A public Div makeDiv() {
325N/A return this;
325N/A }
325N/A
325N/A public void endInclude(Parseable current,String uri, String ns,
325N/A Location loc, Annotations anno) throws BuildException {
325N/A for (OpenIncludes inc = sb.openIncludes;
325N/A inc != null;
325N/A inc = inc.parent) {
325N/A if (inc.uri.equals(uri)) {
325N/A sb.error("recursive_include", uri, (Locator)loc);
325N/A return;
325N/A }
325N/A }
325N/A
325N/A for (Override o = overrides; o != null; o = o.next) {
325N/A o.replacementStatus = o.prp.getReplacementStatus();
325N/A o.prp.setReplacementStatus(RefPattern.REPLACEMENT_REQUIRE);
325N/A }
325N/A try {
325N/A SchemaBuilderImpl isb = new SchemaBuilderImpl(ns, uri, sb);
325N/A current.parseInclude(uri, isb, new GrammarImpl(isb, grammar), ns);
325N/A for (Override o = overrides; o != null; o = o.next) {
325N/A if (o.prp.getReplacementStatus() == RefPattern.REPLACEMENT_REQUIRE) {
325N/A if (o.prp.getName() == null)
325N/A sb.error("missing_start_replacement", (Locator)loc);
325N/A else
325N/A sb.error("missing_define_replacement", o.prp.getName(), (Locator)loc);
325N/A }
325N/A }
325N/A }
325N/A catch (IllegalSchemaException e) {
325N/A sb.noteError();
325N/A }
325N/A finally {
325N/A for (Override o = overrides; o != null; o = o.next)
325N/A o.prp.setReplacementStatus(o.replacementStatus);
325N/A }
325N/A }
325N/A
325N/A public Include makeInclude() {
325N/A return null;
325N/A }
325N/A }
325N/A
325N/A public Grammar makeGrammar(Scope parent) {
325N/A return new GrammarImpl(this, parent);
325N/A }
325N/A
325N/A public ParsedPattern annotate(ParsedPattern p, Annotations anno) throws BuildException {
325N/A return p;
325N/A }
325N/A
325N/A
325N/A public ParsedPattern annotateAfter(ParsedPattern p, ParsedElementAnnotation e) throws BuildException {
325N/A return p;
325N/A }
325N/A
325N/A public ParsedPattern commentAfter(ParsedPattern p, CommentList comments) throws BuildException {
325N/A return p;
325N/A }
325N/A
325N/A
325N/A public ParsedPattern makeExternalRef(Parseable current, String uri, String ns, Scope scope,
325N/A Location loc, Annotations anno)
325N/A throws BuildException {
325N/A for (OpenIncludes inc = openIncludes;
325N/A inc != null;
325N/A inc = inc.parent) {
325N/A if (inc.uri.equals(uri)) {
325N/A error("recursive_include", uri, (Locator)loc);
325N/A return pb.makeError();
325N/A }
325N/A }
325N/A try {
325N/A return current.parseExternal(uri, new SchemaBuilderImpl(ns, uri, this), scope, ns );
325N/A }
325N/A catch (IllegalSchemaException e) {
325N/A noteError();
325N/A return pb.makeError();
325N/A }
325N/A }
325N/A
325N/A
325N/A
325N/A public Location makeLocation(String systemId, int lineNumber, int columnNumber) {
325N/A return new LocatorImpl(systemId, lineNumber, columnNumber);
325N/A }
325N/A
325N/A public Annotations makeAnnotations(CommentList comments, Context context) {
325N/A return this;
325N/A }
325N/A
325N/A public ElementAnnotationBuilder makeElementAnnotationBuilder(String ns, String localName, String prefix,
325N/A Location loc, CommentList comments, Context context) {
325N/A return this;
325N/A }
325N/A
325N/A public CommentList makeCommentList() {
325N/A return this;
325N/A }
325N/A
325N/A public void addComment(String value, Location loc) throws BuildException {
325N/A }
325N/A
325N/A public void addAttribute(String ns, String localName, String prefix, String value, Location loc) {
325N/A // nothing needed
325N/A }
325N/A
325N/A public void addElement(ParsedElementAnnotation ea) {
325N/A // nothing needed
325N/A }
325N/A
325N/A public void addComment(CommentList comments) throws BuildException {
325N/A // nothing needed
325N/A }
325N/A
325N/A public void addLeadingComment(CommentList comments) throws BuildException {
325N/A // nothing needed
325N/A }
325N/A
325N/A public ParsedElementAnnotation makeElementAnnotation() {
325N/A return null;
325N/A }
325N/A
325N/A public void addText(String value, Location loc, CommentList comments) throws BuildException {
325N/A }
325N/A
325N/A public boolean usesComments() {
325N/A return false;
325N/A }
325N/A
325N/A private void error(SAXParseException message) throws BuildException {
325N/A noteError();
325N/A try {
325N/A if (eh != null)
325N/A eh.error(message);
325N/A }
325N/A catch (SAXException e) {
325N/A throw new BuildException(e);
325N/A }
325N/A }
325N/A
325N/A private void warning(SAXParseException message) throws BuildException {
325N/A try {
325N/A if (eh != null)
325N/A eh.warning(message);
325N/A }
325N/A catch (SAXException e) {
325N/A throw new BuildException(e);
325N/A }
325N/A }
325N/A
325N/A private void error(String key, Locator loc) throws BuildException {
325N/A error(new SAXParseException(localizer.message(key), loc));
325N/A }
325N/A
325N/A private void error(String key, String arg, Locator loc) throws BuildException {
325N/A error(new SAXParseException(localizer.message(key, arg), loc));
325N/A }
325N/A
325N/A private void error(String key, String arg1, String arg2, Locator loc) throws BuildException {
325N/A error(new SAXParseException(localizer.message(key, arg1, arg2), loc));
325N/A }
325N/A
325N/A private void error(String key, String arg1, String arg2, String arg3, Locator loc) throws BuildException {
325N/A error(new SAXParseException(localizer.message(key, new Object[]{arg1, arg2, arg3}), loc));
325N/A }
325N/A private void noteError() {
325N/A if (!hadError && parent != null)
325N/A parent.noteError();
325N/A hadError = true;
325N/A }
325N/A
325N/A}