package org.basex.query.item; import static org.basex.query.util.Err.*; import static org.basex.util.Token.*; import javax.xml.namespace.QName; import org.basex.query.QueryContext; import org.basex.query.QueryException; import org.basex.query.util.Err; import org.basex.util.InputInfo; import org.basex.util.Token; import org.basex.util.TokenBuilder; import org.basex.util.Util; /** * QName item. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public final class QNm extends Item { /** Namespace URI. */ private byte[] uri; /** Name with optional prefix. */ private byte[] name; /** Prefix index. */ private int pref; /** * Empty constructor. */ public QNm() { super(AtomType.QNM); name = EMPTY; } /** * Constructor. * @param n name */ public QNm(final byte[] n) { super(AtomType.QNM); name = n; pref = indexOf(n, ':'); } /** * Constructor. * @param n name * @param u namespace URI */ public QNm(final byte[] n, final byte[] u) { this(n); uri(u); } /** * Constructor, binding a statically known namespace. * If no namespace is found, the namespace uri is set to {@code null}. * @param n name * @param ctx query context */ public QNm(final byte[] n, final QueryContext ctx) { this(n); uri(ctx.sc.ns.uri(prefix())); } /** * Constructor for converting a Java QName. * @param qn qname */ public QNm(final QName qn) { this(token(qn.getPrefix().isEmpty() ? qn.getLocalPart() : qn.getPrefix() + ':' + qn.getLocalPart()), token(qn.getNamespaceURI())); } /** * Sets the URI of this QName. * @param u the uri to be set */ public void uri(final byte[] u) { uri = u == null ? null : norm(u); } /** * Returns the URI of this QName. * @return uri */ public byte[] uri() { return uri == null ? EMPTY : uri; } /** * Checks if the URI of this QName has been explicitly set. * @return result of check */ public boolean hasURI() { return uri != null; } @Override public byte[] string(final InputInfo ii) { return name; } /** * Returns the string value. * @return string value */ public byte[] string() { return name; } @Override public boolean bool(final InputInfo ii) throws QueryException { throw CONDTYPE.thrw(ii, type, this); } @Override public boolean eq(final InputInfo ii, final Item it) { // at this stage, item will always be of the same type return eq((QNm) it); } /** * Compares the specified item. * @param n name to be compared * @return result of check */ public boolean eq(final QNm n) { return n == this || Token.eq(local(), n.local()) && Token.eq(uri(), n.uri()); } @Override public int diff(final InputInfo ii, final Item it) throws QueryException { throw Err.diff(ii, it, this); } /** * Checks if the name contains a prefix. * @return result of check */ public boolean hasPrefix() { return pref != -1; } /** * Returns the prefix. * @return prefix */ public byte[] prefix() { return pref == -1 ? EMPTY : substring(name, 0, pref); } /** * Returns the local name. * @return local name */ public byte[] local() { return pref == -1 ? name : substring(name, pref + 1); } /** * Updates the values of this QName. This method is only called * to speed up internal operations. * @param n name * @param u URI */ void update(final byte[] n, final byte[] u) { name = n; pref = indexOf(name, ':'); uri = u; } @Override public QName toJava() { return new QName(Token.string(uri()), Token.string(local()), Token.string(prefix())); } /** * Returns the EQName notation. * @return full name */ public byte[] eqname() { return new TokenBuilder().add('"').add(Str.get(uri()).toString()). add("\":").add(local()).finish(); } @Override public int hash(final InputInfo ii) throws QueryException { return Token.hash(local()); } @Override public String toString() { return Util.info("\"%\"", name); } }