net.sf.saxon.pattern.CombinedNodeTest Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of saxon9 Show documentation
Show all versions of saxon9 Show documentation
Provides a basic XSLT 2.0 and XQuery 1.0 processor (W3C Recommendations,
January 2007). Command line interfaces and implementations of several
Java APIs (DOM, XPath, s9api) are also included.
The newest version!
package net.sf.saxon.pattern;
import net.sf.saxon.expr.Token;
import net.sf.saxon.om.NamePool;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.sort.IntHashSet;
import net.sf.saxon.tinytree.TinyTree;
import net.sf.saxon.type.*;
/**
* A CombinedNodeTest combines two nodetests using one of the operators
* union (=or), intersect (=and), difference (= "and not"). This arises
* when optimizing a union (etc) of two path expressions using the same axis.
* A CombinedNodeTest is also used to support constructs such as element(N,T),
* which can be expressed as (element(N,*) AND element(*,T))
*
* @author Michael H. Kay
*/
public class CombinedNodeTest extends NodeTest {
private NodeTest nodetest1;
private NodeTest nodetest2;
private int operator;
private boolean isGlobalComponentTest;
/**
* Create a NodeTest that combines two other node tests
* @param nt1 the first operand
* @param operator one of Token.UNION, Token.INTERSECT, Token.EXCEPT
* @param nt2 the second operand
*/
public CombinedNodeTest(NodeTest nt1, int operator, NodeTest nt2) {
nodetest1 = nt1;
this.operator = operator;
nodetest2 = nt2;
}
/**
* Indicate whether this CombinedNodeTest actually represents a SequenceType of the form
* schema-element(X) or schema-attribute(X). This information is used only when reconstructing a
* string representation of the NodeTest for diagnostics.
* @param global true if this test represents a schema-element or schema-attribute test
*/
public void setGlobalComponentTest(boolean global) {
isGlobalComponentTest = global;
}
/**
* Test whether this node test is satisfied by a given node.
* @param nodeType The type of node to be matched
@param fingerprint identifies the expanded name of the node to be matched.
*/
public boolean matches(int nodeType, int fingerprint, int annotation) {
switch (operator) {
case Token.UNION:
return nodetest1==null ||
nodetest2==null ||
nodetest1.matches(nodeType, fingerprint, annotation) ||
nodetest2.matches(nodeType, fingerprint, annotation);
case Token.INTERSECT:
return (nodetest1==null || nodetest1.matches(nodeType, fingerprint, annotation)) &&
(nodetest2==null || nodetest2.matches(nodeType, fingerprint, annotation));
case Token.EXCEPT:
return (nodetest1==null || nodetest1.matches(nodeType, fingerprint, annotation)) &&
!(nodetest2==null || nodetest2.matches(nodeType, fingerprint, annotation));
default:
throw new IllegalArgumentException("Unknown operator in Combined Node Test");
}
}
/**
* Test whether this node test is satisfied by a given node on a TinyTree. The node
* must be a document, element, text, comment, or processing instruction node.
* This method is provided
* so that when navigating a TinyTree a node can be rejected without
* actually instantiating a NodeInfo object.
*
* @param tree the TinyTree containing the node
* @param nodeNr the number of the node within the TinyTree
* @return true if the node matches the NodeTest, otherwise false
*/
public boolean matches(TinyTree tree, int nodeNr) {
switch (operator) {
case Token.UNION:
return nodetest1==null ||
nodetest2==null ||
nodetest1.matches(tree, nodeNr) ||
nodetest2.matches(tree, nodeNr);
case Token.INTERSECT:
return (nodetest1==null || nodetest1.matches(tree, nodeNr)) &&
(nodetest2==null || nodetest2.matches(tree, nodeNr));
case Token.EXCEPT:
return (nodetest1==null || nodetest1.matches(tree, nodeNr)) &&
!(nodetest2==null || nodetest2.matches(tree, nodeNr));
default:
throw new IllegalArgumentException("Unknown operator in Combined Node Test");
}
}
/**
* 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.
* @param node the node to be matched
*/
public boolean matches(NodeInfo node) {
switch (operator) {
case Token.UNION:
return nodetest1==null ||
nodetest2==null ||
nodetest1.matches(node) ||
nodetest2.matches(node);
case Token.INTERSECT:
return (nodetest1==null || nodetest1.matches(node)) &&
(nodetest2==null || nodetest2.matches(node));
case Token.EXCEPT:
return (nodetest1==null || nodetest1.matches(node)) &&
!(nodetest2==null || nodetest2.matches(node));
default:
throw new IllegalArgumentException("Unknown operator in Combined Node Test");
}
}
public String toString(NamePool pool) {
if (isGlobalComponentTest) {
if (nodetest1 instanceof SubstitutionGroupTest) {
return nodetest1.toString(pool);
} else {
final int kind = nodetest1.getPrimitiveType();
final String skind = (kind == Type.ELEMENT ? "schema-element(" : "schema-attribute(");
final String name = pool.getClarkName(nodetest1.getFingerprint());
return skind + name + ')';
}
} else if (nodetest1 instanceof NameTest && operator==Token.INTERSECT) {
int kind = nodetest1.getPrimitiveType();
String skind = (kind == Type.ELEMENT ? "element(" : "attribute(");
String content = "";
if (nodetest2 instanceof ContentTypeTest) {
final SchemaType schemaType = ((ContentTypeTest)nodetest2).getSchemaType();
content = ", " + pool.getClarkName(schemaType.getFingerprint());
}
String name = pool.getClarkName(nodetest1.getFingerprint());
return skind + name + content + ')';
} else {
String nt1 = (nodetest1==null ? "true()" : nodetest1.toString(pool));
String nt2 = (nodetest2==null ? "true()" : nodetest2.toString(pool));
return '(' + nt1 + ' ' + Token.tokens[operator] + ' ' + nt2 + ')';
}
}
public String toString() {
if (isGlobalComponentTest) {
if (nodetest1 instanceof SubstitutionGroupTest) {
return nodetest1.toString();
} else {
final int kind = nodetest1.getPrimitiveType();
final String skind = (kind == Type.ELEMENT ? "schema-element(" : "schema-attribute(");
final String name = nodetest1.toString();
return skind + name + ')';
}
} else if (nodetest1 instanceof NameTest && operator==Token.INTERSECT) {
int kind = nodetest1.getPrimitiveType();
String skind = (kind == Type.ELEMENT ? "element(" : "attribute(");
String content = "";
if (nodetest2 instanceof ContentTypeTest) {
final SchemaType schemaType = ((ContentTypeTest)nodetest2).getSchemaType();
content = ", " + schemaType.getFingerprint();
}
String name = nodetest1.toString();
return skind + name + content + ')';
} else {
String nt1 = (nodetest1==null ? "true()" : nodetest1.toString());
String nt2 = (nodetest2==null ? "true()" : nodetest2.toString());
return '(' + nt1 + ' ' + Token.tokens[operator] + ' ' + nt2 + ')';
}
}
/**
* Get the supertype of this type. This isn't actually a well-defined concept: the types
* form a lattice rather than a strict hierarchy.
* @param th the type hierarchy cache
*/
public ItemType getSuperType(TypeHierarchy th) {
switch (operator) {
case Token.UNION:
return Type.getCommonSuperType(nodetest1, nodetest2, th);
case Token.INTERSECT:
return nodetest1;
case Token.EXCEPT:
return nodetest1;
default:
throw new IllegalArgumentException("Unknown operator in Combined Node Test");
}
}
/**
* Get a mask indicating which kinds of nodes this NodeTest can match. This is a combination
* of bits: 1<
© 2015 - 2025 Weber Informatics LLC | Privacy Policy