package org.basex.query.expr;
import static org.basex.query.QueryText.*;
import org.basex.query.QueryContext;
import org.basex.query.QueryException;
import org.basex.query.item.AtomType;
import org.basex.query.item.Item;
import org.basex.query.item.IntSeq;
import org.basex.query.item.SeqType;
import org.basex.query.item.Value;
import org.basex.query.item.SeqType.Occ;
import org.basex.query.iter.Iter;
import org.basex.query.iter.ItemCache;
import org.basex.util.InputInfo;
import org.basex.util.TokenBuilder;
/**
* Expression list.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class List extends Arr {
/**
* Constructor.
* @param ii input info
* @param l expression list
*/
public List(final InputInfo ii, final Expr... l) {
super(ii, l);
}
@Override
public Expr comp(final QueryContext ctx) throws QueryException {
for(int e = expr.length; --e >= 0;) expr[e] = expr[e].comp(ctx);
checkUp(ctx, expr);
// 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;
boolean v = true;
for(final Expr e : expr) {
// check if all expressions are values
v &= e.isValue();
// 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.ZM : Occ.OM);
}
// return cached integer sequence, cached values or self reference
return v ? type.type.instanceOf(AtomType.ITR) ?
optPre(IntSeq.get(expr, size, type.type), ctx) :
optPre(value(ctx), ctx) : this;
}
@Override
public Iter iter(final QueryContext ctx) {
return new Iter() {
Iter ir;
int e;
@Override
public Item next() throws QueryException {
while(true) {
if(ir == null) {
if(e == expr.length) return null;
ir = ctx.iter(expr[e++]);
}
final Item it = ir.next();
if(it != null) return it;
ir = null;
}
}
};
}
@Override
public Value value(final QueryContext ctx) throws QueryException {
final ItemCache ic = new ItemCache();
for(final Expr e : expr) ic.add(ctx.value(e));
return ic.value();
}
@Override
public boolean isVacuous() {
for(final Expr e : expr) if(!e.isVacuous()) return false;
return true;
}
@Override
public String toString() {
return new TokenBuilder(PAR1).addSep(expr, SEP).add(PAR2).toString();
}
}