1
2
3
4
5
6 package dev.metaschema.cli.commands.metapath;
7
8 import org.apache.commons.cli.CommandLine;
9 import org.apache.logging.log4j.LogManager;
10 import org.apache.logging.log4j.Logger;
11
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.Comparator;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.stream.Collectors;
18
19 import dev.metaschema.cli.processor.CallingContext;
20 import dev.metaschema.cli.processor.ExitCode;
21 import dev.metaschema.cli.processor.ExitStatus;
22 import dev.metaschema.cli.processor.command.AbstractTerminalCommand;
23 import dev.metaschema.cli.processor.command.ICommandExecutor;
24 import dev.metaschema.core.metapath.function.FunctionService;
25 import dev.metaschema.core.metapath.function.IArgument;
26 import dev.metaschema.core.metapath.function.IFunction;
27 import dev.metaschema.core.qname.WellKnown;
28 import edu.umd.cs.findbugs.annotations.NonNull;
29
30
31
32
33
34 class ListFunctionsSubcommand
35 extends AbstractTerminalCommand {
36 private static final Logger LOGGER = LogManager.getLogger(ListFunctionsSubcommand.class);
37
38 @NonNull
39 private static final String COMMAND = "list-functions";
40
41 @Override
42 public String getName() {
43 return COMMAND;
44 }
45
46 @Override
47 public String getDescription() {
48 return "Get a listing of supported Metapath functions";
49 }
50
51 @Override
52 public ICommandExecutor newExecutor(CallingContext callingContext, CommandLine cmdLine) {
53 return ICommandExecutor.using(callingContext, cmdLine, this::executeCommand);
54 }
55
56
57
58
59
60
61
62
63
64
65 protected ExitStatus executeCommand(
66 @NonNull CallingContext callingContext,
67 @NonNull CommandLine cmdLine) {
68
69 Map<String, Map<String, List<IFunction>>> namespaceToNameToFunctionMap = FunctionService.getInstance().stream()
70 .collect(Collectors.groupingBy(
71 function -> function.getQName().getNamespace(),
72 Collectors.groupingBy(
73 IFunction::getName,
74 Collectors.toList())));
75
76 List<String> namespaces = new ArrayList<>(namespaceToNameToFunctionMap.keySet());
77
78 Collections.sort(namespaces);
79
80 for (String namespace : namespaces) {
81 assert namespace != null;
82 String prefix = WellKnown.getWellKnownPrefixForUri(namespace);
83
84 if (prefix == null) {
85 LOGGER.atInfo().log("In namespace '{}':", namespace);
86 } else {
87 LOGGER.atInfo().log("In namespace '{}' as '{}':", namespace, prefix);
88 }
89
90 Map<String, List<IFunction>> namespacedFunctions = namespaceToNameToFunctionMap.get(namespace);
91
92 List<String> names = new ArrayList<>(namespacedFunctions.keySet());
93 Collections.sort(names);
94
95 for (String name : names) {
96 List<IFunction> functions = namespacedFunctions.get(name);
97 Collections.sort(functions, Comparator.comparing(IFunction::arity));
98
99 for (IFunction function : functions) {
100 String functionRef = prefix == null
101 ? String.format("Q{%s}%s", function.getQName().getNamespace(), function.getName())
102 : String.format("%s:%s", prefix, function.getName());
103
104 LOGGER.atInfo().log(String.format("%s(%s) as %s",
105 functionRef,
106 function.getArguments().isEmpty()
107 ? ""
108 : function.getArguments().stream().map(IArgument::toSignature)
109 .collect(Collectors.joining(","))
110 + (function.isArityUnbounded() ? ", ..." : ""),
111 function.getResult().toSignature()));
112 }
113 }
114 }
115 return ExitCode.OK.exit();
116 }
117 }