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