/** * Casts the current item. * * @param type expected type * @return cast item * @throws XQException xquery exception */ private long castItr(final Type type) throws XQException { opened(); try { final double d = it.dbl(null); if (!it.num() || d != (long) d) throw new BXQException(NUM, d); return type.e(it, ctx.ctx, null).itr(null); } catch (final QueryException ex) { throw new BXQException(ex); } }
@Override public Item ev(final InputInfo ii, final Item a, final Item b) throws QueryException { final Type ta = a.type, tb = b.type; final boolean t1 = ta.isNumber() || ta.isUntyped(); final boolean t2 = tb.isNumber() || tb.isUntyped(); if (t1 ^ t2) errNum(ii, !t1 ? a : b); if (t1 && t2) { final Type t = type(ta, tb); if (t == ITR) { final long l1 = a.itr(ii); final long l2 = b.itr(ii); checkRange(ii, l1 - (double) l2); return Int.get(l1 - l2); } if (t == DBL) return Dbl.get(a.dbl(ii) - b.dbl(ii)); if (t == FLT) return Flt.get(a.flt(ii) - b.flt(ii)); return Dec.get(a.dec(ii).subtract(b.dec(ii))); } if (ta == tb) { if (ta == DTM || ta == DAT || ta == TIM) return new DTd((Date) a, (Date) b); if (ta == YMD) return new YMd((YMd) a, (YMd) b, false); if (ta == DTD) return new DTd((DTd) a, (DTd) b, false); errNum(ii, !t1 ? a : b); } if (ta == DTM) return new Dtm((Date) a, checkDur(ii, b), false, ii); if (ta == DAT) return new Dat((Date) a, checkDur(ii, b), false, ii); if (ta == TIM) { if (tb != DTD) errType(ii, DTD, b); return new Tim((Tim) a, (DTd) b, false, ii); } errType(ii, ta, b); return null; }
@Override public Item ev(final InputInfo ii, final Item a, final Item b) throws QueryException { final Type ta = a.type, tb = b.type; if (ta == YMD) { if (!tb.isNumber()) errNum(ii, b); return new YMd((Dur) a, b.dbl(ii), true, ii); } if (tb == YMD) { if (!ta.isNumber()) errNum(ii, a); return new YMd((Dur) b, a.dbl(ii), true, ii); } if (ta == DTD) { if (!tb.isNumber()) errNum(ii, b); return new DTd((Dur) a, b.dbl(ii), true, ii); } if (tb == DTD) { if (!ta.isNumber()) errNum(ii, a); return new DTd((Dur) b, a.dbl(ii), true, ii); } final boolean t1 = ta.isNumber() || ta.isUntyped(); final boolean t2 = tb.isNumber() || tb.isUntyped(); if (t1 ^ t2) errType(ii, ta, b); if (t1 && t2) { final Type t = type(ta, tb); if (t == ITR) { final long l1 = a.itr(ii); final long l2 = b.itr(ii); checkRange(ii, l1 * (double) l2); return Int.get(l1 * l2); } if (t == DBL) return Dbl.get(a.dbl(ii) * b.dbl(ii)); if (t == FLT) return Flt.get(a.flt(ii) * b.flt(ii)); return Dec.get(a.dec(ii).multiply(b.dec(ii))); } errNum(ii, !t1 ? a : b); return null; }
@Override public Item ev(final InputInfo ii, final Item a, final Item b) throws QueryException { final Type ta = a.type, tb = b.type; if (ta == tb) { if (ta == YMD) { final BigDecimal bd = BigDecimal.valueOf(((YMd) b).ymd()); if (bd.equals(BigDecimal.ZERO)) DATEZERO.thrw(ii, info()); return Dec.get( BigDecimal.valueOf(((YMd) a).ymd()).divide(bd, 20, BigDecimal.ROUND_HALF_EVEN)); } if (ta == DTD) { final BigDecimal bd = ((DTd) b).dtd(); if (bd.equals(BigDecimal.ZERO)) DATEZERO.thrw(ii, info()); return Dec.get(((DTd) a).dtd().divide(bd, 20, BigDecimal.ROUND_HALF_EVEN)); } } if (ta == YMD) { if (!tb.isNumber()) errNum(ii, b); return new YMd((Dur) a, b.dbl(ii), false, ii); } if (ta == DTD) { if (!tb.isNumber()) errNum(ii, b); return new DTd((Dur) a, b.dbl(ii), false, ii); } checkNum(ii, a, b); final Type t = type(ta, tb); if (t == DBL) return Dbl.get(a.dbl(ii) / b.dbl(ii)); if (t == FLT) return Flt.get(a.flt(ii) / b.flt(ii)); final BigDecimal b1 = a.dec(ii); final BigDecimal b2 = b.dec(ii); if (b2.signum() == 0) DIVZERO.thrw(ii, a); final int s = Math.max(18, Math.max(b1.scale(), b2.scale())); return Dec.get(b1.divide(b2, s, BigDecimal.ROUND_HALF_EVEN)); }
/** * Checks if the specified items are numeric or untyped. * * @param ii input info * @param a first item * @param b second item * @throws QueryException query exception */ final void checkNum(final InputInfo ii, final Item a, final Item b) throws QueryException { final Type ta = a.type; final Type tb = b.type; if (!ta.isUntyped() && !ta.isNumber()) errNum(ii, a); if (!tb.isUntyped() && !tb.isNumber()) errNum(ii, b); }
/** * Returns a duration type error. * * @param ii input info * @param it item * @return duration * @throws QueryException query exception */ final Dur checkDur(final InputInfo ii, final Item it) throws QueryException { final Type ip = it.type; if (!ip.isDuration()) XPDUR.thrw(ii, info(), ip); if (ip == DUR) throw SIMPLDUR.thrw(ii, info(), it); return (Dur) it; }
/** * Returns the numeric type with the highest precedence. * * @param a first item type * @param b second item type * @return type */ static final Type type(final Type a, final Type b) { if (a == DBL || b == DBL || a.isUntyped() || b.isUntyped()) return DBL; if (a == FLT || b == FLT) return FLT; if (a == DEC || b == DEC) return DEC; return ITR; }