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