Search in sources :

Example 11 with FunctionReference

use of org.exist.xquery.value.FunctionReference in project exist by eXist-db.

the class ContentFunctions method eval.

@Override
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
    // is argument the empty sequence?
    if (args[0].isEmpty()) {
        return Sequence.EMPTY_SEQUENCE;
    }
    ContentExtraction ce = new ContentExtraction();
    if (isCalledAs("stream-content")) {
        /* binary content */
        BinaryValue binary = (BinaryValue) args[0].itemAt(0);
        /* callback function */
        FunctionReference ref = (FunctionReference) args[2].itemAt(0);
        Map<String, String> mappings = new HashMap<>();
        if (args[3].hasOne()) {
            NodeValue namespaces = (NodeValue) args[3].itemAt(0);
            parseMappings(namespaces, mappings);
        }
        return streamContent(ce, binary, args[1], ref, mappings, args[4]);
    } else {
        try {
            if (isCalledAs("get-metadata")) {
                context.pushDocumentContext();
                try {
                    final MemTreeBuilder builder = context.getDocumentBuilder();
                    builder.startDocument();
                    builder.startElement(new QName("html", XHTML_NS), null);
                    builder.startElement(new QName("head", XHTML_NS), null);
                    final QName qnMeta = new QName("meta", XHTML_NS);
                    final Metadata metadata = ce.extractMetadata((BinaryValue) args[0].itemAt(0));
                    for (final String name : metadata.names()) {
                        for (final String value : metadata.getValues(name)) {
                            final AttributesImpl attributes = new AttributesImpl();
                            attributes.addAttribute("", "name", "name", "string", name);
                            attributes.addAttribute("", "content", "content", "string", value);
                            builder.startElement(qnMeta, attributes);
                            builder.endElement();
                        }
                    }
                    builder.endElement();
                    builder.endElement();
                    builder.endDocument();
                    return builder.getDocument();
                } finally {
                    context.popDocumentContext();
                }
            } else {
                final DocumentBuilderReceiver builder = new DocumentBuilderReceiver();
                builder.setSuppressWhitespace(false);
                final Metadata metadata = ce.extractContentAndMetadata((BinaryValue) args[0].itemAt(0), (ContentHandler) builder);
                return (NodeValue) builder.getDocument();
            }
        } catch (IOException | SAXException | ContentExtractionException ex) {
            LOG.error(ex.getMessage(), ex);
            throw new XPathException(this, ex.getMessage(), ex);
        }
    }
}
Also used : ContentExtraction(org.exist.contentextraction.ContentExtraction) NodeValue(org.exist.xquery.value.NodeValue) HashMap(java.util.HashMap) XPathException(org.exist.xquery.XPathException) QName(org.exist.dom.QName) Metadata(org.apache.tika.metadata.Metadata) BinaryValue(org.exist.xquery.value.BinaryValue) IOException(java.io.IOException) DocumentBuilderReceiver(org.exist.dom.memtree.DocumentBuilderReceiver) ContentExtractionException(org.exist.contentextraction.ContentExtractionException) SAXException(org.xml.sax.SAXException) AttributesImpl(org.xml.sax.helpers.AttributesImpl) MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) FunctionReference(org.exist.xquery.value.FunctionReference)

Example 12 with FunctionReference

use of org.exist.xquery.value.FunctionReference in project exist by eXist-db.

the class FunSort method eval.

@Override
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
    Sequence seq = args[0];
    Collator collator = collator(args, 1);
    ArrayList<Sequence> keys = new ArrayList<>(seq.getItemCount());
    try (FunctionReference ref = function(args, 2)) {
        final Sequence[] refArgs = new Sequence[1];
        Item item;
        Sequence value;
        for (final SequenceIterator i = seq.iterate(); i.hasNext(); ) {
            item = i.nextItem();
            if (ref != null) {
                refArgs[0] = item.toSequence();
                value = ref.evalFunction(null, null, refArgs);
            } else {
                value = item.toSequence();
            }
            keys.add(Atomize.atomize(value));
        }
    }
    return sort(seq, keys, collator);
}
Also used : Item(org.exist.xquery.value.Item) SequenceIterator(org.exist.xquery.value.SequenceIterator) ArrayList(java.util.ArrayList) FunctionReference(org.exist.xquery.value.FunctionReference) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence) Collator(com.ibm.icu.text.Collator)

Example 13 with FunctionReference

use of org.exist.xquery.value.FunctionReference in project exist by eXist-db.

the class FunHigherOrderFun method eval.

@Override
public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException {
    Sequence result = new ValueSequence();
    if (isCalledAs("for-each")) {
        try (final FunctionReference ref = (FunctionReference) args[1].itemAt(0)) {
            ref.analyze(cachedContextInfo);
            if (funcRefHasDifferentArity(ref, 1)) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "The supplied function (" + ref.getStringValue() + ") has " + ref.getSignature().getArgumentCount() + " arguments - expected 1");
            }
            for (final SequenceIterator i = args[0].iterate(); i.hasNext(); ) {
                final Item item = i.nextItem();
                final Sequence r = ref.evalFunction(null, null, new Sequence[] { item.toSequence() });
                result.addAll(r);
            }
        }
    } else if (isCalledAs("filter")) {
        final FunctionReference refParam;
        final Sequence seq;
        // Hack: switch parameters for backwards compatibility
        if (Type.subTypeOf(args[1].getItemType(), Type.FUNCTION_REFERENCE)) {
            refParam = (FunctionReference) args[1].itemAt(0);
            seq = args[0];
        } else {
            refParam = (FunctionReference) args[0].itemAt(0);
            seq = args[1];
        }
        try (final FunctionReference ref = refParam) {
            ref.analyze(cachedContextInfo);
            if (funcRefHasDifferentArity(ref, 1)) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "The supplied function (" + ref.getStringValue() + ") has " + ref.getSignature().getArgumentCount() + " arguments - expected 1");
            }
            for (final SequenceIterator i = seq.iterate(); i.hasNext(); ) {
                final Item item = i.nextItem();
                final Sequence r = ref.evalFunction(null, null, new Sequence[] { item.toSequence() });
                // two pending tests in exist-core/src/test/xquery/xquery3/fnHigherOrderFunctions.xql
                if (r.effectiveBooleanValue()) {
                    result.add(item);
                }
            }
        }
    } else if (isCalledAs("fold-left")) {
        try (final FunctionReference ref = (FunctionReference) args[2].itemAt(0)) {
            ref.analyze(cachedContextInfo);
            if (funcRefHasDifferentArity(ref, 2)) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "The supplied function (" + ref.getStringValue() + ") has " + ref.getSignature().getArgumentCount() + " arguments - expected 2");
            }
            final Sequence seq = args[0];
            final Sequence zero = args[1];
            result = foldLeft(ref, zero, seq.iterate());
        }
    } else if (isCalledAs("fold-right")) {
        try (final FunctionReference ref = (FunctionReference) args[2].itemAt(0)) {
            ref.analyze(cachedContextInfo);
            if (funcRefHasDifferentArity(ref, 2)) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "The supplied function (" + ref.getStringValue() + ") has " + ref.getSignature().getArgumentCount() + " arguments - expected 2");
            }
            final Sequence zero = args[1];
            final Sequence seq = args[0];
            if (seq instanceof ValueSequence) {
                result = foldRightNonRecursive(ref, zero, ((ValueSequence) seq).iterateInReverse());
            } else if (seq instanceof RangeSequence) {
                result = foldRightNonRecursive(ref, zero, ((RangeSequence) seq).iterateInReverse());
            } else {
                result = foldRight(ref, zero, seq);
            }
        }
    } else if (isCalledAs("for-each-pair")) {
        try (final FunctionReference ref = (FunctionReference) args[2].itemAt(0)) {
            ref.analyze(cachedContextInfo);
            if (funcRefHasDifferentArity(ref, 2)) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "The supplied function (" + ref.getStringValue() + ") has " + ref.getSignature().getArgumentCount() + " arguments - expected 2");
            }
            final SequenceIterator i1 = args[0].iterate();
            final SequenceIterator i2 = args[1].iterate();
            while (i1.hasNext() && i2.hasNext()) {
                final Sequence r = ref.evalFunction(null, null, new Sequence[] { i1.nextItem().toSequence(), i2.nextItem().toSequence() });
                result.addAll(r);
            }
        }
    } else if (isCalledAs("apply")) {
        try (final FunctionReference ref = (FunctionReference) args[0].itemAt(0)) {
            ref.analyze(cachedContextInfo);
            final ArrayType array = (ArrayType) args[1].itemAt(0);
            if (funcRefHasDifferentArity(ref, array.getSize())) {
                throw new XPathException(this, ErrorCodes.FOAP0001, "Number of arguments supplied to fn:apply does not match function signature. Expected: " + ref.getSignature().getArgumentCount() + ", got: " + array.getSize());
            }
            final Sequence[] fargs = array.toArray();
            return ref.evalFunction(null, null, fargs);
        }
    }
    return result;
}
Also used : ArrayType(org.exist.xquery.functions.array.ArrayType) Item(org.exist.xquery.value.Item) SequenceIterator(org.exist.xquery.value.SequenceIterator) ValueSequence(org.exist.xquery.value.ValueSequence) FunctionReference(org.exist.xquery.value.FunctionReference) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence)

Example 14 with FunctionReference

use of org.exist.xquery.value.FunctionReference in project exist by eXist-db.

the class PartialFunctionApplication method createPartial.

private FunctionReference createPartial(Sequence contextSequence, Item contextItem, FunctionCall staticCall) throws XPathException {
    final FunctionSignature signature = staticCall.getSignature();
    final SequenceType[] paramTypes = signature.getArgumentTypes();
    // the parameters of the newly created inline function:
    // old params except the fixed ones
    final List<SequenceType> newParamTypes = new ArrayList<>();
    // the arguments to pass to the inner call
    final List<Expression> callArgs = new ArrayList<>();
    // parameter variables of the new inline function
    final List<QName> variables = new ArrayList<>();
    // the inline function
    final int argCount = staticCall.getArgumentCount();
    for (int i = 0; i < argCount; i++) {
        final Expression param = staticCall.getArgument(i);
        if (param instanceof Function.Placeholder) {
            // overloaded functions like concat may have an arbitrary number of arguments
            if (i < paramTypes.length) {
                newParamTypes.add(paramTypes[i]);
            } else // overloaded function: add last sequence type
            {
                newParamTypes.add(paramTypes[paramTypes.length - 1]);
            }
            // create local parameter variables
            final QName varName = new QName("vp" + i, XMLConstants.NULL_NS_URI);
            variables.add(varName);
            // the argument to the inner call is a variable ref
            final VariableReference ref = new VariableReference(context, varName);
            callArgs.add(ref);
        } else {
            // fixed argument: just compute the argument value
            try {
                param.analyze(cachedContextInfo);
                final Sequence seq = param.eval(contextSequence, contextItem);
                callArgs.add(new PrecomputedValue(context, seq));
            } catch (final XPathException e) {
                if (e.getLine() <= 0) {
                    e.setLocation(line, column, getSource());
                }
                // append location of the function call to the exception message:
                e.addFunctionCall(function.functionDef, this);
                throw e;
            }
        }
    }
    final SequenceType[] newParamArray = newParamTypes.toArray(new SequenceType[0]);
    final QName name = new QName(PARTIAL_FUN_PREFIX + hashCode(), XMLConstants.NULL_NS_URI);
    final FunctionSignature newSignature = new FunctionSignature(name, newParamArray, signature.getReturnType());
    final UserDefinedFunction func = new UserDefinedFunction(context, newSignature);
    func.setLocation(staticCall.getLine(), staticCall.getColumn());
    // add the created parameter variables to the function
    for (final QName varName : variables) {
        func.addVariable(varName);
    }
    final FunctionCall innerCall = new FunctionCall(staticCall);
    innerCall.setArguments(callArgs);
    func.setFunctionBody(innerCall);
    final FunctionCall newCall = new FunctionCall(context, func);
    newCall.setLocation(staticCall.getLine(), staticCall.getColumn());
    return new FunctionReference(newCall);
}
Also used : QName(org.exist.dom.QName) ArrayList(java.util.ArrayList) SequenceType(org.exist.xquery.value.SequenceType) Sequence(org.exist.xquery.value.Sequence) FunctionReference(org.exist.xquery.value.FunctionReference)

Aggregations

FunctionReference (org.exist.xquery.value.FunctionReference)14 Sequence (org.exist.xquery.value.Sequence)7 Item (org.exist.xquery.value.Item)5 ArrayList (java.util.ArrayList)4 XPathException (org.exist.xquery.XPathException)4 ValueSequence (org.exist.xquery.value.ValueSequence)4 IOException (java.io.IOException)3 EXistException (org.exist.EXistException)3 QName (org.exist.dom.QName)3 MemTreeBuilder (org.exist.dom.memtree.MemTreeBuilder)3 PermissionDeniedException (org.exist.security.PermissionDeniedException)3 BrokerPool (org.exist.storage.BrokerPool)3 SequenceIterator (org.exist.xquery.value.SequenceIterator)3 DocumentBuilderReceiver (org.exist.dom.memtree.DocumentBuilderReceiver)2 ClassLoaderSource (org.exist.source.ClassLoaderSource)2 Source (org.exist.source.Source)2 DBBroker (org.exist.storage.DBBroker)2 DatabaseConfigurationException (org.exist.util.DatabaseConfigurationException)2 NodeValue (org.exist.xquery.value.NodeValue)2 SAXException (org.xml.sax.SAXException)2