From 3226a2a710d5392f108dd07b49ff912c9e2e8c16 Mon Sep 17 00:00:00 2001 From: David Waltermire Date: Fri, 19 Jan 2024 22:41:58 -0500 Subject: [PATCH] Fixed a bug causing constraint targets to not get parsed and instead end up as null. Fixed a bug causing empty annotation documentation in XML for enumerated values with no description. --- .../datatype/markup/AbstractMarkupString.java | 41 ++------------ .../core/datatype/markup/IMarkupString.java | 2 + .../impl/ConstraintBindingSupport.java | 10 ++-- .../databind/codegen/BasicMetaschemaTest.java | 1 + .../databind/codegen/GenerationTest.java | 56 +++++++++++++++++++ .../maven/plugin/GenerateSourcesMojo.java | 4 +- .../XmlSimpleTypeDataTypeRestriction.java | 16 +++--- .../schemagen/MetaschemaModuleTest.java | 14 ++++- 8 files changed, 92 insertions(+), 52 deletions(-) create mode 100644 databind/src/test/java/gov/nist/secauto/metaschema/databind/codegen/GenerationTest.java diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/AbstractMarkupString.java b/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/AbstractMarkupString.java index 0ecae053a..667e292af 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/AbstractMarkupString.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/AbstractMarkupString.java @@ -104,43 +104,10 @@ public Document getDocument() { return document; } - // @Override - // public void writeHtml(@NonNull XMLStreamWriter2 xmlStreamWriter, @NonNull - // String namespace) - // throws XMLStreamException { - // - // - // IMarkupString markupString = (IMarkupString<>)value; - // - // MarkupXmlStreamWriter writingVisitor - // = new MarkupXmlStreamWriter(namespace, markupString.isBlock()); - // writingVisitor.visitChildren(getDocument(), xmlStreamWriter); - // xmlStreamWriter.flush(); - // } - // - // @Override - // public void writeHtml(@NonNull OutputStream os, @Nullable String namespace, - // @Nullable String - // prefix) - // throws XMLStreamException { - // XMLOutputFactory2 factory = (XMLOutputFactory2) - // XMLOutputFactory.newInstance(); - // assert factory instanceof WstxOutputFactory; - // factory.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, false); - // XMLStreamWriter2 xmlStreamWriter = (XMLStreamWriter2) - // factory.createXMLStreamWriter(os); - // - // String effectiveNamespace = namespace == null ? DEFAULT_HTML_NS : namespace; - // String effectivePrefix = prefix == null ? DEFAULT_HTML_PREFIX : prefix; - // NamespaceContext nsContext = - // MergedNsContext.construct(xmlStreamWriter.getNamespaceContext(), - // List.of(NamespaceEventImpl.constructNamespace(null, effectivePrefix, - // effectiveNamespace))); - // xmlStreamWriter.setNamespaceContext(nsContext); - // - // - // writeHtml(xmlStreamWriter, effectiveNamespace); - // } + @Override + public boolean isEmpty() { + return getDocument().getFirstChild() == null; + } /** * Parse HTML-based text into markdown as a flexmark AST graph. diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/IMarkupString.java b/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/IMarkupString.java index c120f19a4..a2d162b56 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/IMarkupString.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/IMarkupString.java @@ -55,6 +55,8 @@ public interface IMarkupString> @NonNull Document getDocument(); + boolean isEmpty(); + // /** // * Write HTML content to the provided {@code xmlStreamWriter} using the // provided {@code diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ConstraintBindingSupport.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ConstraintBindingSupport.java index 5f8c2d0b4..56c5e4d3b 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ConstraintBindingSupport.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ConstraintBindingSupport.java @@ -238,7 +238,7 @@ private static IIndexHasKeyConstraint newIndexHasKey( @NonNull ISource source) { IIndexHasKeyConstraint.Builder builder = IIndexHasKeyConstraint.builder() .name(ObjectUtils.requireNonNull(obj.getName())); - applyCommonValues(obj, null, source, builder); + applyCommonValues(obj, obj.getTarget(), source, builder); handleKeyConstraints(ObjectUtils.requireNonNull(obj.getKeyFields()), builder); return builder.build(); } @@ -269,7 +269,7 @@ private static IMatchesConstraint newMatches( @NonNull TargetedMatchesConstraint obj, @NonNull ISource source) { IMatchesConstraint.Builder builder = IMatchesConstraint.builder(); - applyCommonValues(obj, null, source, builder); + applyCommonValues(obj, obj.getTarget(), source, builder); Pattern regex = pattern(obj.getRegex()); if (regex != null) { @@ -291,7 +291,7 @@ private static IIndexConstraint newIndex( @NonNull ISource source) { IIndexConstraint.Builder builder = IIndexConstraint.builder() .name(ObjectUtils.requireNonNull(obj.getName())); - applyCommonValues(obj, null, source, builder); + applyCommonValues(obj, obj.getTarget(), source, builder); handleKeyConstraints(ObjectUtils.requireNonNull(obj.getKeyFields()), builder); return builder.build(); @@ -302,7 +302,7 @@ private static ICardinalityConstraint newHasCardinality( @NonNull AssemblyConstraints.HasCardinality obj, @NonNull ISource source) { ICardinalityConstraint.Builder builder = ICardinalityConstraint.builder(); - applyCommonValues(obj, null, source, builder); + applyCommonValues(obj, obj.getTarget(), source, builder); BigInteger minOccurs = obj.getMinOccurs(); if (minOccurs != null) { @@ -322,7 +322,7 @@ private static IUniqueConstraint newUnique( @NonNull AssemblyConstraints.Unique obj, @NonNull ISource source) { IUniqueConstraint.Builder builder = IUniqueConstraint.builder(); - applyCommonValues(obj, null, source, builder); + applyCommonValues(obj, obj.getTarget(), source, builder); handleKeyConstraints(ObjectUtils.requireNonNull(obj.getKeyFields()), builder); return builder.build(); diff --git a/databind/src/test/java/gov/nist/secauto/metaschema/databind/codegen/BasicMetaschemaTest.java b/databind/src/test/java/gov/nist/secauto/metaschema/databind/codegen/BasicMetaschemaTest.java index d899c3c4e..a3fa4f16d 100644 --- a/databind/src/test/java/gov/nist/secauto/metaschema/databind/codegen/BasicMetaschemaTest.java +++ b/databind/src/test/java/gov/nist/secauto/metaschema/databind/codegen/BasicMetaschemaTest.java @@ -181,4 +181,5 @@ void testLocalDefinitionsMetaschema() "gov.nist.csrc.ns.metaschema.testing.local.definitions.TopLevel", ObjectUtils.notNull(generationDir)); } + } diff --git a/databind/src/test/java/gov/nist/secauto/metaschema/databind/codegen/GenerationTest.java b/databind/src/test/java/gov/nist/secauto/metaschema/databind/codegen/GenerationTest.java new file mode 100644 index 000000000..b8d16283a --- /dev/null +++ b/databind/src/test/java/gov/nist/secauto/metaschema/databind/codegen/GenerationTest.java @@ -0,0 +1,56 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.databind.codegen; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import gov.nist.secauto.metaschema.core.model.MetaschemaException; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.IBindingContext; +import gov.nist.secauto.metaschema.databind.io.DeserializationFeature; +import gov.nist.secauto.metaschema.databind.model.metaschema.BindingModuleLoader; +import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingModule; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.URI; +import java.nio.file.Paths; + +public class GenerationTest { + + @Test + void testOscalBindingModuleLoader() throws MetaschemaException, IOException { + BindingModuleLoader loader = new BindingModuleLoader(); + loader.set(DeserializationFeature.DESERIALIZE_XML_ALLOW_ENTITY_RESOLUTION, true); + IBindingModule module = loader.load(ObjectUtils.notNull(URI.create( + "https://raw.githubusercontent.com/usnistgov/OSCAL/main/src/metaschema/oscal_complete_metaschema.xml"))); + IBindingContext context = IBindingContext.instance().registerModule(module, Paths.get("target/oscal-classes")); + + assertNotNull(module); + } +} diff --git a/metaschema-maven-plugin/src/main/java/gov/nist/secauto/metaschema/maven/plugin/GenerateSourcesMojo.java b/metaschema-maven-plugin/src/main/java/gov/nist/secauto/metaschema/maven/plugin/GenerateSourcesMojo.java index 314ee7ee3..e4066743b 100644 --- a/metaschema-maven-plugin/src/main/java/gov/nist/secauto/metaschema/maven/plugin/GenerateSourcesMojo.java +++ b/metaschema-maven-plugin/src/main/java/gov/nist/secauto/metaschema/maven/plugin/GenerateSourcesMojo.java @@ -28,10 +28,10 @@ import gov.nist.secauto.metaschema.core.model.IModule; import gov.nist.secauto.metaschema.core.model.MetaschemaException; -import gov.nist.secauto.metaschema.core.model.xml.ModuleLoader; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.metaschema.databind.codegen.JavaGenerator; import gov.nist.secauto.metaschema.databind.codegen.config.DefaultBindingConfiguration; +import gov.nist.secauto.metaschema.databind.model.metaschema.BindingModuleLoader; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; @@ -157,7 +157,7 @@ public void execute() throws MojoExecutionException { } // generate Java sources based on provided metaschema sources - final ModuleLoader loader = new ModuleLoader(); + final BindingModuleLoader loader = new BindingModuleLoader(); loader.allowEntityResolution(); final Set modules = new HashSet<>(); for (File source : getSources().collect(Collectors.toList())) { diff --git a/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/xml/schematype/XmlSimpleTypeDataTypeRestriction.java b/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/xml/schematype/XmlSimpleTypeDataTypeRestriction.java index 2805106cc..ef879185f 100644 --- a/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/xml/schematype/XmlSimpleTypeDataTypeRestriction.java +++ b/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/xml/schematype/XmlSimpleTypeDataTypeRestriction.java @@ -86,13 +86,15 @@ public void generate(XmlGenerationState state) { state.writeAttribute("value", allowedValue.getValue()); MarkupLine description = allowedValue.getDescription(); - generateDescriptionAnnotation( - description, - ObjectUtils.notNull(getQName().getNamespaceURI()), - state); - // LOGGER.info(String.format("Field:%s:%s: %s", - // definition.getContainingMetaschema().getLocation(), - // definition.getName(), allowedValue.getValue())); + if (!description.isEmpty()) { + generateDescriptionAnnotation( + description, + ObjectUtils.notNull(getQName().getNamespaceURI()), + state); + // LOGGER.info(String.format("Field:%s:%s: %s", + // definition.getContainingMetaschema().getLocation(), + // definition.getName(), allowedValue.getValue())); + } state.writeEndElement(); // xs:enumeration } diff --git a/schemagen/src/test/java/gov/nist/secauto/metaschema/schemagen/MetaschemaModuleTest.java b/schemagen/src/test/java/gov/nist/secauto/metaschema/schemagen/MetaschemaModuleTest.java index 739c0c91f..5f57d26c1 100644 --- a/schemagen/src/test/java/gov/nist/secauto/metaschema/schemagen/MetaschemaModuleTest.java +++ b/schemagen/src/test/java/gov/nist/secauto/metaschema/schemagen/MetaschemaModuleTest.java @@ -54,7 +54,7 @@ class MetaschemaModuleTest { = ObjectUtils.notNull(Paths.get("../core/metaschema/schema/metaschema/metaschema-module-metaschema.xml")); @Test - void testMetaschemaMetaschema() throws MetaschemaException, IOException { + void testGenerateMetaschemaModuleJson() throws MetaschemaException, IOException { BindingModuleLoader loader = new BindingModuleLoader(); IBindingModule module = loader.load(METASCHEMA_FILE); @@ -76,6 +76,18 @@ void testMetaschemaMetaschema() throws MetaschemaException, IOException { ISchemaGenerator schemaGenerator = new JsonSchemaGenerator(); schemaGenerator.generateFromModule(module, writer, features); } + } + + @Test + void testGenerateMetaschemaModuleXml() throws MetaschemaException, IOException { + BindingModuleLoader loader = new BindingModuleLoader(); + + IBindingModule module = loader.load(METASCHEMA_FILE); + + IMutableConfiguration> features + = new DefaultConfiguration<>(); + features.enableFeature(SchemaGenerationFeature.INLINE_DEFINITIONS); + // features.disableFeature(SchemaGenerationFeature.INLINE_DEFINITIONS); try (Writer writer = Files.newBufferedWriter( Path.of("target/metaschema-schema.xsd"),