From b0341a620883ce2a1fdba3b671d0a97485d7d622 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 1/2] 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 From 209af339f31a02117265e969e36f2094e94d4b1a Mon Sep 17 00:00:00 2001 From: David Waltermire Date: Fri, 6 Sep 2024 12:40:02 -0400 Subject: [PATCH 2/2] Fixed a schema generation bug causing an existing test to fail due to improper handling of JSON keys. Added basic support for arbitrary Metapath command execution, building on #96. Metapath execution allows for evaluating expressions without a module or instance. Resolves usnistgov/metaschema-java#241. --- .lycheeignore | 9 +- .../core/metapath/item/DefaultItemWriter.java | 146 ++++++++++++ .../metaschema/core/metapath/item/IItem.java | 10 + .../core/metapath/item/IItemVisitor.java | 47 ++++ .../core/metapath/item/IItemWriter.java | 56 +++++ .../metapath/item/atomic/IAnyAtomicItem.java | 6 + .../metapath/item/function/IArrayItem.java | 6 + .../core/metapath/item/function/IMapItem.java | 6 + .../node/AbstractFlagInstanceNodeItem.java | 31 +-- .../core/metapath/item/node/INodeItem.java | 6 + .../metaschema/fields_with_flags/example.json | 4 +- metaschema-cli/pom.xml | 11 + .../AbstractValidateContentCommand.java | 2 +- .../commands/MetaschemaCommandSupport.java | 23 -- .../cli/commands/MetaschemaCommands.java | 73 +++++- .../ValidateContentUsingModuleCommand.java | 32 +-- .../metapath/EvaluateMetapathSubCommand.java | 220 ++++++++++++++++++ .../commands/metapath/MetapathCommand.java | 2 +- .../commands/metapath/TestPathSubCommand.java | 119 ---------- .../EvaluateMetapathSubCommandTest.java | 37 +++ pom.xml | 14 ++ .../schemagen/json/IDefineableJsonSchema.java | 2 +- .../builder/AbstractCollectionBuilder.java | 18 +- .../json/impl/builder/KeyedObjectBuilder.java | 36 ++- 24 files changed, 698 insertions(+), 218 deletions(-) create mode 100644 core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/DefaultItemWriter.java create mode 100644 core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItemVisitor.java create mode 100644 core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItemWriter.java delete mode 100644 metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/MetaschemaCommandSupport.java create mode 100644 metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/EvaluateMetapathSubCommand.java delete mode 100644 metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/TestPathSubCommand.java create mode 100644 metaschema-cli/src/test/java/gov/nist/secauto/metaschema/cli/commands/metapath/EvaluateMetapathSubCommandTest.java diff --git a/.lycheeignore b/.lycheeignore index 62480f1f4..159ae8478 100644 --- a/.lycheeignore +++ b/.lycheeignore @@ -16,6 +16,8 @@ https://github.com/hamcrest/JavaHamcrest/hamcrest-core https://github.com/javaparser/.* https://github.com/vsch/flexmark-java/.* https://hc.apache.org/httpcomponents-client-5.0.x/5.1.3/httpclient5/ +http://logback.qos.ch/logback-classic +http://logback.qos.ch/logback-core https://logging.apache.org/log4j/2.x/log4j/.* http://mojo.codehaus.org/.* https://pmd.github.io/latest/pmd_userdocs_cpd.html @@ -34,7 +36,8 @@ http://www.thymeleaf.org/thymeleaf-lib/thymeleaf # broken license references https://opensource.org/licenses/Apache-2.0,https://opensource.org/licenses/EPL-2.0 # prone to long timeouts -http://nexus.sonatype.org/oss-repository-hosting.html/.* https://glassfish.dev.java.net/.* - - +http://nexus.sonatype.org/oss-repository-hosting.html/.* +https://projects.eclipse.org/projects/eclipse.jdt +# fix later +https://github.com/metaschema-framework/liboscal-java/ diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/DefaultItemWriter.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/DefaultItemWriter.java new file mode 100644 index 000000000..321ee4942 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/DefaultItemWriter.java @@ -0,0 +1,146 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.metapath.item; + +import gov.nist.secauto.metaschema.core.metapath.ICollectionValue; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; +import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem; +import gov.nist.secauto.metaschema.core.metapath.item.function.IMapItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; + +import java.io.PrintWriter; + +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * Produces a textual representation of a Metapath sequence. + */ +public class DefaultItemWriter implements IItemWriter { + + @NonNull + private final PrintWriter writer; + @NonNull + private final Visitor visitor = new Visitor(); + + /** + * Construct a new item writer. + * + * @param writer + * the writer to append text to + */ + public DefaultItemWriter(@NonNull PrintWriter writer) { + this.writer = writer; + } + + @Override + public void writeSequence(ISequence sequence) { + boolean wrap = sequence.size() != 1; + if (wrap) { + writer.append('('); + } + boolean first = true; + for (IItem item : sequence) { + + if (first) { + first = false; + } else { + writer.append(','); + } + + item.accept(visitor); + } + + if (wrap) { + writer.append(')'); + } + } + + @Override + public void writeArray(IArrayItem array) { + writer.append('['); + boolean first = true; + for (ICollectionValue value : array) { + assert value != null; + + if (first) { + first = false; + } else { + writer.append(','); + } + + writeCollectionValue(value); + } + writer.append(']'); + } + + @Override + public void writeMap(IMapItem map) { + writer.append("map {"); + boolean first = true; + for (ICollectionValue value : map.values()) { + assert value != null; + + if (first) { + first = false; + } else { + writer.append(','); + } + + writeCollectionValue(value); + } + writer.append('}'); + } + + @Override + public void writeNode(INodeItem node) { + writer.append(node.getBaseUri().toString()); + writer.append('#'); + writer.append(node.getMetapath()); + } + + @Override + public void writeAtomicValue(IAnyAtomicItem node) { + writer.append(node.asString()); + } + + /** + * Write the provided collection value. + * + * @param value + * the value to write + */ + protected void writeCollectionValue(@NonNull ICollectionValue value) { + if (value instanceof IItem) { + ((IItem) value).accept(visitor); + } else if (value instanceof ISequence) { + writeSequence((ISequence) value); + } + } + + private final class Visitor implements IItemVisitor { + + @Override + public void visit(IArrayItem array) { + writeArray(array); + } + + @Override + public void visit(IMapItem map) { + writeMap(map); + } + + @Override + public void visit(INodeItem node) { + writeNode(node); + } + + @Override + public void visit(IAnyAtomicItem node) { + writeAtomicValue(node); + } + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java index 6f884ad0e..378fe5a40 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java @@ -11,6 +11,8 @@ import java.util.stream.Stream; +import edu.umd.cs.findbugs.annotations.NonNull; + public interface IItem extends ICollectionValue { /** @@ -49,4 +51,12 @@ default ISequence asSequence() { default Stream flatten() { return Stream.of(this); } + + /** + * A visitor callback used to visit a variety of Metapath item types. + * + * @param visitor + * the visitor to call back + */ + void accept(@NonNull IItemVisitor visitor); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItemVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItemVisitor.java new file mode 100644 index 000000000..31b5e3a0c --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItemVisitor.java @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.metapath.item; + +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; +import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem; +import gov.nist.secauto.metaschema.core.metapath.item.function.IMapItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; + +import edu.umd.cs.findbugs.annotations.NonNull; + +public interface IItemVisitor { + /** + * Visit the array item instance. + * + * @param array + * the instance to visit + */ + void visit(@NonNull IArrayItem array); + + /** + * Visit the map item instance. + * + * @param map + * the instance to visit + */ + void visit(@NonNull IMapItem map); + + /** + * Visit the node item instance. + * + * @param node + * the instance to visit + */ + void visit(@NonNull INodeItem node); + + /** + * Visit the atomic item instance. + * + * @param item + * the instance to visit + */ + void visit(@NonNull IAnyAtomicItem item); +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItemWriter.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItemWriter.java new file mode 100644 index 000000000..d96146500 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItemWriter.java @@ -0,0 +1,56 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.metapath.item; + +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; +import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem; +import gov.nist.secauto.metaschema.core.metapath.item.function.IMapItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; + +import edu.umd.cs.findbugs.annotations.NonNull; + +public interface IItemWriter { + /** + * Write the provided sequence instance. + * + * @param sequence + * the instance to write + */ + void writeSequence(@NonNull ISequence sequence); + + /** + * Write the provided array item instance. + * + * @param array + * the instance to write + */ + void writeArray(@NonNull IArrayItem array); + + /** + * Write the provided map item instance. + * + * @param map + * the instance to write + */ + void writeMap(@NonNull IMapItem map); + + /** + * Write the provided node item instance. + * + * @param node + * the instance to write + */ + void writeNode(@NonNull INodeItem node); + + /** + * Write the provided atomic item instance. + * + * @param item + * the instance to write + */ + void writeAtomicValue(@NonNull IAnyAtomicItem item); +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java index b7606010b..13f20a671 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java @@ -7,6 +7,7 @@ import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter; import gov.nist.secauto.metaschema.core.metapath.IPrintable; +import gov.nist.secauto.metaschema.core.metapath.item.IItemVisitor; import gov.nist.secauto.metaschema.core.metapath.item.function.IMapItem; import gov.nist.secauto.metaschema.core.metapath.item.function.IMapKey; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -103,4 +104,9 @@ default IStringItem asStringItem() { * than, equal to, or greater than the {@code item}. */ int compareTo(@NonNull IAnyAtomicItem other); + + @Override + default void accept(IItemVisitor visitor) { + visitor.visit(this); + } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java index b96e6d3e6..732ab14a8 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java @@ -15,6 +15,7 @@ import gov.nist.secauto.metaschema.core.metapath.impl.AbstractArrayItem; import gov.nist.secauto.metaschema.core.metapath.impl.ArrayItemN; import gov.nist.secauto.metaschema.core.metapath.item.IItem; +import gov.nist.secauto.metaschema.core.metapath.item.IItemVisitor; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import java.util.ArrayList; @@ -570,4 +571,9 @@ static IArrayItem copyOf(@NonNull Collection(new ArrayList<>(collection)); } + + @Override + default void accept(IItemVisitor visitor) { + visitor.visit(this); + } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IMapItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IMapItem.java index b9458b316..c3c8ed640 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IMapItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IMapItem.java @@ -16,6 +16,7 @@ import gov.nist.secauto.metaschema.core.metapath.impl.AbstractMapItem; import gov.nist.secauto.metaschema.core.metapath.impl.MapItemN; import gov.nist.secauto.metaschema.core.metapath.item.IItem; +import gov.nist.secauto.metaschema.core.metapath.item.IItemVisitor; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import java.util.LinkedHashMap; @@ -782,4 +783,9 @@ IMapItem copyOf(Map map) { ? empty() : new MapItemN<>(new LinkedHashMap<>(map)); } + + @Override + default void accept(IItemVisitor visitor) { + visitor.visit(this); + } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractFlagInstanceNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractFlagInstanceNodeItem.java index a06953449..cc0797426 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractFlagInstanceNodeItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractFlagInstanceNodeItem.java @@ -11,38 +11,11 @@ * A {@link INodeItem} supported by a {@link IFlagInstance}. */ abstract class AbstractFlagInstanceNodeItem + extends AbstractInstanceNodeItem> implements IFlagNodeItem { - @NonNull - private final IFlagInstance instance; - @NonNull - private final IModelNodeItem parent; public AbstractFlagInstanceNodeItem(@NonNull IFlagInstance instance, @NonNull IModelNodeItem parent) { - this.instance = instance; - this.parent = parent; - } - - @Override - public IFlagDefinition getDefinition() { - return getInstance().getDefinition(); - } - - @Override - @NonNull - public IFlagInstance getInstance() { - return instance; - } - - @Override - @NonNull - public IModelNodeItem getParentContentNodeItem() { - return getParentNodeItem(); - } - - @Override - @NonNull - public IModelNodeItem getParentNodeItem() { - return parent; + super(instance, parent); } @Override diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/INodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/INodeItem.java index 73253b545..257521ce4 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/INodeItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/INodeItem.java @@ -5,6 +5,7 @@ import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; import gov.nist.secauto.metaschema.core.metapath.format.IPathSegment; import gov.nist.secauto.metaschema.core.metapath.item.IItem; +import gov.nist.secauto.metaschema.core.metapath.item.IItemVisitor; import gov.nist.secauto.metaschema.core.model.IResourceLocation; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -285,4 +286,9 @@ default Stream flags() { */ @NonNull StaticContext getStaticContext(); + + @Override + default void accept(IItemVisitor visitor) { + visitor.visit(this); + } } diff --git a/databind/src/test/resources/metaschema/fields_with_flags/example.json b/databind/src/test/resources/metaschema/fields_with_flags/example.json index a770cb807..e5f482d5a 100644 --- a/databind/src/test/resources/metaschema/fields_with_flags/example.json +++ b/databind/src/test/resources/metaschema/fields_with_flags/example.json @@ -21,8 +21,8 @@ } ], "complex-fields4": { - "complex-field4-1": {"STRVALUE": "test-string5"}, - "complex-field4-2": {"STRVALUE": "test-string6"} + "complex-field4-1": "test-string5", + "complex-field4-2": "test-string6" } } } \ No newline at end of file diff --git a/metaschema-cli/pom.xml b/metaschema-cli/pom.xml index cf8f97eb1..2ba314ab6 100644 --- a/metaschema-cli/pom.xml +++ b/metaschema-cli/pom.xml @@ -63,6 +63,17 @@ org.apache.logging.log4j log4j-api + + + io.github.hakky54 + logcaptor + test + + + org.assertj + assertj-core + test + diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java index 28de5e906..729ee8023 100644 --- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java +++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java @@ -80,7 +80,7 @@ public abstract class AbstractValidateContentCommand private static final Option CONSTRAINTS_OPTION = ObjectUtils.notNull( Option.builder("c") .hasArgs() - .argName("URI") + .argName("URL") .desc("additional constraint definitions") .build()); @NonNull diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/MetaschemaCommandSupport.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/MetaschemaCommandSupport.java deleted file mode 100644 index 48c246e16..000000000 --- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/MetaschemaCommandSupport.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.cli.commands; - -import gov.nist.secauto.metaschema.core.util.ObjectUtils; - -import org.apache.commons.cli.Option; - -import edu.umd.cs.findbugs.annotations.NonNull; - -public class MetaschemaCommandSupport { - @NonNull - public static final Option METASCHEMA_OPTION = ObjectUtils.notNull( - Option.builder("m") - .hasArg() - .argName("FILE") - .required() - .desc("metaschema resource") - .build()); -} diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/MetaschemaCommands.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/MetaschemaCommands.java index 8f246f4e2..51db4f835 100644 --- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/MetaschemaCommands.java +++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/MetaschemaCommands.java @@ -7,15 +7,84 @@ import gov.nist.secauto.metaschema.cli.commands.metapath.MetapathCommand; import gov.nist.secauto.metaschema.cli.processor.command.ICommand; +import gov.nist.secauto.metaschema.core.model.IModule; +import gov.nist.secauto.metaschema.core.model.MetaschemaException; +import gov.nist.secauto.metaschema.core.model.constraint.IConstraintSet; +import gov.nist.secauto.metaschema.core.model.xml.ExternalConstraintsModulePostProcessor; +import gov.nist.secauto.metaschema.core.model.xml.ModuleLoader; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.UriUtils; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collection; import java.util.List; +import edu.umd.cs.findbugs.annotations.NonNull; + public final class MetaschemaCommands { - public static final List COMMANDS = List.of( + @NonNull + public static final List COMMANDS = ObjectUtils.notNull(List.of( new ValidateModuleCommand(), new GenerateSchemaCommand(), new ValidateContentUsingModuleCommand(), - new MetapathCommand()); + new MetapathCommand())); + + @NonNull + public static final Option METASCHEMA_OPTION = ObjectUtils.notNull( + Option.builder("m") + .hasArg() + .argName("FILE_OR_URL") + .required() + .desc("metaschema resource") + .build()); + + @NonNull + public static IModule handleModule( + @NonNull CommandLine commandLine, + @NonNull URI cwd, + @NonNull Collection constraintSets) throws URISyntaxException, IOException, MetaschemaException { + String moduleName + = ObjectUtils.requireNonNull(commandLine.getOptionValue(MetaschemaCommands.METASCHEMA_OPTION)); + URI moduleUri = UriUtils.toUri(moduleName, cwd); + return handleModule(moduleUri, constraintSets); + } + + @NonNull + public static IModule handleModule( + @NonNull URI moduleResource, + @NonNull Collection constraintSets) throws IOException, MetaschemaException { + ExternalConstraintsModulePostProcessor postProcessor + = new ExternalConstraintsModulePostProcessor(constraintSets); + + ModuleLoader loader = new ModuleLoader(CollectionUtil.singletonList(postProcessor)); + + // BindingModuleLoader loader + // = new BindingModuleLoader(new DefaultBindingContext(), + // CollectionUtil.singletonList(postProcessor)); + + loader.allowEntityResolution(); + return loader.load(moduleResource); + } + + @NonNull + public static URI handleResource( + @NonNull String location, + @NonNull URI cwd) throws IOException { + try { + return UriUtils.toUri(location, cwd); + } catch (URISyntaxException ex) { + IOException newEx = new IOException( // NOPMD - intentional + String.format("Cannot load module as '%s' is not a valid file or URL.", location)); + newEx.addSuppressed(ex); + throw newEx; + } + } private MetaschemaCommands() { // disable construction diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateContentUsingModuleCommand.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateContentUsingModuleCommand.java index 4e1ebcae9..7b7d4f0b0 100644 --- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateContentUsingModuleCommand.java +++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateContentUsingModuleCommand.java @@ -14,11 +14,8 @@ import gov.nist.secauto.metaschema.core.model.constraint.IConstraintSet; import gov.nist.secauto.metaschema.core.model.util.JsonUtil; import gov.nist.secauto.metaschema.core.model.util.XmlUtil; -import gov.nist.secauto.metaschema.core.model.xml.ExternalConstraintsModulePostProcessor; -import gov.nist.secauto.metaschema.core.model.xml.ModuleLoader; import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; -import gov.nist.secauto.metaschema.core.util.UriUtils; import gov.nist.secauto.metaschema.databind.DefaultBindingContext; import gov.nist.secauto.metaschema.databind.IBindingContext; import gov.nist.secauto.metaschema.schemagen.ISchemaGenerator; @@ -68,7 +65,7 @@ public Collection gatherOptions() { List