Пример #1
0
  /**
   * Returns the found command or throws an exception.
   *
   * @param cmp possible completions
   * @param par parent command
   * @param <E> token type
   * @return index
   * @throws QueryException query exception
   */
  private <E extends Enum<E>> E consume(final Class<E> cmp, final Cmd par) throws QueryException {

    final String token = command(null);
    if (!suggest || token == null || !token.isEmpty()) {
      try {
        // return command reference; allow empty strings as input ("NULL")
        return Enum.valueOf(cmp, token == null ? "NULL" : token.toUpperCase(Locale.ENGLISH));
      } catch (final IllegalArgumentException ignore) {
      }
    }

    final Enum<?>[] alt = startWith(cmp, token);
    // handle empty input
    if (token == null) {
      if (par != null) throw help(alt, par);
      if (suggest) throw error(alt, EXPECTING_CMD);
      return null;
    }

    // output error for similar commands
    final byte[] name = uc(token(token));
    final Levenshtein ls = new Levenshtein();
    for (final Enum<?> s : startWith(cmp, null)) {
      final byte[] sm = uc(token(s.name()));
      if (ls.similar(name, sm) && Cmd.class.isInstance(s)) {
        throw error(alt, UNKNOWN_SIMILAR_X, name, sm);
      }
    }

    // show unknown command error or available command extensions
    throw par == null ? error(alt, UNKNOWN_TRY_X, token) : help(alt, par);
  }
Пример #2
0
 /**
  * Returns a key similar to the specified string, or {@code null}.
  *
  * @param key key to be found
  * @return similar key
  */
 public final synchronized String similar(final String key) {
   final byte[] name = token(key);
   final Levenshtein ls = new Levenshtein();
   for (final String prop : props.keySet()) {
     if (ls.similar(name, token(prop), 0)) return prop;
   }
   return null;
 }
Пример #3
0
  /**
   * Finds similar function names and throws an error message.
   *
   * @param name function name
   * @param ii input info
   * @throws QueryException query exception
   */
  public void funError(final QNm name, final InputInfo ii) throws QueryException {
    // find global function
    Functions.get().error(name, ii);

    // find similar local function
    final Levenshtein ls = new Levenshtein();
    final byte[] nm = lc(name.local());
    for (final UserFunc f : funcs) {
      if (ls.similar(nm, lc(f.name.local()), 0)) {
        FUNSIMILAR.thrw(ii, name.string(), f.name.string());
      }
    }
  }
Пример #4
0
 /**
  * Throws an error if one of the pre-defined functions is similar to the specified function name.
  *
  * @param name function name
  * @param ii input info
  * @throws QueryException query exception
  */
 public void error(final QNm name, final InputInfo ii) throws QueryException {
   // compare specified name with names of predefined functions
   final byte[] ln = name.local();
   final Levenshtein ls = new Levenshtein();
   for (int k = 1; k < size; ++k) {
     final int i = indexOf(keys[k], '}');
     final byte[] u = substring(keys[k], 2, i);
     final byte[] l = substring(keys[k], i + 1);
     if (eq(ln, l)) {
       final byte[] ur = name.uri();
       FUNSIMILAR.thrw(
           ii,
           new TokenBuilder(NSGlobal.prefix(ur)).add(':').add(l),
           new TokenBuilder(NSGlobal.prefix(u)).add(':').add(l));
     } else if (ls.similar(ln, l, 0)) {
       FUNSIMILAR.thrw(ii, name.string(), l);
     }
   }
 }
Пример #5
0
  /**
   * Performs a fuzzy search for the specified token with a maximum number of errors.
   *
   * @param token token to look for
   * @param k number of errors allowed
   * @return iterator
   */
  private synchronized IndexIterator fuzzy(final byte[] token, final int k) {
    FTIndexIterator it = FTIndexIterator.FTEMPTY;
    final int tokl = token.length, tl = tp.length;
    final int e = Math.min(tl - 1, tokl + k);
    int s = Math.max(1, tokl - k) - 1;

    while (++s <= e) {
      int p = tp[s];
      if (p == -1) continue;
      int t = s + 1, r = -1;
      while (t < tl && r == -1) r = tp[t++];
      while (p < r) {
        if (ls.similar(inY.readBytes(p, s), token, k)) {
          it = FTIndexIterator.union(iter(pointer(p, s), size(p, s), inZ, token), it);
        }
        p += s + ENTRY;
      }
    }
    return it;
  }
Пример #6
0
  /**
   * Returns an instance of a with the specified name and number of arguments, or {@code null}.
   *
   * @param name name of the function
   * @param args optional arguments
   * @param dyn compile-/run-time flag
   * @param ctx query context
   * @param ii input info
   * @return function instance
   * @throws QueryException query exception
   */
  public static TypedFunc get(
      final QNm name,
      final Expr[] args,
      final boolean dyn,
      final QueryContext ctx,
      final InputInfo ii)
      throws QueryException {

    // get namespace and local name
    // parse data type constructors
    if (eq(name.uri(), XSURI)) {
      final byte[] ln = name.local();
      final AtomType type = AtomType.find(name, false);
      if (type == null) {
        final Levenshtein ls = new Levenshtein();
        for (final AtomType t : AtomType.values()) {
          if (t.par != null
              && t != AtomType.NOT
              && t != AtomType.AAT
              && t != AtomType.BIN
              && ls.similar(lc(ln), lc(t.string()), 0))
            FUNSIMILAR.thrw(ii, name.string(), t.string());
        }
      }
      // no constructor function found, or abstract type specified
      if (type == null || type == AtomType.NOT || type == AtomType.AAT) {
        FUNCUNKNOWN.thrw(ii, name.string());
      }

      if (args.length != 1) FUNCTYPE.thrw(ii, name.string());
      final SeqType to = SeqType.get(type, Occ.ZERO_ONE);
      return TypedFunc.constr(new Cast(ii, args[0], to), to);
    }

    // pre-defined functions
    final StandardFunc fun = Functions.get().get(name, args, ii);
    if (fun != null) {
      if (!ctx.sc.xquery3 && fun.xquery3()) FEATURE30.thrw(ii);
      for (final Function f : Function.UPDATING) {
        if (fun.sig == f) {
          ctx.updating(true);
          break;
        }
      }
      return new TypedFunc(fun, fun.sig.type(args.length));
    }

    // user-defined function
    final TypedFunc tf = ctx.funcs.get(name, args, ii);
    if (tf != null) return tf;

    // Java function (only allowed with administrator permissions)
    final JavaMapping jf = JavaMapping.get(name, args, ctx, ii);
    if (jf != null) return TypedFunc.java(jf);

    // add user-defined function that has not been declared yet
    if (!dyn && FuncType.find(name) == null) return ctx.funcs.add(name, args, ii, ctx);

    // no function found
    return null;
  }
Пример #7
0
  /**
   * Returns the specified function.
   *
   * @param name name of the function
   * @param args optional arguments
   * @param dyn compile-/run-time flag
   * @param ctx query context
   * @param ii input info
   * @return function instance
   * @throws QueryException query exception
   */
  public TypedFunc get(
      final QNm name,
      final Expr[] args,
      final boolean dyn,
      final QueryContext ctx,
      final InputInfo ii)
      throws QueryException {

    // find function
    final byte[] uri = name.uri();
    final byte[] ln = name.local();

    // parse data type constructors
    if (eq(uri, XSURI)) {
      final Type type = AtomType.find(name, true);
      if (type == null || type == AtomType.NOT || type == AtomType.AAT) {
        final Levenshtein ls = new Levenshtein();
        for (final AtomType t : AtomType.values()) {
          if (t.par != null && ls.similar(lc(ln), lc(t.string()), 0))
            FUNSIMILAR.thrw(ii, name.string(), t.string());
        }
        FUNCUNKNOWN.thrw(ii, name.string());
      }
      if (args.length != 1) FUNCTYPE.thrw(ii, name.string());
      final SeqType to = SeqType.get(type, SeqType.Occ.ZO);
      return TypedFunc.constr(new Cast(ii, args[0], to), to);
    }

    // check Java functions - only allowed with administrator permissions
    if (startsWith(uri, JAVAPRE) && ctx.context.user.perm(User.ADMIN)) {
      final String c = string(substring(uri, JAVAPRE.length));
      // convert dashes to upper-case initials
      final TokenBuilder tb = new TokenBuilder().add(c).add('.');
      boolean dash = false;
      for (int p = 0; p < ln.length; p += cl(ln, p)) {
        final int ch = cp(ln, p);
        if (dash) {
          tb.add(Character.toUpperCase(ch));
          dash = false;
        } else {
          dash = ch == '-';
          if (!dash) tb.add(ch);
        }
      }

      final String java = tb.toString();
      final int i = java.lastIndexOf(".");
      final Class<?> cls = Reflect.find(java.substring(0, i));
      if (cls == null) FUNCJAVA.thrw(ii, java);
      final String mth = java.substring(i + 1);
      return TypedFunc.java(new JavaFunc(ii, cls, mth, args));
    }

    // check predefined functions
    final FuncCall fun = Functions.get().get(ln, uri, args, ctx, ii);
    if (fun != null) {
      for (final Function f : Function.UPDATING) {
        if (fun.def == f) {
          ctx.updating = true;
          break;
        }
      }
      return new TypedFunc(fun, fun.def.type(args.length));
    }

    // find local function
    for (int l = 0; l < func.length; ++l) {
      final QNm qn = func[l].name;
      if (eq(ln, qn.local()) && eq(uri, qn.uri()) && args.length == func[l].args.length)
        return new TypedFunc(add(ii, qn, l, args), FuncType.get(func[l]));
    }

    // add function call for function that has not been defined yet
    if (!dyn && Types.find(name, false) == null) {
      return new TypedFunc(
          add(ii, name, add(new UserFunc(ii, name, new Var[args.length], null, false), ii), args),
          FuncType.arity(args.length));
    }
    return null;
  }