package client.net.sf.saxon.ce.pattern;
import client.net.sf.saxon.ce.Configuration;
import client.net.sf.saxon.ce.om.Item;
import client.net.sf.saxon.ce.om.NamePool;
import client.net.sf.saxon.ce.om.NodeInfo;
import client.net.sf.saxon.ce.type.*;
import java.util.HashSet;
/**
* A NodeTest is a simple kind of pattern that enables a context-free test of whether
* a node has a particular
* name. There are several kinds of node test: a full name test, a prefix test, and an
* "any node of a given type" test, an "any node of any type" test, a "no nodes"
* test (used, e.g. for "@comment()").
*
* <p>As well as being used to support XSLT pattern matching, NodeTests act as predicates in
* axis steps, and also act as item types for type matching.</p>
*
* <p>For use in user-written application calling {@link NodeInfo#iterateAxis(byte, NodeTest)},
* it is possible to write a user-defined subclass of <code>NodeTest</code> that implements
* a single method, {@link #matches(int, int, int)}</p>
*
* @author Michael H. Kay
*/
public abstract class NodeTest implements ItemType {
/**
* Test whether a given item conforms to this type. This implements a method of the ItemType interface.
* @param item The item to be tested
* @param allowURIPromotion
* @param config
* @return true if the item is an instance of this type; false otherwise
*/
public boolean matchesItem(Item item, boolean allowURIPromotion, Configuration config) {
return item instanceof NodeInfo && matches((NodeInfo)item);
}
/**
* Get the type from which this item type is derived by restriction. This
* is the supertype in the XPath type heirarchy, as distinct from the Schema
* base type: this means that the supertype of xs:boolean is xs:anyAtomicType,
* whose supertype is item() (rather than xs:anySimpleType).
* <p>
* In fact the concept of "supertype" is not really well-defined, because the types
* form a lattice rather than a hierarchy. The only real requirement on this function
* is that it returns a type that strictly subsumes this type, ideally as narrowly
* as possible.
* @return the supertype, or null if this type is item()
* @param th the type hierarchy cache
*/
public ItemType getSuperType(TypeHierarchy th) {
return AnyNodeTest.getInstance();
// overridden for AnyNodeTest itself
}
/**
* Determine the default priority of this node test when used on its own as a Pattern
*/
public abstract double getDefaultPriority();
/**
* Get the primitive item type corresponding to this item type. For item(),
* this is Type.ITEM. For node(), it is Type.NODE. For specific node kinds,
* it is the value representing the node kind, for example Type.ELEMENT.
* For anyAtomicValue it is Type.ATOMIC_VALUE. For numeric it is Type.NUMBER.
* For other atomic types it is the primitive type as defined in XML Schema,
* except that INTEGER is considered to be a primitive type.
*/
public ItemType getPrimitiveItemType() {
int p = getPrimitiveType();
if (p == Type.NODE) {
return AnyNodeTest.getInstance();
} else {
return NodeKindTest.makeNodeKindTest(p);
}
}
/**
* Get the basic kind of object that this ItemType matches: for a NodeTest, this is the kind of node,
* or Type.Node if it matches different kinds of nodes.
* @return the node kind matched by this node test
*/
public int getPrimitiveType() {
return Type.NODE;
}
/**
* Get the name of the nodes matched by this nodetest, if it matches a specific name.
* Return -1 if the node test matches nodes of more than one name
*/
public int getFingerprint() {
return -1;
}
/**
* Determine whether this item type is atomic (that is, whether it can ONLY match
* atomic values)
*
* @return false: this is not ANY_ATOMIC_TYPE or a subtype thereof
*/
public boolean isAtomicType() {
return false;
}
/**
* Get the item type of the atomic values that will be produced when an item
* of this type is atomized (assuming that atomization succeeds)
*/
public AtomicType getAtomizedItemType() {
// This is overridden for a ContentTypeTest
return BuiltInAtomicType.ANY_ATOMIC;
}
/**
* Test whether this node test is satisfied by a given node. This method is only
* fully supported for a subset of NodeTests, because it doesn't provide all the information
* needed to evaluate all node tests. In particular (a) it can't be used to evaluate a node
* test of the form element(N,T) or schema-element(E) where it is necessary to know whether the
* node is nilled, and (b) it can't be used to evaluate a node test of the form
* document-node(element(X)). This in practice means that it is used (a) to evaluate the
* simple node tests found in the XPath 1.0 subset used in XML Schema, and (b) to evaluate
* node tests where the node kind is known to be an attribute.
* @param nodeKind The kind of node to be matched
* @param fingerprint identifies the expanded name of the node to be matched.
* The value should be -1 for a node with no name.
* @param annotation The actual content type of the node
*
*/
public abstract boolean matches(int nodeKind, int fingerprint, int annotation);
/**
* Test whether this node test is satisfied by a given node. This alternative
* method is used in the case of nodes where calculating the fingerprint is expensive,
* for example DOM or JDOM nodes. The default implementation calls the method
* {@link #matches(int, int, int)}
* @param node the node to be matched
*/
public boolean matches(NodeInfo node) {
return matches(node.getNodeKind(), node.getFingerprint(), node.getTypeAnnotation());
}
/**
* Get a mask indicating which kinds of nodes this NodeTest can match. This is a combination
* of bits: Type.ELEMENT for element nodes, Type.TEXT for text nodes, and so on. The default
* implementation indicates that nodes of all kinds are matched.
*/
public int getNodeKindMask() {
return 1<<Type.ELEMENT | 1<<Type.TEXT | 1<<Type.COMMENT | 1<<Type.PROCESSING_INSTRUCTION |
1<<Type.ATTRIBUTE | 1<<Type.NAMESPACE | 1<<Type.DOCUMENT;
}
/**
* Get the content type allowed by this NodeTest (that is, the type annotation of the matched nodes).
* Return AnyType if there are no restrictions. The default implementation returns AnyType.
*/
public SchemaType getContentType() {
return AnyType.getInstance();
}
/**
* Get the set of node names allowed by this NodeTest. This is returned as a set of Integer fingerprints.
* A null value indicates that all names are permitted (i.e. that there are no constraints on the node name.
* The default implementation returns null.
*/
public HashSet<Integer> getRequiredNodeNames() {
return null;
}
/**
* Determine whether the content type (if present) is nillable
* @return true if the content test (when present) can match nodes that are nilled
*/
public boolean isNillable() {
return false;
}
/**
* Display the type descriptor for diagnostics
*/
public String toString(NamePool pool) {
return toString();
}
}
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.