@Override public final int diff(final Item it, final Collation coll, final InputInfo ii) throws QueryException { return it.type.isUntyped() ? coll == null ? Token.diff(string(), it.string(ii)) : coll.compare(string(), it.string(ii)) : -it.diff(this, coll, ii); }
/** * Checks if the predicates are successful for the specified item. * * @param it item to be checked * @param qc query context * @return result of check * @throws QueryException query exception */ protected final boolean preds(final Item it, final QueryContext qc) throws QueryException { if (preds.length == 0) return true; // set context value and position final Value cv = qc.value; try { if (qc.scoring) { double s = 0; for (final Expr p : preds) { qc.value = it; final Item i = p.test(qc, info); if (i == null) return false; s += i.score(); } it.score(Scoring.avg(s, preds.length)); } else { for (final Expr p : preds) { qc.value = it; if (p.test(qc, info) == null) return false; } } return true; } finally { qc.value = cv; } }
@Override public Value value(final QueryContext ctx) throws QueryException { final int o = (int) ctx.resources.output.size(); final Updates updates = ctx.resources.updates(); final ContextModifier tmp = updates.mod; final TransformModifier pu = new TransformModifier(); updates.mod = pu; try { for (final Let fo : copies) { final Iter ir = ctx.iter(fo.expr); Item i = ir.next(); if (!(i instanceof ANode) || ir.next() != null) throw UPCOPYMULT.get(fo.info, fo.var.name); // copy node to main memory data instance i = ((ANode) i).dbCopy(ctx.context.options); // add resulting node to variable ctx.set(fo.var, i, info); pu.addData(i.data()); } final Value v = ctx.value(expr[0]); if (!v.isEmpty()) throw BASEX_MOD.get(info); updates.prepare(); updates.apply(); return ctx.value(expr[1]); } finally { ctx.resources.output.size(o); updates.mod = tmp; } }
/** * Checks two keys for equality. * * @param its1 first keys * @param its2 second keys * @param coll collations * @return {@code true} if the compare as equal, {@code false} otherwise * @throws QueryException query exception */ private boolean eq(final Item[] its1, final Item[] its2, final Collation[] coll) throws QueryException { final int il = its1.length; for (int i = 0; i < il; i++) { final Item it1 = its1[i], it2 = its2[i]; if (it1 == null ^ it2 == null || it1 != null && !it1.equiv(it2, coll[i], info)) return false; } return true; }
@Override public final boolean eq( final Item it, final Collation coll, final StaticContext sc, final InputInfo ii) throws QueryException { return it.type.isUntyped() ? coll == null ? Token.eq(string(), it.string(ii)) : coll.compare(string(), it.string(ii)) == 0 : it.eq(this, coll, sc, ii); }
@Override public Item item(final QueryContext qc, final InputInfo ii) throws QueryException { final byte[] s; if (exprs.length == 0) { final Item it = ctxValue(qc).item(qc, info); if (it instanceof FItem) throw FISTRING_X.get(ii, it.type); s = it == null ? Token.EMPTY : it.string(ii); } else { s = toEmptyToken(arg(0, qc), qc); } return Int.get(Token.length(s)); }
/** * Compares results. * * @param expected expected result * @param returned returned result * @throws Exception exception */ private static void compare(final ItemList expected, final ItemList returned) throws Exception { // Compare response with expected result assertEquals("Different number of results", expected.size(), returned.size()); final long es = expected.size(); for (int e = 0; e < es; e++) { final Item exp = expected.get(e), ret = returned.get(e); if (!new DeepEqual().equal(exp, ret)) { final TokenBuilder tb = new TokenBuilder("Result ").addLong(e).add(" differs:\nReturned: "); tb.addExt(ret.serialize()).add("\nExpected: ").addExt(exp.serialize()); fail(tb.toString()); } } }
@Override public Item item(final QueryContext qc, final InputInfo ii) throws QueryException { final String form = string(toToken(exprs[0], qc)); final int es = exprs.length; final Object[] args = new Object[es - 1]; for (int e = 1; e < es; e++) { final Item it = exprs[e].item(qc, info); args[e - 1] = it == null ? null : it.type.isUntyped() ? string(it.string(info)) : it.toJava(); } try { return Str.get(String.format(form, args)); } catch (final RuntimeException ex) { throw ERRFORMAT_X_X.get(info, Util.className(ex), ex); } }
/** * Performs the assert-equals function. * * @param ctx query context * @return resulting value * @throws QueryException query exception */ private Item assertEquals(final QueryContext ctx) throws QueryException { final byte[] str = expr.length < 3 ? null : checkStr(expr[2], ctx); final Iter iter1 = ctx.iter(expr[0]), iter2 = ctx.iter(expr[1]); final Compare comp = new Compare(info); Item it1, it2; int c = 1; while (true) { it1 = iter1.next(); it2 = iter2.next(); final boolean empty1 = it1 == null, empty2 = it2 == null; if (empty1 && empty2) return null; if (empty1 || empty2 || !comp.deep(it1.iter(), it2.iter())) break; c++; } if (str != null) throw UNIT_MESSAGE.get(info, str); throw new UnitException(info, UNIT_ASSERT_EQUALS, it1, it2, c); }
/** * Creates annotation child elements. * * @param anns annotations * @param parent parent element * @param uri include uri * @throws QueryException query exception */ final void annotation(final AnnList anns, final FElem parent, final boolean uri) throws QueryException { for (final Ann ann : anns) { final FElem annotation = elem("annotation", parent); if (ann.sig != null) { annotation.add("name", ann.sig.id()); if (uri) annotation.add("uri", ann.sig.uri); } else { annotation.add("name", ann.name.string()); if (uri) annotation.add("uri", ann.name.uri()); } for (final Item it : ann.args) { final FElem literal = elem("literal", annotation); literal.add("type", it.type.toString()).add(it.string(null)); } } }
@Override public Item item(final QueryContext qc, final InputInfo ii) throws QueryException { // compute scoring if (qc.scoring) { double s = 0; boolean f = false; for (final Expr expr : exprs) { final Item it = expr.ebv(qc, info); f |= it.bool(ii); s += it.score(); } return Bln.get(f, Scoring.avg(s, exprs.length)); } // standard evaluation for (final Expr expr : exprs) { if (expr.ebv(qc, info).bool(ii)) return Bln.TRUE; } return Bln.FALSE; }
@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()); } }
/** * Returns a minimum or maximum item. * * @param cmp comparator * @param qc query context * @return resulting item * @throws QueryException query exception */ Item minmax(final OpV cmp, final QueryContext qc) throws QueryException { final Collation coll = toCollation(1, qc); final Iter iter = exprs[0].atomIter(qc, info); Item curr = iter.next(); if (curr == null) return null; // check if first item is comparable cmp.eval(curr, curr, coll, sc, info); // strings if (curr instanceof AStr) { for (Item it; (it = iter.next()) != null; ) { if (!(it instanceof AStr)) throw EXPTYPE_X_X_X.get(info, curr.type, it.type, it); final Type rt = curr.type, ri = it.type; if (cmp.eval(curr, it, coll, sc, info)) curr = it; if (rt != ri && curr.type == URI) curr = STR.cast(curr, qc, sc, info); } return curr; } // dates, durations, booleans, binary values if (curr instanceof ADate || curr instanceof Dur || curr instanceof Bin || curr.type == BLN) { for (Item it; (it = iter.next()) != null; ) { if (curr.type != it.type) throw EXPTYPE_X_X_X.get(info, curr.type, it.type, it); if (cmp.eval(curr, it, coll, sc, info)) curr = it; } return curr; } // numbers if (curr.type.isUntyped()) curr = DBL.cast(curr, qc, sc, info); for (Item it; (it = iter.next()) != null; ) { final Type type = numType(curr, it); if (cmp.eval(curr, it, coll, sc, info) || Double.isNaN(it.dbl(info))) curr = it; if (type != null) curr = (Item) type.cast(curr, qc, sc, info); } return curr; }
/** * Adds the specified entry to the output stream. * * @param entry entry descriptor * @param con contents * @param out output archive * @param level default compression level * @throws QueryException query exception * @throws IOException I/O exception */ private void add(final Item entry, final Item con, final ArchiveOut out, final int level) throws QueryException, IOException { // create new zip entry final String name = string(entry.string(info)); if (name.isEmpty()) ARCH_EMPTY.thrw(info); final ZipEntry ze = new ZipEntry(name); String en = null; // compression level byte[] lvl = null; if (entry instanceof ANode) { final ANode el = (ANode) entry; lvl = el.attribute(Q_LEVEL); // last modified final byte[] mod = el.attribute(Q_LAST_MOD); if (mod != null) { try { ze.setTime(new Int(new Dtm(mod, info)).itr()); } catch (final QueryException qe) { ARCH_DATETIME.thrw(info, mod); } } // encoding final byte[] enc = el.attribute(Q_ENCODING); if (enc != null) { en = string(enc); if (!Charset.isSupported(en)) ARCH_ENCODING.thrw(info, enc); } } // data to be compressed byte[] val = checkStrBin(con); if (con instanceof AStr && en != null && en != Token.UTF8) val = encode(val, en); try { out.level(lvl == null ? level : toInt(lvl)); } catch (final IllegalArgumentException ex) { ARCH_LEVEL.thrw(info, lvl); } out.write(ze, val); }
@Override public final int diff(final Item it, final Collation coll, final InputInfo ii) throws QueryException { return Token.diff( binary(ii), it instanceof Bin ? ((Bin) it).binary(ii) : decode(it.string(ii), ii)); }
/** * Checks if the specified item is a double. Returns the double or throws an exception. * * @param it item * @return double * @throws QueryException query exception */ protected final double toDouble(final Item it) throws QueryException { if (checkNoEmpty(it, AtomType.DBL).type.isNumberOrUntyped()) return it.dbl(info); throw numberError(this, it); }
/** * Checks if the specified non-empty item is a string. Returns its value as token or throws an * exception. * * @param it item to be checked * @return token * @throws QueryException query exception */ protected final byte[] toToken(final Item it) throws QueryException { final Type ip = it.type; if (ip.isStringOrUntyped()) return it.string(info); throw it instanceof FItem ? FIATOM_X.get(info, it.type) : castError(it, AtomType.STR, info); }
@Override public final Item test(final QueryContext qc, final InputInfo ii) throws QueryException { final Item it = ebv(qc, info); return (it instanceof ANum ? it.dbl(info) == qc.pos : it.bool(info)) ? it : null; }
@Override public Item item(final QueryContext qc, final InputInfo ii) throws QueryException { final Item it = unparsedText(qc, false, false); return it == null ? null : parse(it.string(info), false, qc, info); }
/** * Checks if the specified item is a boolean. Returns the boolean or throws an exception. * * @param it item be checked * @return boolean * @throws QueryException query exception */ protected final boolean toBoolean(final Item it) throws QueryException { final Type ip = checkNoEmpty(it, AtomType.BLN).type; if (ip == AtomType.BLN) return it.bool(info); if (ip.isUntyped()) return Bln.parse(it.string(info), info); throw castError(it, AtomType.BLN, info); }
/** * Checks if the specified item is a string or binary item. * * @param it item to be checked * @return byte array * @throws QueryException query exception */ protected final byte[] toBytes(final Item it) throws QueryException { if (checkNoEmpty(it).type.isStringOrUntyped()) return it.string(info); if (it instanceof Bin) return ((Bin) it).binary(info); throw STRBIN_X_X.get(info, it.type, it); }
@Override public final Item atomItem(final QueryContext qc, final InputInfo ii) throws QueryException { final Item it1 = item(qc, info); return it1 == null ? null : it1.atomItem(info); }
/** * Checks if the specified item yields a node or item. Returns the item or throws an exception. * * @param it item to be checked (can be {@code null}) * @return node or atomized item * @throws QueryException query exception */ protected final Item toNodeOrAtomItem(final Item it) throws QueryException { return it == null || it instanceof ANode ? it : it.atomItem(info); }
@Override public Iter iter(final QueryContext qc) throws QueryException { final Item it = item(qc, info); return it != null ? it.iter() : Empty.ITER; }
/** * Checks if the specified item is a number. Returns a token representation or throws an * exception. * * @param it item to be checked * @return number * @throws QueryException query exception */ protected final long toLong(final Item it) throws QueryException { final Type ip = checkNoEmpty(it, AtomType.ITR).type; if (ip.instanceOf(AtomType.ITR) || ip.isUntyped()) return it.itr(info); throw castError(it, AtomType.ITR, info); }
/** * Checks if the specified expression yields a float. Returns the float or throws an exception. * * @param ex expression to be evaluated * @param qc query context * @return float * @throws QueryException query exception */ protected final float toFloat(final Expr ex, final QueryContext qc) throws QueryException { final Item it = ex.atomItem(qc, info); if (checkNoEmpty(it, AtomType.FLT).type.isNumberOrUntyped()) return it.flt(info); throw numberError(this, it); }
/** * Checks if the specified, non-empty item is a double. Returns the double or throws an exception. * * @param it item to be checked * @return number * @throws QueryException query exception */ private ANum toNumber(final Item it) throws QueryException { if (it.type.isUntyped()) return Dbl.get(it.dbl(info)); if (it instanceof ANum) return (ANum) it; throw numberError(this, it); }