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