001: package net.sf.saxon.pattern;
002:
003: import net.sf.saxon.om.Item;
004: import net.sf.saxon.om.NamePool;
005: import net.sf.saxon.om.NodeInfo;
006: import net.sf.saxon.sort.IntHashSet;
007: import net.sf.saxon.tinytree.TinyTree;
008: import net.sf.saxon.type.*;
009: import net.sf.saxon.expr.XPathContext;
010:
011: import java.io.Serializable;
012:
013: /**
014: * A NodeTest is a simple kind of pattern that enables a context-free test of whether
015: * a node has a particular
016: * name. There are several kinds of node test: a full name test, a prefix test, and an
017: * "any node of a given type" test, an "any node of any type" test, a "no nodes"
018: * test (used, e.g. for "@comment()").
019: *
020: * <p>As well as being used to support XSLT pattern matching, NodeTests act as predicates in
021: * axis steps, and also act as item types for type matching.</p>
022: *
023: * @author Michael H. Kay
024: */
025:
026: public abstract class NodeTest implements ItemType, Serializable {
027:
028: /**
029: * Test whether a given item conforms to this type. This implements a method of the ItemType interface.
030: * @param item The item to be tested
031: * @param context
032: * @return true if the item is an instance of this type; false otherwise
033: */
034:
035: public boolean matchesItem(Item item, XPathContext context) {
036: if (item instanceof NodeInfo) {
037: return matches((NodeInfo) item);
038: } else {
039: return false;
040: }
041: }
042:
043: /**
044: * Get the type from which this item type is derived by restriction. This
045: * is the supertype in the XPath type heirarchy, as distinct from the Schema
046: * base type: this means that the supertype of xs:boolean is xdt:anyAtomicType,
047: * whose supertype is item() (rather than xs:anySimpleType).
048: * <p>
049: * In fact the concept of "supertype" is not really well-defined, because the types
050: * form a lattice rather than a hierarchy. The only real requirement on this function
051: * is that it returns a type that strictly subsumes this type, ideally as narrowly
052: * as possible.
053: * @return the supertype, or null if this type is item()
054: * @param th
055: */
056:
057: public ItemType getSuperType(TypeHierarchy th) {
058: return AnyNodeTest.getInstance();
059: // overridden for AnyNodeTest itself
060: }
061:
062: /**
063: * Determine the default priority of this node test when used on its own as a Pattern
064: */
065:
066: public abstract double getDefaultPriority();
067:
068: /**
069: * Get the primitive item type corresponding to this item type. For item(),
070: * this is Type.ITEM. For node(), it is Type.NODE. For specific node kinds,
071: * it is the value representing the node kind, for example Type.ELEMENT.
072: * For anyAtomicValue it is Type.ATOMIC_VALUE. For numeric it is Type.NUMBER.
073: * For other atomic types it is the primitive type as defined in XML Schema,
074: * except that INTEGER is considered to be a primitive type.
075: */
076:
077: public ItemType getPrimitiveItemType() {
078: int p = getPrimitiveType();
079: if (p == Type.NODE) {
080: return AnyNodeTest.getInstance();
081: } else {
082: return NodeKindTest.makeNodeKindTest(p);
083: }
084: }
085:
086: /**
087: * Get the basic kind of object that this ItemType matches: for a NodeTest, this is the kind of node,
088: * or Type.Node if it matches different kinds of nodes.
089: * @return the node kind matched by this node test
090: */
091:
092: public int getPrimitiveType() {
093: return Type.NODE;
094: }
095:
096: /**
097: * Get the name of the nodes matched by this nodetest, if it matches a specific name.
098: * Return -1 if the node test matches nodes of more than one name
099: */
100:
101: public int getFingerprint() {
102: return -1;
103: }
104:
105: /**
106: * Determine whether this item type is atomic (that is, whether it can ONLY match
107: * atomic values)
108: *
109: * @return false: this is not ANY_ATOMIC_TYPE or a subtype thereof
110: */
111:
112: public boolean isAtomicType() {
113: return false;
114: }
115:
116: /**
117: * Get the item type of the atomic values that will be produced when an item
118: * of this type is atomized (assuming that atomization succeeds)
119: */
120:
121: public AtomicType getAtomizedItemType() {
122: // This is overridden for a ContentTypeTest
123: return Type.ANY_ATOMIC_TYPE;
124: }
125:
126: /**
127: * Test whether this node test is satisfied by a given node on a TinyTree. The node
128: * must be a document, element, text, comment, or processing instruction node.
129: * This method is provided
130: * so that when navigating a TinyTree a node can be rejected without
131: * actually instantiating a NodeInfo object.
132: * @param tree the TinyTree containing the node
133: * @param nodeNr the number of the node within the TinyTree
134: * @return true if the node matches the NodeTest, otherwise false
135: *
136: */
137:
138: public abstract boolean matches(TinyTree tree, int nodeNr);
139:
140: /**
141: * Test whether this node test is satisfied by a given node. This method is only
142: * fully supported for a subset of NodeTests, because it doesn't provide all the information
143: * needed to evaluate all node tests. In particular (a) it can't be used to evaluate a node
144: * test of the form element(N,T) or schema-element(E) where it is necessary to know whether the
145: * node is nilled, and (b) it can't be used to evaluate a node test of the form
146: * document-node(element(X)). This in practice means that it is used (a) to evaluate the
147: * simple node tests found in the XPath 1.0 subset used in XML Schema, and (b) to evaluate
148: * node tests where the node kind is known to be an attribute.
149: * @param nodeKind The kind of node to be matched
150: * @param fingerprint identifies the expanded name of the node to be matched.
151: * The value should be -1 for a node with no name.
152: * @param annotation The actual content type of the node
153: *
154: */
155:
156: public abstract boolean matches(int nodeKind, int fingerprint,
157: int annotation);
158:
159: /**
160: * Test whether this node test is satisfied by a given node. This alternative
161: * method is used in the case of nodes where calculating the fingerprint is expensive,
162: * for example DOM or JDOM nodes.
163: * @param node the node to be matched
164: */
165:
166: public abstract boolean matches(NodeInfo node);
167:
168: /**
169: * Get a mask indicating which kinds of nodes this NodeTest can match. This is a combination
170: * of bits: 1<<Type.ELEMENT for element nodes, 1<<Type.TEXT for text nodes, and so on.
171: */
172:
173: public abstract int getNodeKindMask();
174:
175: /**
176: * Get the content type allowed by this NodeTest (that is, the type annotation of the matched nodes).
177: * Return AnyType if there are no restrictions. The default implementation returns AnyType.
178: */
179:
180: public SchemaType getContentType() {
181: return AnyType.getInstance();
182: }
183:
184: /**
185: * Get the set of node names allowed by this NodeTest. This is returned as a set of Integer fingerprints.
186: * A null value indicates that all names are permitted (i.e. that there are no constraints on the node name.
187: * The default implementation returns null.
188: */
189:
190: public IntHashSet getRequiredNodeNames() {
191: return null;
192: }
193:
194: /**
195: * Display the type descriptor for diagnostics
196: */
197:
198: public String toString(NamePool pool) {
199: return toString();
200: }
201:
202: }
203:
204: //
205: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
206: // you may not use this file except in compliance with the License. You may obtain a copy of the
207: // License at http://www.mozilla.org/MPL/
208: //
209: // Software distributed under the License is distributed on an "AS IS" basis,
210: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
211: // See the License for the specific language governing rights and limitations under the License.
212: //
213: // The Original Code is: all this file.
214: //
215: // The Initial Developer of the Original Code is Michael H. Kay.
216: //
217: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
218: //
219: // Contributor(s): none.
220: //
|