• 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

53.73
/exist-core/src/main/java/org/exist/xquery/functions/util/DescribeFunction.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 java.util.Iterator;
52

53
import org.apache.logging.log4j.LogManager;
54
import org.apache.logging.log4j.Logger;
55
import org.exist.dom.QName;
56
import org.exist.dom.memtree.DocumentImpl;
57
import org.exist.dom.memtree.MemTreeBuilder;
58
import org.exist.xquery.*;
59
import org.exist.xquery.Module;
60
import org.exist.xquery.value.FunctionParameterSequenceType;
61
import org.exist.xquery.value.FunctionReturnSequenceType;
62
import org.exist.xquery.value.Item;
63
import org.exist.xquery.value.Sequence;
64
import org.exist.xquery.value.SequenceType;
65
import org.exist.xquery.value.Type;
66
import org.xml.sax.helpers.AttributesImpl;
67

68
import javax.annotation.Nullable;
69
import javax.xml.XMLConstants;
70

71
/**
72
 * Describe a built-in function identified by its QName.
73
 * 
74
 * @author wolf
75
 */
76
public class DescribeFunction extends Function {
77
        
78
        protected static final Logger logger = LogManager.getLogger(DescribeFunction.class);
1✔
79

80
        public final static FunctionSignature signature =
1✔
81
                new FunctionSignature(
1✔
82
                        new QName("describe-function", UtilModule.NAMESPACE_URI, UtilModule.PREFIX),
1✔
83
                        "Describes a built-in function. Returns an element describing the " +
1✔
84
                        "function signature.",
85
                        new SequenceType[] {
1✔
86
                                new FunctionParameterSequenceType("function-name", Type.QNAME, Cardinality.EXACTLY_ONE, "The name of the function to get the signature of"),
1✔
87
                        },
88
                        new FunctionReturnSequenceType(Type.NODE, Cardinality.EXACTLY_ONE, "the signature of the function"),
1✔
89
                        "Use inspect:inspect-function#1 instead!");
1✔
90
        
91
        private final static QName ANNOTATION_QNAME = new QName("annotation", XMLConstants.NULL_NS_URI);
1✔
92
        private final static QName ANNOTATION_VALUE_QNAME = new QName("value", XMLConstants.NULL_NS_URI);
1✔
93
        
94
        public DescribeFunction(XQueryContext context) {
95
                super(context, signature);
1✔
96
        }
1✔
97
        
98
        @Override
99
        public Sequence eval(
100
                Sequence contextSequence,
101
                Item contextItem)
102
                throws XPathException {
103
                
104
                final String fname = getArgument(0).eval(contextSequence, contextItem).getStringValue();
1✔
105
                final QName qname;
106
                try {
107
                        qname = QName.parse(context, fname, context.getDefaultFunctionNamespace());
1✔
108
                } catch (final QName.IllegalQNameException e) {
1✔
109
                        throw new XPathException(this, ErrorCodes.XPST0081, "No namespace defined for prefix " + fname);
×
110
                }
111
                final String uri = qname.getNamespaceURI();
1✔
112

113
                context.pushDocumentContext();
1✔
114
                try {
115
                        final MemTreeBuilder builder = context.getDocumentBuilder();
1✔
116
                        final AttributesImpl attribs = new AttributesImpl();
1✔
117
                        attribs.addAttribute("", "name", "name", "CDATA", qname.getStringValue());
1✔
118
                        attribs.addAttribute("", "module", "module", "CDATA", uri);
1✔
119
                        final int nodeNr = builder.startElement("", "function", "function", attribs);
1✔
120

121
                        FunctionSignature signature;
122
                        @Nullable final Module[] modules = context.getModules(uri);
1✔
123
                        if (modules != null && modules.length > 0) {
1!
124
                                for (final Module module : modules) {
1✔
125
                                        final Iterator<FunctionSignature> i = module.getSignaturesForFunction(qname);
1✔
126
                                        while (i.hasNext()) {
1✔
127
                                                signature = i.next();
1✔
128
                                                writeSignature(signature, builder);
1✔
129
                                        }
130
                                }
131
                        } else {
1✔
132
                                final Iterator<FunctionSignature> i = context.getSignaturesForFunction(qname);
×
133
                                while (i.hasNext()) {
×
134
                                        signature = i.next();
×
135
                                        writeSignature(signature, builder);
×
136
                                }
137
                        }
138
                        builder.endElement();
1✔
139
                        return ((DocumentImpl) builder.getDocument()).getNode(nodeNr);
1✔
140
                } finally {
141
                        context.popDocumentContext();
1✔
142
                }
143
        }
144

145
        /**
146
         * @param signature
147
         * @param builder
148
         * @throws XPathException if an internal error occurs
149
         */
150
        private void writeSignature(FunctionSignature signature, MemTreeBuilder builder) throws XPathException {
151
                final AttributesImpl attribs = new AttributesImpl();
1✔
152
                attribs.addAttribute("", "arguments", "arguments", "CDATA", Integer.toString(signature.getArgumentCount()));
1✔
153
                builder.startElement("", "prototype", "prototype", attribs);
1✔
154
                attribs.clear();
1✔
155
                builder.startElement("", "signature", "signature", attribs);
1✔
156
                builder.characters(signature.toString());
1✔
157
                builder.endElement();
1✔
158
                
159
                writeAnnotations(signature, builder);
1✔
160
                
161
                if(signature.getDescription() != null) {
1!
162
                        builder.startElement("", "description", "description", attribs);
×
163

164
            final StringBuilder description = new StringBuilder();
×
165
            description.append(signature.getDescription());
×
166

167
            description.append("\n\n");
×
168
            
169
            final SequenceType[] argumentTypes = signature.getArgumentTypes();
×
170
            
171
            if(argumentTypes != null && argumentTypes.length>0){
×
172

173
                final StringBuilder args = new StringBuilder();
×
174
                int noArgs=0;
×
175
                
176
                for (final SequenceType argumentType : argumentTypes) {
×
177
                    if (argumentType instanceof FunctionParameterSequenceType fp) {
×
178
                        noArgs++;
×
179
                        args.append("$");
×
180
                        args.append(fp.getAttributeName());
×
181
                        args.append(" : ");
×
182
                        args.append(fp.getDescription());
×
183
                        args.append("\n");
×
184
                    }
185
                }
186

187
                // only add if there were good arguments
188
                if(noArgs>0){
×
189
                    description.append("Parameters:\n");
×
190
                    description.append(args);
×
191
                }
192
            }
193

194
            final SequenceType returnType = signature.getReturnType();
×
195
            if(returnType != null){             
×
196
                if (returnType instanceof FunctionReturnSequenceType fp) {
×
197
                    description.append("\n");
×
198
                    description.append("Returns ");
×
199
                    description.append(fp.getDescription());
×
200
                        description.append("\n");
×
201
                }
202

203
            }
204
            
205
            builder.characters(description.toString());
×
206
                        builder.endElement();
×
207
                }
208
        
209
                if (signature.getDeprecated() != null) {
1!
210
                        builder.startElement("", "deprecated", "deprecated", attribs);
×
211
                        builder.characters(signature.getDeprecated());
×
212
                        builder.endElement();
×
213
                }
214
        
215
                builder.endElement();
1✔
216
        }
1✔
217

218
        private void writeAnnotations(FunctionSignature signature, MemTreeBuilder builder) throws XPathException {
219
                final AttributesImpl attribs = new AttributesImpl();
1✔
220
                final Annotation[] annots = signature.getAnnotations();
1✔
221
                if (annots != null) {
1!
222
                        for (final Annotation annot : annots) {
1✔
223
                                attribs.clear();
1✔
224
                                attribs.addAttribute(null, "name", "name", "CDATA", annot.getName().getStringValue());
1✔
225
                                attribs.addAttribute(null, "namespace", "namespace", "CDATA", annot.getName().getNamespaceURI());
1✔
226
                                builder.startElement(ANNOTATION_QNAME, attribs);
1✔
227
                                final LiteralValue[] value = annot.getValue();
1✔
228
                                if (value != null) {
1!
229
                                        for (final LiteralValue literal : value) {
1!
230
                                                builder.startElement(ANNOTATION_VALUE_QNAME, null);
×
231
                                                builder.characters(literal.getValue().getStringValue());
×
232
                                                builder.endElement();
×
233
                                        }
234
                                }
235
                                builder.endElement();
1✔
236
                        }
237
                }
238
        }
1✔
239
}
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