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) && from==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();
}
if (from != null && from.matches(node, context)) {
return num;
}
SequenceIterator preceding =
node.iterateAxis(Axis.PRECEDING_OR_ANCESTOR, filter);
boolean found = false;
while (true) {
NodeInfo prev = (NodeInfo)preceding.next();
if (prev == null) {
break;
}
if (count.matches(prev, context)) {
if (num == 1 && memoNode != null && prev.isSameNodeInfo(memoNode)) {
num = memoNumber + 1;
found = true;
break;
}
num++;
}
if (from != null && from.matches(prev, context)) {
found = true;
break;
}
}
if (!found && from != null) {
// we've got to the end without matching the from pattern - result is ()
return 0;
}
if (memoise) {
Object[] memo = new Object[2];
memo[0] = node;
memo[1] = new Integer(num);
controller.setUserData(inst, "xsl:number", memo);
}
return num;
}