package org.basex.query.func;
import org.basex.query.QueryContext;
import org.basex.query.QueryException;
import org.basex.query.expr.Expr;
import org.basex.query.item.Bln;
import org.basex.query.item.Item;
import org.basex.query.item.Value;
import org.basex.query.item.map.Map;
import org.basex.query.iter.Iter;
import org.basex.util.InputInfo;
/**
* Functions on maps.
*
* @author BaseX Team 2005-12, BSD License
* @author Leo Woerteler
*/
public final class FNMap extends StandardFunc {
/**
* Constructor.
* @param ii input info
* @param f function definition
* @param e arguments
*/
public FNMap(final InputInfo ii, final Function f, final Expr... e) {
super(ii, f, e);
}
@Override
public Iter iter(final QueryContext ctx) throws QueryException {
switch(sig) {
case _MAP_GET: return get(ctx).iter();
case _MAP_KEYS: return map(ctx).keys().iter();
default: return super.iter(ctx);
}
}
@Override
public Value value(final QueryContext ctx) throws QueryException {
switch(sig) {
case _MAP_GET: return get(ctx);
case _MAP_KEYS: return map(ctx).keys();
default: return super.value(ctx);
}
}
@Override
public Item item(final QueryContext ctx, final InputInfo ii)
throws QueryException {
switch(sig) {
case _MAP_NEW: return newMap(ctx, ii);
case _MAP_ENTRY: return entry(ctx, ii);
case _MAP_CONTAINS: return contains(ctx, ii);
case _MAP_SIZE: return map(ctx).mapSize();
case _MAP_REMOVE: return remove(ctx, ii);
case _MAP_COLLATION: return map(ctx).collation();
default: return super.item(ctx, ii);
}
}
/**
* Removes a key from a map.
* @param ctx query context
* @param ii input info
* @return new map with key removed from it
* @throws QueryException query exception
*/
private Map remove(final QueryContext ctx, final InputInfo ii)
throws QueryException {
return map(ctx).delete(expr[1].item(ctx, ii), ii);
}
/**
* Creates a new map containing the given key-value pair.
* @param ctx query context
* @param ii input info
* @return the singleton map
* @throws QueryException query exception
*/
private Map entry(final QueryContext ctx, final InputInfo ii)
throws QueryException {
return Map.EMPTY.insert(expr[0].item(ctx, ii), ctx.value(expr[1]), ii);
}
/**
* Creates a new map from a list of old ones.
* @param ctx query context
* @param ii input info
* @return new map
* @throws QueryException query exception
*/
private Map newMap(final QueryContext ctx, final InputInfo ii)
throws QueryException {
if(expr.length == 0) return Map.EMPTY;
if(expr.length == 2) checkColl(expr[1], ctx);
Map map = Map.EMPTY;
final Iter maps = expr[0].iter(ctx);
for(Item m; (m = maps.next()) != null;)
map = map.addAll(checkMap(m), ii);
return map;
}
/**
* Looks up the given key in the given map.
* @param ctx query context
* @return bound value or empty sequence if none exists
* @throws QueryException query exception
*/
private Value get(final QueryContext ctx) throws QueryException {
return map(ctx).get(expr[1].item(ctx, input), input);
}
/**
* Checks if the given key is contained in the given map.
* @param ctx query context
* @param ii input info
* @return result of check
* @throws QueryException query exception
*/
private Bln contains(final QueryContext ctx, final InputInfo ii)
throws QueryException {
return map(ctx).contains(expr[1].item(ctx, ii), ii);
}
/**
* Gets the map at the first argument position.
* @param ctx query context
* @return map
* @throws QueryException query exception
*/
private Map map(final QueryContext ctx) throws QueryException {
return checkMap(checkItem(expr[0], ctx));
}
@Override
public boolean uses(final Use u) {
return u == Use.X30 || super.uses(u);
}
}