package org.basex.query.func; import static org.basex.util.Token.*; import static org.basex.query.util.Err.*; import org.basex.query.QueryContext; import org.basex.query.QueryException; import org.basex.query.expr.Expr; import org.basex.query.item.Dbl; import org.basex.query.item.Item; import org.basex.query.item.Int; import org.basex.query.item.QNm; import org.basex.query.item.AtomType; import org.basex.query.item.Str; import org.basex.query.item.Type; import org.basex.query.item.Uri; import org.basex.query.iter.Iter; import org.basex.util.InputInfo; /** * Accessor functions. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public final class FNAcc extends StandardFunc { /** * Constructor. * @param ii input info * @param f function definition * @param e arguments */ public FNAcc(final InputInfo ii, final Function f, final Expr... e) { super(ii, f, e); } @Override public Item item(final QueryContext ctx, final InputInfo ii) throws QueryException { final Expr e = expr.length != 0 ? expr[0] : checkCtx(ctx); switch(sig) { case POSITION: return Int.get(ctx.pos); case LAST: return Int.get(ctx.size); case STRING: return string(e, ii, ctx); case NUMBER: return number(ctx.iter(e), ctx); case STRING_LENGTH: return Int.get(len(checkEStr(expr.length == 0 ? string(e, ii, ctx) : e, ctx))); case NORMALIZE_SPACE: return Str.get(norm(checkEStr(e, ctx))); case NAMESPACE_URI_FROM_QNAME: final Item it = e.item(ctx, input); return it == null ? null : Uri.uri(((QNm) checkType(it, AtomType.QNM)).uri()); default: return super.item(ctx, ii); } } /** * Converts the specified item to a string. * @param e expression * @param ii input info * @param ctx query context * @return double iterator * @throws QueryException query exception */ private Item string(final Expr e, final InputInfo ii, final QueryContext ctx) throws QueryException { final Item it = e.item(ctx, input); if(it == null) return Str.ZERO; final Type t = it.type; if(t.isFunction()) FNSTR.thrw(ii, this); return t == AtomType.STR ? it : Str.get(it.string(ii)); } /** * Converts the specified item to a double. * @param ir iterator * @param ctx query context * @return double iterator * @throws QueryException query exception */ private Item number(final Iter ir, final QueryContext ctx) throws QueryException { final Item it = ir.next(); if(it == null || ir.next() != null) return Dbl.NAN; final Type t = it.type; if(t.isFunction()) FNATM.thrw(input, this); try { return t == AtomType.DBL ? it : AtomType.DBL.cast(it, ctx, input); } catch(final QueryException ex) { return Dbl.NAN; } } @Override public boolean uses(final Use u) { return u == Use.CTX && expr.length == 0 || u == Use.POS && (sig == Function.POSITION || sig == Function.LAST) || super.uses(u); } }