• 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

72.34
/exist-core/src/main/java/org/exist/xquery/FunctionDSL.java
1
/*
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
package org.exist.xquery;
25

26
import org.exist.dom.QName;
27
import org.exist.xquery.value.FunctionParameterSequenceType;
28
import org.exist.xquery.value.FunctionReturnSequenceType;
29
import org.exist.xquery.value.Type;
30

31
import java.util.Arrays;
32
import java.util.stream.Stream;
33

34
/**
35
 * A small DSL which makes defining Functions in Java code
36
 * much simpler and more readable.
37
 *
38
 * It allows you to define functions signatures by using a DSL like:
39
 *
40
 * <pre>
41
 * {@code
42
 * private static final String FS_INSERT_BEFORE_NAME = "insert-before";
43
 * static final FunctionSignature FS_INSERT_BEFORE = functionSignature(
44
 *         FS_INSERT_BEFORE_NAME,
45
 *         "Returns a specified part of binary data.",
46
 *         returnsOpt(Type.BASE64_BINARY),
47
 *         optParam("in", Type.BASE64_BINARY, "The binary data"),
48
 *         param("offset", Type.INTEGER, "The offset to insert at"),
49
 *         optParam("extra", Type.BASE64_BINARY, "The binary data to insert")
50
 * );
51
 * }
52
 * </pre>
53
 *
54
 * If you have a function, that is "overloaded" with multiple arity
55
 * applications possible, you can define it by using a DSL like:
56
 *
57
 * <pre>
58
 * {@code
59
 * private static final String FS_PART_NAME = "part";
60
 * private static final FunctionParameterSequenceType FS_OPT_PARAM_IN = optParam("in", Type.BASE64_BINARY, "The binary data");
61
 * private static final FunctionParameterSequenceType FS_PART_PARAM_OFFSET = param("offset", Type.INTEGER, "The offset to start reading from");
62
 * static final FunctionSignature[] FS_PART = functionSignatures(
63
 *         FS_PART_NAME,
64
 *         "Returns a specified part of binary data.",
65
 *         returnsOpt(Type.BASE64_BINARY),
66
 *         arities(
67
 *             arity(
68
 *                 FS_OPT_PARAM_IN,
69
 *                 FS_PART_PARAM_OFFSET
70
 *             ),
71
 *             arity(
72
 *                 FS_OPT_PARAM_IN,
73
 *                 FS_PART_PARAM_OFFSET,
74
 *                 param("size", Type.INTEGER, "The number of octets to read from the offset")
75
 *             )
76
 *         )
77
 * );
78
 * }
79
 * </pre>
80
 *
81
 * Finally, registering function definitions in a {@link AbstractInternalModule}
82
 * can be done by using a DSL like:
83
 *
84
 * <pre>
85
 * {@code
86
 * public static final FunctionDef[] functions = functionDefs(
87
 *         functionDefs(ConversionFunctions.class,
88
 *             ConversionFunctions.FS_HEX,
89
 *             ConversionFunctions.FS_BIN),
90
 *
91
 *         functionDefs(BasicFunctions.class,
92
 *             BasicFunctions.FS_INSERT_BEFORE,
93
 *             BasicFunctions.FS_PART[0],
94
 *             BasicFunctions.FS_PART[1])
95
 * );
96
 * }
97
 * </pre>
98
 *
99
 * @author <a href="mailto:adam@evolvedbinary.com">Adam Retter</a>
100
 */
101
public class FunctionDSL {
×
102

103
    /**
104
     * Convenience DSL method to create a Function Definition
105
     *
106
     * @param functionSignature The signature of the function
107
     * @param clazz The {@link Function} clazz where the function is implemented
108
     *
109
     * @return The function definition object
110
     */
111
    public static FunctionDef functionDef(final FunctionSignature functionSignature, Class<? extends Function> clazz) {
112
        return new FunctionDef(functionSignature, clazz);
1✔
113
    }
114

115
    /**
116
     * Convenience DSL method for supplying multiple function definitions using Varargs syntax
117
     * where the implementations are all within the same {@link Function} class
118
     *
119
     * @param clazz The {@link Function} class which holds all the implementations described by {@code functionSignature}
120
     * @param functionSignatures The signatures which are implemented by {@code clazz}
121
     *
122
     * @return The array of function definitions
123
     */
124
    public static FunctionDef[] functionDefs(final Class<? extends Function> clazz, final FunctionSignature... functionSignatures) {
125
        return Arrays.stream(functionSignatures)
1✔
126
                .map(fs -> functionDef(fs, clazz))
1✔
127
                .toArray(FunctionDef[]::new);
1✔
128
    }
129

130
    /**
131
     * Convenience DSL method for merging arrays of functions definitions using Varags syntax
132
     *
133
     * @param functionDefss The arrays of function definitions
134
     *
135
     * @return An array containing all function definitions supplied in {@code functionDefss}
136
     */
137
    public static FunctionDef[] functionDefs(final FunctionDef[]... functionDefss) {
138
        return Arrays.stream(functionDefss)
1✔
139
                .map(Arrays::stream)
1✔
140
                .reduce(Stream::concat)
1✔
141
                .map(s -> s.toArray(FunctionDef[]::new))
1✔
142
                .orElse(new FunctionDef[0]);
1✔
143
    }
144

145
    /**
146
     * Creates a new Function signature using Varargs syntax
147
     * for the parameters
148
     *
149
     * @param name The name of the function
150
     * @param description A description of the purpose of the function
151
     * @param returnType The type that is returned by the function
152
     * @param paramTypes The (types of) parameters that the function accepts
153
     *
154
     * @return The function signature object
155
     */
156
    public static FunctionSignature functionSignature(final QName name, final String description,
157
            final FunctionReturnSequenceType returnType, final FunctionParameterSequenceType... paramTypes) {
158
        return new FunctionSignature(
1✔
159
                name,
1✔
160
                description,
1✔
161
                paramTypes,
1✔
162
                returnType
1✔
163
        );
164
    }
165

166
    /**
167
     * Deprecates a function signature
168
     *
169
     * @param deprecationDescription An explanation of the purpose for deprecation
170
     * @param functionSignature The functionSignature to deprecate
171
     *
172
     * @return The function signature object
173
     */
174
    public static FunctionSignature deprecated(final String deprecationDescription, final FunctionSignature functionSignature) {
175
        return new FunctionSignature(
×
176
                functionSignature.getName(),
×
177
                functionSignature.getDescription(),
×
178
                functionSignature.getArgumentTypes(),
×
179
                functionSignature.getReturnType(),
×
180
                deprecationDescription
×
181
        );
182
    }
183

184
//    /**
185
//     * Deprecates a function signature
186
//     *
187
//     * @param fsDeprecates The new functionSignature which deprecates <code>functionSignature</code>
188
//     * @param functionSignature The functionSignature to deprecate
189
//     *
190
//     * @return The function signature object
191
//     */
192
//    public static FunctionSignature deprecated(final FunctionSignature fsDeprecates, final FunctionSignature functionSignature) {
193
//        return new FunctionSignature(
194
//                functionSignature.getName(),
195
//                functionSignature.getDescription(),
196
//                functionSignature.getArgumentTypes(),
197
//                functionSignature.getReturnType(),
198
//                fsDeprecates
199
//        );
200
//    }
201

202
    /**
203
     * Creates multiple Function signatures for functions that have multiple arity definitions
204
     *
205
     * The {@code name}, {@code description} and {@code returnType} parameters remain the same for each function arity
206
     * however the {@code variableParamType} allows you to specify different arguments for each arity definition
207
     *
208
     * @param name The name of the functions
209
     * @param description A description of the purpose of the functions
210
     * @param returnType The type that is returned by all arities of the function
211
     * @param variableParamTypes An array, where each entry is an arry of parameter types for a specific arity of the function
212
     *
213
     * @return The function signature objects
214
     */
215
    public static FunctionSignature[] functionSignatures(final QName name, final String description,
216
                                                         final FunctionReturnSequenceType returnType, final FunctionParameterSequenceType[][] variableParamTypes) {
217
        return Arrays.stream(variableParamTypes)
1✔
218
                .map(paramTypes -> functionSignature(name, description, returnType, paramTypes))
1✔
219
                .toArray(FunctionSignature[]::new);
1✔
220
    }
221

222
    /**
223
     * Wraps the parameter types for a specific function arity
224
     *
225
     * A DSL convenience method to be used to supply multiple {@link #arity(FunctionParameterSequenceType...)} results
226
     * to {@link #functionSignatures(QName, String, FunctionReturnSequenceType, FunctionParameterSequenceType[][])}
227
     *
228
     * @param variableParamTypes A convenience Varargs for the function signature arities
229
     *
230
     * @return The arities of function parameters for a function signature
231
     */
232
    public static FunctionParameterSequenceType[][] arities(final FunctionParameterSequenceType[]... variableParamTypes) {
233
        return variableParamTypes;
1✔
234
    }
235

236
    /**
237
     * Specifies the specific parameter types for an arity of a function signature.
238
     *
239
     * A DSL convenience method to be used inside {@link #arities(FunctionParameterSequenceType[][])}.
240
     *
241
     * @param paramTypes A convenience Varargs for the parameter types for a function arity
242
     *
243
     * @return The parameter types for a function arity
244
     */
245
    public static FunctionParameterSequenceType[] arity(final FunctionParameterSequenceType... paramTypes) {
246
        return paramTypes;
1✔
247
    }
248

249
    /**
250
     * An optional  DSL convenience method for function parameter types
251
     * that may make the function signature DSL more readable
252
     *
253
     * @param paramTypes The parameter types
254
     *
255
     * @return The parameter types
256
     */
257
    public static FunctionParameterSequenceType[] params(final FunctionParameterSequenceType... paramTypes) {
258
        return paramTypes;
1✔
259
    }
260

261
    /**
262
     * Creates a Function Parameter which has a cardinality of {@link Cardinality#ZERO_OR_ONE}
263
     *
264
     * @param name The name of the parameter
265
     * @param type The XDM type of the parameter, i.e. one of {@link org.exist.xquery.value.Type}
266
     * @param description A description of the parameter
267
     *
268
     * @return The function parameter object
269
     */
270
    public static FunctionParameterSequenceType optParam(final String name, final int type, final String description) {
271
        return param(name, type, Cardinality.ZERO_OR_ONE, description);
1✔
272
    }
273

274
    /**
275
     * Creates a Function Parameter which has a cardinality of {@link Cardinality#EXACTLY_ONE}
276
     *
277
     * @param name The name of the parameter
278
     * @param type The XDM type of the parameter, i.e. one of {@link org.exist.xquery.value.Type}
279
     * @param description A description of the parameter
280
     *
281
     * @return The function parameter object
282
     */
283
    public static FunctionParameterSequenceType param(final String name, final int type, final String description) {
284
        return param(name, type, Cardinality.EXACTLY_ONE, description);
1✔
285
    }
286

287
    /**
288
     * Creates a Function Parameter which has a cardinality of {@link Cardinality#ONE_OR_MORE}
289
     *
290
     * @param name The name of the parameter
291
     * @param type The XDM type of the parameter, i.e. one of {@link org.exist.xquery.value.Type}
292
     * @param description A description of the parameter
293
     *
294
     * @return The function parameter object
295
     */
296
    public static FunctionParameterSequenceType manyParam(final String name, final int type, final String description) {
297
        return param(name, type, Cardinality.ONE_OR_MORE, description);
×
298
    }
299

300
    /**
301
     * Creates a Function Parameter which has a cardinality of {@link Cardinality#ZERO_OR_ONE}
302
     *
303
     * @param name The name of the parameter
304
     * @param type The XDM type of the parameter, i.e. one of {@link org.exist.xquery.value.Type}
305
     * @param description A description of the parameter
306
     *
307
     * @return The function parameter object
308
     */
309
    public static FunctionParameterSequenceType optManyParam(final String name, final int type,
310
            final String description) {
311
        return param(name, type, Cardinality.ZERO_OR_MORE, description);
1✔
312
    }
313

314
    /**
315
     * Creates a Function Parameter
316
     *
317
     * @param name The name of the parameter
318
     * @param type The XDM type of the parameter, i.e. one of {@link org.exist.xquery.value.Type}
319
     * @param cardinality The cardinality of the parameter, i.e. one of {@link Cardinality}
320
     * @param description A description of the parameter
321
     *
322
     * @return The function parameter object
323
     */
324
    public static FunctionParameterSequenceType param(final String name, final int type, final Cardinality cardinality,
325
            final String description) {
326
        return new FunctionParameterSequenceType(name, type, cardinality, description);
1✔
327
    }
328

329
    /**
330
     * Creates a Function Parameter
331
     *
332
     * @param name The name of the parameter
333
     * @param type The XDM type of the parameter, i.e. one of {@link org.exist.xquery.value.Type}
334
     * @param cardinality The cardinality of the parameter
335
     * @param description A description of the parameter
336
     *
337
     * @return The function parameter object
338
     *
339
     * @deprecated Use {@link #param(String, int, Cardinality, String)}
340
     */
341
    @Deprecated
342
    public static FunctionParameterSequenceType param(final String name, final int type, final int cardinality,
343
            final String description) {
344
        return new FunctionParameterSequenceType(name, type, cardinality, description);
×
345
    }
346

347
    /**
348
     * Creates a Function Return Type which has a cardinality of {@link Cardinality#ZERO_OR_ONE}
349
     *
350
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
351
     *
352
     * @return The function return type object
353
     */
354
    public static FunctionReturnSequenceType returnsOpt(final int type) {
355
        return returns(type, Cardinality.ZERO_OR_ONE);
1✔
356
    }
357

358
    /**
359
     * Creates a Function Return Type which has a cardinality of {@link Cardinality#ZERO_OR_ONE}
360
     *
361
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
362
     * @param description A description of the return value
363
     *
364
     * @return The function return type object
365
     */
366
    public static FunctionReturnSequenceType returnsOpt(final int type, final String description) {
367
        return returns(type, Cardinality.ZERO_OR_ONE, description);
1✔
368
    }
369

370
    /**
371
     * Creates a Function Return Type which has a cardinality of {@link Cardinality#EXACTLY_ONE}
372
     *
373
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
374
     *
375
     * @return The function return type object
376
     */
377
    public static FunctionReturnSequenceType returns(final int type) {
378
        return returns(type, Cardinality.EXACTLY_ONE);
1✔
379
    }
380

381
    /**
382
     * Creates a Function Return Type which has a cardinality of {@link Cardinality#EXACTLY_ONE}
383
     *
384
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
385
     * @param description A description of the return value
386
     *
387
     * @return The function return type object
388
     */
389
    public static FunctionReturnSequenceType returns(final int type, final String description) {
390
        return returns(type, Cardinality.EXACTLY_ONE, description);
1✔
391
    }
392

393
    /**
394
     * Creates a Function Return Type which has a cardinality of {@link Cardinality#ONE_OR_MORE}
395
     *
396
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
397
     *
398
     * @return The function return type object
399
     */
400
    public static FunctionReturnSequenceType returnsMany(final int type) {
401
        return returns(type, Cardinality.ONE_OR_MORE);
×
402
    }
403

404
    /**
405
     * Creates a Function Return Type which has a cardinality of {@link Cardinality#ONE_OR_MORE}
406
     *
407
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
408
     * @param description A description of the return value
409
     *
410
     * @return The function return type object
411
     */
412
    public static FunctionReturnSequenceType returnsMany(final int type, final String description) {
413
        return returns(type, Cardinality.ONE_OR_MORE, description);
×
414
    }
415

416
    /**
417
     * Creates a Function Return Type which has a cardinality of {@link Cardinality#ZERO_OR_MORE}
418
     *
419
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
420
     *
421
     * @return The function return type object
422
     */
423
    public static FunctionReturnSequenceType returnsOptMany(final int type) {
424
        return returns(type, Cardinality.ZERO_OR_MORE);
1✔
425
    }
426

427
    /**
428
     * Creates a Function Return Type which has a cardinality of {@link Cardinality#ZERO_OR_MORE}
429
     *
430
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
431
     * @param description A description of the return value
432
     *
433
     * @return The function return type object
434
     */
435
    public static FunctionReturnSequenceType returnsOptMany(final int type, final String description) {
436
        return returns(type, Cardinality.ZERO_OR_MORE, description);
1✔
437
    }
438

439
    /**
440
     * Creates a Function Return Type which describes no result.
441
     *
442
     * @return a Function Return Type which has a cardinality of {@link Cardinality#EMPTY_SEQUENCE} and {@link Type#EMPTY_SEQUENCE}
443
     */
444
    public static FunctionReturnSequenceType returnsNothing() {
445
        return new FunctionReturnSequenceType(Type.EMPTY_SEQUENCE, Cardinality.EMPTY_SEQUENCE, null);
1✔
446
    }
447

448
    /**
449
     * Creates a Function Return Type
450
     *
451
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
452
     * @param cardinality The cardinality of the return type, i.e. one of {@link Cardinality}
453
     *
454
     * @return The function return type object
455
     */
456
    public static FunctionReturnSequenceType returns(final int type, final Cardinality cardinality) {
457
        return returns(type, cardinality, null);
1✔
458
    }
459

460
    /**
461
     * Creates a Function Return Type
462
     *
463
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
464
     * @param cardinality The cardinality of the return type
465
     *
466
     * @return The function return type object
467
     *
468
     * @deprecated Use {@link #returns(int, Cardinality)}
469
     */
470
    @Deprecated
471
    public static FunctionReturnSequenceType returns(final int type, final int cardinality) {
472
        return returns(type, cardinality, null);
×
473
    }
474

475
    /**
476
     * Creates a Function Return Type
477
     *
478
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
479
     * @param cardinality The cardinality of the return type, i.e. one of {@link Cardinality}
480
     * @param description A description of the parameter
481
     *
482
     * @return The function return type object
483
     */
484
    public static FunctionReturnSequenceType returns(final int type, final Cardinality cardinality, final String description) {
485
        return new FunctionReturnSequenceType(type, cardinality, description);
1✔
486
    }
487

488
    /**
489
     * Creates a Function Return Type
490
     *
491
     * @param type The XDM type of the return value, i.e. one of {@link org.exist.xquery.value.Type}
492
     * @param cardinality The cardinality of the return type
493
     * @param description A description of the parameter
494
     *
495
     * @return The function return type object
496
     *
497
     * @deprecated Use {@link #returns(int, Cardinality, String)}
498
     */
499
    @Deprecated
500
    public static FunctionReturnSequenceType returns(final int type, final int cardinality, final String description) {
501
        return new FunctionReturnSequenceType(type, cardinality, description);
×
502
    }
503
}
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