• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

evolvedbinary / elemental / 982

29 Apr 2025 08:34PM UTC coverage: 56.409% (+0.007%) from 56.402%
982

push

circleci

adamretter
[feature] Improve README.md badges

28451 of 55847 branches covered (50.94%)

Branch coverage included in aggregate %.

77468 of 131924 relevant lines covered (58.72%)

0.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.21
/exist-core/src/main/java/org/exist/xquery/functions/util/FunctionFunction.java
1
/*
2
 * Elemental
3
 * Copyright (C) 2024, Evolved Binary Ltd
4
 *
5
 * admin@evolvedbinary.com
6
 * https://www.evolvedbinary.com | https://www.elemental.xyz
7
 *
8
 * Use of this software is governed by the Business Source License 1.1
9
 * included in the LICENSE file and at www.mariadb.com/bsl11.
10
 *
11
 * Change Date: 2028-04-27
12
 *
13
 * On the date above, in accordance with the Business Source License, use
14
 * of this software will be governed by the Apache License, Version 2.0.
15
 *
16
 * Additional Use Grant: Production use of the Licensed Work for a permitted
17
 * purpose. A Permitted Purpose is any purpose other than a Competing Use.
18
 * A Competing Use means making the Software available to others in a commercial
19
 * product or service that: substitutes for the Software; substitutes for any
20
 * other product or service we offer using the Software that exists as of the
21
 * date we make the Software available; or offers the same or substantially
22
 * similar functionality as the Software.
23
 *
24
 * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
25
 *       The original license header is included below.
26
 *
27
 * =====================================================================
28
 *
29
 * eXist-db Open Source Native XML Database
30
 * Copyright (C) 2001 The eXist-db Authors
31
 *
32
 * info@exist-db.org
33
 * http://www.exist-db.org
34
 *
35
 * This library is free software; you can redistribute it and/or
36
 * modify it under the terms of the GNU Lesser General Public
37
 * License as published by the Free Software Foundation; either
38
 * version 2.1 of the License, or (at your option) any later version.
39
 *
40
 * This library is distributed in the hope that it will be useful,
41
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
43
 * Lesser General Public License for more details.
44
 *
45
 * You should have received a copy of the GNU Lesser General Public
46
 * License along with this library; if not, write to the Free Software
47
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
48
 */
49
package org.exist.xquery.functions.util;
50

51
import org.apache.logging.log4j.LogManager;
52
import org.apache.logging.log4j.Logger;
53
import org.exist.dom.QName;
54
import org.exist.xquery.*;
55
import org.exist.xquery.Module;
56
import org.exist.xquery.util.Error;
57
import org.exist.xquery.util.Messages;
58
import org.exist.xquery.value.*;
59

60
import javax.annotation.Nullable;
61

62
/**
63
 * @author wolf
64
 */
65
public class FunctionFunction extends BasicFunction {
66
        
67
        protected static final Logger logger = LogManager.getLogger(FunctionFunction.class);
1✔
68
        protected static final FunctionParameterSequenceType functionName = new FunctionParameterSequenceType("name", Type.QNAME, Cardinality.EXACTLY_ONE, "The name of the function");
1✔
69
        protected static final FunctionParameterSequenceType arity = new FunctionParameterSequenceType("arity", Type.INTEGER, Cardinality.EXACTLY_ONE, "The arity of the function");
1✔
70
        protected static final FunctionReturnSequenceType result = new FunctionReturnSequenceType(Type.FUNCTION, Cardinality.EXACTLY_ONE, "the reference to the XQuery function");
1✔
71

72
    public final static FunctionSignature signature =
1✔
73
        new FunctionSignature(
1✔
74
            new QName("function", UtilModule.NAMESPACE_URI, UtilModule.PREFIX),
1✔
75
            "Creates a reference to an XQuery function which can later be called from util:call. " +
1✔
76
            "This allows for higher-order functions to be implemented in XQuery. A higher-order " +
77
            "function is a function that takes another function as argument. " +
78
            "The first argument represents the name of the function, which should be" +
79
            "a valid QName. The second argument is the arity (number of parameters) of " +
80
            "the function. If no function can be found that matches the name and arity, " +
81
            "an error is thrown. " +
82
            "Please note: the arguments to this function " +
83
            "have to be literals or need to be resolvable at compile time at least.",
84
            new SequenceType[] { functionName, arity },
1✔
85
            result
1✔
86
        );
1✔
87
    
88
    private FunctionCall resolvedFunction = null;
1✔
89

90
    public FunctionFunction(XQueryContext context) {
91
        super(context, signature);
1✔
92
    }
1✔
93

94
    public void analyze(AnalyzeContextInfo contextInfo) throws XPathException {
95
            super.analyze(contextInfo);
1✔
96
            final String funcName = getArgument(0).eval(null, null).getStringValue();
1✔
97
            final int arity = ((NumericValue)getArgument(1).eval(null, null).itemAt(0)).getInt();
1✔
98
            final FunctionCall funcCall = lookupFunction(funcName, arity);
1✔
99
            contextInfo.addFlag(SINGLE_STEP_EXECUTION);
1✔
100
            funcCall.analyze(contextInfo);
1✔
101
    }
1✔
102

103
        @Override
104
    public Sequence eval(Sequence[] args, Sequence contextSequence)
105
            throws XPathException {
106
            
107
            final String funcName = args[0].getStringValue();
1✔
108
            final int arity = ((NumericValue) args[1].itemAt(0)).getInt();
1✔
109
            this.resolvedFunction = lookupFunction(funcName, arity);
1✔
110
        return new FunctionReference(this, resolvedFunction);
1✔
111
    }
112

113
    private FunctionCall lookupFunction(String funcName, int arity) throws XPathException {
114
                // try to parse the qname
115
            QName qname;
116
            try {
117
                qname = QName.parse(context, funcName, context.getDefaultFunctionNamespace());
1✔
118
            } catch(final QName.IllegalQNameException e) {
1✔
119
                        throw new XPathException(this, ErrorCodes.XPST0081, "No namespace defined for prefix " + funcName);
×
120
            }
121
            
122
            // check if the function is from a module 
123
            @Nullable final Module[] modules = context.getModules(qname.getNamespaceURI());
1✔
124
            UserDefinedFunction func = null;
1✔
125
            if (modules == null || modules.length == 0) {
1!
126
                func = context.resolveFunction(qname, arity);
1✔
127
            } else {
1✔
128
                    for (final Module module : modules) {
×
129
                                func = ((ExternalModule)module).getFunction(qname, arity, context);
×
130
                                if (func != null) {
×
131
                                        if (module.isInternalModule()) {
×
132
                                                logger.error("Cannot create a reference to an internal Java function");
×
133
                                                throw new XPathException(this, "Cannot create a reference to an internal Java function");
×
134
                                        }
135

136
                                        break;
137
                                }
138
                        }
139
            }
140

141
        if (func == null) {
1!
142
                throw new XPathException(this, Messages.getMessage(Error.FUNC_NOT_FOUND, qname, Integer.toString(arity)));
×
143
        }
144

145
            final FunctionCall funcCall = new FunctionCall(context, func);
1✔
146
        funcCall.setLocation(line, column);
1✔
147
            return funcCall;
1✔
148
        }
149
    
150
    public void resetState(boolean postOptimization) {
151
            super.resetState(postOptimization);
1✔
152
            if (resolvedFunction != null)
1✔
153
                    {resolvedFunction.resetState(postOptimization);}
1✔
154
        if (!postOptimization)
1!
155
            {resolvedFunction = null;}
1✔
156
    }
1✔
157
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc