Esempio n. 1
0
  /**
   * Optimizes descendant-or-self steps and static types.
   *
   * @param ctx query context
   */
  void optSteps(final QueryContext ctx) {
    boolean opt = false;
    Expr[] st = steps;
    for (int l = 1; l < st.length; ++l) {
      if (!(st[l - 1] instanceof Step && st[l] instanceof Step)) continue;

      final Step prev = (Step) st[l - 1];
      final Step curr = (Step) st[l];
      if (!prev.simple(DESCORSELF, false)) continue;

      if (curr.axis == CHILD && !curr.has(Flag.FCS)) {
        // descendant-or-self::node()/child::X -> descendant::X
        final int sl = st.length;
        final Expr[] tmp = new Expr[sl - 1];
        System.arraycopy(st, 0, tmp, 0, l - 1);
        System.arraycopy(st, l, tmp, l - 1, sl - l);
        st = tmp;
        curr.axis = DESC;
        opt = true;
      } else if (curr.axis == ATTR && !curr.has(Flag.FCS)) {
        // descendant-or-self::node()/@X -> descendant-or-self::*/@X
        prev.test = new NameTest(false);
        opt = true;
      }
    }
    if (opt) ctx.compInfo(OPTDESC);

    // set atomic type for single attribute steps to speedup predicate tests
    if (root == null && st.length == 1 && st[0] instanceof Step) {
      final Step curr = (Step) st[0];
      if (curr.axis == ATTR && curr.test.mode == Mode.STD) curr.type = SeqType.NOD_ZO;
    }
    steps = st;
  }
Esempio n. 2
0
  /**
   * Merges expensive descendant-or-self::node() steps.
   *
   * @param qc query context
   * @return original or new expression
   */
  private Expr mergeSteps(final QueryContext qc) {
    boolean opt = false;
    final int sl = steps.length;
    final ExprList stps = new ExprList(sl);
    for (int s = 0; s < sl; s++) {
      final Expr step = steps[s];
      // check for simple descendants-or-self step with succeeding step
      if (s < sl - 1 && step instanceof Step) {
        final Step curr = (Step) step;
        if (curr.simple(DESCORSELF, false)) {
          // check succeeding step
          final Expr next = steps[s + 1];
          // descendant-or-self::node()/child::X -> descendant::X
          if (simpleChild(next)) {
            ((Step) next).axis = DESC;
            opt = true;
            continue;
          }
          // descendant-or-self::node()/(X, Y) -> (descendant::X | descendant::Y)
          Expr e = mergeList(next);
          if (e != null) {
            steps[s + 1] = e;
            opt = true;
            continue;
          }
          // //(X, Y)[text()] -> (/descendant::X | /descendant::Y)[text()]
          if (next instanceof Filter && !next.has(Flag.FCS)) {
            final Filter f = (Filter) next;
            e = mergeList(f.root);
            if (e != null) {
              f.root = e;
              opt = true;
              continue;
            }
          }
        }
      }
      stps.add(step);
    }

    if (opt) {
      qc.compInfo(OPTDESC);
      return get(info, root, stps.finish());
    }
    return this;
  }