gt:                 String detail = e.getMessage();
context: /*
   * Copyright (c) 2005, 2015, 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.binary;
  
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.List;
  
  import com.sun.xml.internal.rngom.ast.builder.Annotations;
  import com.sun.xml.internal.rngom.ast.builder.BuildException;
  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.ast.util.LocatorImpl;
  import com.sun.xml.internal.rngom.dt.builtin.BuiltinDatatypeLibraryFactory;
  import com.sun.xml.internal.rngom.dt.CascadingDatatypeLibraryFactory;
  import com.sun.xml.internal.rngom.nc.NameClass;
  import com.sun.xml.internal.rngom.nc.NameClassBuilderImpl;
  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.org.relaxng.datatype.Datatype;
  import com.sun.xml.internal.org.relaxng.datatype.DatatypeBuilder;
  import com.sun.xml.internal.org.relaxng.datatype.DatatypeException;
  import com.sun.xml.internal.org.relaxng.datatype.DatatypeLibrary;
  import com.sun.xml.internal.org.relaxng.datatype.DatatypeLibraryFactory;
  import com.sun.xml.internal.org.relaxng.datatype.ValidationContext;
  import com.sun.xml.internal.org.relaxng.datatype.helpers.DatatypeLibraryLoader;
  import org.xml.sax.ErrorHandler;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  import org.xml.sax.SAXParseException;
  
  public class SchemaBuilderImpl implements SchemaBuilder, ElementAnnotationBuilder, CommentList {
  
      private final SchemaBuilderImpl parent;
      private boolean hadError = false;
      private final SchemaPatternBuilder pb;
      private final DatatypeLibraryFactory datatypeLibraryFactory;
      private final String inheritNs;
      private final ErrorHandler eh;
      private final OpenIncludes openIncludes;
      private final NameClassBuilder ncb = new NameClassBuilderImpl();
      static final Localizer localizer = new Localizer(SchemaBuilderImpl.class);
  
      static class OpenIncludes {
  
          final String uri;
          final OpenIncludes parent;
  
          OpenIncludes(String uri, OpenIncludes parent) {
              this.uri = uri;
              this.parent = parent;
          }
      }
  
      public ParsedPattern expandPattern(ParsedPattern _pattern)
              throws BuildException, IllegalSchemaException {
          Pattern pattern = (Pattern) _pattern;
          if (!hadError) {
              try {
                  pattern.checkRecursion(0);
                  pattern = pattern.expand(pb);
                  pattern.checkRestrictions(Pattern.START_CONTEXT, null, null);
                  if (!hadError) {
                      return pattern;
                  }
              } catch (SAXParseException e) {
                  error(e);
              } catch (SAXException e) {
                  throw new BuildException(e);
              } catch (RestrictionViolationException e) {
                  if (e.getName() != null) {
                      error(e.getMessageId(), e.getName().toString(), e
                              .getLocator());
                  } else {
                      error(e.getMessageId(), e.getLocator());
                  }
              }
          }
          throw new IllegalSchemaException();
      }
  
      /**
       *
       * @param eh Error handler to receive errors while building the schema.
       */
      public SchemaBuilderImpl(ErrorHandler eh) {
          this(eh,
                  new CascadingDatatypeLibraryFactory(new DatatypeLibraryLoader(),
                  new BuiltinDatatypeLibraryFactory(new DatatypeLibraryLoader())),
                  new SchemaPatternBuilder());
      }
  
      /**
       *
       * @param eh Error handler to receive errors while building the schema.
       * @param datatypeLibraryFactory This is consulted to locate datatype
       * libraries.
       * @param pb Used to build patterns.
       */
      public SchemaBuilderImpl(ErrorHandler eh,
              DatatypeLibraryFactory datatypeLibraryFactory,
              SchemaPatternBuilder pb) {
          this.parent = null;
          this.eh = eh;
          this.datatypeLibraryFactory = datatypeLibraryFactory;
          this.pb = pb;
          this.inheritNs = "";
          this.openIncludes = null;
      }
  
      private SchemaBuilderImpl(String inheritNs,
              String uri,
              SchemaBuilderImpl parent) {
          this.parent = parent;
          this.eh = parent.eh;
          this.datatypeLibraryFactory = parent.datatypeLibraryFactory;
          this.pb = parent.pb;
          this.inheritNs = inheritNs;
          this.openIncludes = new OpenIncludes(uri, parent.openIncludes);
      }
  
      public NameClassBuilder getNameClassBuilder() {
          return ncb;
      }
  
      public ParsedPattern makeChoice(List patterns, Location loc, Annotations anno)
              throws BuildException {
          if (patterns.isEmpty()) {
              throw new IllegalArgumentException();
          }
          Pattern result = (Pattern) patterns.get(0);
          for (int i = 1; i < patterns.size(); i++) {
              result = pb.makeChoice(result, (Pattern) patterns.get(i));
          }
          return result;
      }
  
      public ParsedPattern makeInterleave(List patterns, Location loc, Annotations anno)
              throws BuildException {
          if (patterns.isEmpty()) {
              throw new IllegalArgumentException();
          }
          Pattern result = (Pattern) patterns.get(0);
          for (int i = 1; i < patterns.size(); i++) {
              result = pb.makeInterleave(result, (Pattern) patterns.get(i));
          }
          return result;
      }
  
      public ParsedPattern makeGroup(List patterns, Location loc, Annotations anno)
              throws BuildException {
          if (patterns.isEmpty()) {
              throw new IllegalArgumentException();
          }
          Pattern result = (Pattern) patterns.get(0);
          for (int i = 1; i < patterns.size(); i++) {
              result = pb.makeGroup(result, (Pattern) patterns.get(i));
          }
          return result;
      }
  
      public ParsedPattern makeOneOrMore(ParsedPattern p, Location loc, Annotations anno)
              throws BuildException {
          return pb.makeOneOrMore((Pattern) p);
      }
  
      public ParsedPattern makeZeroOrMore(ParsedPattern p, Location loc, Annotations anno)
              throws BuildException {
          return pb.makeZeroOrMore((Pattern) p);
      }
  
      public ParsedPattern makeOptional(ParsedPattern p, Location loc, Annotations anno)
              throws BuildException {
          return pb.makeOptional((Pattern) p);
      }
  
      public ParsedPattern makeList(ParsedPattern p, Location loc, Annotations anno)
              throws BuildException {
          return pb.makeList((Pattern) p, (Locator) loc);
      }
  
      public ParsedPattern makeMixed(ParsedPattern p, Location loc, Annotations anno)
              throws BuildException {
          return pb.makeMixed((Pattern) p);
      }
  
      public ParsedPattern makeEmpty(Location loc, Annotations anno) {
          return pb.makeEmpty();
      }
  
      public ParsedPattern makeNotAllowed(Location loc, Annotations anno) {
          return pb.makeUnexpandedNotAllowed();
      }
  
      public ParsedPattern makeText(Location loc, Annotations anno) {
          return pb.makeText();
      }
  
      public ParsedPattern makeErrorPattern() {
          return pb.makeError();
      }
  
  //  public ParsedNameClass makeErrorNameClass() {
  //    return new ErrorNameClass();
  //  }
      public ParsedPattern makeAttribute(ParsedNameClass nc, ParsedPattern p, Location loc, Annotations anno)
              throws BuildException {
          return pb.makeAttribute((NameClass) nc, (Pattern) p, (Locator) loc);
      }
  
      public ParsedPattern makeElement(ParsedNameClass nc, ParsedPattern p, Location loc, Annotations anno)
              throws BuildException {
          return pb.makeElement((NameClass) nc, (Pattern) p, (Locator) loc);
      }
  
      private class DummyDataPatternBuilder implements DataPatternBuilder {
  
          public void addParam(String name, String value, Context context, String ns, Location loc, Annotations anno)
                  throws BuildException {
          }
  
          public ParsedPattern makePattern(Location loc, Annotations anno)
                  throws BuildException {
              return pb.makeError();
          }
  
          public ParsedPattern makePattern(ParsedPattern except, Location loc, Annotations anno)
                  throws BuildException {
              return pb.makeError();
          }
  
          public void annotation(ParsedElementAnnotation ea) {
          }
      }
  
      private static class ValidationContextImpl implements ValidationContext {
  
          private ValidationContext vc;
          private String ns;
  
          ValidationContextImpl(ValidationContext vc, String ns) {
              this.vc = vc;
              this.ns = ns.length() == 0 ? null : ns;
          }
  
          public String resolveNamespacePrefix(String prefix) {
              return prefix.length() == 0 ? ns : vc.resolveNamespacePrefix(prefix);
          }
  
          public String getBaseUri() {
              return vc.getBaseUri();
          }
  
          public boolean isUnparsedEntity(String entityName) {
              return vc.isUnparsedEntity(entityName);
          }
  
          public boolean isNotation(String notationName) {
              return vc.isNotation(notationName);
          }
      }
  
      private class DataPatternBuilderImpl implements DataPatternBuilder {
  
          private DatatypeBuilder dtb;
  
          DataPatternBuilderImpl(DatatypeBuilder dtb) {
              this.dtb = dtb;
          }
  
          public void addParam(String name, String value, Context context, String ns, Location loc, Annotations anno)
                  throws BuildException {
              try {
                  dtb.addParameter(name, value, new ValidationContextImpl(context, ns));
              } catch (DatatypeException e) {
                  String detail = e.getMessage();
                  int pos = e.getIndex();
                  String displayedParam;
                  if (pos == DatatypeException.UNKNOWN) {
                      displayedParam = null;
                  } else {
                      displayedParam = displayParam(value, pos);
                  }
                  if (displayedParam != null) {
                      if (detail != null) {
                          error("invalid_param_detail_display", detail, displayedParam, (Locator) loc);
                      } else {
                          error("invalid_param_display", displayedParam, (Locator) loc);
                      }
                  } else if (detail != null) {
                      error("invalid_param_detail", detail, (Locator) loc);
                  } else {
                      error("invalid_param", (Locator) loc);
                  }
              }
          }
  
          String displayParam(String value, int pos) {
              if (pos < 0) {
                  pos = 0;
              } else if (pos > value.length()) {
                  pos = value.length();
              }
              return localizer.message("display_param", value.substring(0, pos), value.substring(pos));
          }
  
          public ParsedPattern makePattern(Location loc, Annotations anno)
                  throws BuildException {
              try {
                  return pb.makeData(dtb.createDatatype());
              } catch (DatatypeException e) {
                  String detail = e.getMessage();
                  if (detail != null) {
                      error("invalid_params_detail", detail, (Locator) loc);
                  } else {
                      error("invalid_params", (Locator) loc);
                  }
                  return pb.makeError();
              }
          }
  
          public ParsedPattern makePattern(ParsedPattern except, Location loc, Annotations anno)
                  throws BuildException {
              try {
                  return pb.makeDataExcept(dtb.createDatatype(), (Pattern) except, (Locator) loc);
              } catch (DatatypeException e) {
  