1
2
3
4
5
6 package dev.metaschema.core.metapath.function;
7
8 import java.util.ServiceLoader;
9 import java.util.ServiceLoader.Provider;
10 import java.util.stream.Stream;
11
12 import dev.metaschema.core.metapath.StaticMetapathException;
13 import dev.metaschema.core.qname.IEnhancedQName;
14 import dev.metaschema.core.util.ObjectUtils;
15 import edu.umd.cs.findbugs.annotations.NonNull;
16 import nl.talsmasoftware.lazy4j.Lazy;
17
18
19
20
21
22 public final class FunctionService implements IFunctionResolver {
23 private static final Lazy<FunctionService> INSTANCE = Lazy.of(FunctionService::new);
24 @NonNull
25 private final ServiceLoader<IFunctionLibrary> loader;
26 @NonNull
27 private final Lazy<IFunctionLibrary> library;
28
29
30
31
32
33
34
35 @NonNull
36 public static FunctionService getInstance() {
37 return ObjectUtils.notNull(INSTANCE.get());
38 }
39
40
41
42
43 @SuppressWarnings("null")
44 public FunctionService() {
45 this.loader = ServiceLoader.load(IFunctionLibrary.class);
46 ServiceLoader<IFunctionLibrary> loader = getLoader();
47
48 this.library = Lazy.of(() -> {
49 FunctionLibrary functionLibrary = new FunctionLibrary();
50 loader.stream()
51 .map(Provider<IFunctionLibrary>::get)
52 .flatMap(IFunctionLibrary::stream)
53 .forEachOrdered(function -> functionLibrary.registerFunction(ObjectUtils.notNull(function)));
54 return functionLibrary;
55 });
56 }
57
58
59
60
61
62
63 @NonNull
64 private ServiceLoader<IFunctionLibrary> getLoader() {
65 return loader;
66 }
67
68 @NonNull
69 private IFunctionLibrary getLibrary() {
70 return ObjectUtils.notNull(library.get());
71 }
72
73
74
75
76
77
78 @NonNull
79 public Stream<IFunction> stream() {
80 return getLibrary().stream();
81 }
82
83 @Override
84 public IFunction getFunction(@NonNull IEnhancedQName name, int arity) {
85 IFunction retval = getLibrary().getFunction(name, arity);
86
87 if (retval == null) {
88 throw new StaticMetapathException(StaticMetapathException.NO_FUNCTION_MATCH,
89 String.format("unable to find function with name '%s' having arity '%d'", name, arity));
90 }
91 return retval;
92 }
93 }