package org.basex.query.up.expr;
import static org.basex.query.util.Err.*;
import static org.basex.query.QueryText.*;
import static org.basex.util.Token.*;
import org.basex.query.QueryContext;
import org.basex.query.QueryException;
import org.basex.query.expr.CAttr;
import org.basex.query.expr.CElem;
import org.basex.query.expr.CFrag;
import org.basex.query.expr.CPI;
import org.basex.query.expr.Expr;
import org.basex.query.item.DBNode;
import org.basex.query.item.Empty;
import org.basex.query.item.Item;
import org.basex.query.item.ANode;
import org.basex.query.item.NodeType;
import org.basex.query.item.QNm;
import org.basex.query.iter.Iter;
import org.basex.query.up.primitives.RenameNode;
import org.basex.util.Atts;
import org.basex.util.InputInfo;
import org.basex.util.Util;
/**
* Rename expression.
*
* @author BaseX Team 2005-12, BSD License
* @author Lukas Kircher
*/
public final class Rename extends Update {
/**
* Constructor.
* @param ii input info
* @param tg target expression
* @param n new name expression
*/
public Rename(final InputInfo ii, final Expr tg, final Expr n) {
super(ii, tg, n);
}
@Override
public Item item(final QueryContext ctx, final InputInfo ii)
throws QueryException {
final Iter t = ctx.iter(expr[0]);
final Item i = t.next();
// check target constraints
if(i == null) throw UPSEQEMP.thrw(input, Util.name(this));
if(t.next() != null) UPWRTRGTYP.thrw(input);
final CFrag ex;
if(i.type == NodeType.ELM) {
ex = new CElem(input, expr[1], null);
} else if(i.type == NodeType.ATT) {
ex = new CAttr(input, false, expr[1], Empty.SEQ);
} else if(i.type == NodeType.PI) {
ex = new CPI(input, expr[1], Empty.SEQ);
} else {
throw UPWRTRGTYP.thrw(input);
}
final QNm rename = ex.item(ctx, input).qname();
final ANode targ = (ANode) i;
// check namespace conflicts...
if(targ.type == NodeType.ELM || targ.type == NodeType.ATT) {
final byte[] rp = rename.prefix();
final byte[] ru = rename.uri();
final Atts at = targ.nsScope();
for(int a = 0, as = at.size(); a < as; a++) {
if(eq(at.name(a), rp) && !eq(at.string(a), ru)) UPNSCONFL.thrw(input);
}
}
final DBNode dbn = ctx.updates.determineDataRef(targ, ctx);
ctx.updates.add(new RenameNode(dbn.pre, dbn.data, input, rename), ctx);
return null;
}
@Override
public String toString() {
return RENAME + ' ' + NODE + ' ' + expr[0] + ' ' + AS + ' ' + expr[1];
}
}