Пример #1
0
  @Override
  public NodeIter iter(final QueryContext ctx) throws QueryException {
    final Value v = checkCtx(ctx);
    if (!v.type.isNode()) NODESPATH.thrw(input, AxisStep.this, v.type);
    final AxisIter ai = axis.iter((ANode) v);

    final NodeCache nc = new NodeCache();
    for (ANode n; (n = ai.next()) != null; ) if (test.eval(n)) nc.add(n.finish());

    // evaluate predicates
    for (final Expr p : preds) {
      ctx.size = nc.size();
      ctx.pos = 1;
      int c = 0;
      for (int n = 0; n < nc.size(); ++n) {
        ctx.value = nc.get(n);
        final Item i = p.test(ctx, input);
        if (i != null) {
          // assign score value
          nc.get(n).score(i.score());
          nc.item[c++] = nc.get(n);
        }
        ctx.pos++;
      }
      nc.size(c);
    }
    return nc;
  }
Пример #2
0
 /**
  * Returns the value of the specified attribute, or {@code null}.
  *
  * @param name attribute to be found
  * @return attribute value
  */
 public byte[] attribute(final QNm name) {
   final AxisIter ai = attributes();
   while (true) {
     final ANode node = ai.next();
     if (node == null) return null;
     if (node.qname().eq(name)) return node.atom();
   }
 }
Пример #3
0
 /**
  * Returns the uri for the specified prefix.
  *
  * @param pref prefix
  * @param ctx query context
  * @return uri
  */
 public final byte[] uri(final byte[] pref, final QueryContext ctx) {
   final Atts at = ns();
   if (at != null) {
     final int i = at.get(pref);
     if (i != -1) return at.val[i];
     final ANode n = parent();
     if (n != null) return n.uri(pref, ctx);
   }
   return pref.length == 0 ? Token.EMPTY : null;
 }
Пример #4
0
 @Override
 public URI getNodeUri() throws XQException {
   opened();
   if (!it.node()) throw new BXQException(NODE);
   final ANode node = (ANode) it;
   try {
     return new URI(Token.string(node.base()));
   } catch (final URISyntaxException ex) {
     throw new BXQException(ex.toString());
   }
 }
Пример #5
0
 /**
  * Removes unused namespaces.
  *
  * @param node to be modified
  */
 private static void noPreserve(final ANode node) {
   final Atts ns = node.namespaces();
   final byte[] pref = node.qname().prefix();
   for (int i = ns.size() - 1; i >= 0; i--) {
     boolean f = eq(ns.name(i), pref);
     final AxisIter atts = node.attributes();
     for (ANode it; f && (it = atts.next()) != null; ) {
       f |= eq(it.qname().prefix(), pref);
     }
     if (!f) ns.delete(i);
   }
 }
Пример #6
0
 /**
  * Inherits namespaces.
  *
  * @param node to be modified
  * @param nsp in-scope namespaces
  */
 private static void inherit(final ANode node, final Atts nsp) {
   final Atts ns = node.namespaces();
   for (int a = nsp.size() - 1; a >= 0; a--) {
     final byte[] pref = nsp.name(a);
     if (!ns.contains(pref)) ns.add(pref, nsp.string(a));
   }
 }
Пример #7
0
 /**
  * Returns the namespace hierarchy.
  *
  * @param nsInherit copy-namespaces inherit
  * @return namespaces [LW][LK] Namespaces: this isn't enough
  */
 public final Atts nsScope(final boolean nsInherit) {
   final Atts ns = new Atts();
   ANode n = this;
   do {
     final Atts nns = n.ns();
     if (!nsInherit) return nns;
     if (nns != null) {
       for (int a = nns.size - 1; a >= 0; a--) {
         final byte[] key = nns.key[a];
         if (!ns.contains(key)) ns.add(key, nns.val[a]);
       }
     }
     n = n.parent();
   } while (n != null && n.type == NodeType.ELM);
   return ns;
 }
Пример #8
0
 /**
  * Executes a prepared statement.
  *
  * @param stmt prepared statement
  * @param ctx query context
  * @return result
  * @throws QueryException query exception
  */
 private NodeCache executePrepStmt(final PreparedStatement stmt, final QueryContext ctx)
     throws QueryException {
   // Get parameters for prepared statement
   final ANode params = (ANode) checkType(expr[1].item(ctx, input), NodeType.ELM);
   if (!params.qname().eq(E_PARAMS)) PARWHICH.thrw(input, params.qname());
   try {
     final int placeCount = stmt.getParameterMetaData().getParameterCount();
     // Check if number of parameters equals number of place holders
     if (placeCount != countParams(params)) PARAMS.thrw(input);
     else setParameters(params.children(), stmt);
     final boolean result = stmt.execute();
     return result ? buildResult(stmt.getResultSet()) : new NodeCache();
   } catch (final SQLException ex) {
     throw SQLEXC.thrw(input, ex.getMessage());
   }
 }
Пример #9
0
  /**
   * Builds full-text information.
   *
   * @param nd node to be added
   * @return number of added nodes
   */
  TokenList build(final ANode nd) {
    // check full-text mode
    if (!(nd instanceof DBNode)) return null;

    // check if full-text data exists for the current node
    final DBNode node = (DBNode) nd;
    return build(node.data, node.pre, nd.string());
  }
Пример #10
0
  @Override
  public void prepare() throws QueryException {
    // build data with all documents, to prevent dirty reads
    md = new MemData(data);
    for (final Item d : docs) {
      final MemData docData;
      if (d.node()) {
        // adding a document node
        final ANode doc = (ANode) d;
        if (doc.ndType() != NodeType.DOC) UPDOCTYPE.thrw(input, doc);
        docData = new MemData(data);
        new DataBuilder(docData).build(doc);
      } else if (d.str()) {
        // adding file(s) from a path
        final String docpath = string(d.atom(input));
        final String nm = ctx.mprop.random(data.meta.name);
        final DirParser p = new DirParser(IO.get(docpath), ctx.prop);
        final MemBuilder b = new MemBuilder(nm, p, ctx.prop);
        try {
          docData = b.build();
        } catch (final IOException e) {
          throw DOCERR.thrw(input, docpath);
        }
      } else {
        throw STRNODTYPE.thrw(input, this, d.type);
      }
      md.insert(md.meta.size, -1, docData);
    }

    // set new names, if needed
    final IntList pres = md.doc();
    if (pres.size() == 1 && name != null) {
      // name is specified and a single document is added: set the name
      final byte[] nm = path == null ? name : concat(path, SLASH, name);
      md.update(pres.get(0), Data.DOC, nm);
    } else if (path != null) {
      // path is specified: replace the path of each new document
      for (int i = 0, is = pres.size(); i < is; i++) {
        final int d = pres.get(i);
        final byte[] old = md.text(d, true);
        final int p = lastIndexOf(old, '/');
        final byte[] nm = p < 0 ? old : subtoken(old, p + 1);
        md.update(d, Data.DOC, concat(path, SLASH, nm));
      }
    }
  }
Пример #11
0
  /**
   * Extracts connection options.
   *
   * @param arg argument with options
   * @param root expected root element
   * @param ctx query context
   * @return options
   * @throws QueryException query exception
   */
  private TokenObjMap<Object> options(final int arg, final QNm root, final QueryContext ctx)
      throws QueryException {
    // initialize token map
    final TokenObjMap<Object> tm = new TokenObjMap<Object>();
    // argument does not exist...
    if (arg >= expr.length) return tm;

    // empty sequence...
    final Item it = expr[arg].item(ctx, input);
    if (it == null) return tm;

    // XQuery map: convert to internal map
    if (it instanceof Map) return ((Map) it).tokenJavaMap(input);
    // no element: convert XQuery map to internal map
    if (!it.type().eq(SeqType.ELM)) throw NODFUNTYPE.thrw(input, this, it.type);

    // parse nodes
    ANode node = (ANode) it;
    if (!node.qname().eq(root)) PARWHICH.thrw(input, node.qname());

    // interpret query parameters
    final AxisIter ai = node.children();
    while ((node = ai.next()) != null) {
      final QNm qn = node.qname();
      if (!qn.uri().eq(Uri.uri(SQLURI))) PARWHICH.thrw(input, qn);
      tm.add(qn.ln(), node.children().next());
    }
    return tm;
  }
Пример #12
0
  /**
   * Returns the path nodes that are the result of this step.
   *
   * @param nodes initial path nodes
   * @param data data reference
   * @return resulting path nodes, or {@code null} if nodes cannot be evaluated
   */
  final ObjList<PathNode> nodes(final ObjList<PathNode> nodes, final Data data) {

    // skip steps with predicates or different namespaces
    if (preds.length != 0 || data.nspaces.globalNS() == null) return null;

    // check restrictions on node type
    int kind = -1, name = 0;
    if (test.type != null) {
      kind = ANode.kind(test.type);
      if (kind == Data.PI) return null;

      if (test.test == Name.NAME) {
        // element/attribute test (*:ln)
        final Names names = kind == Data.ATTR ? data.atnindex : data.tagindex;
        name = names.id(((NameTest) test).ln);
      } else if (test.test != null && test.test != Name.ALL) {
        // skip namespace and standard tests
        return null;
      }
    }

    // skip axes other than descendant, child, and attribute
    if (axis != Axis.ATTR
        && axis != Axis.CHILD
        && axis != Axis.DESC
        && axis != Axis.DESCORSELF
        && axis != Axis.SELF) return null;

    final ObjList<PathNode> tmp = new ObjList<PathNode>();
    for (final PathNode n : nodes) {
      if (axis == Axis.SELF || axis == Axis.DESCORSELF) {
        if (kind == -1 || kind == n.kind && (name == 0 || name == n.name)) {
          if (!tmp.contains(n)) tmp.add(n);
        }
      }
      if (axis != Axis.SELF) add(n, tmp, name, kind);
    }
    return tmp;
  }
Пример #13
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);
    }
  }
Пример #14
0
 /**
  * Adds children of a sub node.
  *
  * @param ch child nodes
  * @param nc node cache
  */
 protected final void addDesc(final AxisMoreIter ch, final NodeCache nc) {
   for (ANode n; (n = ch.next()) != null; ) {
     nc.add(n.finish());
     addDesc(n.children(), nc);
   }
 }
Пример #15
0
 /**
  * Sets the parameters of a prepared statement.
  *
  * @param params parameters
  * @param stmt prepared statement
  * @throws QueryException query exception
  */
 private void setParameters(final AxisMoreIter params, final PreparedStatement stmt)
     throws QueryException {
   int i = 0;
   for (ANode next; (next = params.next()) != null; ) {
     // Check name
     if (!next.qname().eq(E_PARAM)) PARWHICH.thrw(input, next.qname());
     final AxisIter attrs = next.attributes();
     byte[] paramType = null;
     boolean isNull = false;
     for (ANode attr; (attr = attrs.next()) != null; ) {
       // Attribute "type"
       if (eq(attr.nname(), TYPE)) paramType = attr.atom();
       // Attribute "null"
       else if (eq(attr.nname(), NULL))
         isNull = attr.atom() != null && Bln.parse(attr.atom(), input);
       // Not expected attribute
       else throw NOTEXPATTR.thrw(input, string(attr.nname()));
     }
     if (paramType == null) NOPARAMTYPE.thrw(input);
     final byte[] v = next.atom();
     isNull |= v.length == 0;
     setParam(++i, stmt, paramType, isNull ? null : string(v), isNull);
   }
 }
Пример #16
0
 /**
  * Counts the numbers of <sql:parameter/> elements.
  *
  * @param params element <sql:parameter/>
  * @return number of parameters
  */
 private long countParams(final ANode params) {
   final AxisIter ch = params.children();
   long c = ch.size();
   if (c == -1) do ++c; while (ch.next() != null);
   return c;
 }