From 5472808444c8beceb3a6bd0283fa6089ac5a2443 Mon Sep 17 00:00:00 2001 From: wandmagic <156969148+wandmagic@users.noreply.github.com> Date: Tue, 27 Aug 2024 20:38:37 +0000 Subject: [PATCH] introduce metapath expression evaluator subcommand --- .../commands/metapath/MetapathCommand.java | 1 + .../commands/metapath/TestPathSubCommand.java | 119 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/TestPathSubCommand.java diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/MetapathCommand.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/MetapathCommand.java index 258d75cda..ee6b42919 100644 --- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/MetapathCommand.java +++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/MetapathCommand.java @@ -14,6 +14,7 @@ public class MetapathCommand public MetapathCommand() { super(true); addCommandHandler(new ListFunctionsSubcommand()); + addCommandHandler(new TestPathSubCommand()); } @Override diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/TestPathSubCommand.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/TestPathSubCommand.java new file mode 100644 index 000000000..d28fb21dd --- /dev/null +++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/TestPathSubCommand.java @@ -0,0 +1,119 @@ +package gov.nist.secauto.metaschema.cli.commands.metapath; + +import gov.nist.secauto.metaschema.cli.processor.CLIProcessor.CallingContext; +import gov.nist.secauto.metaschema.cli.processor.ExitCode; +import gov.nist.secauto.metaschema.cli.processor.ExitStatus; +import gov.nist.secauto.metaschema.cli.processor.InvalidArgumentException; +import gov.nist.secauto.metaschema.cli.processor.command.AbstractTerminalCommand; +import gov.nist.secauto.metaschema.cli.processor.command.DefaultExtraArgument; +import gov.nist.secauto.metaschema.cli.processor.command.ExtraArgument; +import gov.nist.secauto.metaschema.cli.processor.command.ICommandExecutor; +import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.List; + +import edu.umd.cs.findbugs.annotations.NonNull; + +public class TestPathSubCommand + extends AbstractTerminalCommand { + private static final Logger LOGGER = LogManager.getLogger(TestPathSubCommand.class); + + @NonNull + private static final String COMMAND = "test-path"; + @NonNull + private static final List EXTRA_ARGUMENTS; + @NonNull + private static final Option EXPRESSION_OPTION = ObjectUtils.notNull( + Option.builder("e") + .longOpt("expression") + .required() + .hasArg() + .argName("EXPRESSION") + .desc("The MetaPath expression to execute") + .build()); + + static { + EXTRA_ARGUMENTS = ObjectUtils.notNull(List.of( + new DefaultExtraArgument("input-file", true))); + } + + @Override + public String getName() { + return COMMAND; + } + + @Override + public String getDescription() { + return "Execute a MetaPath expression against a document"; + } + + @SuppressWarnings("null") + @Override + public Collection gatherOptions() { + return List.of(EXPRESSION_OPTION); + } + + @Override + public List getExtraArguments() { + return EXTRA_ARGUMENTS; + } + + @Override + public void validateOptions(CallingContext callingContext, CommandLine cmdLine) throws InvalidArgumentException { + List extraArgs = cmdLine.getArgList(); + if (extraArgs.isEmpty() || extraArgs.size() > 1) { + throw new InvalidArgumentException("Illegal number of arguments."); + } + } + + @Override + public ICommandExecutor newExecutor(CallingContext callingContext, CommandLine cmdLine) { + return ICommandExecutor.using(callingContext, cmdLine, this::executeCommand); + } + + @SuppressWarnings({ + "PMD.OnlyOneReturn", // readability + }) + protected ExitStatus executeCommand( + @NonNull CallingContext callingContext, + @NonNull CommandLine cmdLine) { + List extraArgs = cmdLine.getArgList(); + String inputFile = extraArgs.get(0); + String expression = cmdLine.getOptionValue(EXPRESSION_OPTION); + + Path inputPath = Paths.get(inputFile).toAbsolutePath(); + + if (!Files.exists(inputPath)) { + return ExitCode.INVALID_ARGUMENTS.exitMessage( + String.format("The provided input file '%s' does not exist.", inputPath)); + } + + if (!Files.isReadable(inputPath)) { + return ExitCode.IO_ERROR.exitMessage( + String.format("The provided input file '%s' is not readable.", inputPath)); + } + + try { + // Parse and compile the MetaPath expression + MetapathExpression compiledMetapath = MetapathExpression.compile(expression); + var sequence = compiledMetapath.evaluate(); + + // Print the result + System.out.println("Result: " + sequence.toString()); + + return ExitCode.OK.exit(); + } catch (Exception ex) { + return ExitCode.PROCESSING_ERROR.exit().withThrowable(ex); + } + } +} \ No newline at end of file