/** * 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 Value value(final QueryContext qc) throws QueryException { final ArrayList<User> users = qc.context.users.users(null, qc.context); final TokenList tl = new TokenList(users.size()); for (final User user : users) tl.add(user.name()); return StrSeq.get(tl); }
@Override public Iter iter(final QueryContext qc) throws QueryException { final int el = exprs.length; if (el == 0) { final TokenList tl = new TokenList(); for (final String s : qc.context.databases.listDBs()) tl.add(s); return StrSeq.get(tl).iter(); } final Data data = checkData(qc); final String path = string(exprs.length == 1 ? Token.EMPTY : toToken(exprs[1], qc)); final IntList il = data.resources.docs(path); final TokenList tl = data.resources.binaries(path); return new Iter() { final int is = il.size(), ts = tl.size(); int ip, tp; @Override public Str get(final long i) { return i < is ? Str.get(data.text(il.get((int) i), true)) : i < is + ts ? Str.get(tl.get((int) i - is)) : null; } @Override public Str next() { return ip < is ? get(ip++) : tp < ts ? get(ip + tp++) : null; } @Override public long size() { return is + ts; } }; }
@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); }
/** * Evaluates the tokenize function. * * @param ctx query context * @return function result * @throws QueryException query exception */ private Value tokenize(final QueryContext ctx) throws QueryException { final byte[] val = checkEStr(expr[0], ctx); final Pattern p = pattern(expr[1], expr.length == 3 ? expr[2] : null, ctx); if (p.matcher("").matches()) REGROUP.thrw(info); final TokenList tl = new TokenList(); final String str = string(val); if (!str.isEmpty()) { final Matcher m = p.matcher(str); int s = 0; while (m.find()) { tl.add(str.substring(s, m.start())); s = m.end(); } tl.add(str.substring(s, str.length())); } return StrSeq.get(tl); }
@Override public B64 item(final QueryContext qc, final InputInfo ii) throws QueryException { checkCreate(qc); final IOFile root = new IOFile(toPath(0, qc).toString()); final ArchOptions opts = toOptions(1, Q_OPTIONS, new ArchOptions(), qc); final Iter entries; if (exprs.length > 2) { entries = qc.iter(exprs[2]); } else { final TokenList tl = new TokenList(); for (final String file : root.descendants()) tl.add(file); entries = StrSeq.get(tl).iter(); } final String format = opts.get(ArchOptions.FORMAT); final int level = level(opts); if (!root.isDir()) throw FILE_NO_DIR_X.get(info, root); try (final ArchiveOut out = ArchiveOut.get(format.toLowerCase(Locale.ENGLISH), info)) { out.level(level); try { while (true) { Item en = entries.next(); if (en == null) break; en = checkElemToken(en); final IOFile file = new IOFile(root, string(en.string(info))); if (!file.exists()) throw FILE_NOT_FOUND_X.get(info, file); if (file.isDir()) throw FILE_IS_DIR_X.get(info, file); add(en, new B64(file.read()), out, level, qc); } } catch (final IOException ex) { throw ARCH_FAIL_X.get(info, ex); } return new B64(out.finish()); } }