package org.basex.query.expr;
import static org.basex.query.QueryText.*;
import static org.basex.query.util.Err.*;
import java.io.IOException;
import org.basex.io.serial.Serializer;
import org.basex.query.QueryContext;
import org.basex.query.QueryException;
import org.basex.query.item.Empty;
import org.basex.query.item.Item;
import org.basex.query.item.SeqType;
import org.basex.query.item.Value;
import org.basex.query.iter.Iter;
import org.basex.util.InputInfo;
import org.basex.util.Token;
/**
* Treat as expression.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class Treat extends Single {
/**
* Constructor.
* @param ii input info
* @param e expression
* @param s sequence type
*/
public Treat(final InputInfo ii, final Expr e, final SeqType s) {
super(ii, e);
type = s;
}
@Override
public Expr comp(final QueryContext ctx) throws QueryException {
super.comp(ctx);
return checkUp(expr, ctx).isValue() ? optPre(value(ctx), ctx) : this;
}
@Override
public Iter iter(final QueryContext ctx) throws QueryException {
final Iter iter = ctx.iter(expr);
final Item it = iter.next();
if(it == null) {
if(type.mayBeZero()) return Empty.ITER;
throw XPEMPTY.thrw(input, description());
}
if(type.zeroOrOne()) {
if(iter.next() != null) NOTREATS.thrw(input, description(), type);
if(!it.type.instanceOf(type.type))
NOTREAT.thrw(input, description(), it.type, type);
return it.iter();
}
return new Iter() {
Item i = it;
@Override
public Item next() throws QueryException {
if(i == null) return null;
if(!i.type.instanceOf(type.type))
NOTREAT.thrw(input, description(), i.type, type);
final Item ii = i;
i = iter.next();
return ii;
}
};
}
@Override
public Value value(final QueryContext ctx) throws QueryException {
final Value val = ctx.value(expr);
final long len = val.size();
if(len == 0) {
if(type.mayBeZero()) return val;
throw XPEMPTY.thrw(input, description());
}
if(type.zeroOrOne()) {
if(len > 1) throw NOTREATS.thrw(input, description(), type);
final Item it = val.itemAt(0);
if(!it.type.instanceOf(type.type))
NOTREAT.thrw(input, description(), it.type, type);
return it;
}
for(long i = 0; i < len; i++) {
final Item it = val.itemAt(i);
if(!it.type.instanceOf(type.type))
NOTREAT.thrw(input, description(), it.type, type);
}
return val;
}
@Override
public void plan(final Serializer ser) throws IOException {
ser.openElement(this, TYP, Token.token(type.toString()));
expr.plan(ser);
ser.closeElement();
}
@Override
public String toString() {
return expr + " " + TREAT + ' ' + AS + ' ' + type;
}
}