/**
   * Check that any elements and attributes constructed or returned by this expression are
   * acceptable in the content model of a given complex type. It's always OK to say yes, since the
   * check will be repeated at run-time. The process of checking element and attribute constructors
   * against the content model of a complex type also registers the type of content expected of
   * those constructors, so the static validation can continue recursively.
   */
  public void checkPermittedContents(SchemaType parentType, StaticContext env, boolean whole)
      throws XPathException {
    int fp = nameCode & NamePool.FP_MASK;
    if (fp == StandardNames.XSI_TYPE
        || fp == StandardNames.XSI_SCHEMA_LOCATION
        || fp == StandardNames.XSI_NIL
        || fp == StandardNames.XSI_NO_NAMESPACE_SCHEMA_LOCATION) {
      return;
    }
    if (parentType instanceof SimpleType) {
      StaticError err =
          new StaticError(
              "Attribute "
                  + env.getNamePool().getDisplayName(nameCode)
                  + " is not permitted in the content model of the simple type "
                  + parentType.getDescription());
      err.setIsTypeError(true);
      err.setLocator(this);
      if (getHostLanguage() == Configuration.XSLT) {
        err.setErrorCode("XTTE1510");
      } else {
        err.setErrorCode("XQDY0027");
      }
      throw err;
    }
    SchemaType type;
    try {
      type = ((ComplexType) parentType).getAttributeUseType(fp);
    } catch (SchemaException e) {
      throw new StaticError(e);
    }
    if (type == null) {
      StaticError err =
          new StaticError(
              "Attribute "
                  + env.getNamePool().getDisplayName(nameCode)
                  + " is not permitted in the content model of the complex type "
                  + parentType.getDescription());
      err.setIsTypeError(true);
      err.setLocator(this);
      if (getHostLanguage() == Configuration.XSLT) {
        err.setErrorCode("XTTE1510");
      } else {
        err.setErrorCode("XQDY0027");
      }
      throw err;
    }
    if (type instanceof AnyType) {
      return;
    }

    try {
      select.checkPermittedContents(type, env, true);
      // TODO: does this allow for the fact that the content will be atomized?
    } catch (XPathException e) {
      if (e.getLocator() == null || e.getLocator() == e) {
        e.setLocator(this);
      }
      throw e;
    }
  }