Пример #1
0
  /**
   * Adds a local function.
   *
   * @param fun function instance
   * @param ii input info
   * @return function id
   * @throws QueryException query exception
   */
  public int add(final UserFunc fun, final InputInfo ii) throws QueryException {

    final QNm name = fun.name;

    final byte[] uri = name.uri();
    if (uri.length == 0) FUNNONS.thrw(ii, name.string());

    if (NSGlobal.standard(uri)) {
      if (fun.declared) NAMERES.thrw(ii, name.string());
      funError(name, ii);
    }

    final byte[] ln = name.local();
    for (int l = 0; l < func.length; ++l) {
      final QNm qn = func[l].name;
      final byte[] u = qn.uri();
      final byte[] nm = qn.local();

      if (eq(ln, nm) && eq(uri, u) && fun.args.length == func[l].args.length) {
        // declare function that has been called before
        if (!func[l].declared) {
          func[l] = fun;
          return l;
        }
        // duplicate declaration
        FUNCDEFINED.thrw(ii, fun);
      }
    }
    // add function skeleton
    func = Array.add(func, fun);
    calls = Array.add(calls, new UserFuncCall[0]);
    return func.length - 1;
  }
Пример #2
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 (int n = 0; n < func.length; ++n) {
      if (ls.similar(nm, lc(func[n].name.local()), 0)) {
        FUNSIMILAR.thrw(ii, name.string(), func[n].name.string());
      }
    }
  }
Пример #3
0
  @Override
  public FElem item(final QueryContext ctx, final InputInfo ii) throws QueryException {

    final int s = prepare(ctx);
    try {
      // adds in-scope namespaces
      final Atts ns = new Atts();
      for (int i = 0; i < nspaces.size(); ++i) {
        ns.add(nspaces.name(i), nspaces.string(i));
      }

      // create and check QName
      final QNm nm = qname(ctx, ii);
      final byte[] cp = nm.prefix(), cu = nm.uri();
      if (eq(cp, XML) ^ eq(cu, XMLURI)) CEXML.thrw(input, cu, cp);
      if (eq(cu, XMLNSURI)) CEINV.thrw(input, cu);
      if (eq(cp, XMLNS)) CEINV.thrw(input, cp);

      // analyze element namespace unless it is "xml"
      if (!eq(cp, XML)) {
        // request namespace for the specified uri
        final byte[] uri = ctx.sc.ns.uri(cp);

        // check if element has a namespace
        if (nm.hasURI()) {
          // add to statically known namespaces
          if (!comp && (uri == null || !eq(uri, cu))) ctx.sc.ns.add(cp, cu);
          // add to in-scope namespaces
          if (!ns.contains(cp)) ns.add(cp, cu);
        } else {
          // element has no namespace: assign default uri
          nm.uri(uri);
        }
      }

      // create child and attribute nodes
      final Constr constr = new Constr(ii, ctx).add(expr);
      if (constr.errAtt) NOATTALL.thrw(input);
      if (constr.errNS) NONSALL.thrw(input);
      if (constr.duplAtt != null) (comp ? CATTDUPL : ATTDUPL).thrw(input, constr.duplAtt);
      if (constr.duplNS != null) DUPLNSCONS.thrw(input, constr.duplNS);

      // create node
      final FElem node = new FElem(nm, constr.children, constr.atts, ns);

      // add namespaces from constructor
      final Atts cns = constr.nspaces;
      for (int a = 0; a < cns.size(); ++a) {
        addNS(cns.name(a), cns.string(a), ns);
      }

      // update parent references of attributes and add namespaces
      for (int a = 0; a < constr.atts.size(); ++a) {
        constr.atts.get(a).parent(node);

        final ANode att = constr.atts.get(a);
        final QNm qnm = att.qname();
        // skip attributes without prefixes or URIs
        if (!qnm.hasPrefix() || !qnm.hasURI()) continue;

        // skip XML namespace
        final byte[] apref = qnm.prefix();
        if (eq(apref, XML)) continue;

        final byte[] auri = qnm.uri();
        final byte[] npref = addNS(apref, auri, ns);
        if (npref != null) {
          constr.atts.item[a] =
              new FAttr(new QNm(concat(npref, COLON, qnm.local()), auri), att.string());
        }
      }

      // add inherited namespaces
      final Atts stack = ctx.sc.ns.stack();
      for (int a = stack.size() - 1; a >= 0; a--) {
        final byte[] pref = stack.name(a);
        if (!ns.contains(pref)) ns.add(pref, stack.string(a));
      }

      // update parent references of children
      for (int c = 0; c < constr.children.size(); ++c) {
        final ANode child = constr.children.get(c).parent(node);
        // add inherited and remove unused namespaces
        if (child.type == NodeType.ELM) {
          if (ctx.sc.nsInherit) inherit(child, ns);
          if (!ctx.sc.nsPreserve) noPreserve(child);
          child.optimize();
        }
      }

      // return generated and optimized node
      return node.optimize();

    } finally {
      ctx.sc.ns.size(s);
    }
  }
Пример #4
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;
  }