1
2
3
4
5
6 package dev.metaschema.core.metapath.cst;
7
8 import java.util.List;
9 import java.util.stream.Collectors;
10 import java.util.stream.Stream;
11
12 import dev.metaschema.core.metapath.DynamicContext;
13 import dev.metaschema.core.metapath.IExpression;
14 import dev.metaschema.core.metapath.StaticMetapathException;
15 import dev.metaschema.core.metapath.function.IFunction;
16 import dev.metaschema.core.metapath.item.IItem;
17 import dev.metaschema.core.metapath.item.ISequence;
18 import dev.metaschema.core.util.ObjectUtils;
19 import edu.umd.cs.findbugs.annotations.NonNull;
20
21
22
23
24
25
26 public class DynamicFunctionCall
27 extends AbstractExpression {
28 @NonNull
29 private final IExpression functionIdentifier;
30 @NonNull
31 private final List<IExpression> arguments;
32
33
34
35
36
37
38
39
40
41
42
43
44 public DynamicFunctionCall(
45 @NonNull String text,
46 @NonNull IExpression functionIdentifier,
47 @NonNull List<IExpression> arguments) {
48 super(text);
49 this.functionIdentifier = functionIdentifier;
50 this.arguments = arguments;
51 }
52
53 @Override
54 public List<IExpression> getChildren() {
55 return ObjectUtils.notNull(Stream.concat(
56 Stream.of(functionIdentifier),
57 arguments.stream())
58 .collect(Collectors.toUnmodifiableList()));
59 }
60
61 @Override
62 public Class<? extends IItem> getBaseResultType() {
63 return IItem.class;
64 }
65
66 @Override
67 public <RESULT, CONTEXT> RESULT accept(IExpressionVisitor<RESULT, CONTEXT> visitor, CONTEXT context) {
68 return visitor.visitDynamicFunctionCall(this, context);
69 }
70
71 @Override
72 protected ISequence<?> evaluate(DynamicContext dynamicContext, ISequence<?> focus) {
73 List<ISequence<?>> arguments = ObjectUtils.notNull(this.arguments.stream()
74 .map(expression -> expression.accept(dynamicContext, focus)).collect(Collectors.toList()));
75
76 IItem specifier = functionIdentifier.accept(dynamicContext, focus).getFirstItem(true);
77 IFunction function;
78 if (specifier instanceof IFunction) {
79 function = (IFunction) specifier;
80 } else if (specifier != null) {
81 function = dynamicContext.getStaticContext().lookupFunction(
82 specifier.toAtomicItem().asString(),
83 arguments.size());
84 } else {
85 throw new StaticMetapathException(
86 StaticMetapathException.NO_FUNCTION_MATCH,
87 "Unable to get function name. The error specifier is an empty sequence.");
88 }
89 return function.execute(arguments, dynamicContext, focus);
90 }
91 }