use of io.lacuna.bifurcan.Map in project exist by eXist-db.
the class LoadXQueryModule method eval.
@Override
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
final String targetNamespace = args[0].getStringValue();
if (targetNamespace.isEmpty()) {
throw new XPathException(this, ErrorCodes.FOQM0001, "Target namespace must be a string with length > 0");
}
AnyURIValue[] locationHints = null;
String xqVersion = getXQueryVersion(context.getXQueryVersion());
AbstractMapType externalVars = new MapType(context);
Sequence contextItem = Sequence.EMPTY_SEQUENCE;
// evaluate options
if (getArgumentCount() == 2) {
final AbstractMapType map = (AbstractMapType) args[1].itemAt(0);
final Sequence locationHintsOption = map.get(OPTIONS_LOCATION_HINTS);
locationHints = new AnyURIValue[locationHintsOption.getItemCount()];
for (int i = 0; i < locationHints.length; i++) {
locationHints[i] = (AnyURIValue) locationHintsOption.itemAt(i).convertTo(Type.ANY_URI);
}
final Sequence versions = map.get(OPTIONS_XQUERY_VERSION);
if (!versions.isEmpty()) {
xqVersion = versions.itemAt(0).getStringValue();
}
final Sequence vars = map.get(OPTIONS_VARIABLES);
if (!vars.isEmpty()) {
if (vars.hasOne() && vars.itemAt(0).getType() == Type.MAP) {
externalVars = (AbstractMapType) vars.itemAt(0);
} else {
throw new XPathException(this, ErrorCodes.XPTY0004, "Option 'variables' must be a map");
}
}
contextItem = map.get(OPTIONS_CONTEXT_ITEM);
if (contextItem.getItemCount() > 1) {
throw new XPathException(this, ErrorCodes.XPTY0004, "Option 'context-item' must contain zero or one " + "items");
}
}
// create temporary context so main context is not polluted
final XQueryContext tempContext = new XQueryContext(context.getBroker().getBrokerPool(), context.getProfiler());
tempContext.setModuleLoadPath(context.getModuleLoadPath());
setExternalVars(externalVars, tempContext::declareGlobalVariable);
tempContext.prepareForExecution();
Module[] loadedModules = null;
try {
loadedModules = tempContext.importModule(targetNamespace, null, locationHints);
} catch (final XPathException e) {
if (e.getErrorCode() == ErrorCodes.XQST0059) {
// importModule may throw exception if no location is given and module cannot be resolved
throw new XPathException(this, ErrorCodes.FOQM0002, "Module with URI " + targetNamespace + " not found");
}
throw new XPathException(this, ErrorCodes.FOQM0003, "Error found when importing module: " + e.getMessage());
}
// not found, raise error
if (loadedModules == null || loadedModules.length == 0) {
throw new XPathException(this, ErrorCodes.FOQM0002, "Module with URI " + targetNamespace + " not found");
}
if (!xqVersion.equals(getXQueryVersion(tempContext.getXQueryVersion()))) {
throw new XPathException(ErrorCodes.FOQM0003, "Imported module has wrong XQuery version: " + getXQueryVersion(tempContext.getXQueryVersion()));
}
final IMap<AtomicValue, Sequence> variables = newLinearMap(null);
final IMap<AtomicValue, IMap<AtomicValue, Sequence>> functions = newLinearMap(null);
for (final Module loadedModule : loadedModules) {
loadedModule.setContextItem(contextItem);
setExternalVars(externalVars, loadedModule::declareVariable);
if (!loadedModule.isInternalModule()) {
// ensure variable declarations in the imported module are analyzed.
// unlike when using a normal import statement, this is not done automatically
((ExternalModule) loadedModule).analyzeGlobalVars();
}
getModuleVariables(loadedModule, variables);
getModuleFunctions(loadedModule, tempContext, functions);
}
final IMap<AtomicValue, Sequence> result = Map.from(io.lacuna.bifurcan.List.of(new Maps.Entry<>(RESULT_FUNCTIONS, new MapType(context, functions.mapValues((k, v) -> (Sequence) new MapType(context, v.forked(), Type.INTEGER)).forked(), Type.QNAME)), new Maps.Entry<>(RESULT_VARIABLES, new MapType(context, variables.forked(), Type.QNAME))));
return new MapType(context, result, Type.STRING);
}
Aggregations