Search in sources :

Example 1 with Map

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);
}
Also used : IEntry(io.lacuna.bifurcan.IEntry) AbstractMapType(org.exist.xquery.functions.map.AbstractMapType) java.util(java.util) Module(org.exist.xquery.Module) MapType.newLinearMap(org.exist.xquery.functions.map.MapType.newLinearMap) QName(org.exist.dom.QName) MapType(org.exist.xquery.functions.map.MapType) org.exist.xquery.value(org.exist.xquery.value) XQueryAST(org.exist.xquery.parser.XQueryAST) org.exist.xquery(org.exist.xquery) Maps(io.lacuna.bifurcan.Maps) ConsumerE(com.evolvedbinary.j8fu.function.ConsumerE) IMap(io.lacuna.bifurcan.IMap) Map(io.lacuna.bifurcan.Map) AbstractMapType(org.exist.xquery.functions.map.AbstractMapType) AbstractMapType(org.exist.xquery.functions.map.AbstractMapType) MapType(org.exist.xquery.functions.map.MapType) IMap(io.lacuna.bifurcan.IMap) IEntry(io.lacuna.bifurcan.IEntry) Module(org.exist.xquery.Module)

Aggregations

ConsumerE (com.evolvedbinary.j8fu.function.ConsumerE)1 IEntry (io.lacuna.bifurcan.IEntry)1 IMap (io.lacuna.bifurcan.IMap)1 Map (io.lacuna.bifurcan.Map)1 Maps (io.lacuna.bifurcan.Maps)1 java.util (java.util)1 QName (org.exist.dom.QName)1 org.exist.xquery (org.exist.xquery)1 Module (org.exist.xquery.Module)1 AbstractMapType (org.exist.xquery.functions.map.AbstractMapType)1 MapType (org.exist.xquery.functions.map.MapType)1 MapType.newLinearMap (org.exist.xquery.functions.map.MapType.newLinearMap)1 XQueryAST (org.exist.xquery.parser.XQueryAST)1 org.exist.xquery.value (org.exist.xquery.value)1