This is a long question, and quite complicated, at least to me.
I am trying to make a Java module, which is included in BaseX as a jar-file in `lib/custom`. The module contains one XQuery function:
named-entity-recognition($grammar as item(), $options as map(*)?) as function(item()) as node()*
This is a higher-order XQuery function that returns another (anonymous) XQuery function. The returned function is a parser (for named entities), similar to what the `invisible-xml` function returns.
The relevant part (I think) is the following Java function:
@Requires(Permission.NONE)
@Deterministic
@ContextDependent
publicFuncItem namedEntityRecognition(Object grammar, Map<String, String> options) throwsQueryException {
// Types of the arguments of the generated function.
finalVar[] generatedFunctionParameters= { newVarScope().addNew(newQNm("input"), SeqType.ITEM_O, queryContext, null) };
// Type of the generated function.
finalFuncType generatedFunctionType= FuncType.get(SeqType.NODE_ZM, generatedFunctionParameters[0].declType);
// The generated function.
NamedEntityRecognitionFunction nerf= newNamedEntityRecognitionFunction(grammar, options, generatedFunctionType, queryContext);
// Return a function item.
returnnewFuncItem(null, nerf, generatedFunctionParameters, AnnList.EMPTY, generatedFunctionType, generatedFunctionParameters.length, null);
}
The NamedEntityRecognitionFunction has a public Value value(final QueryContext qc) function that does the actual parsing. It starts by getting the value of its (only) parameter:
Value inputValue = arg(0).value(qc); // Java
The namedEntityRecognition function works fine when I use it like this (XQuery):
let $ner-parse := ner:named-entity-recognition($grammar, map{}) return $input => $ner-parse()
However, is does not work when the parsing function is put into a declared variable, like
declare variable $ner-parse as function(item()) as node()* := ner:named-entity-recognition($grammar,map{}); $input => $ner-parse()
In this case, the parameter value obtained by arg(0).value(qc) is null. When I debug this expression, it turns out that the parameter ($input) is not on the stack. The stack (which is qc.stack) is all nulls, and the begin and end indexes of the stack are both 0, meaning that the stack is empty..
This probably means that the query context of a local (let) variable is different from the query context of a global (declare) variable. Maybe I need to indicate that the namedEntityRecognition function returns a higher order function (but how)?
The code for this can be found at https://github.com/nverwer/basex-ner-xar.
If anyone can shed some light on this, that would be very much appreciated.
Best regards, Nico Verwer
I forgot to mention that I am using BaseX 11.5, and compile my code against the 11.5 tag in the github repo of BaseX..
Hello Gunther,
Thank you for your response. It gives me something to look at. I am currently working on 3 different projects, so I will probably continue with this at the end of the week.
the code in your project seems to have dependencies that cannot be resolved.
That is indeed a problem. I should make these dependencies available somehow. Maybe Github or Maven central.
Thanks for your example code. I will see if I can use it to reproduce (and fix?) my problem.
Best regards, Nico
Dear Gunther,
Thank you for the test code. I gradually changed it into my code that did not work, and found the problem:
private static Expr[] parameterVars(FuncType funcType, QueryContext queryContext) { Expr[] paramVars = new Expr[funcType.argTypes.length]; for (int i = 0; i < paramVars.length; ++i) { paramVars[i] = new VarRef(null, new VarScope().addNew(new QNm("arg"+i), funcType.argTypes[i], queryContext, null)); } return paramVars; }
I was trying to be clever, and derive the parameter VarRefs from the function type. But this cannot get to the original parameter names, and I invented new names; new QNm("arg"+i). But these names are different from the original names, and somehow this means that in some cases there will be no parameters on the stack.
What is strange / interesting, is that with the above code, the following works:
let $ner-parse := ner:named-entity-recognition($grammar, map{}) return $input => $ner-parse()
But using a declared variable does not work:
declare variable $ner-parse as function(item()) as node()* := ner:named-entity-recognition($grammar,map{}); $input => $ner-parse()
Now I make sure I use the same names for the generated VarRefs, and my function is always called with the parameter values on the stack.
Thanks for your help!
Best regards, Nico
basex-talk@mailman.uni-konstanz.de