package org.basex.query.path; import static org.basex.util.Token.*; import static org.basex.query.QueryText.*; import org.basex.data.Data; import org.basex.query.QueryContext; import org.basex.query.item.ANode; import org.basex.query.item.NodeType; import org.basex.query.item.QNm; /** * Name test. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public final class NameTest extends Test { /** Local name. */ public final byte[] ln; /** * Empty constructor ('*'). * @param att attribute flag */ public NameTest(final boolean att) { this(null, Name.ALL, att); } /** * Constructor. * @param nm name * @param t type of name test * @param att attribute flag */ public NameTest(final QNm nm, final Name t, final boolean att) { type = att ? NodeType.ATT : NodeType.ELM; ln = nm != null ? nm.local() : null; name = nm; test = t; } @Override public boolean comp(final QueryContext ctx) { // retrieve current data reference final Data data = ctx.data(); if(data == null) return true; // skip optimizations if several namespaces are defined in the database final byte[] ns = data.nspaces.globalNS(); if(ns == null) return true; // true if results can be expected boolean ok = true; if(test == Name.STD && !name.hasPrefix()) { // no results if default and database namespaces of elements are different ok = type == NodeType.ATT || ctx.sc.nsElem == null || eq(ns, ctx.sc.nsElem); if(ok) { // namespace is irrelevant or identical: ignore prefix to speed up test if(ns.length != 0) ctx.compInfo(OPTPREF, ln); test = Name.NAME; } } // check existence of tag/attribute names ok = ok && (test != Name.NAME || (type == NodeType.ELM ? data.tagindex : data.atnindex).id(ln) != 0); if(!ok) ctx.compInfo(OPTNAME, name); return ok; } @Override public boolean eval(final ANode node) { // only elements and attributes will yield results if(node.type != type) return false; switch(test) { // wildcard - accept all nodes case ALL: return true; // namespaces wildcard - check only name case NAME: return eq(ln, local(node.name())); // name wildcard - check only namespace case NS: return eq(name.uri(), node.update(tmpq).uri()); default: // check attributes, or check everything return type == NodeType.ATT && !name.hasPrefix() ? eq(ln, node.name()) : name.eq(node.update(tmpq)); } } @Override public String toString() { if(test == Name.ALL) return "*"; if(test == Name.NAME) return "*:" + string(name.string()); final String uri = name.uri().length == 0 || name.hasPrefix() ? "" : '{' + string(name.uri()) + '}'; return uri + (test == Name.NS ? "*" : string(name.string())); } }