From 4905565e3d78591f20d7a0ed9ebf52b03a06e4d8 Mon Sep 17 00:00:00 2001 From: David Waltermire Date: Fri, 4 Aug 2023 09:27:06 -0400 Subject: [PATCH] Integrating further metaschema-java refactoring. --- pom.xml | 15 +- .../oscal/lib/OscalBindingContext.java | 8 +- .../nist/secauto/oscal/lib/OscalUtils.java | 68 -------- .../function/library/HasOscalNamespace.java | 3 + .../function/library/ResolveProfile.java | 3 + .../control/catalog/AbstractControl.java | 2 +- .../control/catalog/IControlContainer.java | 9 +- .../control/catalog/IGroupContainer.java | 3 +- .../lib/model/metadata/AbstractProperty.java | 1 + .../oscal/lib/model/metadata/IProperty.java | 4 +- .../resolver/ProfileResolutionException.java | 4 +- .../lib/profile/resolver/ProfileResolver.java | 163 +++++++++--------- .../profile/resolver/alter/AddVisitor.java | 21 ++- .../profile/resolver/alter/RemoveVisitor.java | 14 +- .../merge/FlatteningStructuringVisitor.java | 2 +- .../policy/AbstractCustomReferencePolicy.java | 43 +++-- .../policy/ICustomReferencePolicyHandler.java | 21 ++- .../resolver/policy/IIdentifierParser.java | 3 +- .../resolver/policy/IReferenceVisitor.java | 26 +-- .../policy/ReferenceCountingVisitor.java | 18 +- .../selection/ControlSelectionVisitor.java | 19 +- .../DefaultControlSelectionFilter.java | 12 +- .../resolver/selection/IControlFilter.java | 25 +-- .../selection/IControlSelectionFilter.java | 11 +- .../support/AbstractCatalogEntityVisitor.java | 58 ++++--- .../support/AbstractCatalogVisitor.java | 12 +- .../resolver/support/AbstractEntityItem.java | 5 +- .../resolver/support/BasicIndexer.java | 18 +- .../resolver/support/ICatalogVisitor.java | 14 +- .../profile/resolver/support/IEntityItem.java | 16 +- .../profile/resolver/support/IIndexer.java | 33 ++-- .../nist/secauto/oscal/java/ExamplesTest.java | 31 ++-- .../oscal/java/MetaschemaVisitorTest.java | 38 ++-- .../oscal/java/OscalBindingContextTest.java | 9 +- .../secauto/oscal/java/ReadWriteTest.java | 32 ++-- .../resolver/ProfileResolutionTests.java | 13 +- .../oscal/lib/profile/resolver/TestUtil.java | 8 +- .../policy/ReferenceCountingVisitorTest.java | 2 +- .../DefaultControlSelectionFilterTest.java | 3 +- .../FilterNonSelectedVisitorTest.java | 2 +- .../resolver/selection/ImportTest.java | 20 +-- src/test/resources/log4j2-test.xml | 4 +- src/test/resources/profile-test-helper.xsl | 75 ++++++++ 43 files changed, 495 insertions(+), 396 deletions(-) create mode 100644 src/test/resources/profile-test-helper.xsl diff --git a/pom.xml b/pom.xml index 01356d0a..6226a045 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ gov.nist.secauto oss-parent - 26 + 27-SNAPSHOT gov.nist.secauto.oscal @@ -243,18 +243,7 @@ org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - - org.junit.jupiter - junit-jupiter-params + junit-jupiter test diff --git a/src/main/java/gov/nist/secauto/oscal/lib/OscalBindingContext.java b/src/main/java/gov/nist/secauto/oscal/lib/OscalBindingContext.java index cd427f25..67bcba83 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/OscalBindingContext.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/OscalBindingContext.java @@ -26,9 +26,9 @@ package gov.nist.secauto.oscal.lib; -import gov.nist.secauto.metaschema.binding.DefaultBindingContext; -import gov.nist.secauto.metaschema.binding.IBindingMatcher; import gov.nist.secauto.metaschema.core.model.constraint.IConstraintSet; +import gov.nist.secauto.metaschema.databind.DefaultBindingContext; +import gov.nist.secauto.metaschema.databind.IBindingMatcher; import gov.nist.secauto.oscal.lib.model.AssessmentPlan; import gov.nist.secauto.oscal.lib.model.AssessmentResults; import gov.nist.secauto.oscal.lib.model.Catalog; @@ -51,6 +51,8 @@ public class OscalBindingContext extends DefaultBindingContext { @NonNull + public static final String NS_OSCAL = "http://csrc.nist.gov/ns/oscal/1.0"; + @NonNull private static final OscalBindingContext SINGLETON = new OscalBindingContext(); @NonNull @@ -186,7 +188,7 @@ private static final class Matcher implements IBindingMatcher { @Override public Class getBoundClassForXmlQName(QName startElementQName) { Class clazz = null; - if ("http://csrc.nist.gov/ns/oscal/1.0".equals(startElementQName.getNamespaceURI())) { + if (NS_OSCAL.equals(startElementQName.getNamespaceURI())) { switch (startElementQName.getLocalPart()) { case "catalog": clazz = Catalog.class; diff --git a/src/main/java/gov/nist/secauto/oscal/lib/OscalUtils.java b/src/main/java/gov/nist/secauto/oscal/lib/OscalUtils.java index 9a1fb520..42b26735 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/OscalUtils.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/OscalUtils.java @@ -26,22 +26,12 @@ package gov.nist.secauto.oscal.lib; -import com.fasterxml.jackson.databind.util.ByteBufferBackedInputStream; - import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.BackMatter.Resource; -import gov.nist.secauto.oscal.lib.model.BackMatter.Resource.Base64; import gov.nist.secauto.oscal.lib.model.BackMatter.Resource.Rlink; -import org.xml.sax.EntityResolver; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -import java.io.IOException; import java.net.URI; -import java.nio.ByteBuffer; import java.util.List; -import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -49,7 +39,6 @@ import edu.umd.cs.findbugs.annotations.Nullable; public final class OscalUtils { - public static final String OSCAL_VERSION = "1.0.4"; private static final Pattern INTERNAL_REFERENCE_FRAGMENT_PATTERN = Pattern.compile("^#(.+)$"); private OscalUtils() { @@ -103,37 +92,6 @@ public static String internalReferenceFragmentToId(@NonNull String fragment) { return retval; } - public static boolean hasBase64Data(@NonNull Resource resource) { - return resource.getBase64() != null; - } - - @Nullable - public static ByteBuffer getBase64Data(@NonNull Resource resource) { - Base64 base64 = resource.getBase64(); - - ByteBuffer retval = null; - if (base64 != null) { - retval = base64.getValue(); - } - return retval; - } - - @Nullable - public static URI getResourceURI(@NonNull Resource resource, @Nullable String preferredMediaType) { - URI retval; - if (hasBase64Data(resource)) { - UUID uuid = resource.getUuid(); - if (uuid == null) { - throw new IllegalArgumentException("resource has a null UUID"); - } - retval = ObjectUtils.notNull(URI.create("#" + uuid)); - } else { - Rlink rlink = findMatchingRLink(resource, preferredMediaType); - retval = rlink == null ? null : rlink.getHref(); - } - return retval; - } - @Nullable public static Rlink findMatchingRLink(@NonNull Resource resource, @Nullable String preferredMediaType) { // find a suitable rlink reference @@ -153,30 +111,4 @@ public static Rlink findMatchingRLink(@NonNull Resource resource, @Nullable Stri } return retval; } - - @Nullable - public static InputSource newInputSource(@NonNull Resource resource, @NonNull EntityResolver resolver, - @Nullable String preferredMediaType) throws IOException { - URI uri = getResourceURI(resource, preferredMediaType); - if (uri == null) { - throw new IOException(String.format("unable to determine URI for resource '%s'", resource.getUuid())); - } - - InputSource retval; - try { - retval = resolver.resolveEntity(null, uri.toASCIIString()); - } catch (SAXException ex) { - throw new IOException(ex); - } - - if (hasBase64Data(resource)) { - // handle base64 encoded data - ByteBuffer buffer = getBase64Data(resource); - if (buffer == null) { - throw new IOException(String.format("null base64 value for resource '%s'", resource.getUuid())); - } - retval.setByteStream(new ByteBufferBackedInputStream(buffer)); - } - return retval; - } } diff --git a/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/HasOscalNamespace.java b/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/HasOscalNamespace.java index fa9256ce..1d29f3ee 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/HasOscalNamespace.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/HasOscalNamespace.java @@ -38,6 +38,7 @@ import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem; import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.model.AssessmentPart; import gov.nist.secauto.oscal.lib.model.ControlPart; import gov.nist.secauto.oscal.lib.model.Property; @@ -52,6 +53,7 @@ public final class HasOscalNamespace { @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name("has-oscal-namespace") + .namespace(OscalBindingContext.NS_OSCAL) .argument(IArgument.newBuilder() .name("namespace") .type(IStringItem.class) @@ -69,6 +71,7 @@ public final class HasOscalNamespace { @NonNull static final IFunction SIGNATURE_TWO_ARGS = IFunction.builder() .name("has-oscal-namespace") + .namespace(OscalBindingContext.NS_OSCAL) .argument(IArgument.newBuilder() .name("propOrPart") .type(IAssemblyNodeItem.class) diff --git a/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/ResolveProfile.java b/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/ResolveProfile.java index e29cf2b9..f2edfa53 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/ResolveProfile.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/ResolveProfile.java @@ -36,6 +36,7 @@ import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolutionException; import gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolver; @@ -50,6 +51,7 @@ public final class ResolveProfile { @NonNull static final IFunction SIGNATURE_NO_ARG = IFunction.builder() .name("resolve-profile") + .namespace(OscalBindingContext.NS_OSCAL) .returnType(INodeItem.class) .focusDependent() .contextDependent() @@ -61,6 +63,7 @@ public final class ResolveProfile { @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name("resolve-profile") + .namespace(OscalBindingContext.NS_OSCAL) .argument(IArgument.newBuilder() .name("profile") .type(INodeItem.class) diff --git a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractControl.java b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractControl.java index bbfa44a0..23a3df33 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractControl.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractControl.java @@ -26,10 +26,10 @@ package gov.nist.secauto.oscal.lib.model.control.catalog; -import gov.nist.secauto.metaschema.binding.io.IDeserializationHandler; import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine; import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.io.IDeserializationHandler; import gov.nist.secauto.oscal.lib.model.Control; import gov.nist.secauto.oscal.lib.model.ControlPart; import gov.nist.secauto.oscal.lib.model.Link; diff --git a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/IControlContainer.java b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/IControlContainer.java index d554ab67..35cd1c44 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/IControlContainer.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/IControlContainer.java @@ -48,7 +48,8 @@ public interface IControlContainer { boolean addControl(@NonNull Control item); /** - * Remove the first matching {@link Control} item from the underlying collection. + * Remove the first matching {@link Control} item from the underlying + * collection. * * @param item * the item to remove @@ -68,7 +69,8 @@ public interface IControlContainer { boolean addParam(@NonNull Parameter item); /** - * Remove the first matching {@link Parameter} item from the underlying collection. + * Remove the first matching {@link Parameter} item from the underlying + * collection. * * @param item * the item to remove @@ -77,7 +79,8 @@ public interface IControlContainer { boolean removeParam(@NonNull Parameter item); /** - * Get the parameter identifiers referenced in the object's context, but not by their child objects. + * Get the parameter identifiers referenced in the object's context, but not by + * their child objects. * * @return a stream of identifiers */ diff --git a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/IGroupContainer.java b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/IGroupContainer.java index 6162c613..8f9f7ed7 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/IGroupContainer.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/IGroupContainer.java @@ -46,7 +46,8 @@ public interface IGroupContainer extends IControlContainer { boolean addGroup(@NonNull CatalogGroup item); /** - * Remove the first matching {@link CatalogGroup} item from the underlying collection. + * Remove the first matching {@link CatalogGroup} item from the underlying + * collection. * * @param item * the item to remove diff --git a/src/main/java/gov/nist/secauto/oscal/lib/model/metadata/AbstractProperty.java b/src/main/java/gov/nist/secauto/oscal/lib/model/metadata/AbstractProperty.java index fa30290c..ef91b23d 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/metadata/AbstractProperty.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/metadata/AbstractProperty.java @@ -112,6 +112,7 @@ public Builder uuid(@NonNull UUID uuid) { return this; } + @SuppressWarnings("PMD.NullAssignment") // needed @NonNull public Builder namespace(@NonNull URI namespace) { if (IProperty.OSCAL_NAMESPACE.equals(namespace)) { diff --git a/src/main/java/gov/nist/secauto/oscal/lib/model/metadata/IProperty.java b/src/main/java/gov/nist/secauto/oscal/lib/model/metadata/IProperty.java index a026e78c..dae33a69 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/metadata/IProperty.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/metadata/IProperty.java @@ -26,6 +26,8 @@ package gov.nist.secauto.oscal.lib.model.metadata; +import gov.nist.secauto.oscal.lib.OscalBindingContext; + import java.net.URI; import edu.umd.cs.findbugs.annotations.NonNull; @@ -33,7 +35,7 @@ public interface IProperty { @SuppressWarnings("null") @NonNull - URI OSCAL_NAMESPACE = URI.create("http://csrc.nist.gov/ns/oscal"); + URI OSCAL_NAMESPACE = URI.create(OscalBindingContext.NS_OSCAL); @SuppressWarnings("null") @NonNull URI RMF_NAMESPACE = URI.create("http://csrc.nist.gov/ns/rmf"); diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolutionException.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolutionException.java index 06694c1f..55e75870 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolutionException.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolutionException.java @@ -47,8 +47,8 @@ public ProfileResolutionException(String message) { } /** - * Create a new profile resolution exception with the provided {@code message} based on the provided - * {@code cause}. + * Create a new profile resolution exception with the provided {@code message} + * based on the provided {@code cause}. * * @param message * a description of the error that occurred diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolver.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolver.java index c431700f..25710e6c 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolver.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolver.java @@ -26,12 +26,10 @@ package gov.nist.secauto.oscal.lib.profile.resolver; -import gov.nist.secauto.metaschema.binding.io.BindingException; -import gov.nist.secauto.metaschema.binding.io.DeserializationFeature; -import gov.nist.secauto.metaschema.binding.io.IBoundLoader; -import gov.nist.secauto.metaschema.binding.model.IAssemblyClassBinding; -import gov.nist.secauto.metaschema.binding.model.RootAssemblyDefinition; +import com.fasterxml.jackson.databind.util.ByteBufferBackedInputStream; + import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.IDocumentLoader; import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; import gov.nist.secauto.metaschema.core.metapath.StaticContext; @@ -45,10 +43,16 @@ import gov.nist.secauto.metaschema.core.metapath.item.node.IRootAssemblyNodeItem; import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.io.BindingException; +import gov.nist.secauto.metaschema.databind.io.DeserializationFeature; +import gov.nist.secauto.metaschema.databind.io.IBoundLoader; +import gov.nist.secauto.metaschema.databind.model.IAssemblyClassBinding; import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.OscalUtils; import gov.nist.secauto.oscal.lib.model.BackMatter; import gov.nist.secauto.oscal.lib.model.BackMatter.Resource; +import gov.nist.secauto.oscal.lib.model.BackMatter.Resource.Base64; +import gov.nist.secauto.oscal.lib.model.BackMatter.Resource.Rlink; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.Control; import gov.nist.secauto.oscal.lib.model.Merge; @@ -74,15 +78,14 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.xml.sax.EntityResolver; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.nio.ByteBuffer; import java.nio.file.Path; import java.time.ZoneOffset; import java.time.ZonedDateTime; @@ -128,7 +131,8 @@ public enum StructuringDirective { private DynamicContext dynamicContext; /** - * Gets the configured loader or creates a new default loader if no loader was configured. + * Gets the configured loader or creates a new default loader if no loader was + * configured. * * @return the bound loader */ @@ -155,7 +159,7 @@ public void setBoundLoader(@NonNull IBoundLoader loader) { public DynamicContext getDynamicContext() { synchronized (this) { if (dynamicContext == null) { - dynamicContext = new StaticContext().newDynamicContext(); + dynamicContext = StaticContext.builder().build().newDynamicContext(); dynamicContext.setDocumentLoader(getBoundLoader()); } assert dynamicContext != null; @@ -170,11 +174,6 @@ public void setDynamicContext(@NonNull DynamicContext dynamicContext) { } } - @NonNull - protected EntityResolver getEntityResolver(@NonNull URI documentUri) { - return new DocumentEntityResolver(documentUri); - } - @Nullable private static IRootAssemblyNodeItem getRoot( @NonNull IDocumentNodeItem document, @@ -272,9 +271,8 @@ protected IDocumentNodeItem resolveProfile( handleModify(resolvedCatalog, profileItem); return INodeItemFactory.instance().newDocumentNodeItem( - new RootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class))), + ObjectUtils.requireNonNull( + (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class)), ObjectUtils.requireNonNull(profileItem.getBaseUri()), resolvedCatalog); } @@ -359,25 +357,30 @@ protected IIndexer resolveImport( LOGGER.atDebug().log("resolving profile import '{}'", importUri); } - InputSource source = newImportSource(importUri, profileItem); - URI sourceUri = ObjectUtils.notNull(URI.create(source.getSystemId())); + IDocumentNodeItem importedDocument = getImport(importUri, profileItem); + URI importedUri = importedDocument.getDocumentUri(); + assert importedUri != null; // always non-null + + // Import import = Import. + // InputSource source = newImportSource(importUri, profileItem); + // URI sourceUri = ObjectUtils.notNull(URI.create(source.getSystemId())); // check for import cycle try { requireNonCycle( - sourceUri, + importedUri, importHistory); } catch (ImportCycleException ex) { throw new IOException(ex); } // track the import in the import history - importHistory.push(sourceUri); + importHistory.push(importedUri); try { - IDocumentNodeItem document = getDynamicContext().getDocumentLoader().loadAsNodeItem(source); - IDocumentNodeItem importedCatalog = resolve(document, importHistory); + IDocumentNodeItem importedCatalog = resolve(importedDocument, importHistory); - // Create a defensive deep copy of the document and associated values, since we will be making + // Create a defensive deep copy of the document and associated values, since we + // will be making // changes to the data. try { IRootAssemblyNodeItem importedCatalogRoot = ObjectUtils.requireNonNull(getRoot(importedCatalog, CATALOG)); @@ -397,45 +400,70 @@ protected IIndexer resolveImport( } finally { // pop the resolved catalog from the import history URI poppedUri = ObjectUtils.notNull(importHistory.pop()); - assert sourceUri.equals(poppedUri); + assert importedUri.equals(poppedUri); } } - @NonNull - protected InputSource newImportSource( + private IDocumentNodeItem getImport( @NonNull URI importUri, - @NonNull IRootAssemblyNodeItem profileItem) throws IOException { + @NonNull IRootAssemblyNodeItem importingProfile) throws IOException { - // Get the entity resolver to resolve relative references in the profile - EntityResolver resolver = getEntityResolver( - ObjectUtils.requireNonNull(profileItem.getDocumentNodeItem().getDocumentUri())); + URI importingDocumentUri = ObjectUtils.requireNonNull(importingProfile.getDocumentNodeItem().getDocumentUri()); - InputSource source; + IDocumentNodeItem retval; if (OscalUtils.isInternalReference(importUri)) { // handle internal reference String uuid = OscalUtils.internalReferenceFragmentToId(importUri); - Profile profile = toProfile(profileItem); + Profile profile = INodeItem.toValue(importingProfile); Resource resource = profile.getResourceByUuid(ObjectUtils.notNull(UUID.fromString(uuid))); if (resource == null) { throw new IOException( String.format("unable to find the resource identified by '%s' used in profile import", importUri)); } - source = OscalUtils.newInputSource(resource, resolver, null); + retval = getImport(resource, importingDocumentUri); } else { - try { - source = resolver.resolveEntity(null, importUri.toASCIIString()); - } catch (SAXException ex) { - throw new IOException(ex); - } + URI uri = importingDocumentUri.resolve(importUri); + assert uri != null; + + retval = getDynamicContext().getDocumentLoader().loadAsNodeItem(uri); } + return retval; + } - if (source == null || source.getSystemId() == null) { - throw new IOException(String.format("Unable to resolve import '%s'.", importUri.toString())); + @Nullable + private IDocumentNodeItem getImport( + @NonNull Resource resource, + @NonNull URI baseUri) throws IOException { + + IDocumentLoader loader = getDynamicContext().getDocumentLoader(); + + IDocumentNodeItem retval = null; + // first try base64 data + Base64 base64 = resource.getBase64(); + ByteBuffer buffer = base64 == null ? null : base64.getValue(); + if (buffer != null) { + URI resourceUri = baseUri.resolve("#" + resource.getUuid()); + assert resourceUri != null; + try (InputStream is = new ByteBufferBackedInputStream(buffer)) { + retval = loader.loadAsNodeItem(is, resourceUri); + } } - return source; + if (retval == null) { + Rlink rlink = OscalUtils.findMatchingRLink(resource, null); + URI uri = rlink == null ? null : rlink.getHref(); + + if (uri == null) { + throw new IOException(String.format("unable to determine URI for resource '%s'", resource.getUuid())); + } + + uri = baseUri.resolve(uri); + assert uri != null; + retval = loader.loadAsNodeItem(uri); + } + return retval; } private static void requireNonCycle(@NonNull URI uri, @NonNull Stack importHistory) @@ -507,14 +535,17 @@ protected void structureFlat(@NonNull Catalog resolvedCatalog, @NonNull IRootAss // { // // rebuild an index - // IDocumentNodeItem resolvedCatalogItem = DefaultNodeItemFactory.instance().newDocumentNodeItem( + // IDocumentNodeItem resolvedCatalogItem = + // DefaultNodeItemFactory.instance().newDocumentNodeItem( // new RootAssemblyDefinition( // ObjectUtils.notNull( - // (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class))), + // (IAssemblyClassBinding) + // OscalBindingContext.instance().getClassBinding(Catalog.class))), // resolvedCatalog, // profileDocument.getBaseUri()); // - // // FIXME: need to find a better way to create an index that doesn't auto select groups + // // FIXME: need to find a better way to create an index that doesn't auto + // select groups // IIndexer indexer = new BasicIndexer(); // ControlSelectionVisitor selectionVisitor // = new ControlSelectionVisitor(IControlFilter.ALWAYS_MATCH, indexer); @@ -523,9 +554,8 @@ protected void structureFlat(@NonNull Catalog resolvedCatalog, @NonNull IRootAss // rebuild the document, since the paths have changed IDocumentNodeItem resolvedCatalogItem = INodeItemFactory.instance().newDocumentNodeItem( - new RootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class))), + ObjectUtils.requireNonNull( + (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class)), ObjectUtils.requireNonNull(profileItem.getBaseUri()), resolvedCatalog); @@ -536,9 +566,8 @@ protected void structureFlat(@NonNull Catalog resolvedCatalog, @NonNull IRootAss protected void handleModify(@NonNull Catalog resolvedCatalog, @NonNull IRootAssemblyNodeItem profileItem) throws ProfileResolutionException { IDocumentNodeItem resolvedCatalogDocument = INodeItemFactory.instance().newDocumentNodeItem( - new RootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class))), + ObjectUtils.requireNonNull( + (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class)), ObjectUtils.requireNonNull(profileItem.getBaseUri()), resolvedCatalog); @@ -721,34 +750,4 @@ private static void handleReferences(@NonNull Catalog resolvedCatalog, @NonNull index.append(profileIndex); } - private class DocumentEntityResolver implements EntityResolver { - @NonNull - private final URI documentUri; - - public DocumentEntityResolver(@NonNull URI documentUri) { - this.documentUri = documentUri; - } - - @NonNull - protected URI getDocumentUri() { - return documentUri; - } - - @Override - public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { - - URI resolvedUri = getDocumentUri().resolve(systemId); - - EntityResolver resolver = getDynamicContext().getDocumentLoader().getEntityResolver(); - - InputSource retval; - if (resolver == null) { - retval = new InputSource(resolvedUri.toASCIIString()); - } else { - retval = resolver.resolveEntity(publicId, resolvedUri.toASCIIString()); - } - return retval; - } - - } } diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/alter/AddVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/alter/AddVisitor.java index ac3dfe51..75870f57 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/alter/AddVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/alter/AddVisitor.java @@ -95,8 +95,8 @@ public enum TargetType { * * @param clazz * the class to identify the target type for - * @return the associated target type or {@code null} if the class is not associated with a target - * type + * @return the associated target type or {@code null} if the class is not + * associated with a target type */ @Nullable public static TargetType forClass(@NonNull Class clazz) { @@ -114,8 +114,8 @@ public static TargetType forClass(@NonNull Class clazz) { * * @param name * the field name to identify the target type for - * @return the associated target type or {@code null} if the name is not associated with a target - * type + * @return the associated target type or {@code null} if the name is not + * associated with a target type */ @Nullable public static TargetType forFieldName(@Nullable String name) { @@ -168,7 +168,8 @@ public enum Position { * * @param name * the name to identify the position for - * @return the associated position or {@code null} if the name is not associated with a position + * @return the associated position or {@code null} if the name is not associated + * with a position */ @Nullable public static Position forName(@Nullable String name) { @@ -257,8 +258,8 @@ public Boolean visitGroup(CatalogGroup group, Context context) { *
  • the context matches if: *
      *
    • the target item's id matches the "by-id"; or
    • - *
    • the "by-id" is not defined and the target item is the control matching the target - * context
    • + *
    • the "by-id" is not defined and the target item is the control matching + * the target context
    • *
    *
  • * @@ -268,7 +269,8 @@ public Boolean visitGroup(CatalogGroup group, Context context) { * @param targetItem * the current target to process * @param titleConsumer - * a consumer to apply a title to or {@code null} if the object has no title field + * a consumer to apply a title to or {@code null} if the object has no + * title field * @param paramsSupplier * a supplier for the child {@link Parameter} collection * @param propsSupplier @@ -332,7 +334,8 @@ private static void handleCollection( // boolean handleChildren = !Collections.disjoint(context.getTargetItemTypes(), // getApplicableTypes(itemType)); // if (handleChildren && handler != null) { - // // if the child item type is applicable and there is a handler, iterate over children + // // if the child item type is applicable and there is a handler, iterate over + // children // Iterator iter = collectionSupplier.get().iterator(); // while (iter.hasNext()) { // T item = iter.next(); diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/alter/RemoveVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/alter/RemoveVisitor.java index 7376bac9..c93209ef 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/alter/RemoveVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/alter/RemoveVisitor.java @@ -93,8 +93,8 @@ public enum TargetType { * * @param clazz * the class to identify the target type for - * @return the associated target type or {@code null} if the class is not associated with a target - * type + * @return the associated target type or {@code null} if the class is not + * associated with a target type */ @Nullable public static TargetType forClass(@NonNull Class clazz) { @@ -112,8 +112,8 @@ public static TargetType forClass(@NonNull Class clazz) { * * @param name * the field name to identify the target type for - * @return the associated target type or {@code null} if the name is not associated with a target - * type + * @return the associated target type or {@code null} if the name is not + * associated with a target type */ @Nullable public static TargetType forFieldName(@Nullable String name) { @@ -184,7 +184,8 @@ private static boolean handle( } } } else if (handleChildren && handler != null) { - // if the child item type is applicable and there is a handler, iterate over children + // if the child item type is applicable and there is a handler, iterate over + // children Iterator iter = supplier.get().iterator(); while (iter.hasNext()) { T item = iter.next(); @@ -394,7 +395,8 @@ private Context( @Nullable TargetType itemType) { // determine the set of effective item types to search for - // this helps with short-circuit searching for parts of the graph that cannot match + // this helps with short-circuit searching for parts of the graph that cannot + // match @NonNull Set targetItemTypes = ObjectUtils.notNull(EnumSet.allOf(TargetType.class)); filterTypes(targetItemTypes, "by-name", NAME_TYPES, objectName, itemType); filterTypes(targetItemTypes, "by-class", CLASS_TYPES, objectClass, itemType); diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/merge/FlatteningStructuringVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/merge/FlatteningStructuringVisitor.java index 0266421a..c61faacd 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/merge/FlatteningStructuringVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/merge/FlatteningStructuringVisitor.java @@ -26,11 +26,11 @@ package gov.nist.secauto.oscal.lib.profile.resolver.merge; -import gov.nist.secauto.oscal.lib.model.BackMatter.Resource; import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.IRootAssemblyNodeItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.model.BackMatter.Resource; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; import gov.nist.secauto.oscal.lib.model.ControlPart; diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AbstractCustomReferencePolicy.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AbstractCustomReferencePolicy.java index 2ee0c03a..6306088c 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AbstractCustomReferencePolicy.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AbstractCustomReferencePolicy.java @@ -57,10 +57,11 @@ public IIdentifierParser getIdentifierParser() { } /** - * Get the possible item types that can be searched in the order in which the identifier will be - * looked up. + * Get the possible item types that can be searched in the order in which the + * identifier will be looked up. *

    - * The {@code reference} object is provided to allow for context sensitive item type tailoring. + * The {@code reference} object is provided to allow for context sensitive item + * type tailoring. * * @param reference * the reference object @@ -79,7 +80,8 @@ public IIdentifierParser getIdentifierParser() { * @param item * the referenced item * @param visitorContext - * the reference visitor state, which can be used for further processing + * the reference visitor state, which can be used for further + * processing * @return {@code true} if the hit was handled or {@code false} otherwise * @throws ProfileResolutionEvaluationException * if there was an error handing the index hit @@ -149,7 +151,8 @@ protected void handleUnselected( // NOPMD noop default * @param item * the referenced item * @param visitorContext - * the reference visitor state, which can be used for further processing + * the reference visitor state, which can be used for further + * processing * @throws ProfileResolutionEvaluationException * if there was an error handing the index hit */ @@ -162,8 +165,8 @@ protected void handleSelected( // NOPMD noop default } /** - * Handle an index miss for a reference. This occurs when the referenced item was not found in the - * index. + * Handle an index miss for a reference. This occurs when the referenced item + * was not found in the index. *

    * Subclasses can override this method to perform extra processing. * @@ -176,8 +179,10 @@ protected void handleSelected( // NOPMD noop default * @param identifier * the parsed identifier * @param visitorContext - * the reference visitor state, which can be used for further processing - * @return {@code true} if the reference is handled by this method or {@code false} otherwise + * the reference visitor state, which can be used for further + * processing + * @return {@code true} if the reference is handled by this method or + * {@code false} otherwise * @throws ProfileResolutionEvaluationException * if there was an error handing the index miss */ @@ -192,8 +197,9 @@ protected boolean handleIndexMiss( } /** - * Handle the case where the identifier was not a syntax match for an expected identifier. This can - * occur when the reference is malformed, using an unrecognized syntax. + * Handle the case where the identifier was not a syntax match for an expected + * identifier. This can occur when the reference is malformed, using an + * unrecognized syntax. *

    * Subclasses can override this method to perform extra processing. * @@ -202,8 +208,10 @@ protected boolean handleIndexMiss( * @param reference * the identifier reference object generating the hit * @param visitorContext - * the reference visitor state, which can be used for further processing - * @return {@code true} if the reference is handled by this method or {@code false} otherwise + * the reference visitor state, which can be used for further + * processing + * @return {@code true} if the reference is handled by this method or + * {@code false} otherwise * @throws ProfileResolutionEvaluationException * if there was an error handing the index miss due to a non match */ @@ -222,7 +230,8 @@ public boolean handleReference( @NonNull ReferenceCountingVisitor.Context visitorContext) { String referenceText = getReferenceText(type); - // if the reference text does not exist, ignore the reference; otherwise, handle it. + // if the reference text does not exist, ignore the reference; otherwise, handle + // it. return referenceText == null || handleIdentifier(contextItem, type, getIdentifierParser().parse(referenceText), visitorContext); } @@ -237,8 +246,10 @@ public boolean handleReference( * @param identifier * the identifier * @param visitorContext - * the reference visitor state, which can be used for further processing - * @return {@code true} if the reference is handled by this method or {@code false} otherwise + * the reference visitor state, which can be used for further + * processing + * @return {@code true} if the reference is handled by this method or + * {@code false} otherwise * @throws ProfileResolutionEvaluationException * if there was an error handing the reference */ diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ICustomReferencePolicyHandler.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ICustomReferencePolicyHandler.java index 833af774..b9c73c97 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ICustomReferencePolicyHandler.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ICustomReferencePolicyHandler.java @@ -48,8 +48,8 @@ public boolean handleIndexMiss( }; /** - * A callback used to handle the case where an identifier could not be parsed from the reference - * text. + * A callback used to handle the case where an identifier could not be parsed + * from the reference text. * * @param policy * the reference policy for this reference @@ -57,7 +57,8 @@ public boolean handleIndexMiss( * the reference object * @param visitor * the reference visitor used to resolve referenced objects - * @return {@code true} if the reference is considered handled, or {@code false} otherwise + * @return {@code true} if the reference is considered handled, or {@code false} + * otherwise */ default boolean handleIdentifierNonMatch( @NonNull ICustomReferencePolicy policy, @@ -67,8 +68,8 @@ default boolean handleIdentifierNonMatch( } /** - * A callback used to handle the case where an identifier could be parsed from the reference text, - * but the index didn't contain a matching entity. + * A callback used to handle the case where an identifier could be parsed from + * the reference text, but the index didn't contain a matching entity. * * @param policy * the reference policy for this reference @@ -80,7 +81,8 @@ default boolean handleIdentifierNonMatch( * the parsed identifier * @param visitor * the reference visitor used to resolve referenced objects - * @return {@code true} if the reference is considered handled, or {@code false} otherwise + * @return {@code true} if the reference is considered handled, or {@code false} + * otherwise */ default boolean handleIndexMiss( @NonNull ICustomReferencePolicy policy, @@ -92,8 +94,8 @@ default boolean handleIndexMiss( } /** - * A callback used to handle the case where an identifier could be parsed and the index contains a - * matching entity. + * A callback used to handle the case where an identifier could be parsed and + * the index contains a matching entity. * * @param policy * the reference policy for this reference @@ -103,7 +105,8 @@ default boolean handleIndexMiss( * the entity that is referenced * @param visitor * the reference visitor used to resolve referenced objects - * @return {@code true} if the reference is considered handled, or {@code false} otherwise + * @return {@code true} if the reference is considered handled, or {@code false} + * otherwise */ default boolean handleIndexHit( @NonNull ICustomReferencePolicy policy, diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/IIdentifierParser.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/IIdentifierParser.java index 3fa99ea6..b21b362e 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/IIdentifierParser.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/IIdentifierParser.java @@ -59,7 +59,8 @@ public String update(@NonNull String reference, @NonNull String newIdentifier) { String parse(@NonNull String referenceText); /** - * Substitute the provided {@code newIdentifier} with the identifier in the {@code referenceText}. + * Substitute the provided {@code newIdentifier} with the identifier in the + * {@code referenceText}. * * @param referenceText * the reference text containing the original identifier diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/IReferenceVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/IReferenceVisitor.java index d0315c45..e93b10f7 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/IReferenceVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/IReferenceVisitor.java @@ -43,8 +43,8 @@ public interface IReferenceVisitor extends ICatalogVisitor { /** - * Visit the provided {@code item} representing an OSCAL {@link CatalogGroup} and handle any - * enclosed references. + * Visit the provided {@code item} representing an OSCAL {@link CatalogGroup} + * and handle any enclosed references. * * @param item * the Metapath node item containing reference nodes @@ -55,8 +55,8 @@ public interface IReferenceVisitor extends ICatalogVisitor { Void visitGroup(@NonNull IAssemblyNodeItem item, Void childResult, T context); /** - * Visit the provided {@code item} representing an OSCAL {@link Control} and handle any enclosed - * references. + * Visit the provided {@code item} representing an OSCAL {@link Control} and + * handle any enclosed references. * * @param item * the Metapath node item containing reference nodes @@ -67,7 +67,8 @@ public interface IReferenceVisitor extends ICatalogVisitor { Void visitControl(@NonNull IAssemblyNodeItem item, Void childResult, T context); // // /** - // * Visit the provided {@code item} representing an OSCAL {@link Parameter} and handle any enclosed + // * Visit the provided {@code item} representing an OSCAL {@link Parameter} and + // handle any enclosed // * references. // * // * @param item @@ -78,7 +79,8 @@ public interface IReferenceVisitor extends ICatalogVisitor { // void resolveParameter(@NonNull IModelNodeItem item); // // /** - // * Visit the provided {@code item} representing an OSCAL {@link ControlPart} and handle any + // * Visit the provided {@code item} representing an OSCAL {@link ControlPart} + // and handle any // enclosed // * references. // * @@ -90,7 +92,8 @@ public interface IReferenceVisitor extends ICatalogVisitor { // void resolvePart(@NonNull IModelNodeItem item, T context); // // /** - // * Visit the provided {@code item} representing an OSCAL {@link Role} and handle any enclosed + // * Visit the provided {@code item} representing an OSCAL {@link Role} and + // handle any enclosed // * references. // * // * @param item @@ -101,7 +104,8 @@ public interface IReferenceVisitor extends ICatalogVisitor { // void resolveRole(@NonNull IModelNodeItem item); // // /** - // * Visit the provided {@code item} representing an OSCAL {@link Party} and handle any enclosed + // * Visit the provided {@code item} representing an OSCAL {@link Party} and + // handle any enclosed // * references. // * // * @param item @@ -112,7 +116,8 @@ public interface IReferenceVisitor extends ICatalogVisitor { // void resolveParty(@NonNull IModelNodeItem item); // // /** - // * Visit the provided {@code item} representing an OSCAL {@link Location} and handle any enclosed + // * Visit the provided {@code item} representing an OSCAL {@link Location} and + // handle any enclosed // * references. // * // * @param item @@ -123,7 +128,8 @@ public interface IReferenceVisitor extends ICatalogVisitor { // void resolveLocation(@NonNull IModelNodeItem item); // // /** - // * Visit the provided {@code item} representing an OSCAL {@link Resource} and handle any enclosed + // * Visit the provided {@code item} representing an OSCAL {@link Resource} and + // handle any enclosed // * references. // * // * @param item diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ReferenceCountingVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ReferenceCountingVisitor.java index 8689dfde..510413ff 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ReferenceCountingVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ReferenceCountingVisitor.java @@ -136,7 +136,8 @@ public static ReferenceCountingVisitor instance() { } public ReferenceCountingVisitor() { - // visit everything except parts, roles, locations, parties, parameters, and resources, which are + // visit everything except parts, roles, locations, parties, parameters, and + // resources, which are // handled differently by this visitor super(ObjectUtils.notNull(EnumSet.complementOf( EnumSet.of( @@ -170,7 +171,8 @@ protected Void aggregateResults(Void first, Void second, Context context) { // // BackMatter backMatter = profile.getBackMatter(); // if (backMatter != null) { - // for (BackMatter.Resource resource : CollectionUtil.listOrEmpty(backMatter.getResources())) { + // for (BackMatter.Resource resource : + // CollectionUtil.listOrEmpty(backMatter.getResources())) { // visitResource(resource); // } // } @@ -211,7 +213,8 @@ public Void visitGroup( Context context) { IIndexer index = context.getIndexer(); // handle the group if it is selected - // a group will only be selected if it contains a descendant control that is selected + // a group will only be selected if it contains a descendant control that is + // selected if (IIndexer.SelectionStatus.SELECTED.equals(index.getSelectionStatus(item))) { CatalogGroup group = ObjectUtils.requireNonNull((CatalogGroup) item.getValue()); String id = group.getId(); @@ -416,7 +419,8 @@ private static void resolvePart( .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); item.getModelItemsByName("prose") .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); - // item.getModelItemsByName("part").forEach(child -> visitor.visitPart(ObjectUtils.notNull(child), + // item.getModelItemsByName("part").forEach(child -> + // visitor.visitPart(ObjectUtils.notNull(child), // context)); } @@ -432,7 +436,8 @@ private static void handleMarkup( @NonNull IFieldNodeItem contextItem, @NonNull IMarkupString text, @NonNull Context context) { - for (Node node : CollectionUtil.toIterable(text.getNodesAsStream().iterator())) { + for (Node node : CollectionUtil.toIterable( + ObjectUtils.notNull(text.getNodesAsStream().iterator()))) { if (node instanceof InsertAnchorNode) { handleInsert(contextItem, (InsertAnchorNode) node, context); } else if (node instanceof InlineLinkNode) { @@ -567,7 +572,8 @@ protected void entityDispatch(@NonNull IEntityItem entity, @NonNull Context cont // } // // @Override - // protected Void aggregateResults(Object first, Object second, Object context) { + // protected Void aggregateResults(Object first, Object second, Object context) + // { // return null; // } diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionVisitor.java index c5c63b93..5a82944b 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionVisitor.java @@ -47,21 +47,24 @@ /** * Walks a {@link Catalog} indexing all nodes that can be referenced. *

    - * For each {@link CatalogGroup}, {@link Control}, and {@link ControlPart}, determine if that object - * is {@link SelectionStatus#SELECTED} or {@link SelectionStatus#UNSELECTED}. + * For each {@link CatalogGroup}, {@link Control}, and {@link ControlPart}, + * determine if that object is {@link SelectionStatus#SELECTED} or + * {@link SelectionStatus#UNSELECTED}. *

    - * A {@link Control} is {@link SelectionStatus#SELECTED} if it matches the configured - * {@link IControlFilter}, otherwise it is {@link SelectionStatus#UNSELECTED}. + * A {@link Control} is {@link SelectionStatus#SELECTED} if it matches the + * configured {@link IControlFilter}, otherwise it is + * {@link SelectionStatus#UNSELECTED}. *

    * A {@link CatalogGroup} is {@link SelectionStatus#SELECTED} if it contains a * {@link SelectionStatus#SELECTED} descendant {@link Control}, otherwise it is * {@link SelectionStatus#UNSELECTED}. *

    - * A {@link ControlPart} is {@link SelectionStatus#SELECTED} if its containing control is - * {@link SelectionStatus#SELECTED}. + * A {@link ControlPart} is {@link SelectionStatus#SELECTED} if its containing + * control is {@link SelectionStatus#SELECTED}. *

    - * All other indexed nodes will have the {@link SelectionStatus#UNKNOWN}, since these nodes require - * reference counting to determine if they are to be kept or not. + * All other indexed nodes will have the {@link SelectionStatus#UNKNOWN}, since + * these nodes require reference counting to determine if they are to be kept or + * not. */ public class ControlSelectionVisitor extends AbstractIndexingVisitor { diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultControlSelectionFilter.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultControlSelectionFilter.java index 2ce28d5f..6e11a422 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultControlSelectionFilter.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultControlSelectionFilter.java @@ -52,7 +52,8 @@ public class DefaultControlSelectionFilter implements IControlSelectionFilter { private final List selections; /** - * Construct a new selection filter based on the provided list of select criteria. + * Construct a new selection filter based on the provided list of select + * criteria. * * @param selections * a list of select criteria @@ -78,13 +79,14 @@ public Pair apply(IControl control) { } /** - * Checks if the provided control identifier matches the criteria defined by this object. + * Checks if the provided control identifier matches the criteria defined by + * this object. * * @param id * the control identifier to match - * @return a {@link Pair} whose first member is {@code true} for a match or {@code false} otherwise, - * and whose second member is {@code true} if the match applies to any child controls or - * {@code false} otherwise + * @return a {@link Pair} whose first member is {@code true} for a match or + * {@code false} otherwise, and whose second member is {@code true} if + * the match applies to any child controls or {@code false} otherwise */ @SuppressWarnings("null") @NonNull diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/IControlFilter.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/IControlFilter.java index 330669bd..a1f1eea3 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/IControlFilter.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/IControlFilter.java @@ -77,7 +77,8 @@ public interface IControlFilter { }; /** - * Construct a new filter instance based on the provided profile import statement. + * Construct a new filter instance based on the provided profile import + * statement. * * @param profileImport * an OSCAL profile import statement @@ -95,14 +96,15 @@ static IControlFilter newInstance(@NonNull IControlSelectionFilter includes, } /** - * Determines if the control is matched by this filter. This method returns a {@link Pair} where the - * first member of the pair indicates if the control matches, and the second indicates if the match - * applies to child controls as well. + * Determines if the control is matched by this filter. This method returns a + * {@link Pair} where the first member of the pair indicates if the control + * matches, and the second indicates if the match applies to child controls as + * well. * * @param control * the control to check for a match - * @return a pair indicating the status of the match ({@code true} for a match or {@code false} - * otherwise), and if a match applies to child controls + * @return a pair indicating the status of the match ({@code true} for a match + * or {@code false} otherwise), and if a match applies to child controls */ @NonNull default Pair match(@NonNull IControl control) { @@ -110,16 +112,17 @@ default Pair match(@NonNull IControl control) { } /** - * Determines if the control is matched by this filter. This method returns a {@link Pair} where the - * first member of the pair indicates if the control matches, and the second indicates if the match - * applies to child controls as well. + * Determines if the control is matched by this filter. This method returns a + * {@link Pair} where the first member of the pair indicates if the control + * matches, and the second indicates if the match applies to child controls as + * well. * * @param control * the control to check for a match * @param defaultMatch * the match status to use if the filter doesn't have an explicit hit - * @return a pair indicating the status of the match ({@code true} for a match or {@code false} - * otherwise), and if a match applies to child controls + * @return a pair indicating the status of the match ({@code true} for a match + * or {@code false} otherwise), and if a match applies to child controls */ @NonNull Pair match(@NonNull IControl control, boolean defaultMatch); diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/IControlSelectionFilter.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/IControlSelectionFilter.java index 82a3bae3..6dbabe11 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/IControlSelectionFilter.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/IControlSelectionFilter.java @@ -75,14 +75,15 @@ static IControlSelectionFilter matchIds(@NonNull String... identifiers) { } /** - * Determines if the control is matched by this filter. This method returns a {@link Pair} where the - * first member of the pair indicates if the control matches, and the second indicates if the match - * applies to child controls as well. + * Determines if the control is matched by this filter. This method returns a + * {@link Pair} where the first member of the pair indicates if the control + * matches, and the second indicates if the match applies to child controls as + * well. * * @param control * the control to check for a match - * @return a pair indicating the status of the match ({@code true} for a match or {@code false} - * otherwise), and if a match applies to child controls + * @return a pair indicating the status of the match ({@code true} for a match + * or {@code false} otherwise), and if a match applies to child controls */ @NonNull @Override diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractCatalogEntityVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractCatalogEntityVisitor.java index 5d49f7b4..d8834b2c 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractCatalogEntityVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractCatalogEntityVisitor.java @@ -42,7 +42,8 @@ /** * Visits a catalog document and its children as designated. *

    - * This implementation is stateless. The {@code T} parameter can be used to convey state as needed. + * This implementation is stateless. The {@code T} parameter can be used to + * convey state as needed. * * @param * the state type @@ -74,7 +75,8 @@ public abstract class AbstractCatalogEntityVisitor private final Set itemTypesToVisit; /** - * Create a new visitor that will visit the item types identified by {@code itemTypesToVisit}. + * Create a new visitor that will visit the item types identified by + * {@code itemTypesToVisit}. * * @param itemTypesToVisit * the item type the visitor will visit @@ -178,8 +180,8 @@ protected R visitControlInternal(IAssemblyNodeItem item, R childResult, T state) /** * Called when visiting a parameter. *

    - * Can be overridden by classes extending this interface to support processing of the visited - * object. + * Can be overridden by classes extending this interface to support processing + * of the visited object. * * @param item * the Metapath item for the parameter @@ -200,8 +202,8 @@ protected R visitParameter( /** * Called when visiting a part. *

    - * Can be overridden by classes extending this interface to support processing of the visited - * object. + * Can be overridden by classes extending this interface to support processing + * of the visited object. * * @param item * the Metapath item for the part @@ -223,7 +225,7 @@ protected void visitPart( // NOPMD noop default * Visits each contained role, location, and party. * * @param rootItem - * the root Metaschema node item containing the "metadata" node + * the root Module node item containing the "metadata" node * @param state * the calling context information */ @@ -260,13 +262,13 @@ protected void visitMetadata(@NonNull IRootAssemblyNodeItem rootItem, T state) { /** * Called when visiting a role in the "metadata" section of an OSCAL document. *

    - * Can be overridden by classes extending this interface to support processing of the visited - * object. + * Can be overridden by classes extending this interface to support processing + * of the visited object. * * @param item - * the role Metaschema node item which is a child of the "metadata" node + * the role Module node item which is a child of the "metadata" node * @param metadataItem - * the "metadata" Metaschema node item containing the role + * the "metadata" Module node item containing the role * @param state * the calling context information */ @@ -278,15 +280,17 @@ protected void visitRole( // NOPMD noop default } /** - * Called when visiting a location in the "metadata" section of an OSCAL document. + * Called when visiting a location in the "metadata" section of an OSCAL + * document. *

    - * Can be overridden by classes extending this interface to support processing of the visited - * object. + * Can be overridden by classes extending this interface to support processing + * of the visited object. * * @param item - * the location Metaschema node item which is a child of the "metadata" node + * the location Module node item which is a child of the "metadata" + * node * @param metadataItem - * the "metadata" Metaschema node item containing the location + * the "metadata" Module node item containing the location * @param state * the calling context information */ @@ -300,13 +304,13 @@ protected void visitLocation( // NOPMD noop default /** * Called when visiting a party in the "metadata" section of an OSCAL document. *

    - * Can be overridden by classes extending this interface to support processing of the visited - * object. + * Can be overridden by classes extending this interface to support processing + * of the visited object. * * @param item - * the party Metaschema node item which is a child of the "metadata" node + * the party Module node item which is a child of the "metadata" node * @param metadataItem - * the "metadata" Metaschema node item containing the party + * the "metadata" Module node item containing the party * @param state * the calling context information */ @@ -323,7 +327,7 @@ protected void visitParty( // NOPMD noop default * Visits each contained resource. * * @param rootItem - * the root Metaschema node item containing the "back-matter" node + * the root Module node item containing the "back-matter" node * @param state * the calling context information */ @@ -338,15 +342,17 @@ protected void visitBackMatter(@NonNull IRootAssemblyNodeItem rootItem, T state) } /** - * Called when visiting a resource in the "back-matter" section of an OSCAL document. + * Called when visiting a resource in the "back-matter" section of an OSCAL + * document. *

    - * Can be overridden by classes extending this interface to support processing of the visited - * object. + * Can be overridden by classes extending this interface to support processing + * of the visited object. * * @param resource - * the resource Metaschema node item which is a child of the "metadata" node + * the resource Module node item which is a child of the "metadata" + * node * @param backMatter - * the resource Metaschema node item containing the party + * the resource Module node item containing the party * @param state * the calling context information */ diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractCatalogVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractCatalogVisitor.java index ace9fe08..142a0518 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractCatalogVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractCatalogVisitor.java @@ -36,9 +36,11 @@ * Used to visit a catalog containing groups and controls. * * @param - * the type of the state object used to pass calling context information + * the type of the state object used to pass calling context + * information * @param - * the type of the result for visiting a collection of groups and/or controls + * the type of the result for visiting a collection of groups and/or + * controls */ public abstract class AbstractCatalogVisitor implements ICatalogVisitor { @@ -55,7 +57,8 @@ protected R visitCatalog(@NonNull IDocumentNodeItem catalogDocument, T state) { } /** - * Visit the child groups and controls (in that order) of a given catalog or group container. + * Visit the child groups and controls (in that order) of a given catalog or + * group container. * * @param catalogOrGroup * the catalog or group Metapath item currently being visited @@ -114,7 +117,8 @@ protected R visitGroupInternal( } /** - * Visit the child controls (in that order) of a given catalog, group, or control container. + * Visit the child controls (in that order) of a given catalog, group, or + * control container. * * @param catalogOrGroupOrControl * the catalog, group, or control Metapath item currently being visited diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractEntityItem.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractEntityItem.java index b1348842..bd24e3d4 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractEntityItem.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractEntityItem.java @@ -66,7 +66,8 @@ public String getOriginalIdentifier() { // @NonNull // public String getIdentifier() { // final String checkedReassignedIdentifier = reassignedIdentifier; - // return checkedReassignedIdentifier == null ? originalIdentifier : checkedReassignedIdentifier; + // return checkedReassignedIdentifier == null ? originalIdentifier : + // checkedReassignedIdentifier; // } @Override @@ -84,7 +85,7 @@ public void setInstance(IModelNodeItem item) { @NonNull @SuppressWarnings("unchecked") public T getInstanceValue() { - return (T) getInstance().getValue(); + return ObjectUtils.notNull((T) getInstance().getValue()); } @Override diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/BasicIndexer.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/BasicIndexer.java index 213d8b4c..420cb976 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/BasicIndexer.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/BasicIndexer.java @@ -26,7 +26,6 @@ package gov.nist.secauto.oscal.lib.profile.resolver.support; -import gov.nist.secauto.oscal.lib.model.BackMatter.Resource; import gov.nist.secauto.metaschema.core.datatype.adapter.UuidAdapter; import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; import gov.nist.secauto.metaschema.core.metapath.MetapathExpression.ResultType; @@ -34,6 +33,7 @@ import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.model.BackMatter.Resource; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; import gov.nist.secauto.oscal.lib.model.ControlPart; @@ -190,11 +190,14 @@ public Collection getEntitiesByItemType(@NonNull IEntityItem.ItemTy return entityGroup == null ? CollectionUtil.emptyList() : ObjectUtils.notNull(entityGroup.values()); } // - // public EntityItem getEntity(@NonNull ItemType itemType, @NonNull UUID identifier) { - // return getEntity(itemType, ObjectUtils.notNull(identifier.toString()), false); + // public EntityItem getEntity(@NonNull ItemType itemType, @NonNull UUID + // identifier) { + // return getEntity(itemType, ObjectUtils.notNull(identifier.toString()), + // false); // } // - // public EntityItem getEntity(@NonNull ItemType itemType, @NonNull String identifier) { + // public EntityItem getEntity(@NonNull ItemType itemType, @NonNull String + // identifier) { // return getEntity(itemType, identifier, itemType.isUuid()); // } @@ -327,10 +330,11 @@ protected final AbstractEntityItem.Builder newBuilder( /** * Create a new builder with the provided info. *

    - * This method can be overloaded to support applying additional data to the returned builder. + * This method can be overloaded to support applying additional data to the + * returned builder. *

    - * When working with identifiers that are case insensitve, it is important to ensure that the - * identifiers are normalized to lower case. + * When working with identifiers that are case insensitve, it is important to + * ensure that the identifiers are normalized to lower case. * * @param item * the Metapath node to associate with the entity diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/ICatalogVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/ICatalogVisitor.java index 7d928e96..9bb43168 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/ICatalogVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/ICatalogVisitor.java @@ -34,17 +34,19 @@ * Used to visit a catalog containing groups and controls. * * @param - * the type of the context object used to pass calling context information + * the type of the context object used to pass calling context + * information * @param - * the type of the result for visiting a collection of groups and/or controls + * the type of the result for visiting a collection of groups and/or + * controls */ public interface ICatalogVisitor { /** * Called when visiting a group. *

    - * Can be overridden by classes extending this interface to support processing of the visited - * object. + * Can be overridden by classes extending this interface to support processing + * of the visited object. * * @param group * the Metapath item for the group @@ -62,8 +64,8 @@ default R visitGroup(@NonNull IAssemblyNodeItem group, R childResult, T state) { /** * Called when visiting a control. *

    - * Can be overridden by classes extending this interface to support processing of the visited - * object. + * Can be overridden by classes extending this interface to support processing + * of the visited object. * * @param control * the Metapath item for the control diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/IEntityItem.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/IEntityItem.java index 30e8decc..af20d127 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/IEntityItem.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/IEntityItem.java @@ -58,13 +58,14 @@ public boolean isUuid() { /** * Get the identifier originally assigned to this entity. *

    - * If the identifier value was reassigned, the return value of this method will be different than - * value returned by {@link #getIdentifier()}. In such cases, a call to - * {@link #isIdentifierReassigned()} is expected to return {@code true}. + * If the identifier value was reassigned, the return value of this method will + * be different than value returned by {@link #getIdentifier()}. In such cases, + * a call to {@link #isIdentifierReassigned()} is expected to return + * {@code true}. *

    - * If the value was not reassigned, the return value of this method will be the same value returned - * by {@link #getIdentifier()}. In this case, {@link #isIdentifierReassigned()} is expected to - * return {@code false}. + * If the value was not reassigned, the return value of this method will be the + * same value returned by {@link #getIdentifier()}. In this case, + * {@link #isIdentifierReassigned()} is expected to return {@code false}. * * @return the original identifier value before reassignment */ @@ -82,7 +83,8 @@ public boolean isUuid() { /** * Determine if the identifier was reassigned. * - * @return {@code true} if the identifier was reassigned, or {@code false} otherwise + * @return {@code true} if the identifier was reassigned, or {@code false} + * otherwise */ boolean isIdentifierReassigned(); diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/IIndexer.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/IIndexer.java index e07b4784..76e517b3 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/IIndexer.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/IIndexer.java @@ -32,6 +32,7 @@ import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.CustomCollectors; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem.ItemType; import org.apache.logging.log4j.Level; @@ -58,7 +59,7 @@ enum SelectionStatus { } MetapathExpression HAS_PROP_KEEP_METAPATH = MetapathExpression - .compile("prop[@name='keep' and has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]/@value = 'always'"); + .compile("prop[@name='keep' and has-oscal-namespace('" + OscalBindingContext.NS_OSCAL + "')]/@value = 'always'"); Predicate KEEP_ENTITY_PREDICATE = new Predicate<>() { @@ -76,8 +77,8 @@ static boolean isReferencedEntity(@NonNull IEntityItem entity) { } /** - * Keep entities that have a reference count greater than zero or are required to be kept based on - * the "keep"="always property. + * Keep entities that have a reference count greater than zero or are required + * to be kept based on the "keep"="always property. * * @param entities * the entity items to filter @@ -88,8 +89,8 @@ static Stream getReferencedEntitiesAsStream(@NonNull Collection serializer = bindingContext.newSerializer(Format.YAML, Catalog.class); // serialize the catalog as yaml - serializer.serialize( - (Catalog) INodeItem.toValue(resolvedCatalog), - ObjectUtils.notNull(System.out)); + @SuppressWarnings("resource") // not owned + OutputStream os = ObjectUtils.notNull(System.out); + + serializer.serialize((Catalog) INodeItem.toValue(resolvedCatalog), os); } } diff --git a/src/test/java/gov/nist/secauto/oscal/java/MetaschemaVisitorTest.java b/src/test/java/gov/nist/secauto/oscal/java/MetaschemaVisitorTest.java index 2247a5b6..0e50b3d3 100644 --- a/src/test/java/gov/nist/secauto/oscal/java/MetaschemaVisitorTest.java +++ b/src/test/java/gov/nist/secauto/oscal/java/MetaschemaVisitorTest.java @@ -26,13 +26,14 @@ package gov.nist.secauto.oscal.java; -import gov.nist.secauto.metaschema.binding.io.IBoundLoader; import gov.nist.secauto.metaschema.core.metapath.DynamicContext; import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; import gov.nist.secauto.metaschema.core.metapath.StaticContext; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.io.IBoundLoader; import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.metapath.function.library.ResolveProfile; @@ -57,10 +58,10 @@ void test() throws FileNotFoundException, IOException, URISyntaxException { OscalBindingContext bindingContext = OscalBindingContext.instance(); IBoundLoader loader = bindingContext.newBoundLoader(); - StaticContext staticContext = new StaticContext(); - @SuppressWarnings("null") - @NonNull URI baseUri = new File("").getAbsoluteFile().toURI(); - staticContext.setBaseUri(baseUri); + URI baseUri = ObjectUtils.notNull(new File("").getAbsoluteFile().toURI()); + StaticContext staticContext = StaticContext.builder() + .baseUri(baseUri) + .build(); DynamicContext dynamicContext = staticContext.newDynamicContext(); dynamicContext.setDocumentLoader(loader); @@ -82,31 +83,40 @@ void test() throws FileNotFoundException, IOException, URISyntaxException { // File("resolved-catalog.xml"))); // evaluatePath(MetapathExpression.compile("resolve-profile(doc(resolve-uri(/profile/import/@href, - // document-uri(/profile))))/(profile, catalog)//control/@id"), nodeItem, dynamicContext); + // document-uri(/profile))))/(profile, catalog)//control/@id"), nodeItem, + // dynamicContext); evaluatePath(MetapathExpression.compile("//control/@id"), resolvedProfile, dynamicContext); // evaluatePath(MetapathExpression.compile("doc(resolve-uri(/profile/import/@href, - // document-uri(/profile)))/catalog/metadata/last-modified"), nodeItem, dynamicContext); + // document-uri(/profile)))/catalog/metadata/last-modified"), nodeItem, + // dynamicContext); // evaluatePath( // MetapathExpression.compile("doc(resolve-uri(/profile/import/@href, - // document-uri(/profile)))/catalog/metadata/last-modified - /catalog/metadata/last-modified"), + // document-uri(/profile)))/catalog/metadata/last-modified - + // /catalog/metadata/last-modified"), // nodeItem, dynamicContext); // evaluatePath(MetapathExpression.compile("doc(resolve-uri(/profile/import/@href, - // document-uri(/profile)))/catalog/metadata/last-modified + duration('PT1H')"), nodeItem, + // document-uri(/profile)))/catalog/metadata/last-modified + duration('PT1H')"), + // nodeItem, // dynamicContext); // evaluatePath(MetapathExpression.compile("doc(resolve-uri(/profile/import/@href, // document-uri(/profile)))/catalog/metadata/last-modified,/catalog/metadata/last-modified"), // nodeItem, dynamicContext); // evaluatePath(MetapathExpression.compile("doc('target/download/content/NIST_SP-800-53_rev5_catalog.xml')"), // nodeItem, dynamicContext); - // evaluatePath(Metapath.parseMetapathString("2 eq 1 + 1[/catalog]"), nodeContext, visitor); + // evaluatePath(Metapath.parseMetapathString("2 eq 1 + 1[/catalog]"), + // nodeContext, visitor); // evaluatePath(Metapath.parseMetapathString("/catalog/back-matter/resource[rlink/@href='https://doi.org/10.6028/NIST.SP.800-53r5']"), // nodeItem, dynamicContext); - // evaluatePath(MetapathExpression.compile("/catalog//(@id,@uuid)"), nodeItem, dynamicContext); - // evaluatePath(MetapathExpression.compile("exists(/catalog//(@id,@uuid))"), nodeItem, + // evaluatePath(MetapathExpression.compile("/catalog//(@id,@uuid)"), nodeItem, + // dynamicContext); + // evaluatePath(MetapathExpression.compile("exists(/catalog//(@id,@uuid))"), + // nodeItem, // dynamicContext); - // evaluatePath(MetapathExpression.compile("/catalog//control//prop/@name"), nodeItem, + // evaluatePath(MetapathExpression.compile("/catalog//control//prop/@name"), + // nodeItem, // dynamicContext); - // evaluatePath(Metapath.parseMetapathString("(/catalog//control[@id='ac-1'])"), nodeItem, + // evaluatePath(Metapath.parseMetapathString("(/catalog//control[@id='ac-1'])"), + // nodeItem, // dynamicContext); } diff --git a/src/test/java/gov/nist/secauto/oscal/java/OscalBindingContextTest.java b/src/test/java/gov/nist/secauto/oscal/java/OscalBindingContextTest.java index 24246736..76fdbf11 100644 --- a/src/test/java/gov/nist/secauto/oscal/java/OscalBindingContextTest.java +++ b/src/test/java/gov/nist/secauto/oscal/java/OscalBindingContextTest.java @@ -29,10 +29,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import gov.nist.secauto.metaschema.binding.io.Format; -import gov.nist.secauto.metaschema.binding.io.IBoundLoader; -import gov.nist.secauto.metaschema.binding.io.ISerializer; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.io.Format; +import gov.nist.secauto.metaschema.databind.io.IBoundLoader; +import gov.nist.secauto.metaschema.databind.io.ISerializer; import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.Profile; @@ -66,7 +66,8 @@ static void initialize() { // NOPMD actually used @Test void testLoadCatalogYaml(@TempDir Path tempDir) throws IOException { - // the YAML catalog is currently malformed, this will create a proper one for this test + // the YAML catalog is currently malformed, this will create a proper one for + // this test Catalog catalog = loader.load(ObjectUtils.notNull( new File("target/download/content/NIST_SP-800-53_rev5_catalog.yaml").getCanonicalFile())); diff --git a/src/test/java/gov/nist/secauto/oscal/java/ReadWriteTest.java b/src/test/java/gov/nist/secauto/oscal/java/ReadWriteTest.java index cac6d7b9..73e0eeb1 100644 --- a/src/test/java/gov/nist/secauto/oscal/java/ReadWriteTest.java +++ b/src/test/java/gov/nist/secauto/oscal/java/ReadWriteTest.java @@ -28,12 +28,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue; -import gov.nist.secauto.metaschema.binding.IBindingContext; -import gov.nist.secauto.metaschema.binding.io.DeserializationFeature; -import gov.nist.secauto.metaschema.binding.io.Format; -import gov.nist.secauto.metaschema.binding.io.IDeserializer; -import gov.nist.secauto.metaschema.binding.io.ISerializer; 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.io.Format; +import gov.nist.secauto.metaschema.databind.io.IDeserializer; +import gov.nist.secauto.metaschema.databind.io.ISerializer; import gov.nist.secauto.oscal.lib.model.Catalog; import org.apache.logging.log4j.LogManager; @@ -50,6 +50,8 @@ class ReadWriteTest { private static final Logger LOGGER = LogManager.getLogger(ReadWriteTest.class); + private static final int ITERATIONS = 1; + @NonNull private static CLASS measureDeserializer( @NonNull String format, @@ -65,6 +67,7 @@ private static CLASS measureDeserializer( CLASS retval = null; long totalTime = 0; + int totalIterations = 0; for (int i = 0; i < iterations; i++) { long startTime = System.nanoTime(); retval = deserializer.deserialize(file); @@ -73,10 +76,15 @@ private static CLASS measureDeserializer( if (LOGGER.isInfoEnabled()) { LOGGER.info(String.format("%s read in %d milliseconds from %s", format, timeElapsed, file)); } - totalTime += timeElapsed; + + // allow for JVM warmup + if (iterations == 1 || i > 1) { + totalTime += timeElapsed; + ++totalIterations; + } } - long average = totalTime / iterations - 1; if (iterations > 1 && LOGGER.isInfoEnabled()) { + long average = totalTime / totalIterations; LOGGER.info(String.format("%s read in %d milliseconds (on average) from %s", format, average, file)); } @@ -92,6 +100,7 @@ private static void measureSerializer( @NonNull ISerializer serializer, int iterations) throws IOException { long totalTime = 0; + int totalIterations = 0; for (int i = 0; i < iterations; i++) { long startTime = System.nanoTime(); serializer.serialize(root, file); @@ -100,13 +109,16 @@ private static void measureSerializer( if (LOGGER.isInfoEnabled()) { LOGGER.info(String.format("%s written in %d milliseconds to %s", format, timeElapsed, file)); } - if (iterations == 1 || i > 0) { + + // allow for JVM warmup + if (iterations == 1 || i > 1) { totalTime += timeElapsed; + ++totalIterations; } } - long average = totalTime / (iterations == 1 ? 1 : iterations - 1); if (iterations > 1 && LOGGER.isInfoEnabled()) { + long average = totalTime / totalIterations; LOGGER.info(String.format("%s written in %d milliseconds (on average) to %s", format, average, file)); } } @@ -169,6 +181,6 @@ void testOscalCatalogMetrics(@NonNull @TempDir Path tempDir) throws IOException // outDir.mkdirs(); // Path outPath = outDir.toPath(); Path outPath = tempDir; - chainReadWrite(catalogSourceXml, Catalog.class, outPath, 1); + chainReadWrite(catalogSourceXml, Catalog.class, outPath, ITERATIONS); } } diff --git a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolutionTests.java b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolutionTests.java index 6c7a8a5b..5554e8c3 100644 --- a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolutionTests.java +++ b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/ProfileResolutionTests.java @@ -31,12 +31,12 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; -import gov.nist.secauto.metaschema.binding.io.DefaultBoundLoader; -import gov.nist.secauto.metaschema.binding.io.Format; -import gov.nist.secauto.metaschema.binding.io.ISerializer; import gov.nist.secauto.metaschema.core.metapath.DynamicContext; import gov.nist.secauto.metaschema.core.metapath.StaticContext; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; +import gov.nist.secauto.metaschema.databind.io.DefaultBoundLoader; +import gov.nist.secauto.metaschema.databind.io.Format; +import gov.nist.secauto.metaschema.databind.io.ISerializer; import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.profile.resolver.selection.ImportCycleException; @@ -74,7 +74,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; class ProfileResolutionTests { - private static final String XSLT_PATH = "oscal/src/utils/resolver-pipeline/oscal-profile-test-helper.xsl"; + private static final String XSLT_PATH = "src/test/resources/profile-test-helper.xsl"; private static final String PROFILE_UNIT_TEST_PATH = "oscal/src/specifications/profile-resolution/profile-resolution-examples"; private static final String JUNIT_TEST_PATH = "src/test/resources"; @@ -86,7 +86,7 @@ class ProfileResolutionTests { @BeforeAll static void setup() throws SaxonApiException { - DynamicContext context = new StaticContext().newDynamicContext(); + DynamicContext context = StaticContext.builder().build().newDynamicContext(); context.setDocumentLoader(new DefaultBoundLoader(OscalBindingContext.instance())); profileResolver = new ProfileResolver(); profileResolver.setDynamicContext(context); @@ -183,7 +183,8 @@ void performTest(String profileName) throws IOException, SaxonApiException { StringWriter writer = new StringWriter(); serializer.serialize(catalog, writer); - // OscalBindingContext.instance().newSerializer(Format.YAML, Catalog.class).serialize(catalog, + // OscalBindingContext.instance().newSerializer(Format.YAML, + // Catalog.class).serialize(catalog, // System.out); // System.out.println("Pre scrub: " + writer.getBuffer().toString()); diff --git a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/TestUtil.java b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/TestUtil.java index 99b7f0ff..ff969fed 100644 --- a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/TestUtil.java +++ b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/TestUtil.java @@ -26,11 +26,10 @@ package gov.nist.secauto.oscal.lib.profile.resolver; -import gov.nist.secauto.metaschema.binding.model.IAssemblyClassBinding; import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory; -import gov.nist.secauto.metaschema.core.model.IRootAssemblyDefinition; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.model.IAssemblyClassBinding; import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.control.AbstractParameter; @@ -181,9 +180,8 @@ public static IDocumentNodeItem newImportedCatalog() { .build()); return INodeItemFactory.instance().newDocumentNodeItem( - IRootAssemblyDefinition.toRootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class))), + ObjectUtils.requireNonNull( + (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class)), ObjectUtils.notNull(Paths.get("").toUri()), importedCatalog); } diff --git a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ReferenceCountingVisitorTest.java b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ReferenceCountingVisitorTest.java index 16bc7180..823317c0 100644 --- a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ReferenceCountingVisitorTest.java +++ b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/ReferenceCountingVisitorTest.java @@ -26,9 +26,9 @@ package gov.nist.secauto.oscal.lib.profile.resolver.policy; -import gov.nist.secauto.metaschema.binding.io.Format; import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; +import gov.nist.secauto.metaschema.databind.io.Format; import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.profile.resolver.TestUtil; diff --git a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultControlSelectionFilterTest.java b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultControlSelectionFilterTest.java index 083bd150..fa6654d1 100644 --- a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultControlSelectionFilterTest.java +++ b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultControlSelectionFilterTest.java @@ -204,7 +204,8 @@ void testSingleSelectionWithIdsFilter() { } /** - * Test the filtering of a single match criteria using "with-ids" and "with-child=yes". + * Test the filtering of a single match criteria using "with-ids" and + * "with-child=yes". */ @Test @SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT") diff --git a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/FilterNonSelectedVisitorTest.java b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/FilterNonSelectedVisitorTest.java index 2db57f7a..8a9f8ef0 100644 --- a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/FilterNonSelectedVisitorTest.java +++ b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/FilterNonSelectedVisitorTest.java @@ -28,9 +28,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import gov.nist.secauto.metaschema.binding.io.Format; import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; +import gov.nist.secauto.metaschema.databind.io.Format; import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.CatalogGroup; diff --git a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ImportTest.java b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ImportTest.java index fa267221..7f116f24 100644 --- a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ImportTest.java +++ b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ImportTest.java @@ -26,14 +26,13 @@ package gov.nist.secauto.oscal.lib.profile.resolver.selection; -import gov.nist.secauto.metaschema.binding.model.IAssemblyClassBinding; import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory; import gov.nist.secauto.metaschema.core.metapath.item.node.IRootAssemblyNodeItem; -import gov.nist.secauto.metaschema.core.model.IRootAssemblyDefinition; import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.model.IAssemblyClassBinding; import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.IncludeAll; @@ -67,9 +66,8 @@ private static IDocumentNodeItem newImportedCatalog() { .build()); return INodeItemFactory.instance().newDocumentNodeItem( - IRootAssemblyDefinition.toRootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class))), + ObjectUtils.requireNonNull( + (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class)), ObjectUtils.notNull(Paths.get("").toUri()), importedCatalog); } @@ -82,9 +80,6 @@ void test() throws ProfileResolutionException { // setup the imported catalog IDocumentNodeItem importedCatalogDocumentItem = newImportedCatalog(); - // setup the profile - Profile profile = new Profile(); - ProfileImport profileImport = new ProfileImport(); profileImport.setIncludeAll(new IncludeAll()); profileImport.setExcludeControls(Collections.singletonList( @@ -92,12 +87,15 @@ void test() throws ProfileResolutionException { .withId("control1") .build())); profileImport.setHref(cwd); + + // setup the profile + Profile profile = new Profile(); + profile.addImport(profileImport); IDocumentNodeItem profileDocumentItem = INodeItemFactory.instance().newDocumentNodeItem( - IRootAssemblyDefinition.toRootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Profile.class))), + ObjectUtils.requireNonNull( + (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Profile.class)), cwd, profile); diff --git a/src/test/resources/log4j2-test.xml b/src/test/resources/log4j2-test.xml index bc7f9040..e347850b 100644 --- a/src/test/resources/log4j2-test.xml +++ b/src/test/resources/log4j2-test.xml @@ -13,10 +13,10 @@ - + - + diff --git a/src/test/resources/profile-test-helper.xsl b/src/test/resources/profile-test-helper.xsl new file mode 100644 index 00000000..06c5f40b --- /dev/null +++ b/src/test/resources/profile-test-helper.xsl @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ... + + + + ... + + + + ... + + + + ... + + + + + + + + + + \ No newline at end of file