public static int getNumberAny(Expression inst, NodeInfo node, Pattern count,
Pattern from, XPathContext context, boolean hasVariablesInPatterns) throws XPathException {
NodeInfo memoNode = null;
int memoNumber = 0;
Controller controller = context.getController();
boolean memoise = (!hasVariablesInPatterns && count!=null);
if (memoise) {
Object[] memo = (Object[])controller.getUserData(inst, "xsl:number");
if (memo != null) {
memoNode = (NodeInfo)memo[0];
memoNumber = ((Integer)memo[1]).intValue();
}
}
int num = 0;
if (count==null) {
if (node.getFingerprint()==-1) { // unnamed node
count = new NodeTestPattern(NodeKindTest.makeNodeKindTest(node.getNodeKind()));
} else {
count = new NodeTestPattern(new NameTest(node));
}
num = 1;
} else if (count.matches(node, context)) {
num = 1;
}
// We use a special axis invented for the purpose: the union of the preceding and
// ancestor axes, but in reverse document order
// Pass part of the filtering down to the axis iterator if possible
NodeTest filter;
if (from==null) {
filter = count.getNodeTest();
} else if (from.getNodeKind()==Type.ELEMENT && count.getNodeKind()==Type.ELEMENT) {
filter = NodeKindTest.ELEMENT;
} else {
filter = AnyNodeTest.getInstance();
}
SequenceIterator preceding =
node.iterateAxis(Axis.PRECEDING_OR_ANCESTOR, filter);
while (true) {
NodeInfo prev = (NodeInfo)preceding.next();
if (prev == null) {
break;
}
if (from!=null && from.matches(prev, context)) {
return num;
}
if (count.matches(prev, context)) {
if (num==1 && memoNode!=null && prev.isSameNodeInfo(memoNode)) {
num = memoNumber + 1;
break;
}
num++;
}
}
if (memoise) {
Object[] memo = new Object[2];
memo[0] = node;
memo[1] = new Integer(num);
controller.setUserData(inst, "xsl:number", memo);
}
return num;
}