package org.basex.query.up.expr; import static org.basex.query.QueryText.*; import static org.basex.query.util.Err.*; import static org.basex.util.Token.*; import org.basex.query.QueryContext; import org.basex.query.QueryException; import org.basex.query.expr.Constr; import org.basex.query.expr.Expr; import org.basex.query.item.ANode; import org.basex.query.item.DBNode; import org.basex.query.item.FComm; import org.basex.query.item.FPI; import org.basex.query.item.Item; import org.basex.query.item.NodeType; import org.basex.query.item.Type; import org.basex.query.iter.Iter; import org.basex.query.iter.NodeCache; import org.basex.query.up.primitives.ReplaceElementContent; import org.basex.query.up.primitives.ReplaceNode; import org.basex.query.up.primitives.ReplaceValue; import org.basex.util.InputInfo; import org.basex.util.Util; /** * Replace expression. * * @author BaseX Team 2005-12, BSD License * @author Lukas Kircher */ public final class Replace extends Update { /** 'Value of' flag. */ private final boolean value; /** * Constructor. * @param ii input info * @param t target expression * @param r source expression * @param v replace value of */ public Replace(final InputInfo ii, final Expr t, final Expr r, final boolean v) { super(ii, t, r); value = v; } @Override public Item item(final QueryContext ctx, final InputInfo ii) throws QueryException { final Constr c = new Constr(ii, ctx).add(expr[1]); if(c.errAtt) UPNOATTRPER.thrw(input); if(c.duplAtt != null) UPATTDUPL.thrw(input, c.duplAtt); 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)); final Type tp = i.type; if(!(i instanceof ANode) || tp == NodeType.DOC || t.next() != null) UPTRGMULT.thrw(input); final ANode targ = (ANode) i; final DBNode dbn = ctx.updates.determineDataRef(targ, ctx); // replace node final NodeCache aList = c.atts; NodeCache list = c.children; if(value) { // replace value of node final byte[] txt = list.size() < 1 ? EMPTY : list.get(0).string(); if(tp == NodeType.COM) FComm.parse(txt, input); if(tp == NodeType.PI) FPI.parse(txt, input); ctx.updates.add(tp == NodeType.ELM ? new ReplaceElementContent(dbn.pre, dbn.data, input, txt) : new ReplaceValue(dbn.pre, dbn.data, input, txt), ctx); } else { final ANode par = targ.parent(); if(par == null) UPNOPAR.thrw(input, i); if(tp == NodeType.ATT) { // replace attribute node if(list.size() > 0) UPWRATTR.thrw(input); list = checkNS(aList, par, ctx); } else { // replace non-attribute node if(aList.size() > 0) UPWRELM.thrw(input); } // conforms to specification: insertion sequence may be empty ctx.updates.add(new ReplaceNode(dbn.pre, dbn.data, input, list), ctx); } return null; } @Override public String toString() { return REPLACE + (value ? ' ' + VALUEE + ' ' + OF : "") + ' ' + NODE + ' ' + expr[0] + ' ' + WITH + ' ' + expr[1]; } }