@Override public Value value(final QueryContext qc) throws QueryException { final FItem getKey = checkArity(exprs[1], 1, qc); final long k = Math.min(toLong(exprs[2], qc), Integer.MAX_VALUE); if (k < 1) return Empty.SEQ; final Iter iter = exprs[0].iter(qc); final MinHeap<Item, Item> heap = new MinHeap<>( new Comparator<Item>() { @Override public int compare(final Item it1, final Item it2) { try { return OpV.LT.eval(it1, it2, sc.collation, sc, info) ? -1 : 1; } catch (final QueryException qe) { throw new QueryRTException(qe); } } }); try { for (Item it; (it = iter.next()) != null; ) { heap.insert(checkNoEmpty(getKey.invokeItem(qc, info, it)), it); if (heap.size() > k) heap.removeMin(); } } catch (final QueryRTException ex) { throw ex.getCause(); } final ValueBuilder vb = new ValueBuilder(); while (!heap.isEmpty()) vb.addFront(heap.removeMin()); return vb.value(); }
/** * Converts the specified result to an XQuery value. * * @param obj result object * @param qc query context * @param sc static context * @return value * @throws QueryException query exception */ public static Value toValue(final Object obj, final QueryContext qc, final StaticContext sc) throws QueryException { if (obj == null) return Empty.SEQ; if (obj instanceof Value) return (Value) obj; if (obj instanceof Iter) return ((Iter) obj).value(); // find XQuery mapping for specified type final Type type = type(obj); if (type != null) return type.cast(obj, qc, sc, null); // primitive arrays if (obj instanceof byte[]) return BytSeq.get((byte[]) obj); if (obj instanceof long[]) return IntSeq.get((long[]) obj, AtomType.ITR); if (obj instanceof char[]) return Str.get(new String((char[]) obj)); if (obj instanceof boolean[]) return BlnSeq.get((boolean[]) obj); if (obj instanceof double[]) return DblSeq.get((double[]) obj); if (obj instanceof float[]) return FltSeq.get((float[]) obj); // no array: return Java type if (!obj.getClass().isArray()) return new Jav(obj, qc); // empty array final int s = Array.getLength(obj); if (s == 0) return Empty.SEQ; // string array if (obj instanceof String[]) { final String[] r = (String[]) obj; final byte[][] b = new byte[r.length][]; for (int v = 0; v < s; v++) b[v] = token(r[v]); return StrSeq.get(b); } // character array if (obj instanceof char[][]) { final char[][] r = (char[][]) obj; final byte[][] b = new byte[r.length][]; for (int v = 0; v < s; v++) b[v] = token(new String(r[v])); return StrSeq.get(b); } // short array if (obj instanceof short[]) { final short[] r = (short[]) obj; final long[] b = new long[r.length]; for (int v = 0; v < s; v++) b[v] = r[v]; return IntSeq.get(b, AtomType.SHR); } // integer array if (obj instanceof int[]) { final int[] r = (int[]) obj; final long[] b = new long[r.length]; for (int v = 0; v < s; v++) b[v] = r[v]; return IntSeq.get(b, AtomType.INT); } // any other array (also nested ones) final Object[] objs = (Object[]) obj; final ValueBuilder vb = new ValueBuilder(objs.length); for (final Object o : objs) vb.add(toValue(o, qc, sc)); return vb.value(); }
@Override public Expr compile(final QueryContext ctx) throws QueryException { for (int e = 0; e < expr.length; e++) expr[e] = expr[e].compile(ctx); // compute number of results size = 0; for (final Expr e : expr) { final long c = e.size(); if (c == -1) { size = c; break; } size += c; } // evaluate sequence type type = SeqType.EMP; Value[] val = new Value[expr.length]; for (int v = 0; v < expr.length; v++) { final Expr e = expr[v]; // check if all expressions are values if (val != null) { if (e.isValue()) val[v] = (Value) e; else val = null; } // skip expression that will not add any results if (e.isEmpty()) continue; // evaluate sequence type final SeqType et = e.type(); type = type == SeqType.EMP ? et : SeqType.get( et.type == type.type ? et.type : AtomType.ITEM, et.mayBeZero() && type.mayBeZero() ? Occ.ZERO_MORE : Occ.ONE_MORE); } // return cached integer sequence, cached values or self reference Expr e = this; final int s = (int) size; if (val != null && size <= Integer.MAX_VALUE) { if (type.type == AtomType.STR) e = StrSeq.get(val, s); else if (type.type == AtomType.BLN) e = BlnSeq.get(val, s); else if (type.type == AtomType.FLT) e = FltSeq.get(val, s); else if (type.type == AtomType.DBL) e = DblSeq.get(val, s); else if (type.type == AtomType.DEC) e = DecSeq.get(val, s); else if (type.type == AtomType.BYT) e = BytSeq.get(val, s); else if (type.type.instanceOf(AtomType.ITR)) e = IntSeq.get(val, s, type.type); else { final ValueBuilder vb = new ValueBuilder(s); for (final Value v : val) vb.add(v); e = vb.value(); } } return optPre(e, ctx); }
/** * Binds the specified parameter to a variable. * * @param rxp parameter * @param args argument array * @param values values to be bound; the parameter's default value is assigned if the argument is * {@code null} or empty * @throws QueryException query exception */ private void bind(final RestXqParam rxp, final Expr[] args, final String... values) throws QueryException { final Value val; if (values == null || values.length == 0) { val = rxp.value; } else { final ValueBuilder vb = new ValueBuilder(); for (final String s : values) vb.add(new Atm(s)); val = vb.value(); } bind(rxp.name, args, val); }
@Override public Item item(final QueryContext qc, final InputInfo ii) throws QueryException { final Iter ir = iter(qc); final Item it = ir.next(); if (it == null || ir.size() == 1) return it; final Item n = ir.next(); if (n != null) { final ValueBuilder vb = new ValueBuilder().add(it).add(n); if (ir.next() != null) vb.add(Str.get(DOTS)); throw SEQFOUND_X.get(info, vb.value()); } return it; }
/** * Returns a parameter. * * @param value value * @param name name * @param declared variable declaration flags * @return parameter * @throws QueryException HTTP exception */ private RestXqParam param(final Value value, final QNm name, final boolean[] declared) throws QueryException { // [CG] RESTXQ: allow identical field names? final long vs = value.size(); if (vs < 2) error(ANN_PARAMS, "%", name.string(), 2); // name of parameter final String key = toString(value.itemAt(0), name); // variable template final QNm qnm = checkVariable(toString(value.itemAt(1), name), declared); // default value final ValueBuilder vb = new ValueBuilder(); for (int v = 2; v < vs; v++) vb.add(value.itemAt(v)); return new RestXqParam(qnm, key, vb.value()); }
@Override public Value value(final QueryContext qc) throws QueryException { final FItem f = checkArity(exprs[1], 1, qc); final Iter iter = exprs[0].iter(qc); Item it = iter.next(); if (it == null) return Empty.SEQ; final Value v1 = f.invokeValue(qc, info, it); it = iter.next(); if (it == null) return v1; final ValueBuilder vb = new ValueBuilder().add(v1); do { vb.add(f.invokeValue(qc, info, it)); } while ((it = iter.next()) != null); return vb.value(); }
@Override public final Item ebv(final QueryContext qc, final InputInfo ii) throws QueryException { final Item it; if (seqType().zeroOrOne()) { it = item(qc, info); } else { final Iter ir = iter(qc); it = ir.next(); if (it != null && !(it instanceof ANode)) { final Item n = ir.next(); if (n != null) { final ValueBuilder vb = new ValueBuilder().add(it).add(n); if (ir.next() != null) vb.add(Str.get(DOTS)); throw EBV_X.get(info, vb.value()); } } } return it == null ? Bln.FALSE : it; }
@Override public Value value(final QueryContext ctx) throws QueryException { final ValueBuilder vb = new ValueBuilder(); for (final Expr e : expr) vb.add(ctx.value(e)); return vb.value(); }
@Override public Value value(final QueryContext qc) { final ValueBuilder vb = new ValueBuilder(); for (final Object k : System.getenv().keySet()) vb.add(Str.get(k.toString())); return vb.value(); }