* Enumerate the results of the expression
*/
public SequenceIterator iterate(XPathContext context) throws XPathException {
Controller controller = context.getController();
Item arg2;
try {
arg2 = argument[2].evaluateItem(context);
} catch (XPathException e) {
if ("XPDY0002".equals(e.getErrorCodeLocalPart())) {
dynamicError("Cannot call the key() function when there is no context item", "XTDE1270", context);
return null;
} else if ("XPDY0050".equals(e.getErrorCodeLocalPart())) {
dynamicError("In the key() function," +
" the node supplied in the third argument (or the context node if absent)" +
" must be in a tree whose root is a document node", "XTDE1270", context);
return null;
} else if ("XPTY0020".equals(e.getErrorCodeLocalPart())) {
dynamicError("Cannot call the key() function when the context item is an atomic value",
"XTDE1270", context);
return null;
}
throw e;
}
NodeInfo origin = (NodeInfo)arg2;
NodeInfo root = origin.getRoot();
if (root.getNodeKind() != Type.DOCUMENT) {
dynamicError("In the key() function," +
" the node supplied in the third argument (or the context node if absent)" +
" must be in a tree whose root is a document node", "XTDE1270", context);
return null;
}
DocumentInfo doc = (DocumentInfo)root;
KeyDefinitionSet selectedKeySet = staticKeySet;
if (selectedKeySet == null) {
String givenkeyname = argument[0].evaluateItem(context).getStringValue();
StructuredQName qName = null;
try {
qName = StructuredQName.fromLexicalQName(
givenkeyname, false,
controller.getConfiguration().getNameChecker(),
nsContext);
} catch (XPathException err) {
dynamicError("Invalid key name: " + err.getMessage(), "XTDE1260", context);
}
selectedKeySet = controller.getKeyManager().getKeyDefinitionSet(qName);
if (selectedKeySet == null) {
dynamicError("Key '" + givenkeyname + "' has not been defined", "XTDE1260", context);
return null;
}
}
// if (internal) {
// System.err.println("Using key " + fprint + " on doc " + doc);
// }
// If the second argument is a singleton, we evaluate the function
// directly; otherwise we recurse to evaluate it once for each Item
// in the sequence.
Expression expression = argument[1];
SequenceIterator allResults;
if (Cardinality.allowsMany(expression.getCardinality())) {
final XPathContext keyContext = context;
final DocumentInfo document = doc;
final KeyManager keyManager = controller.getKeyManager();
final KeyDefinitionSet keySet = selectedKeySet;
MappingFunction map = new MappingFunction() {
// Map a value to the sequence of nodes having that value as a key value
public SequenceIterator map(Item item) throws XPathException {
return keyManager.selectByKey(
keySet, document, (AtomicValue)item, keyContext);
}
};
SequenceIterator keys = argument[1].iterate(context);
SequenceIterator allValues = new MappingIterator(keys, map);
allResults = new DocumentOrderIterator(allValues, LocalOrderComparer.getInstance());
} else {
try {
AtomicValue keyValue = (AtomicValue)argument[1].evaluateItem(context);
if (keyValue == null) {
return EmptyIterator.getInstance();
}
KeyManager keyManager = controller.getKeyManager();
allResults = keyManager.selectByKey(selectedKeySet, doc, keyValue, context);
} catch (XPathException e) {
e.maybeSetLocation(this);
throw e;
}