diff --git a/.gitignore b/.gitignore index 23bd7a46..67992560 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ target/ pom.xml.releaseBackup release.properties .fbExcludeFilterFile +/.apt_generated/ diff --git a/pom.xml b/pom.xml index a9eca366..85a360de 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,12 @@ - + 4.0.0 gov.nist.secauto oss-parent - 27 + 28-SNAPSHOT gov.nist.secauto.oscal @@ -27,8 +29,8 @@ https://github.com/usnistgov/liboscal-java scm:git:git@github.com:usnistgov/liboscal-java.git scm:git:git@github.com:usnistgov/liboscal-java.git - HEAD - + HEAD + @@ -122,16 +124,17 @@ UTF-8 UTF-8 - 0.12.2 + 1.0.0-M2-SNAPSHOT 1.1.1 3.14.0 13.0.10.Final 23.0.0 2.12.0 - 2.22.0 + 2.23.1 12.4 - 4.7.3 + 4.8.3 + 5.2.0 5.2.3 2.7.11 @@ -200,13 +203,24 @@ + + org.apache.xmlbeans + xmlbeans + ${dependency.xmlbeans.version} + gov.nist.secauto.metaschema - metaschema-java-binding + metaschema-core + ${dependency.metaschema-framework.version} + + + + gov.nist.secauto.metaschema + metaschema-databind ${dependency.metaschema-framework.version} @@ -244,18 +258,7 @@ org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - - org.junit.jupiter - junit-jupiter-params + junit-jupiter test @@ -296,47 +299,28 @@ - - - src/main/resources - - - ${project.build.directory}/generated-resources/oscal - - **/*.json - - ${resources.jsonschema.path} - - - ${project.build.directory}/generated-resources/oscal - - **/*.xsd - - ${resources.xmlschema.path} - - - - org.apache.maven.plugins - maven-toolchains-plugin - ${plugin.maven-toolchains.version} - - - - toolchain - - - - - - - 11 - temurin - - - - + + org.apache.maven.plugins + maven-toolchains-plugin + ${plugin.maven-toolchains.version} + + + + toolchain + + + + + + + 11 + temurin + + + + org.apache.maven.plugins maven-pmd-plugin @@ -388,13 +372,24 @@ spotbugs-exclude.xml + + org.apache.maven.plugins + maven-checkstyle-plugin + + + ${project.build.sourceDirectory} + + ${project.build.testSourceDirectory} + + + - - org.apache.maven.plugins - maven-toolchains-plugin - + + org.apache.maven.plugins + maven-toolchains-plugin + io.github.git-commit-id git-commit-id-maven-plugin @@ -427,45 +422,6 @@ - - maven-resources-plugin - - - copy-oscal-xml-schema - generate-resources - - copy-resources - - - - ${project.build.directory}/generated-resources/oscal/schema/xml - - - - ${project.basedir}/oscal/xml/schema - - - - - - copy-oscal-json-schema - generate-resources - - copy-resources - - - - ${project.build.directory}/generated-resources/oscal/schema/json - - - - ${project.basedir}/oscal/json/schema - - - - - - org.codehaus.mojo templating-maven-plugin @@ -561,13 +517,15 @@ ${dependency.metaschema-framework.version} - default-cli + oscal-codegen + generate-sources generate-sources ${project.basedir}/oscal/src/metaschema + ${project.build.directory}/generated-sources/metaschema ${project.basedir}/src/main/metaschema-bindings/oscal-metaschema-bindings.xml @@ -578,7 +536,25 @@ - generate-schemas + generate-xml-schemas + + generate-schemas + + + + ${project.basedir}/oscal/src/metaschema + + ${project.build.directory}/generated-resources/oscal/schema/xml + + oscal_*_metaschema.xml + + + xsd + + + + + generate-json-schemas generate-schemas @@ -586,10 +562,13 @@ ${project.basedir}/oscal/src/metaschema - ${project.build.directory}/generated-resources/oscal + ${project.build.directory}/generated-resources/oscal/schema/json oscal_*_metaschema.xml + + json + @@ -613,7 +592,7 @@ add-oscal-resources - process-resources + generate-resources add-resource diff --git a/src/main/java-templates/gov/nist/secauto/oscal/lib/LibOscalVersion.java b/src/main/java-templates/gov/nist/secauto/oscal/lib/LibOscalVersion.java index 7748e115..1b23e131 100644 --- a/src/main/java-templates/gov/nist/secauto/oscal/lib/LibOscalVersion.java +++ b/src/main/java-templates/gov/nist/secauto/oscal/lib/LibOscalVersion.java @@ -25,7 +25,7 @@ */ package gov.nist.secauto.oscal.lib; -import gov.nist.secauto.metaschema.model.common.util.IVersionInfo; +import gov.nist.secauto.metaschema.core.util.IVersionInfo; public final class LibOscalVersion implements IVersionInfo { public static final String NAME = "liboscal-java"; diff --git a/src/main/java-templates/gov/nist/secauto/oscal/lib/OscalVersion.java b/src/main/java-templates/gov/nist/secauto/oscal/lib/OscalVersion.java index 8ce27e8d..6c94b35a 100644 --- a/src/main/java-templates/gov/nist/secauto/oscal/lib/OscalVersion.java +++ b/src/main/java-templates/gov/nist/secauto/oscal/lib/OscalVersion.java @@ -25,7 +25,7 @@ */ package gov.nist.secauto.oscal.lib; -import gov.nist.secauto.metaschema.model.common.util.IVersionInfo; +import gov.nist.secauto.metaschema.core.util.IVersionInfo; public final class OscalVersion implements IVersionInfo { public static final String NAME = "oscal"; 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 95b945b9..d99921f7 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.model.common.constraint.IConstraintSet; +import gov.nist.secauto.metaschema.core.metapath.StaticContext; +import gov.nist.secauto.metaschema.core.model.IModuleLoader; +import gov.nist.secauto.metaschema.databind.DefaultBindingContext; import gov.nist.secauto.oscal.lib.model.AssessmentPlan; import gov.nist.secauto.oscal.lib.model.AssessmentResults; import gov.nist.secauto.oscal.lib.model.Catalog; @@ -42,18 +42,22 @@ import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Path; -import java.util.Set; - -import javax.xml.namespace.QName; +import java.util.List; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; public class OscalBindingContext extends DefaultBindingContext { @NonNull + public static final StaticContext OSCAL_STATIC_METAPATH_CONTEXT = StaticContext.builder() + .defaultModelNamespace(OscalModelConstants.NS_URI_OSCAL) + .build(); + @NonNull private static final OscalBindingContext SINGLETON = new OscalBindingContext(); @NonNull + @SuppressFBWarnings(value = "SING_SINGLETON_GETTER_NOT_SYNCHRONIZED", justification = "class initialization") public static OscalBindingContext instance() { return SINGLETON; } @@ -61,19 +65,33 @@ public static OscalBindingContext instance() { /** * Construct a new OSCAL-flavored binding context with custom constraints. * - * @param constraintSets - * a set of additional constraints to apply + * @param modulePostProcessors + * a list of module post processors to call after loading a module */ - public OscalBindingContext(@NonNull Set constraintSets) { - super(constraintSets); - registerBindingMatcher(new Matcher()); + @SuppressFBWarnings(value = "SING_SINGLETON_HAS_NONPRIVATE_CONSTRUCTOR", + justification = "public constructor allows customized use in specialized usecases") + public OscalBindingContext(@NonNull List modulePostProcessors) { + super(modulePostProcessors); + registerBindingMatcher(Catalog.class); + registerBindingMatcher(Profile.class); + registerBindingMatcher(SystemSecurityPlan.class); + registerBindingMatcher(ComponentDefinition.class); + registerBindingMatcher(AssessmentPlan.class); + registerBindingMatcher(AssessmentResults.class); + registerBindingMatcher(PlanOfActionAndMilestones.class); } /** * Construct a new OSCAL-flavored binding context. */ protected OscalBindingContext() { - registerBindingMatcher(new Matcher()); + registerBindingMatcher(Catalog.class); + registerBindingMatcher(Profile.class); + registerBindingMatcher(SystemSecurityPlan.class); + registerBindingMatcher(ComponentDefinition.class); + registerBindingMatcher(AssessmentPlan.class); + registerBindingMatcher(AssessmentResults.class); + registerBindingMatcher(PlanOfActionAndMilestones.class); } @NonNull @@ -181,71 +199,4 @@ public PlanOfActionAndMilestones loadPlanOfActionAndMilestones(@NonNull Path pat public PlanOfActionAndMilestones loadPlanOfActionAndMilestones(@NonNull File file) throws IOException { return newBoundLoader().load(PlanOfActionAndMilestones.class, file); } - - 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())) { - switch (startElementQName.getLocalPart()) { - case "catalog": - clazz = Catalog.class; - break; - case "profile": - clazz = Profile.class; - break; - case "system-security-plan": - clazz = SystemSecurityPlan.class; - break; - case "component-definition": - clazz = ComponentDefinition.class; - break; - case "assessment-plan": - clazz = AssessmentPlan.class; - break; - case "assessment-results": - clazz = AssessmentResults.class; - break; - case "plan-of-action-and-milestones": - clazz = PlanOfActionAndMilestones.class; - break; - default: - throw new UnsupportedOperationException("Unrecognized element name: " + startElementQName.toString()); - } - } - return clazz; - } - - @Override - public Class getBoundClassForJsonName(String name) { - Class retval; - switch (name) { - case "catalog": - retval = Catalog.class; - break; - case "profile": - retval = Profile.class; - break; - case "system-security-plan": - retval = SystemSecurityPlan.class; - break; - case "component-definition": - retval = ComponentDefinition.class; - break; - case "assessment-plan": - retval = AssessmentPlan.class; - break; - case "assessment-results": - retval = AssessmentResults.class; - break; - case "plan-of-action-and-milestones": - retval = PlanOfActionAndMilestones.class; - break; - default: - throw new UnsupportedOperationException("Unrecognized field name: " + name); - } - return retval; - } - - } } diff --git a/src/main/java/gov/nist/secauto/oscal/lib/OscalModelConstants.java b/src/main/java/gov/nist/secauto/oscal/lib/OscalModelConstants.java new file mode 100644 index 00000000..7862b4ca --- /dev/null +++ b/src/main/java/gov/nist/secauto/oscal/lib/OscalModelConstants.java @@ -0,0 +1,79 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.oscal.lib; + +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import java.net.URI; + +import javax.xml.namespace.QName; + +import edu.umd.cs.findbugs.annotations.NonNull; + +public final class OscalModelConstants { + + @NonNull + public static final String NS_OSCAL = "http://csrc.nist.gov/ns/oscal/1.0"; + @NonNull + public static final URI NS_URI_OSCAL = ObjectUtils.notNull(URI.create(NS_OSCAL)); + @NonNull + public static final QName QNAME_METADATA = new QName(NS_OSCAL, "metadata"); + @NonNull + public static final QName QNAME_BACK_MATTER = new QName(NS_OSCAL, "back-matter"); + @NonNull + public static final QName QNAME_PROFILE = new QName(NS_OSCAL, "profile"); + @NonNull + public static final QName QNAME_IMPORT = new QName(NS_OSCAL, "import"); + @NonNull + public static final QName QNAME_TITLE = new QName(NS_OSCAL, "title"); + @NonNull + public static final QName QNAME_PROP = new QName(NS_OSCAL, "prop"); + @NonNull + public static final QName QNAME_LINK = new QName(NS_OSCAL, "link"); + @NonNull + public static final QName QNAME_CITATION = new QName(NS_OSCAL, "citation"); + @NonNull + public static final QName QNAME_TEXT = new QName(NS_OSCAL, "text"); + @NonNull + public static final QName QNAME_PROSE = new QName(NS_OSCAL, "prose"); + @NonNull + public static final QName QNAME_PARAM = new QName(NS_OSCAL, "param"); + @NonNull + public static final QName QNAME_ROLE = new QName(NS_OSCAL, "role"); + @NonNull + public static final QName QNAME_LOCATION = new QName(NS_OSCAL, "location"); + @NonNull + public static final QName QNAME_PARTY = new QName(NS_OSCAL, "party"); + @NonNull + public static final QName QNAME_GROUP = new QName(NS_OSCAL, "group"); + @NonNull + public static final QName QNAME_CONTROL = new QName(NS_OSCAL, "control"); + + private OscalModelConstants() { + // disable construction + } +} 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 8c851b1a..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.model.common.util.ObjectUtils; +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 b810ea74..e5e0b76f 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 @@ -26,34 +26,42 @@ package gov.nist.secauto.oscal.lib.metapath.function.library; -import gov.nist.secauto.metaschema.model.common.metapath.DynamicContext; -import gov.nist.secauto.metaschema.model.common.metapath.ISequence; -import gov.nist.secauto.metaschema.model.common.metapath.MetapathException; -import gov.nist.secauto.metaschema.model.common.metapath.function.FunctionUtils; -import gov.nist.secauto.metaschema.model.common.metapath.function.IArgument; -import gov.nist.secauto.metaschema.model.common.metapath.function.IFunction; -import gov.nist.secauto.metaschema.model.common.metapath.function.InvalidTypeFunctionException; -import gov.nist.secauto.metaschema.model.common.metapath.item.IBooleanItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDefinitionNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.INodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IStringItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; -import gov.nist.secauto.oscal.lib.model.AssessmentPart; -import gov.nist.secauto.oscal.lib.model.ControlPart; -import gov.nist.secauto.oscal.lib.model.Property; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.MetapathConstants; +import gov.nist.secauto.metaschema.core.metapath.MetapathException; +import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; +import gov.nist.secauto.metaschema.core.metapath.function.IArgument; +import gov.nist.secauto.metaschema.core.metapath.function.IFunction; +import gov.nist.secauto.metaschema.core.metapath.function.InvalidTypeFunctionException; +import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; +import gov.nist.secauto.metaschema.core.metapath.item.IItem; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyUriItem; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem; +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.metapath.item.node.IFlagNodeItem; +import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition; +import gov.nist.secauto.metaschema.core.model.IFlagInstance; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.OscalModelConstants; import gov.nist.secauto.oscal.lib.model.metadata.AbstractProperty; import java.net.URI; import java.util.List; +import javax.xml.namespace.QName; + import edu.umd.cs.findbugs.annotations.NonNull; public final class HasOscalNamespace { + @NonNull + private static final QName NS_FLAG_QNAME = new QName("ns"); @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name("has-oscal-namespace") - .argument(IArgument.newBuilder() + .namespace(OscalModelConstants.NS_OSCAL) + .argument(IArgument.builder() .name("namespace") .type(IStringItem.class) .oneOrMore() @@ -70,12 +78,54 @@ public final class HasOscalNamespace { @NonNull static final IFunction SIGNATURE_TWO_ARGS = IFunction.builder() .name("has-oscal-namespace") - .argument(IArgument.newBuilder() + .namespace(OscalModelConstants.NS_OSCAL) + .argument(IArgument.builder() + .name("propOrPart") + .type(IAssemblyNodeItem.class) + .one() + .build()) + .argument(IArgument.builder() + .name("namespace") + .type(IStringItem.class) + .oneOrMore() + .build()) + .allowUnboundedArity(true) + .focusIndependent() + .contextIndependent() + .deterministic() + .returnType(IBooleanItem.class) + .returnOne() + .functionHandler(HasOscalNamespace::executeTwoArg) + .build(); + + @NonNull + static final IFunction SIGNATURE_ONE_ARG_METAPATH = IFunction.builder() + .name("has-oscal-namespace") + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) + .argument(IArgument.builder() + .name("namespace") + .type(IStringItem.class) + .oneOrMore() + .build()) + .allowUnboundedArity(true) + .returnType(IBooleanItem.class) + .focusDependent() + .contextIndependent() + .deterministic() + .returnOne() + .functionHandler(HasOscalNamespace::executeOneArg) + .build(); + + @NonNull + static final IFunction SIGNATURE_TWO_ARGS_METAPATH = IFunction.builder() + .name("has-oscal-namespace") + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) + .argument(IArgument.builder() .name("propOrPart") - .type(IDefinitionNodeItem.class) + .type(IAssemblyNodeItem.class) .one() .build()) - .argument(IArgument.newBuilder() + .argument(IArgument.builder() .name("namespace") .type(IStringItem.class) .oneOrMore() @@ -101,19 +151,16 @@ public static ISequence executeOneArg( @NonNull IFunction function, @NonNull List> arguments, @NonNull DynamicContext dynamicContext, - INodeItem focus) { - INodeItem node = focus; - if (node == null) { - return ISequence.empty(); - } - + IItem focus) { assert arguments.size() == 1; ISequence namespaceArgs = FunctionUtils.asType( ObjectUtils.notNull(arguments.get(0))); + if (namespaceArgs.isEmpty()) { return ISequence.empty(); } + IAssemblyNodeItem node = FunctionUtils.requireType(IAssemblyNodeItem.class, focus); return ISequence.of(hasNamespace(FunctionUtils.asType(node), namespaceArgs)); } @@ -125,50 +172,60 @@ public static ISequence executeTwoArg( @NonNull IFunction function, @NonNull List> arguments, @NonNull DynamicContext dynamicContext, - INodeItem focus) { - ISequence nodeSequence = FunctionUtils.asType( - ObjectUtils.notNull(arguments.get(0))); - - IItem node = FunctionUtils.getFirstItem(nodeSequence, true); - if (node == null) { - return ISequence.empty(); - } - + IItem focus) { assert arguments.size() == 2; + ISequence namespaceArgs = FunctionUtils.asType( ObjectUtils.notNull(arguments.get(1))); if (namespaceArgs.isEmpty()) { return ISequence.empty(); } - return ISequence.of(hasNamespace(FunctionUtils.asType(node), namespaceArgs)); + ISequence nodeSequence = FunctionUtils.asType( + ObjectUtils.notNull(arguments.get(0))); + + // always not null, since the first item is required + IAssemblyNodeItem node = FunctionUtils.asType(ObjectUtils.requireNonNull(nodeSequence.getFirstItem(true))); + return ISequence.of(hasNamespace(node, namespaceArgs)); } @SuppressWarnings("PMD.LinguisticNaming") // false positive @NonNull public static IBooleanItem hasNamespace( - @NonNull IDefinitionNodeItem propOrPart, - @NonNull ISequence namespaces) - throws MetapathException { + @NonNull IAssemblyNodeItem propOrPart, + @NonNull ISequence namespaces) { Object propOrPartObject = propOrPart.getValue(); if (propOrPartObject == null) { throw new InvalidTypeFunctionException(InvalidTypeFunctionException.NODE_HAS_NO_TYPED_VALUE, propOrPart); } - URI nodeNamespace; - if (propOrPartObject instanceof Property) { - nodeNamespace = ((Property) propOrPartObject).getNs(); - } else if (propOrPartObject instanceof ControlPart) { - nodeNamespace = ((ControlPart) propOrPartObject).getNs(); - } else if (propOrPartObject instanceof AssessmentPart) { - nodeNamespace = ((AssessmentPart) propOrPartObject).getNs(); + URI nodeNamespace = null; + // get the "ns" flag value + IFlagNodeItem ns = propOrPart.getFlagByName(NS_FLAG_QNAME); + if (ns == null) { + // check if the node actually has a "ns" flag + IAssemblyDefinition definition = propOrPart.getDefinition(); + IFlagInstance flag = definition.getFlagInstanceByName(NS_FLAG_QNAME); + if (flag == null) { + throw new MetapathException( + String.format( + "Node at path '%s' bound to '%s' based on the assembly definition '%s' has no OSCAL namespace", + propOrPart.getMetapath(), + propOrPart.getClass().getName(), + propOrPart.getDefinition().getName())); + + } + + Object defaultValue = flag.getDefinition().getDefaultValue(); + if (defaultValue != null) { + nodeNamespace = IAnyUriItem.valueOf(ObjectUtils.notNull(defaultValue.toString())).asUri(); + } } else { - throw new MetapathException( - String.format("Node of definition type '%s' has no OSCAL namespace", propOrPart.getDefinition().getName())); + nodeNamespace = IAnyUriItem.cast(FnData.fnDataItem(ns)).asUri(); } String nodeNamespaceString = AbstractProperty.normalizeNamespace(nodeNamespace).toString(); - return IBooleanItem.valueOf(namespaces.asStream() + return IBooleanItem.valueOf(namespaces.stream() .map(node -> nodeNamespaceString.equals(node.asString())) .anyMatch(bool -> bool)); } diff --git a/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/OscalFunctionLibrary.java b/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/OscalFunctionLibrary.java index 3303daa4..24640153 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/OscalFunctionLibrary.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/OscalFunctionLibrary.java @@ -28,8 +28,8 @@ import com.google.auto.service.AutoService; -import gov.nist.secauto.metaschema.model.common.metapath.function.FunctionLibrary; -import gov.nist.secauto.metaschema.model.common.metapath.function.IFunctionLibrary; +import gov.nist.secauto.metaschema.core.metapath.function.FunctionLibrary; +import gov.nist.secauto.metaschema.core.metapath.function.IFunctionLibrary; @AutoService(IFunctionLibrary.class) public class OscalFunctionLibrary @@ -40,6 +40,13 @@ public OscalFunctionLibrary() { registerFunction(ResolveProfile.SIGNATURE_ONE_ARG); registerFunction(HasOscalNamespace.SIGNATURE_ONE_ARG); registerFunction(HasOscalNamespace.SIGNATURE_TWO_ARGS); + + // for backwards compatibility with no function namespace + registerFunction(ResolveProfile.SIGNATURE_NO_ARG_METAPATH); + registerFunction(ResolveProfile.SIGNATURE_ONE_ARG_METAPATH); + registerFunction(HasOscalNamespace.SIGNATURE_ONE_ARG_METAPATH); + registerFunction(HasOscalNamespace.SIGNATURE_TWO_ARGS_METAPATH); + } } 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 b0329a92..df70623b 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 @@ -26,16 +26,18 @@ package gov.nist.secauto.oscal.lib.metapath.function.library; -import gov.nist.secauto.metaschema.model.common.metapath.DynamicContext; -import gov.nist.secauto.metaschema.model.common.metapath.ISequence; -import gov.nist.secauto.metaschema.model.common.metapath.MetapathException; -import gov.nist.secauto.metaschema.model.common.metapath.function.FunctionUtils; -import gov.nist.secauto.metaschema.model.common.metapath.function.IArgument; -import gov.nist.secauto.metaschema.model.common.metapath.function.IFunction; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.INodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.MetapathConstants; +import gov.nist.secauto.metaschema.core.metapath.MetapathException; +import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; +import gov.nist.secauto.metaschema.core.metapath.function.IArgument; +import gov.nist.secauto.metaschema.core.metapath.function.IFunction; +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.metapath.item.node.INodeItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.OscalModelConstants; 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 +52,7 @@ public final class ResolveProfile { @NonNull static final IFunction SIGNATURE_NO_ARG = IFunction.builder() .name("resolve-profile") + .namespace(OscalModelConstants.NS_OSCAL) .returnType(INodeItem.class) .focusDependent() .contextDependent() @@ -61,7 +64,37 @@ public final class ResolveProfile { @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name("resolve-profile") - .argument(IArgument.newBuilder() + .namespace(OscalModelConstants.NS_OSCAL) + .argument(IArgument.builder() + .name("profile") + .type(INodeItem.class) + .zeroOrOne() + .build()) + .focusDependent() + .contextDependent() + .deterministic() + .returnType(INodeItem.class) + .returnOne() + .functionHandler(ResolveProfile::executeOneArg) + .build(); + + @NonNull + static final IFunction SIGNATURE_NO_ARG_METAPATH = IFunction.builder() + .name("resolve-profile") + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) + .returnType(INodeItem.class) + .focusDependent() + .contextDependent() + .deterministic() + .returnOne() + .functionHandler(ResolveProfile::executeNoArg) + .build(); + + @NonNull + static final IFunction SIGNATURE_ONE_ARG_METAPATH = IFunction.builder() + .name("resolve-profile") + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) + .argument(IArgument.builder() .name("profile") .type(INodeItem.class) .zeroOrOne() @@ -86,13 +119,12 @@ public static ISequence executeNoArg( @NonNull IFunction function, @NonNull List> arguments, @NonNull DynamicContext dynamicContext, - INodeItem focus) { + IItem focus) { - INodeItem item = focus; - if (item == null) { + if (focus == null) { return ISequence.empty(); } - return ISequence.of(resolveProfile(FunctionUtils.asType(item), dynamicContext)); + return ISequence.of(resolveProfile(FunctionUtils.asType(focus), dynamicContext)); } @SuppressWarnings({ "unused", @@ -103,11 +135,11 @@ public static ISequence executeOneArg( @NonNull IFunction function, @NonNull List> arguments, @NonNull DynamicContext dynamicContext, - INodeItem focus) { + IItem focus) { ISequence arg = FunctionUtils.asType( ObjectUtils.notNull(arguments.get(0))); - IItem item = FunctionUtils.getFirstItem(arg, true); + IItem item = arg.getFirstItem(true); if (item == null) { return ISequence.empty(); } @@ -118,7 +150,7 @@ public static ISequence executeOneArg( @NonNull public static IDocumentNodeItem resolveProfile(@NonNull IDocumentNodeItem profile, @NonNull DynamicContext dynamicContext) { - Object profileObject = profile.getValue(); + Object profileObject = INodeItem.toValue(profile); IDocumentNodeItem retval; if (profileObject instanceof Catalog) { diff --git a/src/main/java/gov/nist/secauto/oscal/lib/model/control/AbstractParameter.java b/src/main/java/gov/nist/secauto/oscal/lib/model/control/AbstractParameter.java index cde066e7..c08e4f26 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/control/AbstractParameter.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/control/AbstractParameter.java @@ -26,10 +26,10 @@ package gov.nist.secauto.oscal.lib.model.control; -import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine; -import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupMultiline; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine; +import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.Link; import gov.nist.secauto.oscal.lib.model.Parameter; import gov.nist.secauto.oscal.lib.model.ParameterConstraint; @@ -57,7 +57,7 @@ public Stream getParameterReferences() { Stream aggregatesIds = CollectionUtil.listOrEmpty(getProps()).stream() .filter(Objects::nonNull) .filter(prop -> prop.isNamespaceEqual(IProperty.OSCAL_NAMESPACE) && "aggregates".equals(prop.getName())) - .map(prop -> prop.getValue()); + .map(Property::getValue); // handle select/choice/insert ParameterSelection selection = getSelect(); diff --git a/src/main/java/gov/nist/secauto/oscal/lib/model/control/AbstractPart.java b/src/main/java/gov/nist/secauto/oscal/lib/model/control/AbstractPart.java index 1cf375fc..9d391f8b 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/control/AbstractPart.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/control/AbstractPart.java @@ -26,11 +26,11 @@ package gov.nist.secauto.oscal.lib.model.control; -import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine; -import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupMultiline; -import gov.nist.secauto.metaschema.model.common.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine; +import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; +import gov.nist.secauto.metaschema.core.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.ControlPart; import gov.nist.secauto.oscal.lib.model.Link; import gov.nist.secauto.oscal.lib.model.Property; @@ -65,7 +65,7 @@ public Stream getPartsRecursively() { return Stream.concat( Stream.of(this), CollectionUtil.listOrEmpty(getParts()).stream() - .flatMap(part -> part.getPartsRecursively())); + .flatMap(AbstractPart::getPartsRecursively)); } @NonNull diff --git a/src/main/java/gov/nist/secauto/oscal/lib/model/control/IPart.java b/src/main/java/gov/nist/secauto/oscal/lib/model/control/IPart.java index 0f7c3398..f3bf39b1 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/control/IPart.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/control/IPart.java @@ -26,8 +26,8 @@ package gov.nist.secauto.oscal.lib.model.control; -import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupMultiline; -import gov.nist.secauto.metaschema.model.common.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode; +import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; +import gov.nist.secauto.metaschema.core.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode; import gov.nist.secauto.oscal.lib.model.ControlPart; import java.util.List; diff --git a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalog.java b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalog.java index 68175622..ccbcd640 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalog.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalog.java @@ -26,9 +26,10 @@ package gov.nist.secauto.oscal.lib.model.control.catalog; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.AbstractOscalInstance; +import gov.nist.secauto.oscal.lib.model.control.AbstractParameter; import java.util.stream.Stream; @@ -45,7 +46,7 @@ public Stream getReferencedParameterIds() { return ObjectUtils.notNull( CollectionUtil.listOrEmpty(getParams()).stream() .flatMap(ObjectUtils::filterNull) - .flatMap(param -> param.getParameterReferences()) + .flatMap(AbstractParameter::getParameterReferences) .distinct()); } } diff --git a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalogGroup.java b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalogGroup.java index 96d46a73..36daa7b1 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalogGroup.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalogGroup.java @@ -26,15 +26,16 @@ package gov.nist.secauto.oscal.lib.model.control.catalog; -import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; import gov.nist.secauto.oscal.lib.model.ControlPart; import gov.nist.secauto.oscal.lib.model.Link; import gov.nist.secauto.oscal.lib.model.Parameter; import gov.nist.secauto.oscal.lib.model.Property; +import gov.nist.secauto.oscal.lib.model.control.AbstractParameter; import java.util.LinkedList; import java.util.List; @@ -63,7 +64,7 @@ public Stream getReferencedParameterIds() { // get parameters referenced by the control's parameters Stream parameterIds = CollectionUtil.listOrEmpty(getParams()).stream() .flatMap(ObjectUtils::filterNull) - .flatMap(param -> param.getParameterReferences()); + .flatMap(AbstractParameter::getParameterReferences); return ObjectUtils.notNull( Stream.concat(insertIds, parameterIds).distinct()); diff --git a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalogVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalogVisitor.java index b66676cc..949c7875 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalogVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/control/catalog/AbstractCatalogVisitor.java @@ -26,8 +26,8 @@ package gov.nist.secauto.oscal.lib.model.control.catalog; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; @@ -64,15 +64,15 @@ public RESULT visitCatalog(Catalog catalog, CONTEXT context) { RESULT result = CollectionUtil.listOrEmpty(catalog.getGroups()).stream() .filter(Objects::nonNull) .map(childGroup -> visitGroup(ObjectUtils.notNull(childGroup), context)) - .reduce(defaultResult(), (previous, current) -> aggregateResult(previous, current)); + .reduce(defaultResult(), this::aggregateResult); result = CollectionUtil.listOrEmpty(catalog.getControls()).stream() .filter(Objects::nonNull) .map(childControl -> visitControl(ObjectUtils.notNull(childControl), context)) - .reduce(result, (previous, current) -> aggregateResult(previous, current)); + .reduce(result, this::aggregateResult); return CollectionUtil.listOrEmpty(catalog.getParams()).stream() .filter(Objects::nonNull) .map(childParameter -> visitParameter(ObjectUtils.notNull(childParameter), context)) - .reduce(result, (previous, current) -> aggregateResult(previous, current)); + .reduce(result, this::aggregateResult); } @Override @@ -80,15 +80,15 @@ public RESULT visitGroup(@NonNull CatalogGroup group, CONTEXT context) { RESULT result = CollectionUtil.listOrEmpty(group.getGroups()).stream() .filter(Objects::nonNull) .map(childGroup -> visitGroup(ObjectUtils.notNull(childGroup), context)) - .reduce(defaultResult(), (previous, current) -> aggregateResult(previous, current)); + .reduce(defaultResult(), this::aggregateResult); result = CollectionUtil.listOrEmpty(group.getControls()).stream() .filter(Objects::nonNull) .map(childControl -> visitControl(ObjectUtils.notNull(childControl), context)) - .reduce(result, (previous, current) -> aggregateResult(previous, current)); + .reduce(result, this::aggregateResult); return CollectionUtil.listOrEmpty(group.getParams()).stream() .filter(Objects::nonNull) .map(childParameter -> visitParameter(ObjectUtils.notNull(childParameter), context)) - .reduce(result, (previous, current) -> aggregateResult(previous, current)); + .reduce(result, this::aggregateResult); } @Override @@ -96,11 +96,11 @@ public RESULT visitControl(Control control, CONTEXT context) { RESULT result = CollectionUtil.listOrEmpty(control.getControls()).stream() .filter(Objects::nonNull) .map(childControl -> visitControl(ObjectUtils.notNull(childControl), context)) - .reduce(defaultResult(), (previous, current) -> aggregateResult(previous, current)); + .reduce(defaultResult(), this::aggregateResult); return CollectionUtil.listOrEmpty(control.getParams()).stream() .filter(Objects::nonNull) .map(childParameter -> visitParameter(ObjectUtils.notNull(childParameter), context)) - .reduce(result, (previous, current) -> aggregateResult(previous, current)); + .reduce(result, this::aggregateResult); } @Override 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 8ac4ede1..71c09c82 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,15 +26,16 @@ package gov.nist.secauto.oscal.lib.model.control.catalog; -import gov.nist.secauto.metaschema.binding.io.IDeserializationHandler; -import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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; import gov.nist.secauto.oscal.lib.model.Parameter; import gov.nist.secauto.oscal.lib.model.Property; +import gov.nist.secauto.oscal.lib.model.control.AbstractParameter; import java.util.LinkedList; import java.util.List; @@ -86,7 +87,7 @@ public Stream getReferencedParameterIds() { // get parameters referenced by the control's parameters Stream parameterIds = CollectionUtil.listOrEmpty(getParams()).stream() .flatMap(ObjectUtils::filterNull) - .flatMap(param -> param.getParameterReferences()); + .flatMap(AbstractParameter::getParameterReferences); return ObjectUtils.notNull( Stream.concat(insertIds, parameterIds).distinct()); 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/AbstractLink.java b/src/main/java/gov/nist/secauto/oscal/lib/model/metadata/AbstractLink.java index cf1841e2..de5e0dbc 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/model/metadata/AbstractLink.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/model/metadata/AbstractLink.java @@ -26,8 +26,8 @@ package gov.nist.secauto.oscal.lib.model.metadata; -import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.Link; import java.net.URI; 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 5f92db17..882b982e 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 @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.model.metadata; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.oscal.lib.model.Property; import java.net.URI; @@ -112,9 +112,10 @@ 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)) { + if (OSCAL_NAMESPACE.equals(namespace)) { this.namespace = null; } else { this.namespace = Objects.requireNonNull(namespace); diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ModifyPhaseUtils.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ModifyPhaseUtils.java index 8ff97a57..dbf66e77 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ModifyPhaseUtils.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/ModifyPhaseUtils.java @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; import java.util.Collections; import java.util.LinkedHashMap; 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 7429b824..7b0cba18 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,31 +26,40 @@ 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 gov.nist.secauto.metaschema.model.common.metapath.DynamicContext; -import gov.nist.secauto.metaschema.model.common.metapath.MetapathExpression; -import gov.nist.secauto.metaschema.model.common.metapath.StaticContext; -import gov.nist.secauto.metaschema.model.common.metapath.format.IPathFormatter; -import gov.nist.secauto.metaschema.model.common.metapath.item.DefaultNodeItemFactory; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueAssemblyNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRootAssemblyNodeItem; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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; +import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; +import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; +import gov.nist.secauto.metaschema.core.metapath.item.IItem; +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.INodeItem; +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.IBoundObject; +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.IBoundDefinitionModelAssembly; import gov.nist.secauto.oscal.lib.OscalBindingContext; +import gov.nist.secauto.oscal.lib.OscalModelConstants; 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; import gov.nist.secauto.oscal.lib.model.Metadata; +import gov.nist.secauto.oscal.lib.model.Metadata.Location; +import gov.nist.secauto.oscal.lib.model.Metadata.Party; +import gov.nist.secauto.oscal.lib.model.Metadata.Role; import gov.nist.secauto.oscal.lib.model.Modify; import gov.nist.secauto.oscal.lib.model.Modify.ProfileSetParameter; import gov.nist.secauto.oscal.lib.model.Parameter; @@ -72,15 +81,13 @@ 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.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; @@ -91,19 +98,41 @@ import java.util.UUID; import java.util.stream.Collectors; +import javax.xml.namespace.QName; + import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; public class ProfileResolver { private static final Logger LOGGER = LogManager.getLogger(ProfileResolver.class); + @NonNull + private static final QName IMPORT_QNAME = new QName(OscalModelConstants.NS_OSCAL, "import"); + + @NonNull private static final MetapathExpression METAPATH_SET_PARAMETER - = MetapathExpression.compile("/profile/modify/set-parameter"); + = MetapathExpression.compile("modify/set-parameter", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); + @NonNull private static final MetapathExpression METAPATH_ALTER - = MetapathExpression.compile("/profile/modify/alter"); + = MetapathExpression.compile("modify/alter", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); + @NonNull private static final MetapathExpression METAPATH_ALTER_REMOVE - = MetapathExpression.compile("remove"); + = MetapathExpression.compile("remove", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); + @NonNull private static final MetapathExpression METAPATH_ALTER_ADD - = MetapathExpression.compile("add"); + = MetapathExpression.compile("add", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); + @NonNull + private static final MetapathExpression CATALOG_OR_PROFILE + = MetapathExpression.compile("/(catalog|profile)", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); + @NonNull + private static final MetapathExpression CATALOG + = MetapathExpression.compile("/catalog", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); public enum StructuringDirective { FLAT, @@ -115,7 +144,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 */ @@ -142,7 +172,9 @@ public void setBoundLoader(@NonNull IBoundLoader loader) { public DynamicContext getDynamicContext() { synchronized (this) { if (dynamicContext == null) { - dynamicContext = new StaticContext().newDynamicContext(); + dynamicContext = new DynamicContext(StaticContext.builder() + .defaultModelNamespace(OscalModelConstants.NS_URI_OSCAL) + .build()); dynamicContext.setDocumentLoader(getBoundLoader()); } assert dynamicContext != null; @@ -157,70 +189,61 @@ 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, + @NonNull MetapathExpression rootPath) { + ISequence result = rootPath.evaluate(document); + IItem item = result.getFirstItem(false); + + return item == null ? null : FunctionUtils.asType(item); } - public IDocumentNodeItem resolveProfile(@NonNull URL url) + @NonNull + public IDocumentNodeItem resolve(@NonNull URL url) throws URISyntaxException, IOException, ProfileResolutionException { IBoundLoader loader = getBoundLoader(); IDocumentNodeItem catalogOrProfile = loader.loadAsNodeItem(url); - return resolve(catalogOrProfile); + return resolve(catalogOrProfile, new Stack<>()); } - public IDocumentNodeItem resolveProfile(@NonNull Path path) throws IOException, ProfileResolutionException { - IBoundLoader loader = getBoundLoader(); - IDocumentNodeItem catalogOrProfile = loader.loadAsNodeItem(path); - return resolve(catalogOrProfile); + @NonNull + public IDocumentNodeItem resolve(@NonNull File file) throws IOException, ProfileResolutionException { + return resolve(ObjectUtils.notNull(file.toPath())); } - public IDocumentNodeItem resolveProfile(@NonNull File file) throws IOException, ProfileResolutionException { - return resolveProfile(ObjectUtils.notNull(file.toPath())); + @NonNull + public IDocumentNodeItem resolve(@NonNull Path path) throws IOException, ProfileResolutionException { + IBoundLoader loader = getBoundLoader(); + IDocumentNodeItem catalogOrProfile = loader.loadAsNodeItem(path); + return resolve(catalogOrProfile, new Stack<>()); } - /** - * Resolve the profile to a catalog. - * - * @param profileDocument - * a {@link IDocumentNodeItem} containing the profile to resolve - * @param importHistory - * the import stack for cycle detection - * @return the resolved profile - * @throws IOException - * if an error occurred while loading the profile or an import - * @throws ProfileResolutionException - * if an error occurred while resolving the profile - */ @NonNull - protected IDocumentNodeItem resolveProfile( - @NonNull IDocumentNodeItem profileDocument, - @NonNull Stack importHistory) throws IOException, ProfileResolutionException { - Catalog resolvedCatalog = new Catalog(); - - generateMetadata(resolvedCatalog, profileDocument); - - IIndexer index = resolveImports(resolvedCatalog, profileDocument, importHistory); - handleReferences(resolvedCatalog, profileDocument, index); - handleMerge(resolvedCatalog, profileDocument, index); - handleModify(resolvedCatalog, profileDocument); - - return DefaultNodeItemFactory.instance().newDocumentNodeItem( - new RootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class))), - resolvedCatalog, - profileDocument.getBaseUri()); + public IDocumentNodeItem resolve( + @NonNull IDocumentNodeItem profileOrCatalogDocument) + throws IOException, ProfileResolutionException { + return resolve(profileOrCatalogDocument, new Stack<>()); } @NonNull - public IDocumentNodeItem resolve(@NonNull IDocumentNodeItem profileOrCatalog) + public IDocumentNodeItem resolve( + @NonNull IDocumentNodeItem profileOrCatalogDocument, + @NonNull Stack importHistory) throws IOException, ProfileResolutionException { - return resolve(profileOrCatalog, new Stack<>()); + IRootAssemblyNodeItem profileOrCatalog = getRoot( + profileOrCatalogDocument, + CATALOG_OR_PROFILE); + if (profileOrCatalog == null) { + throw new ProfileResolutionException( + String.format("The provided document '%s' does not contain a catalog or profile.", + profileOrCatalogDocument.getDocumentUri())); + } + return resolve(profileOrCatalog, importHistory); } @NonNull - protected IDocumentNodeItem resolve(@NonNull IDocumentNodeItem profileOrCatalog, + public IDocumentNodeItem resolve(@NonNull IRootAssemblyNodeItem profileOrCatalog, @NonNull Stack importHistory) throws IOException, ProfileResolutionException { Object profileObject = profileOrCatalog.getValue(); @@ -228,7 +251,7 @@ protected IDocumentNodeItem resolve(@NonNull IDocumentNodeItem profileOrCatalog, IDocumentNodeItem retval; if (profileObject instanceof Catalog) { // already a catalog - retval = profileOrCatalog; + retval = profileOrCatalog.getDocumentNodeItem(); } else { // must be a profile retval = resolveProfile(profileOrCatalog, importHistory); @@ -236,11 +259,37 @@ protected IDocumentNodeItem resolve(@NonNull IDocumentNodeItem profileOrCatalog, return retval; } - private static Profile toProfile(@NonNull IDocumentNodeItem profileDocument) { - Object object = profileDocument.getValue(); - assert object != null; + /** + * Resolve the profile to a catalog. + * + * @param profileItem + * a {@link IDocumentNodeItem} containing the profile to resolve + * @param importHistory + * the import stack for cycle detection + * @return the resolved profile + * @throws IOException + * if an error occurred while loading the profile or an import + * @throws ProfileResolutionException + * if an error occurred while resolving the profile + */ + @NonNull + protected IDocumentNodeItem resolveProfile( + @NonNull IRootAssemblyNodeItem profileItem, + @NonNull Stack importHistory) throws IOException, ProfileResolutionException { + Catalog resolvedCatalog = new Catalog(); - return (Profile) object; + generateMetadata(resolvedCatalog, profileItem); + + IIndexer index = resolveImports(resolvedCatalog, profileItem, importHistory); + handleReferences(resolvedCatalog, profileItem, index); + handleMerge(resolvedCatalog, profileItem, index); + handleModify(resolvedCatalog, profileItem); + + return INodeItemFactory.instance().newDocumentNodeItem( + ObjectUtils.requireNonNull( + (IBoundDefinitionModelAssembly) OscalBindingContext.instance().getBoundDefinitionForClass(Catalog.class)), + ObjectUtils.requireNonNull(profileItem.getBaseUri()), + resolvedCatalog); } @NonNull @@ -251,10 +300,12 @@ private static Profile toProfile(@NonNull IRootAssemblyNodeItem profileItem) { return (Profile) object; } - private static void generateMetadata(@NonNull Catalog resolvedCatalog, @NonNull IDocumentNodeItem profileDocument) { + private static void generateMetadata( + @NonNull Catalog resolvedCatalog, + @NonNull IRootAssemblyNodeItem profileItem) { resolvedCatalog.setUuid(UUID.randomUUID()); - Profile profile = toProfile(profileDocument); + Profile profile = toProfile(profileItem); Metadata profileMetadata = profile.getMetadata(); Metadata resolvedMetadata = new Metadata(); @@ -271,7 +322,7 @@ private static void generateMetadata(@NonNull Catalog resolvedCatalog, @NonNull resolvedMetadata.addProp(AbstractProperty.builder("resolution-tool").value("libOSCAL-Java").build()); - URI profileUri = profileDocument.getDocumentUri(); + URI profileUri = ObjectUtils.requireNonNull(profileItem.getDocumentNodeItem().getDocumentUri()); resolvedMetadata.addLink(AbstractLink.builder(profileUri).relation("source-profile").build()); resolvedCatalog.setMetadata(resolvedMetadata); @@ -280,24 +331,23 @@ private static void generateMetadata(@NonNull Catalog resolvedCatalog, @NonNull @NonNull private IIndexer resolveImports( @NonNull Catalog resolvedCatalog, - @NonNull IDocumentNodeItem profileDocument, + @NonNull IRootAssemblyNodeItem profileItem, @NonNull Stack importHistory) throws IOException, ProfileResolutionException { - IRootAssemblyNodeItem profileItem = profileDocument.getRootAssemblyNodeItem(); - // first verify there is at least one import - List profileImports = profileItem.getModelItemsByName("import"); + @SuppressWarnings("unchecked") List profileImports + = (List) profileItem.getModelItemsByName(IMPORT_QNAME); if (profileImports.isEmpty()) { throw new ProfileResolutionException(String.format("Profile '%s' has no imports", profileItem.getBaseUri())); } // now process each import IIndexer retval = new BasicIndexer(); - for (IRequiredValueModelNodeItem profileImportItem : profileImports) { + for (IAssemblyNodeItem profileImportItem : profileImports) { IIndexer result = resolveImport( ObjectUtils.notNull(profileImportItem), - profileDocument, + profileItem, importHistory, resolvedCatalog); retval.append(result); @@ -307,11 +357,11 @@ private IIndexer resolveImports( @NonNull protected IIndexer resolveImport( - @NonNull IRequiredValueModelNodeItem profileImportItem, - @NonNull IDocumentNodeItem profileDocument, + @NonNull IAssemblyNodeItem profileImportItem, + @NonNull IRootAssemblyNodeItem profileItem, @NonNull Stack importHistory, @NonNull Catalog resolvedCatalog) throws IOException, ProfileResolutionException { - ProfileImport profileImport = (ProfileImport) profileImportItem.getValue(); + ProfileImport profileImport = ObjectUtils.requireNonNull((ProfileImport) profileImportItem.getValue()); URI importUri = profileImport.getHref(); if (importUri == null) { @@ -322,79 +372,110 @@ protected IIndexer resolveImport( LOGGER.atDebug().log("resolving profile import '{}'", importUri); } - InputSource source = newImportSource(importUri, profileDocument); - 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 { - importedCatalog = DefaultNodeItemFactory.instance().newDocumentNodeItem( - importedCatalog.getRootAssemblyNodeItem().getDefinition(), - OscalBindingContext.instance().copyBoundObject(importedCatalog.getValue(), null), - importedCatalog.getDocumentUri()); + IRootAssemblyNodeItem importedCatalogRoot = ObjectUtils.requireNonNull(getRoot(importedCatalog, CATALOG)); + Catalog catalogCopy = (Catalog) OscalBindingContext.instance().deepCopy( + (IBoundObject) ObjectUtils.requireNonNull(importedCatalogRoot).getValue(), null); - return new Import(profileDocument, profileImportItem) - .resolve(importedCatalog, resolvedCatalog); + importedCatalog = INodeItemFactory.instance().newDocumentNodeItem( + importedCatalogRoot.getDefinition(), + ObjectUtils.requireNonNull(importedCatalog.getDocumentUri()), + catalogCopy); + + return new Import(profileItem, profileImportItem).resolve(importedCatalog, resolvedCatalog); } catch (BindingException ex) { throw new IOException(ex); } } 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 IDocumentNodeItem profileDocument) throws IOException { + @NonNull IRootAssemblyNodeItem importingProfile) throws IOException { - // Get the entity resolver to resolve relative references in the profile - EntityResolver resolver = getEntityResolver(profileDocument.getDocumentUri()); + URI importingDocumentUri = ObjectUtils.requireNonNull(importingProfile.getDocumentNodeItem().getDocumentUri()); - InputSource source; + IDocumentNodeItem retval; if (OscalUtils.isInternalReference(importUri)) { // handle internal reference String uuid = OscalUtils.internalReferenceFragmentToId(importUri); - IRootAssemblyNodeItem profileItem = profileDocument.getRootAssemblyNodeItem(); - 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; + retval = loader.loadAsNodeItem(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) @@ -402,7 +483,7 @@ private static void requireNonCycle(@NonNull URI uri, @NonNull Stack import List cycle = checkCycle(uri, importHistory); if (!cycle.isEmpty()) { throw new ImportCycleException(String.format("Importing resource '%s' would result in the import cycle: %s", uri, - cycle.stream().map(cycleUri -> cycleUri.toString()).collect(Collectors.joining(" -> ", " -> ", "")))); + cycle.stream().map(URI::toString).collect(Collectors.joining(" -> ", " -> ", "")))); } } @@ -437,12 +518,14 @@ private static StructuringDirective getStructuringDirective(Profile profile) { return retval; } - protected void handleMerge(@NonNull Catalog resolvedCatalog, @NonNull IDocumentNodeItem profileDocument, + protected void handleMerge( + @NonNull Catalog resolvedCatalog, + @NonNull IRootAssemblyNodeItem profileItem, @NonNull IIndexer importIndex) { // handle combine // handle structuring - switch (getStructuringDirective(toProfile(profileDocument))) { + switch (getStructuringDirective(toProfile(profileItem))) { case AS_IS: // do nothing break; @@ -450,13 +533,13 @@ protected void handleMerge(@NonNull Catalog resolvedCatalog, @NonNull IDocumentN throw new UnsupportedOperationException("custom structuring"); case FLAT: default: - structureFlat(resolvedCatalog, profileDocument, importIndex); + structureFlat(resolvedCatalog, profileItem, importIndex); break; } } - protected void structureFlat(@NonNull Catalog resolvedCatalog, @NonNull IDocumentNodeItem profileDocument, + protected void structureFlat(@NonNull Catalog resolvedCatalog, @NonNull IRootAssemblyNodeItem profileItem, @NonNull IIndexer importIndex) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("applying flat structuring directive"); @@ -464,14 +547,17 @@ protected void structureFlat(@NonNull Catalog resolvedCatalog, @NonNull IDocumen // { // // 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); @@ -479,25 +565,23 @@ protected void structureFlat(@NonNull Catalog resolvedCatalog, @NonNull IDocumen // } // rebuild the document, since the paths have changed - IDocumentNodeItem resolvedCatalogItem = DefaultNodeItemFactory.instance().newDocumentNodeItem( - new RootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class))), - resolvedCatalog, - profileDocument.getBaseUri()); + IDocumentNodeItem resolvedCatalogItem = INodeItemFactory.instance().newDocumentNodeItem( + ObjectUtils.requireNonNull( + (IBoundDefinitionModelAssembly) OscalBindingContext.instance().getBoundDefinitionForClass(Catalog.class)), + ObjectUtils.requireNonNull(profileItem.getBaseUri()), + resolvedCatalog); FlatteningStructuringVisitor.instance().visitCatalog(resolvedCatalogItem, importIndex); } @SuppressWarnings("PMD.ExceptionAsFlowControl") // ok - protected void handleModify(@NonNull Catalog resolvedCatalog, @NonNull IDocumentNodeItem profileDocument) + protected void handleModify(@NonNull Catalog resolvedCatalog, @NonNull IRootAssemblyNodeItem profileItem) throws ProfileResolutionException { - IDocumentNodeItem resolvedCatalogDocument = DefaultNodeItemFactory.instance().newDocumentNodeItem( - new RootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class))), - resolvedCatalog, - profileDocument.getBaseUri()); + IDocumentNodeItem resolvedCatalogDocument = INodeItemFactory.instance().newDocumentNodeItem( + ObjectUtils.requireNonNull( + (IBoundDefinitionModelAssembly) OscalBindingContext.instance().getBoundDefinitionForClass(Catalog.class)), + ObjectUtils.requireNonNull(profileItem.getBaseUri()), + resolvedCatalog); try { IIndexer indexer = new BasicIndexer(); @@ -505,9 +589,9 @@ protected void handleModify(@NonNull Catalog resolvedCatalog, @NonNull IDocument ObjectUtils.notNull(EnumSet.of(IEntityItem.ItemType.CONTROL, IEntityItem.ItemType.PARAMETER))); visitor.visitCatalog(resolvedCatalogDocument, indexer); - METAPATH_SET_PARAMETER.evaluate(profileDocument) + METAPATH_SET_PARAMETER.evaluate(profileItem) .forEach(item -> { - IRequiredValueAssemblyNodeItem setParameter = (IRequiredValueAssemblyNodeItem) item; + IAssemblyNodeItem setParameter = (IAssemblyNodeItem) item; try { handleSetParameter(setParameter, indexer); } catch (ProfileResolutionEvaluationException ex) { @@ -519,17 +603,17 @@ protected void handleModify(@NonNull Catalog resolvedCatalog, @NonNull IDocument } }); - METAPATH_ALTER.evaluate(profileDocument) + METAPATH_ALTER.evaluate(profileItem) .forEach(item -> { - handleAlter((IRequiredValueAssemblyNodeItem) item, indexer); + handleAlter((IAssemblyNodeItem) item, indexer); }); } catch (ProfileResolutionEvaluationException ex) { throw new ProfileResolutionException(ex.getLocalizedMessage(), ex); } } - protected void handleSetParameter(IRequiredValueAssemblyNodeItem item, IIndexer indexer) { - ProfileSetParameter setParameter = (Modify.ProfileSetParameter) item.getValue(); + protected void handleSetParameter(IAssemblyNodeItem item, IIndexer indexer) { + ProfileSetParameter setParameter = ObjectUtils.requireNonNull((Modify.ProfileSetParameter) item.getValue()); String paramId = ObjectUtils.requireNonNull(setParameter.getParamId()); IEntityItem entity = indexer.getEntity(IEntityItem.ItemType.PARAMETER, paramId, false); if (entity == null) { @@ -556,8 +640,9 @@ protected void handleSetParameter(IRequiredValueAssemblyNodeItem item, IIndexer param.setSelect(setParameter.getSelect()); } - protected void handleAlter(IRequiredValueAssemblyNodeItem item, IIndexer indexer) { - Modify.Alter alter = (Modify.Alter) item.getValue(); + @SuppressWarnings("PMD.ExceptionAsFlowControl") + protected void handleAlter(IAssemblyNodeItem item, IIndexer indexer) { + Modify.Alter alter = ObjectUtils.requireNonNull((Modify.Alter) item.getValue()); String controlId = ObjectUtils.requireNonNull(alter.getControlId()); IEntityItem entity = indexer.getEntity(IEntityItem.ItemType.CONTROL, controlId, false); if (entity == null) { @@ -572,7 +657,7 @@ protected void handleAlter(IRequiredValueAssemblyNodeItem item, IIndexer indexer METAPATH_ALTER_REMOVE.evaluate(item) .forEach(nodeItem -> { - IRequiredValueNodeItem removeItem = (IRequiredValueNodeItem) nodeItem; + INodeItem removeItem = (INodeItem) nodeItem; Modify.Alter.Remove remove = ObjectUtils.notNull((Modify.Alter.Remove) removeItem.getValue()); try { @@ -597,7 +682,7 @@ protected void handleAlter(IRequiredValueAssemblyNodeItem item, IIndexer indexer }); METAPATH_ALTER_ADD.evaluate(item) .forEach(nodeItem -> { - IRequiredValueNodeItem addItem = (IRequiredValueNodeItem) nodeItem; + INodeItem addItem = (INodeItem) nodeItem; Modify.Alter.Add add = ObjectUtils.notNull((Modify.Alter.Add) addItem.getValue()); String byId = add.getById(); try { @@ -626,13 +711,13 @@ protected void handleAlter(IRequiredValueAssemblyNodeItem item, IIndexer indexer }); } - private static void handleReferences(@NonNull Catalog resolvedCatalog, @NonNull IDocumentNodeItem profileDocument, + private static void handleReferences(@NonNull Catalog resolvedCatalog, @NonNull IRootAssemblyNodeItem profileItem, @NonNull IIndexer index) { BasicIndexer profileIndex = new BasicIndexer(); new ControlIndexingVisitor(ObjectUtils.notNull(EnumSet.allOf(ItemType.class))) - .visitProfile(profileDocument, profileIndex); + .visitProfile(profileItem, profileIndex); // copy roles, parties, and locations with prop name:keep and any referenced Metadata resolvedMetadata = resolvedCatalog.getMetadata(); @@ -640,19 +725,19 @@ private static void handleReferences(@NonNull Catalog resolvedCatalog, @NonNull IIndexer.filterDistinct( ObjectUtils.notNull(CollectionUtil.listOrEmpty(resolvedMetadata.getRoles()).stream()), profileIndex.getEntitiesByItemType(IEntityItem.ItemType.ROLE), - item -> item.getId()) + Role::getId) .collect(Collectors.toCollection(LinkedList::new))); resolvedMetadata.setParties( IIndexer.filterDistinct( ObjectUtils.notNull(CollectionUtil.listOrEmpty(resolvedMetadata.getParties()).stream()), profileIndex.getEntitiesByItemType(IEntityItem.ItemType.PARTY), - item -> item.getUuid()) + Party::getUuid) .collect(Collectors.toCollection(LinkedList::new))); resolvedMetadata.setLocations( IIndexer.filterDistinct( ObjectUtils.notNull(CollectionUtil.listOrEmpty(resolvedMetadata.getLocations()).stream()), profileIndex.getEntitiesByItemType(IEntityItem.ItemType.LOCATION), - item -> item.getUuid()) + Location::getUuid) .collect(Collectors.toCollection(LinkedList::new))); // copy resources @@ -663,7 +748,7 @@ private static void handleReferences(@NonNull Catalog resolvedCatalog, @NonNull List resources = IIndexer.filterDistinct( ObjectUtils.notNull(resolvedResources.stream()), profileIndex.getEntitiesByItemType(IEntityItem.ItemType.RESOURCE), - item -> item.getUuid()) + Resource::getUuid) .collect(Collectors.toCollection(LinkedList::new)); if (!resources.isEmpty()) { @@ -678,34 +763,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 6fdd7015..71139283 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 @@ -26,10 +26,10 @@ package gov.nist.secauto.oscal.lib.profile.resolver.alter; -import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.CustomCollectors; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.CustomCollectors; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; @@ -75,7 +75,7 @@ public enum TargetType { static { { Map, TargetType> map = new ConcurrentHashMap<>(); - for (TargetType type : TargetType.values()) { + for (TargetType type : values()) { map.put(type.getClazz(), type); } CLASS_TO_TYPE = CollectionUtil.unmodifiableMap(map); @@ -83,7 +83,7 @@ public enum TargetType { { Map map = new ConcurrentHashMap<>(); - for (TargetType type : TargetType.values()) { + for (TargetType type : values()) { map.put(type.fieldName(), type); } NAME_TO_TYPE = CollectionUtil.unmodifiableMap(map); @@ -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) { @@ -157,7 +157,7 @@ public enum Position { static { Map map = new ConcurrentHashMap<>(); - for (Position position : Position.values()) { + for (Position position : values()) { map.put(position.name().toLowerCase(Locale.ROOT), position); } NAME_TO_POSITION = CollectionUtil.unmodifiableMap(map); @@ -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(); @@ -369,14 +372,14 @@ private static boolean handleChild( // if id match, inject the new items into the collection switch (context.getPosition()) { case AFTER: { - newItemsSupplier.get().forEach(add -> iter.add(add)); + newItemsSupplier.get().forEach(iter::add); retval = true; break; } case BEFORE: { iter.previous(); List adds = newItemsSupplier.get(); - adds.forEach(add -> iter.add(add)); + adds.forEach(iter::add); item = iter.next(); retval = true; break; @@ -434,26 +437,26 @@ public Boolean visitControl(Control control, Context context) { boolean retval = handleCurrent( control, - title -> control.setTitle(title), - () -> control.getParams(), - () -> control.getProps(), - () -> control.getLinks(), - () -> control.getParts(), + control::setTitle, + control::getParams, + control::getProps, + control::getLinks, + control::getParts, context); // visit params retval = retval || handleChild( TargetType.PARAM, - () -> control.getParams(), - () -> context.getParams(), + control::getParams, + context::getParams, child -> visitParameter(ObjectUtils.notNull(child), context), context); // visit parts retval = retval || handleChild( TargetType.PART, - () -> control.getParts(), - () -> context.getParts(), + control::getParts, + context::getParts, child -> visitPart(child, context), context); @@ -482,8 +485,8 @@ public Boolean visitParameter(Parameter parameter, Context context) { parameter, null, null, - () -> parameter.getProps(), - () -> parameter.getLinks(), + parameter::getProps, + parameter::getLinks, null, context); } @@ -515,19 +518,17 @@ public boolean visitPart(ControlPart part, Context context) { part, null, null, - () -> part.getProps(), - () -> part.getLinks(), - () -> part.getParts(), + part::getProps, + part::getLinks, + part::getParts, context); - // visit parts - retval = retval || handleChild( + return retval || handleChild( TargetType.PART, - () -> part.getParts(), - () -> context.getParts(), + part::getParts, + context::getParts, child -> visitPart(child, context), context); - return retval; } static class Context { @@ -610,20 +611,19 @@ public Context( } if (Position.BEFORE.equals(position) || Position.AFTER.equals(position)) { - if (sequenceTarget) { - if (sequenceTarget && !params.isEmpty() && parts.isEmpty()) { - targetItemTypes.retainAll(Set.of(TargetType.PARAM)); - } else if (sequenceTarget && !parts.isEmpty() && params.isEmpty()) { - targetItemTypes.retainAll(Set.of(TargetType.PART)); - } else { - throw new ProfileResolutionEvaluationException( - "When using position before or after, only one collection of parameters or parts can be specified."); - } - } else { + if (!sequenceTarget) { throw new ProfileResolutionEvaluationException( "When using position before or after, one collection of parameters or parts can be specified." + " Other additions must not be used."); } + if (sequenceTarget && !params.isEmpty() && parts.isEmpty()) { + targetItemTypes.retainAll(Set.of(TargetType.PARAM)); + } else if (sequenceTarget && !parts.isEmpty() && params.isEmpty()) { + targetItemTypes.retainAll(Set.of(TargetType.PART)); + } else { + throw new ProfileResolutionEvaluationException( + "When using position before or after, only one collection of parameters or parts can be specified."); + } } if (targetItemTypes.isEmpty()) { @@ -731,7 +731,7 @@ public boolean appliesTo(@NonNull Object obj) { } case PART: { ControlPart part = (ControlPart) obj; - actualId = part.getId() == null ? null : part.getId().toString(); + actualId = part.getId() == null ? null : part.getId(); break; } default: 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 effb8fd0..c19a2e81 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 @@ -26,8 +26,8 @@ package gov.nist.secauto.oscal.lib.profile.resolver.alter; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; @@ -73,7 +73,7 @@ public enum TargetType { static { { Map, TargetType> map = new ConcurrentHashMap<>(); - for (TargetType type : TargetType.values()) { + for (TargetType type : values()) { map.put(type.getClazz(), type); } CLASS_TO_TYPE = CollectionUtil.unmodifiableMap(map); @@ -81,7 +81,7 @@ public enum TargetType { { Map map = new ConcurrentHashMap<>(); - for (TargetType type : TargetType.values()) { + for (TargetType type : values()) { map.put(type.fieldName(), type); } NAME_TO_TYPE = CollectionUtil.unmodifiableMap(map); @@ -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,10 +184,7 @@ private static boolean handle( } } } else if (handleChildren && handler != null) { - // 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(); + for (T item : supplier.get()) { if (item != null) { retval = retval || handler.apply(item); } @@ -264,14 +261,11 @@ public Boolean visitControl(Control control, Context context) { null, context); - // visit parts - retval = retval || handle( + return retval || handle( TargetType.PART, () -> CollectionUtil.listOrEmpty(control.getParts()), child -> visitPart(child, context), context); - - return retval; } @Override @@ -285,13 +279,11 @@ public Boolean visitParameter(Parameter parameter, Context context) { null, context); - // visit links - retval = retval || handle( + return retval || handle( TargetType.LINK, () -> CollectionUtil.listOrEmpty(parameter.getLinks()), null, context); - return retval; } /** @@ -320,13 +312,11 @@ public boolean visitPart(ControlPart part, Context context) { null, context); - // visit parts - retval = retval || handle( + return retval || handle( TargetType.PART, () -> CollectionUtil.listOrEmpty(part.getParts()), child -> visitPart(child, context), context); - return retval; } static final class Context { @@ -394,7 +384,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); @@ -480,7 +471,7 @@ public boolean isApplicableTo(@NonNull Object obj) { ControlPart part = (ControlPart) obj; actualName = part.getName(); actualClass = part.getClazz(); - actualId = part.getId() == null ? null : part.getId().toString(); + actualId = part.getId() == null ? null : part.getId(); actualNamespace = part.getNs() == null ? IProperty.OSCAL_NAMESPACE.toString() : part.getNs().toString(); break; } 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 5cac8f47..ac4fdfc4 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,10 +26,10 @@ package gov.nist.secauto.oscal.lib.profile.resolver.merge; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRootAssemblyNodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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; @@ -47,19 +47,24 @@ import gov.nist.secauto.oscal.lib.profile.resolver.support.IIndexer; import gov.nist.secauto.oscal.lib.profile.resolver.support.IIndexer.SelectionStatus; +import java.net.URI; import java.util.EnumSet; import java.util.UUID; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; public class FlatteningStructuringVisitor extends AbstractCatalogEntityVisitor { private static final FlatteningStructuringVisitor SINGLETON = new FlatteningStructuringVisitor(); + @SuppressFBWarnings(value = "SING_SINGLETON_GETTER_NOT_SYNCHRONIZED", justification = "class initialization") public static FlatteningStructuringVisitor instance() { return SINGLETON; } + @SuppressFBWarnings(value = "SING_SINGLETON_HAS_NONPRIVATE_CONSTRUCTOR", + justification = "public constructor allows for extension usecases") public FlatteningStructuringVisitor() { super(ObjectUtils.notNull(EnumSet.of(ItemType.GROUP, ItemType.CONTROL))); } @@ -91,15 +96,19 @@ public Void visitCatalog(@NonNull IDocumentNodeItem catalogItem, IIndexer index) } // process references, looking for orphaned links to groups - ReferenceCountingVisitor.instance().visitCatalog(catalogItem, index, catalogItem.getDocumentUri()); + URI catalogUri = ObjectUtils.requireNonNull(catalogItem.getDocumentUri()); + ReferenceCountingVisitor.instance().visitCatalog(catalogItem, index, catalogUri); FlatteningFilterNonSelectedVisitor.instance().visitCatalog(catalogItem, index); return null; } @Override - public Void visitGroup(IRequiredValueModelNodeItem item, Void childResult, IIndexer index) { - CatalogGroup group = (CatalogGroup) item.getValue(); + public Void visitGroup( + IAssemblyNodeItem item, + Void childResult, + IIndexer index) { + CatalogGroup group = ObjectUtils.requireNonNull((CatalogGroup) item.getValue()); String id = group.getId(); if (id != null) { IEntityItem entity = index.getEntity(ItemType.GROUP, id); @@ -114,8 +123,11 @@ public Void visitGroup(IRequiredValueModelNodeItem item, Void childResult, IInde } @Override - public Void visitControl(IRequiredValueModelNodeItem item, Void childResult, IIndexer index) { - Control control = (Control) item.getValue(); + public Void visitControl( + IAssemblyNodeItem item, + Void childResult, + IIndexer index) { + Control control = ObjectUtils.requireNonNull((Control) item.getValue()); String id = ObjectUtils.requireNonNull(control.getId()); IEntityItem entity = index.getEntity(ItemType.CONTROL, id); assert entity != null; @@ -128,9 +140,11 @@ public Void visitControl(IRequiredValueModelNodeItem item, Void childResult, IIn } @Override - protected Void visitParameter(IRequiredValueModelNodeItem item, - IRequiredValueModelNodeItem catalogOrGroupOrControl, IIndexer index) { - Parameter parameter = (Parameter) item.getValue(); + protected Void visitParameter( + IAssemblyNodeItem item, + IAssemblyNodeItem catalogOrGroupOrControl, + IIndexer index) { + Parameter parameter = ObjectUtils.requireNonNull((Parameter) item.getValue()); String id = ObjectUtils.requireNonNull(parameter.getId()); IEntityItem entity = index.getEntity(ItemType.PARAMETER, id); assert entity != null; @@ -141,9 +155,11 @@ protected Void visitParameter(IRequiredValueModelNodeItem item, } @Override - protected void visitRole(IRequiredValueModelNodeItem item, IRequiredValueModelNodeItem metadataItem, + protected void visitRole( + IAssemblyNodeItem item, + IAssemblyNodeItem metadataItem, IIndexer index) { - Role role = (Role) item.getValue(); + Role role = ObjectUtils.requireNonNull((Role) item.getValue()); String id = ObjectUtils.requireNonNull(role.getId()); IEntityItem entity = index.getEntity(ItemType.ROLE, id); assert entity != null; @@ -152,9 +168,11 @@ protected void visitRole(IRequiredValueModelNodeItem item, IRequiredValueModelNo } @Override - protected void visitLocation(IRequiredValueModelNodeItem item, IRequiredValueModelNodeItem metadataItem, + protected void visitLocation( + IAssemblyNodeItem item, + IAssemblyNodeItem metadataItem, IIndexer index) { - Location location = (Location) item.getValue(); + Location location = ObjectUtils.requireNonNull((Location) item.getValue()); UUID uuid = ObjectUtils.requireNonNull(location.getUuid()); IEntityItem entity = index.getEntity(ItemType.LOCATION, uuid); assert entity != null; @@ -163,9 +181,11 @@ protected void visitLocation(IRequiredValueModelNodeItem item, IRequiredValueMod } @Override - protected void visitParty(IRequiredValueModelNodeItem item, IRequiredValueModelNodeItem metadataItem, + protected void visitParty( + IAssemblyNodeItem item, + IAssemblyNodeItem metadataItem, IIndexer index) { - Party location = (Party) item.getValue(); + Party location = ObjectUtils.requireNonNull((Party) item.getValue()); UUID uuid = ObjectUtils.requireNonNull(location.getUuid()); IEntityItem entity = index.getEntity(ItemType.PARTY, uuid); assert entity != null; @@ -174,9 +194,11 @@ protected void visitParty(IRequiredValueModelNodeItem item, IRequiredValueModelN } @Override - protected void visitResource(IRequiredValueModelNodeItem item, IRootAssemblyNodeItem rootItem, + protected void visitResource( + IAssemblyNodeItem item, + IRootAssemblyNodeItem rootItem, IIndexer index) { - Resource location = (Resource) item.getValue(); + Resource location = ObjectUtils.requireNonNull((Resource) item.getValue()); UUID uuid = ObjectUtils.requireNonNull(location.getUuid()); IEntityItem entity = index.getEntity(ItemType.RESOURCE, uuid); assert entity != null; @@ -185,15 +207,15 @@ protected void visitResource(IRequiredValueModelNodeItem item, IRootAssemblyNode } private static void handlePartSelection( - @NonNull IRequiredValueModelNodeItem groupOrControlItem, + @NonNull IAssemblyNodeItem groupOrControlItem, @NonNull IIndexer index, @NonNull SelectionStatus selectionStatus) { - CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream() - .map(item -> (IRequiredValueModelNodeItem) item) + CHILD_PART_METAPATH.evaluate(groupOrControlItem).stream() + .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(partItem -> { index.setSelectionStatus(ObjectUtils.requireNonNull(partItem), selectionStatus); - ControlPart part = (ControlPart) partItem.getValue(); + ControlPart part = ObjectUtils.requireNonNull((ControlPart) partItem.getValue()); String id = part.getId(); if (id != null) { IEntityItem entity = index.getEntity(ItemType.PART, id); @@ -208,22 +230,23 @@ private static final class FlatteningFilterNonSelectedVisitor extends FilterNonSelectedVisitor { private static final FlatteningFilterNonSelectedVisitor SINGLETON = new FlatteningFilterNonSelectedVisitor(); + @SuppressFBWarnings(value = "SING_SINGLETON_GETTER_NOT_SYNCHRONIZED", justification = "class initialization") public static FlatteningFilterNonSelectedVisitor instance() { return SINGLETON; } @Override - public DefaultResult visitControl(IRequiredValueModelNodeItem item, DefaultResult childResult, + public DefaultResult visitControl(IAssemblyNodeItem item, DefaultResult childResult, Context context) { assert childResult != null; - Control control = (Control) item.getValue(); + Control control = ObjectUtils.requireNonNull((Control) item.getValue()); IIndexer index = context.getIndexer(); // this control should always be found in the index IEntityItem entity = ObjectUtils.requireNonNull( index.getEntity(ItemType.CONTROL, ObjectUtils.requireNonNull(control.getId()), false)); - IRequiredValueModelNodeItem parent = ObjectUtils.notNull(item.getParentContentNodeItem()); + IAssemblyNodeItem parent = ObjectUtils.notNull(item.getParentContentNodeItem()); DefaultResult retval = new DefaultResult(); if (SelectionStatus.SELECTED.equals(index.getSelectionStatus(item))) { // keep this control 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 519c0ac4..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 @@ -26,8 +26,8 @@ package gov.nist.secauto.oscal.lib.profile.resolver.policy; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolutionEvaluationException; import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem; @@ -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,13 +80,14 @@ 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 */ protected boolean handleIndexHit( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull TYPE reference, @NonNull IEntityItem item, @NonNull ReferenceCountingVisitor.Context visitorContext) { @@ -130,7 +132,7 @@ protected boolean handleIndexHit( * if there was an error handing the index hit */ protected void handleUnselected( // NOPMD noop default - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull TYPE reference, @NonNull IEntityItem item, @NonNull ReferenceCountingVisitor.Context visitorContext) { @@ -149,12 +151,13 @@ 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 */ protected void handleSelected( // NOPMD noop default - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull TYPE reference, @NonNull IEntityItem item, @NonNull ReferenceCountingVisitor.Context visitorContext) { @@ -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,13 +179,15 @@ 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 */ protected boolean handleIndexMiss( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull TYPE reference, @NonNull List itemTypes, @NonNull String identifier, @@ -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,13 +208,15 @@ 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 */ protected boolean handleIdentifierNonMatch( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull TYPE reference, @NonNull ReferenceCountingVisitor.Context visitorContext) { // provide no handler by default @@ -217,12 +225,13 @@ protected boolean handleIdentifierNonMatch( @Override public boolean handleReference( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull TYPE type, @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,13 +246,15 @@ 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 */ protected boolean handleIdentifier( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull TYPE type, @Nullable String identifier, @NonNull ReferenceCountingVisitor.Context visitorContext) { diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AbstractMultiItemTypeReferencePolicy.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AbstractMultiItemTypeReferencePolicy.java index fd9e0ad3..ed71bf45 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AbstractMultiItemTypeReferencePolicy.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AbstractMultiItemTypeReferencePolicy.java @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.policy; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem; import java.util.List; diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AnchorReferencePolicy.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AnchorReferencePolicy.java index 9065301a..f196ee4c 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AnchorReferencePolicy.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/AnchorReferencePolicy.java @@ -30,9 +30,9 @@ import com.vladsch.flexmark.util.sequence.BasedSequence; import com.vladsch.flexmark.util.sequence.CharSubSequence; -import gov.nist.secauto.metaschema.model.common.metapath.format.IPathFormatter; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.CustomCollectors; +import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; +import gov.nist.secauto.metaschema.core.util.CustomCollectors; import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem; import org.apache.logging.log4j.LogManager; @@ -74,7 +74,7 @@ public void setReferenceText(@NonNull InlineLinkNode link, @NonNull String newVa @Override protected void handleUnselected( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull InlineLinkNode link, @NonNull IEntityItem item, @NonNull ReferenceCountingVisitor.Context visitorContext) { @@ -93,7 +93,7 @@ protected void handleUnselected( @Override protected boolean handleIndexMiss( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull InlineLinkNode reference, @NonNull List itemTypes, @NonNull String identifier, @@ -112,7 +112,7 @@ protected boolean handleIndexMiss( @Override protected boolean handleIdentifierNonMatch( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull InlineLinkNode reference, @NonNull ReferenceCountingVisitor.Context visitorContext) { if (LOGGER.isDebugEnabled()) { 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/IReferencePolicy.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/IReferencePolicy.java index 90c56a6e..2d6d9967 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/IReferencePolicy.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/IReferencePolicy.java @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.policy; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; import gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolutionEvaluationException; import edu.umd.cs.findbugs.annotations.NonNull; @@ -37,7 +37,7 @@ public interface IReferencePolicy { @Override public boolean handleReference( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull Object reference, @NonNull ReferenceCountingVisitor.Context referenceVisitorContext) { return true; @@ -71,7 +71,7 @@ static IReferencePolicy ignore() { * if there was an error handing the reference */ boolean handleReference( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull T reference, @NonNull ReferenceCountingVisitor.Context referenceVisitorContext); } 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 9afc8730..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 @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.policy; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; import gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolutionEvaluationException; @@ -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 @@ -52,11 +52,11 @@ public interface IReferenceVisitor extends ICatalogVisitor { * if there was an error handing the reference */ @Override - Void visitGroup(@NonNull IRequiredValueModelNodeItem item, Void childResult, T context); + 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 @@ -64,10 +64,11 @@ public interface IReferenceVisitor extends ICatalogVisitor { * if there was an error handing the reference */ @Override - Void visitControl(@NonNull IRequiredValueModelNodeItem item, Void childResult, T context); + 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 @@ -75,10 +76,11 @@ public interface IReferenceVisitor extends ICatalogVisitor { // * @throws ProfileResolutionEvaluationException // * if there was an error handing the reference // */ - // void resolveParameter(@NonNull IRequiredValueModelNodeItem item); + // 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. // * @@ -87,10 +89,11 @@ public interface IReferenceVisitor extends ICatalogVisitor { // * @throws ProfileResolutionEvaluationException // * if there was an error handing the reference // */ - // void resolvePart(@NonNull IRequiredValueModelNodeItem item, T context); + // 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 @@ -98,10 +101,11 @@ public interface IReferenceVisitor extends ICatalogVisitor { // * @throws ProfileResolutionEvaluationException // * if there was an error handing the reference // */ - // void resolveRole(@NonNull IRequiredValueModelNodeItem item); + // 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 @@ -109,10 +113,11 @@ public interface IReferenceVisitor extends ICatalogVisitor { // * @throws ProfileResolutionEvaluationException // * if there was an error handing the reference // */ - // void resolveParty(@NonNull IRequiredValueModelNodeItem item); + // 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 @@ -120,10 +125,11 @@ public interface IReferenceVisitor extends ICatalogVisitor { // * @throws ProfileResolutionEvaluationException // * if there was an error handing the reference // */ - // void resolveLocation(@NonNull IRequiredValueModelNodeItem item); + // 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 @@ -131,5 +137,5 @@ public interface IReferenceVisitor extends ICatalogVisitor { // * @throws ProfileResolutionEvaluationException // * if there was an error handing the reference // */ - // void resolveResource(@NonNull IRequiredValueModelNodeItem item); + // void resolveResource(@NonNull IModelNodeItem item); } diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/InsertReferencePolicy.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/InsertReferencePolicy.java index 7a3282dc..08f267ec 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/InsertReferencePolicy.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/InsertReferencePolicy.java @@ -28,12 +28,12 @@ import com.vladsch.flexmark.util.sequence.BasedSequence; -import gov.nist.secauto.metaschema.model.common.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode; -import gov.nist.secauto.metaschema.model.common.metapath.format.IPathFormatter; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.CustomCollectors; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode; +import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.CustomCollectors; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem; import org.apache.logging.log4j.LogManager; @@ -77,7 +77,7 @@ public void setReferenceText(@NonNull InsertAnchorNode insert, @NonNull String n @Override protected boolean handleIndexMiss( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull InsertAnchorNode insert, @NonNull List itemTypes, @NonNull String identifier, diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/LinkReferencePolicy.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/LinkReferencePolicy.java index 9f25a762..38bd7de5 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/LinkReferencePolicy.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/LinkReferencePolicy.java @@ -26,10 +26,10 @@ package gov.nist.secauto.oscal.lib.profile.resolver.policy; -import gov.nist.secauto.metaschema.model.common.metapath.format.IPathFormatter; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.CustomCollectors; +import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.CustomCollectors; import gov.nist.secauto.oscal.lib.model.Link; import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem; @@ -73,7 +73,7 @@ public void setReferenceText(@NonNull Link link, @NonNull String newValue) { @Override protected void handleUnselected( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull Link link, @NonNull IEntityItem item, @NonNull ReferenceCountingVisitor.Context visitorContext) { @@ -92,7 +92,7 @@ protected void handleUnselected( @Override protected boolean handleIndexMiss( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull Link link, @NonNull List itemTypes, @NonNull String identifier, @@ -113,7 +113,7 @@ protected boolean handleIndexMiss( @Override protected boolean handleIdentifierNonMatch( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull Link reference, @NonNull ReferenceCountingVisitor.Context visitorContext) { if (LOGGER.isDebugEnabled()) { diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/PatternIdentifierParser.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/PatternIdentifierParser.java index fdf6687b..98ce6f70 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/PatternIdentifierParser.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/PatternIdentifierParser.java @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.policy; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolutionEvaluationException; import java.util.Objects; diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/PropertyReferencePolicy.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/PropertyReferencePolicy.java index 07ab8be8..aa8b773d 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/PropertyReferencePolicy.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/policy/PropertyReferencePolicy.java @@ -26,10 +26,10 @@ package gov.nist.secauto.oscal.lib.profile.resolver.policy; -import gov.nist.secauto.metaschema.model.common.metapath.format.IPathFormatter; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.CustomCollectors; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; +import gov.nist.secauto.metaschema.core.util.CustomCollectors; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.Property; import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem; @@ -76,7 +76,7 @@ public void setReferenceText(@NonNull Property property, @NonNull String newValu @Override protected void handleUnselected( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull Property property, @NonNull IEntityItem item, @NonNull ReferenceCountingVisitor.Context visitorContext) { @@ -95,7 +95,7 @@ protected void handleUnselected( @Override protected boolean handleIndexMiss( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull Property property, @NonNull List itemTypes, @NonNull String identifier, 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 112cdc32..6ad9a107 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 @@ -29,16 +29,20 @@ import com.vladsch.flexmark.ast.InlineLinkNode; import com.vladsch.flexmark.util.ast.Node; -import gov.nist.secauto.metaschema.model.common.datatype.markup.IMarkupString; -import gov.nist.secauto.metaschema.model.common.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode; -import gov.nist.secauto.metaschema.model.common.metapath.MetapathExpression; -import gov.nist.secauto.metaschema.model.common.metapath.format.IPathFormatter; -import gov.nist.secauto.metaschema.model.common.metapath.function.library.FnData; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IMarkupItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.datatype.markup.IMarkupString; +import gov.nist.secauto.metaschema.core.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode; +import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; +import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; +import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IMarkupItem; +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.IFieldNodeItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.OscalBindingContext; +import gov.nist.secauto.oscal.lib.OscalModelConstants; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; import gov.nist.secauto.oscal.lib.model.ControlPart; @@ -69,7 +73,7 @@ import edu.umd.cs.findbugs.annotations.Nullable; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -public class ReferenceCountingVisitor +public final class ReferenceCountingVisitor extends AbstractCatalogEntityVisitor implements IReferenceVisitor { private static final Logger LOGGER = LogManager.getLogger(ReferenceCountingVisitor.class); @@ -79,19 +83,25 @@ public class ReferenceCountingVisitor @NonNull private static final MetapathExpression PARAM_MARKUP_METAPATH = MetapathExpression - .compile("label|usage|constraint/(description|tests/remarks)|guideline/prose|select/choice|remarks"); + .compile( + "label|usage|constraint/(description|tests/remarks)|guideline/prose|select/choice|remarks", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); @NonNull private static final MetapathExpression ROLE_MARKUP_METAPATH - = MetapathExpression.compile("title|description|remarks"); + = MetapathExpression.compile("title|description|remarks", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); @NonNull private static final MetapathExpression LOCATION_MARKUP_METAPATH - = MetapathExpression.compile("title|remarks"); + = MetapathExpression.compile("title|remarks", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); @NonNull private static final MetapathExpression PARTY_MARKUP_METAPATH - = MetapathExpression.compile("title|remarks"); + = MetapathExpression.compile("title|remarks", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); @NonNull private static final MetapathExpression RESOURCE_MARKUP_METAPATH - = MetapathExpression.compile("title|description|remarks"); + = MetapathExpression.compile("title|description|remarks", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); @NonNull private static final IReferencePolicy PROPERTY_POLICY_IGNORE = IReferencePolicy.ignore(); @@ -129,12 +139,14 @@ public class ReferenceCountingVisitor LINK_POLICIES.put("corresp", LinkReferencePolicy.create(IEntityItem.ItemType.PART)); } + @SuppressFBWarnings(value = "SING_SINGLETON_GETTER_NOT_SYNCHRONIZED", justification = "class initialization") public static ReferenceCountingVisitor instance() { return SINGLETON; } - public ReferenceCountingVisitor() { - // visit everything except parts, roles, locations, parties, parameters, and resources, which are + private ReferenceCountingVisitor() { + // visit everything except parts, roles, locations, parties, parameters, and + // resources, which are // handled differently by this visitor super(ObjectUtils.notNull(EnumSet.complementOf( EnumSet.of( @@ -168,7 +180,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); // } // } @@ -203,12 +216,16 @@ public void visitCatalog(@NonNull IDocumentNodeItem catalogItem, @NonNull IIndex } @Override - public Void visitGroup(@NonNull IRequiredValueModelNodeItem item, Void childResult, Context context) { + public Void visitGroup( + IAssemblyNodeItem item, + Void childResult, + 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 = (CatalogGroup) item.getValue(); + CatalogGroup group = ObjectUtils.requireNonNull((CatalogGroup) item.getValue()); String id = group.getId(); boolean resolve; @@ -235,11 +252,14 @@ public Void visitGroup(@NonNull IRequiredValueModelNodeItem item, Void childResu } @Override - public Void visitControl(@NonNull IRequiredValueModelNodeItem item, Void childResult, Context context) { + public Void visitControl( + IAssemblyNodeItem item, + Void childResult, + Context context) { IIndexer index = context.getIndexer(); // handle the control if it is selected if (IIndexer.SelectionStatus.SELECTED.equals(index.getSelectionStatus(item))) { - Control control = (Control) item.getValue(); + Control control = ObjectUtils.requireNonNull((Control) item.getValue()); IEntityItem entity = context.getIndexer().getEntity(IEntityItem.ItemType.CONTROL, ObjectUtils.notNull(control.getId()), false); @@ -257,21 +277,25 @@ public Void visitControl(@NonNull IRequiredValueModelNodeItem item, Void childRe } @Override - protected void visitParts(@NonNull IRequiredValueModelNodeItem groupOrControlItem, Context context) { + protected void visitParts( + IAssemblyNodeItem groupOrControlItem, + Context context) { // visits all descendant parts - CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream() - .map(item -> (IRequiredValueModelNodeItem) item) + CHILD_PART_METAPATH.evaluate(groupOrControlItem).stream() + .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(partItem -> { visitPart(ObjectUtils.notNull(partItem), groupOrControlItem, context); }); } @Override - protected void visitPart(IRequiredValueModelNodeItem item, IRequiredValueModelNodeItem groupOrControlItem, + protected void visitPart( + IAssemblyNodeItem item, + IAssemblyNodeItem groupOrControlItem, Context context) { assert context != null; - ControlPart part = (ControlPart) item.getValue(); + ControlPart part = ObjectUtils.requireNonNull((ControlPart) item.getValue()); String id = part.getId(); boolean resolve; @@ -295,14 +319,17 @@ protected void visitPart(IRequiredValueModelNodeItem item, IRequiredValueModelNo } protected void resolveGroup( - @NonNull IRequiredValueModelNodeItem item, + @NonNull IAssemblyNodeItem item, @NonNull Context context) { if (IIndexer.SelectionStatus.SELECTED.equals(context.getIndexer().getSelectionStatus(item))) { // process children - item.getModelItemsByName("title").forEach(child -> handleMarkup(ObjectUtils.notNull(child), context)); - item.getModelItemsByName("prop").forEach(child -> handleProperty(ObjectUtils.notNull(child), context)); - item.getModelItemsByName("link").forEach(child -> handleLink(ObjectUtils.notNull(child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_TITLE) + .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) + .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) + .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); // always visit parts visitParts(item, context); @@ -312,12 +339,15 @@ protected void resolveGroup( } protected void resolveControl( - @NonNull IRequiredValueModelNodeItem item, + @NonNull IAssemblyNodeItem item, @NonNull Context context) { // process non-control, non-param children - item.getModelItemsByName("title").forEach(child -> handleMarkup(ObjectUtils.notNull(child), context)); - item.getModelItemsByName("prop").forEach(child -> handleProperty(ObjectUtils.notNull(child), context)); - item.getModelItemsByName("link").forEach(child -> handleLink(ObjectUtils.notNull(child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_TITLE) + .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) + .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) + .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); // always visit parts visitParts(item, context); @@ -326,82 +356,97 @@ protected void resolveControl( } private static void resolveRole(@NonNull IEntityItem entity, @NonNull Context context) { - IRequiredValueModelNodeItem item = entity.getInstance(); - item.getModelItemsByName("prop").forEach(child -> handleProperty(ObjectUtils.notNull(child), context)); - item.getModelItemsByName("link").forEach(child -> handleLink(ObjectUtils.notNull(child), context)); - ROLE_MARKUP_METAPATH.evaluate(item).asList() - .forEach(child -> handleMarkup(ObjectUtils.notNull((IRequiredValueModelNodeItem) child), context)); + IModelNodeItem item = entity.getInstance(); + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) + .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) + .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + ROLE_MARKUP_METAPATH.evaluate(item).getValue() + .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); } private static void resolveParty(@NonNull IEntityItem entity, @NonNull Context context) { - IRequiredValueModelNodeItem item = entity.getInstance(); - item.getModelItemsByName("prop").forEach(child -> handleProperty(ObjectUtils.notNull(child), context)); - item.getModelItemsByName("link").forEach(child -> handleLink(ObjectUtils.notNull(child), context)); - PARTY_MARKUP_METAPATH.evaluate(item).asList() - .forEach(child -> handleMarkup(ObjectUtils.notNull((IRequiredValueModelNodeItem) child), context)); + IModelNodeItem item = entity.getInstance(); + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) + .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) + .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + PARTY_MARKUP_METAPATH.evaluate(item).getValue() + .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); } public static void resolveLocation(@NonNull IEntityItem entity, @NonNull Context context) { - IRequiredValueModelNodeItem item = entity.getInstance(); - item.getModelItemsByName("prop").forEach(child -> handleProperty(ObjectUtils.notNull(child), context)); - item.getModelItemsByName("link").forEach(child -> handleLink(ObjectUtils.notNull(child), context)); - LOCATION_MARKUP_METAPATH.evaluate(item).asList() - .forEach(child -> handleMarkup(ObjectUtils.notNull((IRequiredValueModelNodeItem) child), context)); + IModelNodeItem item = entity.getInstance(); + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) + .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) + .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + LOCATION_MARKUP_METAPATH.evaluate(item).getValue() + .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); } public static void resolveResource(@NonNull IEntityItem entity, @NonNull Context context) { - IRequiredValueModelNodeItem item = entity.getInstance(); + IModelNodeItem item = entity.getInstance(); - item.getModelItemsByName("prop").forEach(child -> handleProperty(ObjectUtils.notNull(child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) + .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - item.getModelItemsByName("citation").forEach(child -> { + item.getModelItemsByName(OscalModelConstants.QNAME_CITATION).forEach(child -> { if (child != null) { - child.getModelItemsByName("text") - .forEach(citationChild -> handleMarkup(ObjectUtils.notNull(citationChild), context)); - child.getModelItemsByName("prop") - .forEach(citationChild -> handleProperty(ObjectUtils.notNull(citationChild), context)); - child.getModelItemsByName("link") - .forEach(citationChild -> handleLink(ObjectUtils.notNull(citationChild), context)); + child.getModelItemsByName(OscalModelConstants.QNAME_TEXT) + .forEach(citationChild -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) citationChild), context)); + child.getModelItemsByName(OscalModelConstants.QNAME_PROP) + .forEach(citationChild -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) citationChild), context)); + child.getModelItemsByName(OscalModelConstants.QNAME_LINK) + .forEach(citationChild -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) citationChild), context)); } }); - RESOURCE_MARKUP_METAPATH.evaluate(item).asList() - .forEach(child -> handleMarkup(ObjectUtils.notNull((IRequiredValueModelNodeItem) child), context)); + RESOURCE_MARKUP_METAPATH.evaluate(item).getValue() + .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); } public static void resolveParameter(@NonNull IEntityItem entity, @NonNull Context context) { - IRequiredValueModelNodeItem item = entity.getInstance(); - - item.getModelItemsByName("prop").forEach(child -> handleProperty(ObjectUtils.notNull(child), context)); - item.getModelItemsByName("link").forEach(child -> handleLink(ObjectUtils.notNull(child), context)); - PARAM_MARKUP_METAPATH.evaluate(item).asList() - .forEach(child -> handleMarkup(ObjectUtils.notNull((IRequiredValueModelNodeItem) child), context)); + IModelNodeItem item = entity.getInstance(); + + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) + .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) + .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + PARAM_MARKUP_METAPATH.evaluate(item).getValue() + .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); } private static void resolvePart( - @NonNull IRequiredValueModelNodeItem item, + @NonNull IAssemblyNodeItem item, @NonNull Context context) { - item.getModelItemsByName("title").forEach(child -> handleMarkup(ObjectUtils.notNull(child), context)); - item.getModelItemsByName("prop").forEach(child -> handleProperty(ObjectUtils.notNull(child), context)); - item.getModelItemsByName("link").forEach(child -> handleLink(ObjectUtils.notNull(child), context)); - item.getModelItemsByName("prose").forEach(child -> handleMarkup(ObjectUtils.notNull(child), context)); - // item.getModelItemsByName("part").forEach(child -> visitor.visitPart(ObjectUtils.notNull(child), + item.getModelItemsByName(OscalModelConstants.QNAME_TITLE) + .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) + .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) + .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); + item.getModelItemsByName(OscalModelConstants.QNAME_PROSE) + .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); + // item.getModelItemsByName("part").forEach(child -> + // visitor.visitPart(ObjectUtils.notNull(child), // context)); } private static void handleMarkup( - @NonNull IRequiredValueModelNodeItem item, + @NonNull IFieldNodeItem item, @NonNull Context context) { IMarkupItem markupItem = (IMarkupItem) FnData.fnDataItem(item); - IMarkupString markup = markupItem.getValue(); + IMarkupString markup = markupItem.asMarkup(); handleMarkup(item, markup, context); } private static void handleMarkup( - @NonNull IRequiredValueModelNodeItem contextItem, + @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) { @@ -411,7 +456,7 @@ private static void handleMarkup( } private static void handleInsert( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IFieldNodeItem contextItem, @NonNull InsertAnchorNode node, @NonNull Context context) { boolean retval = INSERT_POLICY.handleReference(contextItem, node, context); @@ -423,7 +468,7 @@ private static void handleInsert( } private static void handleAnchor( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IFieldNodeItem contextItem, @NonNull InlineLinkNode node, @NonNull Context context) { boolean result = ANCHOR_POLICY.handleReference(contextItem, node, context); @@ -435,9 +480,9 @@ private static void handleAnchor( } private static void handleProperty( - @NonNull IRequiredValueModelNodeItem item, + @NonNull IAssemblyNodeItem item, @NonNull Context context) { - Property property = (Property) item.getValue(); + Property property = ObjectUtils.requireNonNull((Property) item.getValue()); QName qname = property.getQName(); IReferencePolicy policy = PROPERTY_POLICIES.get(qname); @@ -451,9 +496,9 @@ private static void handleProperty( } private static void handleLink( - @NonNull IRequiredValueModelNodeItem item, + @NonNull IAssemblyNodeItem item, @NonNull Context context) { - Link link = (Link) item.getValue(); + Link link = ObjectUtils.requireNonNull((Link) item.getValue()); IReferencePolicy policy = null; String rel = link.getRel(); if (rel != null) { @@ -499,7 +544,7 @@ public void resolveEntity( } protected void entityDispatch(@NonNull IEntityItem entity, @NonNull Context context) { - IRequiredValueModelNodeItem item = entity.getInstance(); + IAssemblyNodeItem item = (IAssemblyNodeItem) entity.getInstance(); switch (entity.getItemType()) { case CONTROL: resolveControl(item, context); @@ -536,7 +581,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; // } @@ -579,7 +625,7 @@ public boolean isResolved(@NonNull IEntityItem entity) { } public void incrementReferenceCount( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull IEntityItem.ItemType type, @NonNull UUID identifier) { incrementReferenceCountInternal( @@ -590,7 +636,7 @@ public void incrementReferenceCount( } public void incrementReferenceCount( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull IEntityItem.ItemType type, @NonNull String identifier) { incrementReferenceCountInternal( @@ -601,7 +647,7 @@ public void incrementReferenceCount( } private void incrementReferenceCountInternal( - @NonNull IRequiredValueModelNodeItem contextItem, + @NonNull IModelNodeItem contextItem, @NonNull IEntityItem.ItemType type, @NonNull String identifier, boolean normalize) { diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionState.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionState.java index 7ea8ccd3..0354607b 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionState.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionState.java @@ -26,11 +26,12 @@ package gov.nist.secauto.oscal.lib.profile.resolver.selection; -import gov.nist.secauto.metaschema.model.common.metapath.MetapathExpression; -import gov.nist.secauto.metaschema.model.common.metapath.format.IPathFormatter; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueAssemblyNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; +import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; +import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; import gov.nist.secauto.oscal.lib.profile.resolver.support.IIndexer; @@ -44,14 +45,16 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; public class ControlSelectionState implements IControlSelectionState { - private static final MetapathExpression GROUP_CHILDREN = MetapathExpression.compile("group|descendant::control"); + private static final MetapathExpression GROUP_CHILDREN = MetapathExpression.compile( + "group|descendant::control", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); @NonNull private final IIndexer index; @NonNull private final IControlFilter filter; @NonNull - private final Map itemSelectionState = new ConcurrentHashMap<>(); + private final Map, SelectionState> itemSelectionState = new ConcurrentHashMap<>(); @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "provides intentional access to index state") public ControlSelectionState(@NonNull IIndexer index, @NonNull IControlFilter filter) { @@ -71,12 +74,12 @@ public IControlFilter getFilter() { } @Override - public boolean isSelected(@NonNull IRequiredValueModelNodeItem item) { + public boolean isSelected(@NonNull IModelNodeItem item) { return getSelectionState(item).isSelected(); } @NonNull - protected SelectionState getSelectionState(@NonNull IRequiredValueModelNodeItem item) { + protected SelectionState getSelectionState(@NonNull IModelNodeItem item) { SelectionState retval = itemSelectionState.get(item); if (retval == null) { Object itemValue = ObjectUtils.requireNonNull(item.getValue()); @@ -85,7 +88,7 @@ protected SelectionState getSelectionState(@NonNull IRequiredValueModelNodeItem Control control = (Control) itemValue; // get the parent control if the parent is a control - IRequiredValueAssemblyNodeItem parentItem = ObjectUtils.requireNonNull(item.getParentContentNodeItem()); + IAssemblyNodeItem parentItem = ObjectUtils.requireNonNull(item.getParentContentNodeItem()); Object parentValue = parentItem.getValue(); Control parentControl = parentValue instanceof Control ? (Control) parentValue : null; @@ -103,9 +106,9 @@ protected SelectionState getSelectionState(@NonNull IRequiredValueModelNodeItem } else if (itemValue instanceof CatalogGroup) { // get control selection status - boolean selected = GROUP_CHILDREN.evaluate(item).asStream() + boolean selected = GROUP_CHILDREN.evaluate(item).stream() .map(child -> { - return getSelectionState((IRequiredValueModelNodeItem) ObjectUtils.requireNonNull(child)).isSelected(); + return getSelectionState((IModelNodeItem) ObjectUtils.requireNonNull(child)).isSelected(); }) .reduce(false, (first, second) -> first || second); 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 8aecb410..2dcc21ed 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 @@ -26,10 +26,10 @@ package gov.nist.secauto.oscal.lib.profile.resolver.selection; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRootAssemblyNodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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.Catalog; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; @@ -43,36 +43,45 @@ import org.apache.logging.log4j.Logger; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** * 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 +public final class ControlSelectionVisitor extends AbstractIndexingVisitor { private static final Logger LOGGER = LogManager.getLogger(ControlSelectionVisitor.class); private static final ControlSelectionVisitor SINGLETON = new ControlSelectionVisitor(); + @SuppressFBWarnings(value = "SING_SINGLETON_GETTER_NOT_SYNCHRONIZED", justification = "class initialization") public static ControlSelectionVisitor instance() { return SINGLETON; } + private ControlSelectionVisitor() { + // disable construction + } + @Override protected IIndexer getIndexer(IControlSelectionState state) { return state.getIndex(); @@ -98,10 +107,12 @@ public void visitProfile( @NonNull IControlSelectionState state) { visit(catalogDocument, state); - IRootAssemblyNodeItem root = profileDocument.getRootAssemblyNodeItem(); + profileDocument.modelItems().forEachOrdered(item -> { + IRootAssemblyNodeItem root = ObjectUtils.requireNonNull((IRootAssemblyNodeItem) item); - visitMetadata(root, state); - visitBackMatter(root, state); + visitMetadata(root, state); + visitBackMatter(root, state); + }); } @Override @@ -111,11 +122,11 @@ public Boolean visitCatalog(IDocumentNodeItem catalogDocument, IControlSelection } @Override - public Boolean visitGroup(IRequiredValueModelNodeItem groupItem, Boolean childSelected, + public Boolean visitGroup(IAssemblyNodeItem groupItem, Boolean childSelected, IControlSelectionState state) { super.visitGroup(groupItem, childSelected, state); if (LOGGER.isTraceEnabled()) { - CatalogGroup group = (CatalogGroup) groupItem.getValue(); + CatalogGroup group = ObjectUtils.requireNonNull((CatalogGroup) groupItem.getValue()); LOGGER.atTrace().log("Selecting group '{}'. match={}", group.getId(), childSelected); } @@ -133,15 +144,15 @@ public Boolean visitGroup(IRequiredValueModelNodeItem groupItem, Boolean childSe } private void handlePartSelection( - @NonNull IRequiredValueModelNodeItem groupOrControlItem, + @NonNull IAssemblyNodeItem groupOrControlItem, boolean selected, IControlSelectionState state) { if (isVisitedItemType(IEntityItem.ItemType.PART)) { SelectionStatus selectionStatus = selected ? SelectionStatus.SELECTED : SelectionStatus.UNSELECTED; IIndexer index = getIndexer(state); - CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream() - .map(item -> (IRequiredValueModelNodeItem) item) + CHILD_PART_METAPATH.evaluate(groupOrControlItem).stream() + .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(partItem -> { index.setSelectionStatus(ObjectUtils.requireNonNull(partItem), selectionStatus); }); @@ -150,7 +161,7 @@ private void handlePartSelection( @Override public Boolean visitControl( - IRequiredValueModelNodeItem controlItem, + IAssemblyNodeItem controlItem, Boolean childResult, IControlSelectionState state) { super.visitControl(controlItem, childResult, state); 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 e34f5838..55d3be91 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 @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.selection; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.Matching; import gov.nist.secauto.oscal.lib.model.control.catalog.IControl; import gov.nist.secauto.oscal.lib.model.control.profile.IProfileSelectControlById; @@ -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 @@ -63,7 +64,7 @@ public DefaultControlSelectionFilter(@NonNull List new Selection(selection)) + .map(Selection::new) .collect(Collectors.toUnmodifiableList()); } @@ -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 @@ -92,7 +94,7 @@ protected Pair match(String id) { return selections.parallelStream() .map(selection -> selection.match(id)) // filter out non-matches - .filter(pair -> pair.getLeft()) + .filter(Pair::getLeft) // aggregate matches .reduce((first, second) -> { Pair result; @@ -101,7 +103,7 @@ protected Pair match(String id) { boolean withChild = first.getLeft() && first.getRight() || second.getLeft() && second.getRight(); result = Pair.of(true, withChild); } else { - result = IControlSelectionFilter.NON_MATCH; + result = NON_MATCH; } return result; }) diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultResult.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultResult.java index 0ab48de7..9234183f 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultResult.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/DefaultResult.java @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.selection; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/FilterNonSelectedVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/FilterNonSelectedVisitor.java index 022a8a51..942e4d39 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/FilterNonSelectedVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/FilterNonSelectedVisitor.java @@ -26,10 +26,11 @@ package gov.nist.secauto.oscal.lib.profile.resolver.selection; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRootAssemblyNodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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.INodeItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.OscalModelConstants; import gov.nist.secauto.oscal.lib.model.BackMatter; import gov.nist.secauto.oscal.lib.model.BackMatter.Resource; import gov.nist.secauto.oscal.lib.model.Catalog; @@ -59,13 +60,18 @@ public class FilterNonSelectedVisitor extends AbstractCatalogEntityVisitor { private static final Logger LOGGER = LogManager.getLogger(FilterNonSelectedVisitor.class); + @NonNull private static final FilterNonSelectedVisitor SINGLETON = new FilterNonSelectedVisitor(); + @NonNull + @SuppressFBWarnings(value = "SING_SINGLETON_GETTER_NOT_SYNCHRONIZED", justification = "class initialization") public static FilterNonSelectedVisitor instance() { return SINGLETON; } @SuppressWarnings("null") + + @SuppressFBWarnings(value = "SING_SINGLETON_HAS_NONPRIVATE_CONSTRUCTOR", justification = "allows for extension") protected FilterNonSelectedVisitor() { // all other entity types are handled in a special way by this visitor super(EnumSet.of(IEntityItem.ItemType.GROUP, IEntityItem.ItemType.CONTROL, IEntityItem.ItemType.PARAMETER)); @@ -75,19 +81,23 @@ public void visitCatalog(@NonNull IDocumentNodeItem catalogItem, @NonNull IIndex Context context = new Context(indexer); IResult result = visitCatalog(catalogItem, context); - IRootAssemblyNodeItem root = catalogItem.getRootAssemblyNodeItem(); - - Catalog catalog = (Catalog) catalogItem.getValue(); + Catalog catalog = (Catalog) INodeItem.toValue(catalogItem); result.applyTo(catalog); - root.getModelItemsByName("metadata").forEach(child -> { - assert child != null; - visitMetadata(child, context); - }); - - root.getModelItemsByName("back-matter").forEach(child -> { - assert child != null; - visitBackMatter(child, context); + catalogItem.modelItems().forEachOrdered(root -> { + root.getModelItemsByName(OscalModelConstants.QNAME_METADATA).stream() + .map(child -> (IAssemblyNodeItem) child) + .forEachOrdered(child -> { + assert child != null; + visitMetadata(child, context); + }); + + root.getModelItemsByName(OscalModelConstants.QNAME_BACK_MATTER).stream() + .map(child -> (IAssemblyNodeItem) child) + .forEachOrdered(child -> { + assert child != null; + visitBackMatter(child, context); + }); }); } @@ -101,8 +111,8 @@ protected DefaultResult aggregateResults(DefaultResult first, DefaultResult seco return first.append(ObjectUtils.notNull(second)); } - protected void visitMetadata(@NonNull IRequiredValueModelNodeItem metadataItem, Context context) { - Metadata metadata = (Metadata) metadataItem.getValue(); + protected void visitMetadata(@NonNull IAssemblyNodeItem metadataItem, Context context) { + Metadata metadata = ObjectUtils.requireNonNull((Metadata) metadataItem.getValue()); IIndexer index = context.getIndexer(); // prune roles, parties, and locations @@ -139,8 +149,8 @@ protected void visitMetadata(@NonNull IRequiredValueModelNodeItem metadataItem, } @SuppressWarnings("static-method") - private void visitBackMatter(@NonNull IRequiredValueModelNodeItem backMatterItem, Context context) { - BackMatter backMatter = (BackMatter) backMatterItem.getValue(); + private void visitBackMatter(@NonNull IAssemblyNodeItem backMatterItem, Context context) { + BackMatter backMatter = ObjectUtils.requireNonNull((BackMatter) backMatterItem.getValue()); IIndexer index = context.getIndexer(); for (IEntityItem entity : IIndexer.getUnreferencedEntitiesAsStream(index.getEntitiesByItemType(ItemType.RESOURCE)) @@ -156,10 +166,10 @@ private void visitBackMatter(@NonNull IRequiredValueModelNodeItem backMatterItem @Override public DefaultResult visitGroup( - IRequiredValueModelNodeItem item, + IAssemblyNodeItem item, DefaultResult childResult, Context context) { - CatalogGroup group = (CatalogGroup) item.getValue(); + CatalogGroup group = ObjectUtils.requireNonNull((CatalogGroup) item.getValue()); IIndexer index = context.getIndexer(); String groupId = group.getId(); @@ -190,16 +200,16 @@ public DefaultResult visitGroup( @Override public DefaultResult visitControl( - IRequiredValueModelNodeItem item, + IAssemblyNodeItem item, DefaultResult childResult, Context context) { - Control control = (Control) item.getValue(); + Control control = ObjectUtils.requireNonNull((Control) item.getValue()); IIndexer index = context.getIndexer(); // this control should always be found in the index IEntityItem entity = ObjectUtils.requireNonNull( index.getEntity(ItemType.CONTROL, ObjectUtils.requireNonNull(control.getId()), false)); - IRequiredValueModelNodeItem parent = ObjectUtils.notNull(item.getParentContentNodeItem()); + IAssemblyNodeItem parent = ObjectUtils.notNull(item.getParentContentNodeItem()); DefaultResult retval = new DefaultResult(); if (SelectionStatus.SELECTED.equals(index.getSelectionStatus(item))) { // keep this control @@ -226,12 +236,12 @@ public DefaultResult visitControl( return retval; } - protected static void removePartsFromIndex(@NonNull IRequiredValueModelNodeItem groupOrControlItem, + protected static void removePartsFromIndex(@NonNull IAssemblyNodeItem groupOrControlItem, @NonNull IIndexer index) { - CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream() - .map(item -> (IRequiredValueModelNodeItem) item) + CHILD_PART_METAPATH.evaluate(groupOrControlItem).stream() + .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(partItem -> { - ControlPart part = (ControlPart) partItem.getValue(); + ControlPart part = ObjectUtils.requireNonNull((ControlPart) partItem.getValue()); String id = part.getId(); if (id != null) { IEntityItem entity = index.getEntity(IEntityItem.ItemType.PART, id); @@ -243,9 +253,9 @@ protected static void removePartsFromIndex(@NonNull IRequiredValueModelNodeItem } @Override - protected DefaultResult visitParameter(IRequiredValueModelNodeItem item, IRequiredValueModelNodeItem parent, + protected DefaultResult visitParameter(IAssemblyNodeItem item, IAssemblyNodeItem parent, Context context) { - Parameter param = (Parameter) item.getValue(); + Parameter param = ObjectUtils.requireNonNull((Parameter) item.getValue()); IIndexer index = context.getIndexer(); // this parameter should always be found in the index IEntityItem entity = ObjectUtils.requireNonNull( 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 d5c41b9e..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 @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.selection; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.IncludeAll; import gov.nist.secauto.oscal.lib.model.ProfileImport; import gov.nist.secauto.oscal.lib.model.control.catalog.IControl; @@ -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 48c5c527..7a7295b5 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 @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.selection; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.control.catalog.IControl; import org.apache.commons.lang3.tuple.Pair; @@ -46,25 +46,15 @@ public interface IControlSelectionFilter extends Function MATCH = ObjectUtils.notNull(Pair.of(true, true)); @NonNull - IControlSelectionFilter ALL_MATCH = new IControlSelectionFilter() { - @Override - public Pair apply(IControl control) { - return MATCH; - } - }; + IControlSelectionFilter ALL_MATCH = control -> MATCH; @NonNull - IControlSelectionFilter NONE_MATCH = new IControlSelectionFilter() { - @Override - public Pair apply(IControl control) { - return NON_MATCH; - } - }; + IControlSelectionFilter NONE_MATCH = control -> NON_MATCH; @NonNull static IControlSelectionFilter matchIds(@NonNull String... identifiers) { return new IControlSelectionFilter() { - private Set keys = Arrays.stream(identifiers).collect(Collectors.toUnmodifiableSet()); + private final Set keys = Arrays.stream(identifiers).collect(Collectors.toUnmodifiableSet()); @Override public @NonNull Pair apply(IControl control) { @@ -75,14 +65,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/selection/IControlSelectionState.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/IControlSelectionState.java index 49d5df1d..a042a06b 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/IControlSelectionState.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/IControlSelectionState.java @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.selection; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; import gov.nist.secauto.oscal.lib.profile.resolver.support.IIndexer; import edu.umd.cs.findbugs.annotations.NonNull; @@ -35,5 +35,5 @@ public interface IControlSelectionState { @NonNull IIndexer getIndex(); - boolean isSelected(@NonNull IRequiredValueModelNodeItem item); + boolean isSelected(@NonNull IModelNodeItem item); } diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/Import.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/Import.java index 6ad076fc..a86f2490 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/Import.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/Import.java @@ -29,16 +29,21 @@ import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.util.VersionUtil; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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.INodeItem; +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.oscal.lib.model.BackMatter; import gov.nist.secauto.oscal.lib.model.BackMatter.Resource; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; import gov.nist.secauto.oscal.lib.model.Metadata; +import gov.nist.secauto.oscal.lib.model.Metadata.Location; +import gov.nist.secauto.oscal.lib.model.Metadata.Party; +import gov.nist.secauto.oscal.lib.model.Metadata.Role; import gov.nist.secauto.oscal.lib.model.Parameter; import gov.nist.secauto.oscal.lib.model.ProfileImport; import gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolutionEvaluationException; @@ -58,23 +63,23 @@ public class Import { @NonNull - private final IDocumentNodeItem profileDocument; + private final IRootAssemblyNodeItem profile; @NonNull - private final IModelNodeItem profileImportItem; + private final IAssemblyNodeItem profileImportItem; public Import( - @NonNull IDocumentNodeItem profileDocument, - @NonNull IModelNodeItem profileImportItem) { + @NonNull IRootAssemblyNodeItem profile, + @NonNull IAssemblyNodeItem profileImportItem) { - this.profileDocument = profileDocument; + this.profile = profile; this.profileImportItem = profileImportItem; } - protected IDocumentNodeItem getProfileItem() { - return profileDocument; + protected IRootAssemblyNodeItem getProfileItem() { + return profile; } - protected IModelNodeItem getProfileImportItem() { + protected IAssemblyNodeItem getProfileImportItem() { return profileImportItem; } @@ -83,8 +88,8 @@ protected ProfileImport getProfileImport() { return ObjectUtils.requireNonNull((ProfileImport) profileImportItem.getValue()); } - private static Catalog toCatalog(IDocumentNodeItem catalogDocument) { - return (Catalog) catalogDocument.getValue(); + private static Catalog toCatalog(@NonNull IDocumentNodeItem catalogDocument) { + return (Catalog) INodeItem.toValue(catalogDocument); } @NonNull @@ -183,19 +188,19 @@ private static void resolveMetadata( IIndexer.filterDistinct( ObjectUtils.notNull(CollectionUtil.listOrEmpty(resolved.getRoles()).stream()), indexer.getEntitiesByItemType(IEntityItem.ItemType.ROLE), - item -> item.getId()) + Role::getId) .collect(Collectors.toCollection(LinkedList::new))); resolved.setParties( IIndexer.filterDistinct( ObjectUtils.notNull(CollectionUtil.listOrEmpty(resolved.getParties()).stream()), indexer.getEntitiesByItemType(IEntityItem.ItemType.PARTY), - item -> item.getUuid()) + Party::getUuid) .collect(Collectors.toCollection(LinkedList::new))); resolved.setLocations( IIndexer.filterDistinct( ObjectUtils.notNull(CollectionUtil.listOrEmpty(resolved.getLocations()).stream()), indexer.getEntitiesByItemType(IEntityItem.ItemType.LOCATION), - item -> item.getUuid()) + Location::getUuid) .collect(Collectors.toCollection(LinkedList::new))); } @@ -215,7 +220,7 @@ private static void generateBackMatter( List resources = IIndexer.filterDistinct( ObjectUtils.notNull(resolvedResources.stream()), indexer.getEntitiesByItemType(IEntityItem.ItemType.RESOURCE), - item -> item.getUuid()) + Resource::getUuid) .collect(Collectors.toCollection(LinkedList::new)); if (!resources.isEmpty()) { 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 94e27496..6af50725 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 @@ -26,12 +26,14 @@ package gov.nist.secauto.oscal.lib.profile.resolver.support; -import gov.nist.secauto.metaschema.model.common.metapath.MetapathExpression; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRootAssemblyNodeItem; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; +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.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.OscalBindingContext; +import gov.nist.secauto.oscal.lib.OscalModelConstants; import java.util.Collections; import java.util.EnumSet; @@ -42,7 +44,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 @@ -53,10 +56,12 @@ public abstract class AbstractCatalogEntityVisitor extends AbstractCatalogVisitor { @NonNull public static final MetapathExpression CHILD_PART_METAPATH - = MetapathExpression.compile("part|part//part"); + = MetapathExpression.compile("part|part//part", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); @NonNull private static final MetapathExpression BACK_MATTER_RESOURCES_METAPATH - = MetapathExpression.compile("back-matter/resource"); + = MetapathExpression.compile("back-matter/resource", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); @NonNull private static final Set GROUP_CONTAINER_TYPES = ObjectUtils.notNull(EnumSet.of( @@ -74,7 +79,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 @@ -95,14 +101,16 @@ protected boolean isVisitedItemType(@NonNull IEntityItem.ItemType type) { public R visitCatalog(IDocumentNodeItem catalogDocument, T state) { R result = super.visitCatalog(catalogDocument, state); - IRootAssemblyNodeItem root = catalogDocument.getRootAssemblyNodeItem(); - visitMetadata(root, state); - visitBackMatter(root, state); + catalogDocument.modelItems().forEachOrdered(item -> { + IRootAssemblyNodeItem root = ObjectUtils.requireNonNull((IRootAssemblyNodeItem) item); + visitMetadata(root, state); + visitBackMatter(root, state); + }); return result; } @Override - protected R visitGroupContainer(IRequiredValueModelNodeItem catalogOrGroup, R initialResult, T state) { + protected R visitGroupContainer(IAssemblyNodeItem catalogOrGroup, R initialResult, T state) { R retval; if (Collections.disjoint(getItemTypesToVisit(), GROUP_CONTAINER_TYPES)) { retval = initialResult; @@ -113,7 +121,7 @@ protected R visitGroupContainer(IRequiredValueModelNodeItem catalogOrGroup, R in } @Override - protected R visitControlContainer(IRequiredValueModelNodeItem catalogOrGroupOrControl, R initialResult, T state) { + protected R visitControlContainer(IAssemblyNodeItem catalogOrGroupOrControl, R initialResult, T state) { R retval; if (Collections.disjoint(getItemTypesToVisit(), CONTROL_CONTAINER_TYPES)) { retval = initialResult; @@ -123,21 +131,22 @@ protected R visitControlContainer(IRequiredValueModelNodeItem catalogOrGroupOrCo // handle parameters if (isVisitedItemType(IEntityItem.ItemType.PARAMETER)) { - retval = catalogOrGroupOrControl.getModelItemsByName("param").stream() - .map(paramItem -> { - return visitParameter(ObjectUtils.requireNonNull(paramItem), catalogOrGroupOrControl, state); - }) + retval = catalogOrGroupOrControl.getModelItemsByName(OscalModelConstants.QNAME_PARAM).stream() + .map(paramItem -> visitParameter( + ObjectUtils.requireNonNull((IAssemblyNodeItem) paramItem), + catalogOrGroupOrControl, + state)) .reduce(retval, (first, second) -> aggregateResults(first, second, state)); - } // TODO Auto-generated method stub + } } return retval; } - protected void visitParts(@NonNull IRequiredValueModelNodeItem groupOrControlItem, T state) { + protected void visitParts(@NonNull IAssemblyNodeItem groupOrControlItem, T state) { // handle parts if (isVisitedItemType(IEntityItem.ItemType.PART)) { - CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream() - .map(item -> (IRequiredValueModelNodeItem) item) + CHILD_PART_METAPATH.evaluate(groupOrControlItem).stream() + .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(partItem -> { visitPart(ObjectUtils.requireNonNull(partItem), groupOrControlItem, state); }); @@ -145,7 +154,7 @@ protected void visitParts(@NonNull IRequiredValueModelNodeItem groupOrControlIte } @Override - protected R visitGroupInternal(@NonNull IRequiredValueModelNodeItem item, R childResult, T state) { + protected R visitGroupInternal(@NonNull IAssemblyNodeItem item, R childResult, T state) { if (isVisitedItemType(IEntityItem.ItemType.PART)) { visitParts(item, state); } @@ -158,7 +167,7 @@ protected R visitGroupInternal(@NonNull IRequiredValueModelNodeItem item, R chil } @Override - protected R visitControlInternal(IRequiredValueModelNodeItem item, R childResult, T state) { + protected R visitControlInternal(IAssemblyNodeItem item, R childResult, T state) { if (isVisitedItemType(IEntityItem.ItemType.PART)) { visitParts(item, state); } @@ -173,8 +182,8 @@ protected R visitControlInternal(IRequiredValueModelNodeItem item, R childResult /** * 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 @@ -185,8 +194,8 @@ protected R visitControlInternal(IRequiredValueModelNodeItem item, R childResult * @return a meaningful result of the given type */ protected R visitParameter( - @NonNull IRequiredValueModelNodeItem item, - @NonNull IRequiredValueModelNodeItem catalogOrGroupOrControl, + @NonNull IAssemblyNodeItem item, + @NonNull IAssemblyNodeItem catalogOrGroupOrControl, T state) { // do nothing return newDefaultResult(state); @@ -195,8 +204,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 @@ -206,8 +215,8 @@ protected R visitParameter( * the calling context information */ protected void visitPart( // NOPMD noop default - @NonNull IRequiredValueModelNodeItem item, - @NonNull IRequiredValueModelNodeItem groupOrControl, + @NonNull IAssemblyNodeItem item, + @NonNull IAssemblyNodeItem groupOrControl, T state) { // do nothing } @@ -218,68 +227,78 @@ 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 */ protected void visitMetadata(@NonNull IRootAssemblyNodeItem rootItem, T state) { - rootItem.getModelItemsByName("metadata").forEach(metadataItem -> { - if (isVisitedItemType(IEntityItem.ItemType.ROLE)) { - metadataItem.getModelItemsByName("role").forEach(roleItem -> { - visitRole(ObjectUtils.requireNonNull(roleItem), metadataItem, state); - }); - } + rootItem.getModelItemsByName(OscalModelConstants.QNAME_METADATA).stream() + .map(metadataItem -> (IAssemblyNodeItem) metadataItem) + .forEach(metadataItem -> { + if (isVisitedItemType(IEntityItem.ItemType.ROLE)) { + metadataItem.getModelItemsByName(OscalModelConstants.QNAME_ROLE).stream() + .map(roleItem -> (IAssemblyNodeItem) roleItem) + .forEachOrdered(roleItem -> { + visitRole(ObjectUtils.requireNonNull(roleItem), metadataItem, state); + }); + } - if (isVisitedItemType(IEntityItem.ItemType.LOCATION)) { - metadataItem.getModelItemsByName("location").forEach(locationItem -> { - visitLocation(ObjectUtils.requireNonNull(locationItem), metadataItem, state); - }); - } + if (isVisitedItemType(IEntityItem.ItemType.LOCATION)) { + metadataItem.getModelItemsByName(OscalModelConstants.QNAME_LOCATION).stream() + .map(locationItem -> (IAssemblyNodeItem) locationItem) + .forEachOrdered(locationItem -> { + visitLocation(ObjectUtils.requireNonNull(locationItem), metadataItem, state); + }); + } - if (isVisitedItemType(IEntityItem.ItemType.PARTY)) { - metadataItem.getModelItemsByName("party").forEach(partyItem -> { - visitParty(ObjectUtils.requireNonNull(partyItem), metadataItem, state); + if (isVisitedItemType(IEntityItem.ItemType.PARTY)) { + metadataItem.getModelItemsByName(OscalModelConstants.QNAME_PARTY).stream() + .map(partyItem -> (IAssemblyNodeItem) partyItem) + .forEachOrdered(partyItem -> { + visitParty(ObjectUtils.requireNonNull(partyItem), metadataItem, 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 */ protected void visitRole( // NOPMD noop default - @NonNull IRequiredValueModelNodeItem item, - @NonNull IRequiredValueModelNodeItem metadataItem, + @NonNull IAssemblyNodeItem item, + @NonNull IAssemblyNodeItem metadataItem, T state) { // do nothing } /** - * 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 */ protected void visitLocation( // NOPMD noop default - @NonNull IRequiredValueModelNodeItem item, - @NonNull IRequiredValueModelNodeItem metadataItem, + @NonNull IAssemblyNodeItem item, + @NonNull IAssemblyNodeItem metadataItem, T state) { // do nothing } @@ -287,19 +306,19 @@ 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 */ protected void visitParty( // NOPMD noop default - @NonNull IRequiredValueModelNodeItem item, - @NonNull IRequiredValueModelNodeItem metadataItem, + @NonNull IAssemblyNodeItem item, + @NonNull IAssemblyNodeItem metadataItem, T state) { // do nothing } @@ -310,14 +329,14 @@ 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 */ protected void visitBackMatter(@NonNull IRootAssemblyNodeItem rootItem, T state) { if (isVisitedItemType(IEntityItem.ItemType.RESOURCE)) { - BACK_MATTER_RESOURCES_METAPATH.evaluate(rootItem).asStream() - .map(item -> (IRequiredValueModelNodeItem) item) + BACK_MATTER_RESOURCES_METAPATH.evaluate(rootItem).stream() + .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(resourceItem -> { visitResource(ObjectUtils.requireNonNull(resourceItem), rootItem, state); }); @@ -325,21 +344,23 @@ 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 item - * the resource Metaschema node item which is a child of the "metadata" node - * @param backMatterItem - * the resource Metaschema node item containing the party + * @param resource + * the resource Module node item which is a child of the "metadata" + * node + * @param backMatter + * the resource Module node item containing the party * @param state * the calling context information */ protected void visitResource( // NOPMD noop default - @NonNull IRequiredValueModelNodeItem item, - @NonNull IRootAssemblyNodeItem backMatterItem, + @NonNull IAssemblyNodeItem resource, + @NonNull IRootAssemblyNodeItem backMatter, T state) { // do nothing } 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 696d8fa3..a3ac0f91 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 @@ -26,9 +26,10 @@ package gov.nist.secauto.oscal.lib.profile.resolver.support; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.OscalModelConstants; import edu.umd.cs.findbugs.annotations.NonNull; @@ -36,9 +37,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 { @@ -47,11 +50,16 @@ public abstract class AbstractCatalogVisitor implements ICatalogVisitor visitGroupContainer( + ObjectUtils.requireNonNull((IAssemblyNodeItem) catalogOrGroup), result, state), + (result1, result2) -> aggregateResults(result1, result2, 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 @@ -62,12 +70,14 @@ protected R visitCatalog(@NonNull IDocumentNodeItem catalogDocument, T state) { * @return a meaningful result of the given type */ protected R visitGroupContainer( - @NonNull IRequiredValueModelNodeItem catalogOrGroup, + @NonNull IAssemblyNodeItem catalogOrGroup, R initialResult, T state) { - R result = catalogOrGroup.getModelItemsByName("group").stream() + R result = catalogOrGroup.getModelItemsByName(OscalModelConstants.QNAME_GROUP).stream() .map(groupItem -> { - return visitGroupItem(ObjectUtils.requireNonNull(groupItem), state); + return visitGroupItem( + ObjectUtils.requireNonNull((IAssemblyNodeItem) groupItem), + state); }) .reduce(initialResult, (first, second) -> aggregateResults(first, second, state)); return visitControlContainer(catalogOrGroup, result, state); @@ -78,21 +88,21 @@ protected R visitGroupContainer( *

    * This method will first visit the group's children, then the group itself. * - * @param item + * @param group * the group Metapath item to visit * @param state * the current visitor state * @return a meaningful result of the given type */ - protected R visitGroupItem(@NonNull IRequiredValueModelNodeItem item, T state) { - R childResult = visitGroupContainer(item, newDefaultResult(state), state); - return visitGroupInternal(item, childResult, state); + protected R visitGroupItem(@NonNull IAssemblyNodeItem group, T state) { + R childResult = visitGroupContainer(group, newDefaultResult(state), state); + return visitGroupInternal(group, childResult, state); } /** * Called when visiting a group after visiting it's children. * - * @param item + * @param group * the group Metapath item currently being visited * @param childResult * the result of visiting the group's children @@ -101,14 +111,15 @@ protected R visitGroupItem(@NonNull IRequiredValueModelNodeItem item, T state) { * @return a meaningful result of the given type */ protected R visitGroupInternal( - @NonNull IRequiredValueModelNodeItem item, + @NonNull IAssemblyNodeItem group, R childResult, T state) { - return visitGroup(item, childResult, state); + return visitGroup(group, childResult, state); } /** - * 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 @@ -119,12 +130,12 @@ protected R visitGroupInternal( * @return a meaningful result of the given type */ protected R visitControlContainer( - @NonNull IRequiredValueModelNodeItem catalogOrGroupOrControl, + @NonNull IAssemblyNodeItem catalogOrGroupOrControl, R initialResult, T state) { - return catalogOrGroupOrControl.getModelItemsByName("control").stream() - .map(controlItem -> { - return visitControlItem(ObjectUtils.requireNonNull(controlItem), state); + return catalogOrGroupOrControl.getModelItemsByName(OscalModelConstants.QNAME_CONTROL).stream() + .map(control -> { + return visitControlItem(ObjectUtils.requireNonNull((IAssemblyNodeItem) control), state); }) .reduce(initialResult, (first, second) -> aggregateResults(first, second, state)); } @@ -134,21 +145,21 @@ protected R visitControlContainer( *

    * This method will first visit the control's children, then the control itself. * - * @param item - * the group Metapath item to visit + * @param control + * the control Metapath item to visit * @param state * the current visitor state * @return a meaningful result of the given type */ - protected R visitControlItem(@NonNull IRequiredValueModelNodeItem item, T state) { - R childResult = visitControlContainer(item, newDefaultResult(state), state); - return visitControlInternal(item, childResult, state); + protected R visitControlItem(@NonNull IAssemblyNodeItem control, T state) { + R childResult = visitControlContainer(control, newDefaultResult(state), state); + return visitControlInternal(control, childResult, state); } /** * Called when visiting a control after visiting it's children. * - * @param controlItem + * @param control * the Metapath item for the control currently being visited * @param childResult * the result of visiting the control's children @@ -156,7 +167,7 @@ protected R visitControlItem(@NonNull IRequiredValueModelNodeItem item, T state) * the calling context information * @return a meaningful result of the given type */ - protected R visitControlInternal(@NonNull IRequiredValueModelNodeItem controlItem, R childResult, T state) { - return visitControl(controlItem, childResult, state); + protected R visitControlInternal(@NonNull IAssemblyNodeItem control, R childResult, T state) { + return visitControl(control, childResult, state); } } 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 733484c0..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 @@ -26,8 +26,8 @@ package gov.nist.secauto.oscal.lib.profile.resolver.support; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import java.net.URI; @@ -38,7 +38,7 @@ public abstract class AbstractEntityItem implements IEntityItem { @NonNull private final String originalIdentifier; @NonNull - private IRequiredValueModelNodeItem instance; + private IModelNodeItem instance; @NonNull private final ItemType itemType; @NonNull @@ -66,17 +66,18 @@ public String getOriginalIdentifier() { // @NonNull // public String getIdentifier() { // final String checkedReassignedIdentifier = reassignedIdentifier; - // return checkedReassignedIdentifier == null ? originalIdentifier : checkedReassignedIdentifier; + // return checkedReassignedIdentifier == null ? originalIdentifier : + // checkedReassignedIdentifier; // } @Override @NonNull - public IRequiredValueModelNodeItem getInstance() { + public IModelNodeItem getInstance() { return instance; } @Override - public void setInstance(IRequiredValueModelNodeItem item) { + public void setInstance(IModelNodeItem item) { instance = item; } @@ -84,7 +85,7 @@ public void setInstance(IRequiredValueModelNodeItem item) { @NonNull @SuppressWarnings("unchecked") public T getInstanceValue() { - return (T) getInstance().getValue(); + return ObjectUtils.notNull((T) getInstance().getValue()); } @Override @@ -127,12 +128,12 @@ public int resetReferenceCount() { static final class Builder { private String originalIdentifier; private String reassignedIdentifier; - private IRequiredValueModelNodeItem instance; + private IModelNodeItem instance; private ItemType itemType; private URI source; @NonNull - public Builder instance(@NonNull IRequiredValueModelNodeItem item, @NonNull ItemType itemType) { + public Builder instance(@NonNull IModelNodeItem item, @NonNull ItemType itemType) { this.instance = item; this.itemType = itemType; return this; diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractIndexingVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractIndexingVisitor.java index 74978902..70d7bdf4 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractIndexingVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/AbstractIndexingVisitor.java @@ -26,9 +26,9 @@ package gov.nist.secauto.oscal.lib.profile.resolver.support; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRootAssemblyNodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.IRootAssemblyNodeItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import java.util.EnumSet; import java.util.Set; @@ -50,48 +50,48 @@ public AbstractIndexingVisitor(@NonNull Set itemTypesToInd protected abstract IIndexer getIndexer(T state); @Override - public R visitGroup(IRequiredValueModelNodeItem item, R childResult, T state) { + public R visitGroup(IAssemblyNodeItem item, R childResult, T state) { getIndexer(state).addGroup(item); return childResult; } @Override - public R visitControl(IRequiredValueModelNodeItem item, R childResult, T state) { + public R visitControl(IAssemblyNodeItem item, R childResult, T state) { getIndexer(state).addControl(item); return childResult; } @Override - protected R visitParameter(@NonNull IRequiredValueModelNodeItem parameterItem, - @NonNull IRequiredValueModelNodeItem catalogOrGroupOrControl, T state) { + protected R visitParameter(@NonNull IAssemblyNodeItem parameterItem, + @NonNull IAssemblyNodeItem catalogOrGroupOrControl, T state) { getIndexer(state).addParameter(parameterItem); return newDefaultResult(state); } @Override - protected void visitPart(@NonNull IRequiredValueModelNodeItem partItem, - @NonNull IRequiredValueModelNodeItem catalogOrGroupOrControl, T state) { + protected void visitPart(@NonNull IAssemblyNodeItem partItem, + @NonNull IAssemblyNodeItem catalogOrGroupOrControl, T state) { getIndexer(state).addPart(partItem); } @Override - protected void visitRole(IRequiredValueModelNodeItem roleItem, IRequiredValueModelNodeItem metadataItem, T state) { + protected void visitRole(IAssemblyNodeItem roleItem, IAssemblyNodeItem metadataItem, T state) { getIndexer(state).addRole(roleItem); } @Override - protected void visitLocation(IRequiredValueModelNodeItem locationItem, IRequiredValueModelNodeItem metadataItem, + protected void visitLocation(IAssemblyNodeItem locationItem, IAssemblyNodeItem metadataItem, T state) { getIndexer(state).addLocation(locationItem); } @Override - protected void visitParty(IRequiredValueModelNodeItem partyItem, IRequiredValueModelNodeItem metadataItem, T state) { + protected void visitParty(IAssemblyNodeItem partyItem, IAssemblyNodeItem metadataItem, T state) { getIndexer(state).addParty(partyItem); } @Override - protected void visitResource(IRequiredValueModelNodeItem resourceItem, IRootAssemblyNodeItem rootItem, T state) { + protected void visitResource(IAssemblyNodeItem resourceItem, IRootAssemblyNodeItem rootItem, T state) { getIndexer(state).addResource(resourceItem); } } 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 90e866ac..3a6ebd16 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,13 +26,14 @@ package gov.nist.secauto.oscal.lib.profile.resolver.support; -import gov.nist.secauto.metaschema.model.common.datatype.adapter.UuidAdapter; -import gov.nist.secauto.metaschema.model.common.metapath.MetapathExpression; -import gov.nist.secauto.metaschema.model.common.metapath.MetapathExpression.ResultType; -import gov.nist.secauto.metaschema.model.common.metapath.item.INodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; +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.OscalBindingContext; 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; @@ -62,7 +63,8 @@ public class BasicIndexer implements IIndexer { private static final Logger LOGGER = LogManager.getLogger(ProfileResolver.class); private static final MetapathExpression CONTAINER_METAPATH - = MetapathExpression.compile("(ancestor::control|ancestor::group)[1])"); + = MetapathExpression.compile("(ancestor::control|ancestor::group)[1])", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); @NonNull private final Map> entityTypeToIdentifierToEntityMap; @@ -126,11 +128,11 @@ public boolean isSelected(@NonNull IEntityItem entity) { retval = IIndexer.SelectionStatus.SELECTED.equals(getSelectionStatus(entity.getInstance())); break; case PART: { - IRequiredValueModelNodeItem instance = entity.getInstance(); + IModelNodeItem instance = entity.getInstance(); IIndexer.SelectionStatus status = getSelectionStatus(instance); if (IIndexer.SelectionStatus.UNKNOWN.equals(status)) { // lookup the status if not known - IRequiredValueModelNodeItem containerItem = CONTAINER_METAPATH.evaluateAs(instance, ResultType.NODE); + IModelNodeItem containerItem = CONTAINER_METAPATH.evaluateAs(instance, ResultType.NODE); assert containerItem != null; status = getSelectionStatus(containerItem); @@ -190,11 +192,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()); // } @@ -255,62 +260,62 @@ public boolean removeItem(@NonNull IEntityItem entity) { } @Override - public IEntityItem addRole(IRequiredValueModelNodeItem item) { - Role role = (Role) item.getValue(); + public IEntityItem addRole(IModelNodeItem item) { + Role role = ObjectUtils.requireNonNull((Role) item.getValue()); String identifier = ObjectUtils.requireNonNull(role.getId()); return addItem(newBuilder(item, ItemType.ROLE, identifier)); } @Override - public IEntityItem addLocation(IRequiredValueModelNodeItem item) { - Location location = (Location) item.getValue(); + public IEntityItem addLocation(IModelNodeItem item) { + Location location = ObjectUtils.requireNonNull((Location) item.getValue()); UUID identifier = ObjectUtils.requireNonNull(location.getUuid()); return addItem(newBuilder(item, ItemType.LOCATION, identifier)); } @Override - public IEntityItem addParty(IRequiredValueModelNodeItem item) { - Party party = (Party) item.getValue(); + public IEntityItem addParty(IModelNodeItem item) { + Party party = ObjectUtils.requireNonNull((Party) item.getValue()); UUID identifier = ObjectUtils.requireNonNull(party.getUuid()); return addItem(newBuilder(item, ItemType.PARTY, identifier)); } @Override - public IEntityItem addGroup(IRequiredValueModelNodeItem item) { - CatalogGroup group = (CatalogGroup) item.getValue(); + public IEntityItem addGroup(IModelNodeItem item) { + CatalogGroup group = ObjectUtils.requireNonNull((CatalogGroup) item.getValue()); String identifier = group.getId(); return identifier == null ? null : addItem(newBuilder(item, ItemType.GROUP, identifier)); } @Override - public IEntityItem addControl(IRequiredValueModelNodeItem item) { - Control control = (Control) item.getValue(); + public IEntityItem addControl(IModelNodeItem item) { + Control control = ObjectUtils.requireNonNull((Control) item.getValue()); String identifier = ObjectUtils.requireNonNull(control.getId()); return addItem(newBuilder(item, ItemType.CONTROL, identifier)); } @Override - public IEntityItem addParameter(IRequiredValueModelNodeItem item) { - Parameter parameter = (Parameter) item.getValue(); + public IEntityItem addParameter(IModelNodeItem item) { + Parameter parameter = ObjectUtils.requireNonNull((Parameter) item.getValue()); String identifier = ObjectUtils.requireNonNull(parameter.getId()); return addItem(newBuilder(item, ItemType.PARAMETER, identifier)); } @Override - public IEntityItem addPart(IRequiredValueModelNodeItem item) { - ControlPart part = (ControlPart) item.getValue(); + public IEntityItem addPart(IModelNodeItem item) { + ControlPart part = ObjectUtils.requireNonNull((ControlPart) item.getValue()); String identifier = part.getId(); return identifier == null ? null : addItem(newBuilder(item, ItemType.PART, identifier)); } @Override - public IEntityItem addResource(IRequiredValueModelNodeItem item) { - Resource resource = (Resource) item.getValue(); + public IEntityItem addResource(IModelNodeItem item) { + Resource resource = ObjectUtils.requireNonNull((Resource) item.getValue()); UUID identifier = ObjectUtils.requireNonNull(resource.getUuid()); return addItem(newBuilder(item, ItemType.RESOURCE, identifier)); @@ -318,7 +323,7 @@ public IEntityItem addResource(IRequiredValueModelNodeItem item) { @NonNull protected final AbstractEntityItem.Builder newBuilder( - @NonNull IRequiredValueModelNodeItem item, + @NonNull IModelNodeItem item, @NonNull ItemType itemType, @NonNull UUID identifier) { return newBuilder(item, itemType, ObjectUtils.notNull(identifier.toString())); @@ -327,10 +332,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 @@ -342,7 +348,7 @@ protected final AbstractEntityItem.Builder newBuilder( */ @NonNull protected AbstractEntityItem.Builder newBuilder( - @NonNull IRequiredValueModelNodeItem item, + @NonNull IModelNodeItem item, @NonNull ItemType itemType, @NonNull String identifier) { return new AbstractEntityItem.Builder() diff --git a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/ControlIndexingVisitor.java b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/ControlIndexingVisitor.java index e424f8c5..f6a9c747 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/ControlIndexingVisitor.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/ControlIndexingVisitor.java @@ -26,8 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.support; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRootAssemblyNodeItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.IRootAssemblyNodeItem; import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem.ItemType; import java.util.Set; @@ -60,8 +59,7 @@ protected Void aggregateResults(Void first, Void second, IIndexer state) { return null; } - public void visitProfile(@NonNull IDocumentNodeItem profileDocument, @NonNull IIndexer index) { - IRootAssemblyNodeItem root = profileDocument.getRootAssemblyNodeItem(); + public void visitProfile(@NonNull IRootAssemblyNodeItem root, @NonNull IIndexer index) { visitMetadata(root, index); visitBackMatter(root, index); } 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 96842848..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 @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.support; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem; import edu.umd.cs.findbugs.annotations.NonNull; @@ -34,19 +34,21 @@ * 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 item + * @param group * the Metapath item for the group * @param childResult * the result of evaluating the group's children @@ -54,7 +56,7 @@ public interface ICatalogVisitor { * the calling context information * @return a meaningful result of the given type */ - default R visitGroup(@NonNull IRequiredValueModelNodeItem item, R childResult, T state) { + default R visitGroup(@NonNull IAssemblyNodeItem group, R childResult, T state) { // do nothing by default return childResult; } @@ -62,10 +64,10 @@ default R visitGroup(@NonNull IRequiredValueModelNodeItem item, R childResult, T /** * 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 item + * @param control * the Metapath item for the control * @param childResult * the result of evaluating the control's children @@ -73,7 +75,7 @@ default R visitGroup(@NonNull IRequiredValueModelNodeItem item, R childResult, T * the calling context information * @return a meaningful result of the given type */ - default R visitControl(@NonNull IRequiredValueModelNodeItem item, R childResult, T state) { + default R visitControl(@NonNull IAssemblyNodeItem control, R childResult, T state) { // do nothing by default return childResult; } 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 afeacf98..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 @@ -26,7 +26,7 @@ package gov.nist.secauto.oscal.lib.profile.resolver.support; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; import java.net.URI; @@ -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,14 +83,15 @@ 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(); @NonNull - IRequiredValueModelNodeItem getInstance(); + IModelNodeItem getInstance(); - void setInstance(@NonNull IRequiredValueModelNodeItem item); + void setInstance(@NonNull IModelNodeItem item); @NonNull T getInstanceValue(); 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 f91ed7e9..032838db 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 @@ -26,12 +26,14 @@ package gov.nist.secauto.oscal.lib.profile.resolver.support; -import gov.nist.secauto.metaschema.model.common.metapath.MetapathExpression; -import gov.nist.secauto.metaschema.model.common.metapath.MetapathExpression.ResultType; -import gov.nist.secauto.metaschema.model.common.metapath.item.INodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.CustomCollectors; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; +import gov.nist.secauto.metaschema.core.metapath.MetapathExpression.ResultType; +import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; +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.model.metadata.IProperty; import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem.ItemType; import org.apache.logging.log4j.Level; @@ -57,27 +59,21 @@ enum SelectionStatus { UNKNOWN; } - MetapathExpression HAS_PROP_KEEP_METAPATH = MetapathExpression - .compile("prop[@name='keep' and has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]/@value = 'always'"); + MetapathExpression HAS_PROP_KEEP_METAPATH = MetapathExpression.compile( + "prop[@name='keep' and has-oscal-namespace('" + IProperty.OSCAL_NAMESPACE + "')]/@value = 'always'", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); - Predicate KEEP_ENTITY_PREDICATE = new Predicate<>() { - - @Override - public boolean test(IEntityItem entity) { - return entity.getReferenceCount() > 0 - || (Boolean) ObjectUtils - .notNull(IIndexer.HAS_PROP_KEEP_METAPATH.evaluateAs(entity.getInstance(), ResultType.BOOLEAN)); - } - - }; + Predicate KEEP_ENTITY_PREDICATE = entity -> entity.getReferenceCount() > 0 + || (Boolean) ObjectUtils + .notNull(HAS_PROP_KEEP_METAPATH.evaluateAs(entity.getInstance(), ResultType.BOOLEAN)); static boolean isReferencedEntity(@NonNull IEntityItem entity) { return KEEP_ENTITY_PREDICATE.test(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 +84,8 @@ static Stream getReferencedEntitiesAsStream(@NonNull Collection serializer = bindingContext.newSerializer(Format.YAML, Catalog.class); @@ -82,21 +85,23 @@ void simpleLoadAndSave() throws IOException { @Test void testConstraintValidation() throws MalformedURLException, IOException, URISyntaxException, ProfileResolutionException { - // Initialize the Metaschema framework - OscalBindingContext bindingContext = OscalBindingContext.instance(); // manages the Metaschema model + // Initialize the Module framework + OscalBindingContext bindingContext = OscalBindingContext.instance(); // manages the Module model IBoundLoader loader = bindingContext.newBoundLoader(); // supports loading OSCAL documents loader.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS); IDocumentNodeItem nodeItem = loader.loadAsNodeItem(new URL( "https://raw.githubusercontent.com/Rene2mt/fedramp-automation/a692b9385d8fbcacbb1d3e3d0b0d7e3c45a205d0/src/content/baselines/rev5/xml/FedRAMP_rev5_HIGH-baseline_profile.xml")); - DynamicContext dynamicContext = new StaticContext().newDynamicContext(); + DynamicContext dynamicContext = new DynamicContext(StaticContext.builder() + .defaultModelNamespace(nodeItem.getNamespace()) + .build()); dynamicContext.setDocumentLoader(loader); FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler(); - DefaultConstraintValidator validator = new DefaultConstraintValidator(dynamicContext, handler); + DefaultConstraintValidator validator = new DefaultConstraintValidator(handler); - validator.validate(nodeItem); - validator.finalizeValidation(); + validator.validate(nodeItem, dynamicContext); + validator.finalizeValidation(dynamicContext); assertTrue(handler.isPassing()); @@ -105,6 +110,9 @@ void testConstraintValidation() // Create a serializer which can be used to write multiple catalogs ISerializer serializer = bindingContext.newSerializer(Format.YAML, Catalog.class); // serialize the catalog as yaml - serializer.serialize((Catalog) resolvedCatalog.getValue(), 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 54069fc5..647d1187 100644 --- a/src/test/java/gov/nist/secauto/oscal/java/MetaschemaVisitorTest.java +++ b/src/test/java/gov/nist/secauto/oscal/java/MetaschemaVisitorTest.java @@ -26,16 +26,18 @@ package gov.nist.secauto.oscal.java; -import gov.nist.secauto.metaschema.binding.io.IBoundLoader; -import gov.nist.secauto.metaschema.model.common.metapath.DynamicContext; -import gov.nist.secauto.metaschema.model.common.metapath.INodeContext; -import gov.nist.secauto.metaschema.model.common.metapath.ISequence; -import gov.nist.secauto.metaschema.model.common.metapath.MetapathExpression; -import gov.nist.secauto.metaschema.model.common.metapath.StaticContext; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; +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; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.io.File; @@ -50,16 +52,17 @@ class MetaschemaVisitorTest { + @Disabled @Test 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); - DynamicContext dynamicContext = staticContext.newDynamicContext(); + URI baseUri = ObjectUtils.notNull(new File("").getAbsoluteFile().toURI()); + StaticContext staticContext = OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT.buildFrom() + .baseUri(baseUri) + .build(); + DynamicContext dynamicContext = new DynamicContext(staticContext); dynamicContext.setDocumentLoader(loader); // File file = new @@ -73,42 +76,51 @@ void test() throws FileNotFoundException, IOException, URISyntaxException { // Profile profile = nodeItem.toBoundObject(); IDocumentNodeItem resolvedProfile = ResolveProfile.resolveProfile(nodeItem, dynamicContext); - OscalBindingContext.instance().validate(resolvedProfile); + OscalBindingContext.instance().validate(resolvedProfile, loader, null); // OscalBindingContext.instance().newSerializer(Format.XML, // Catalog.class).serialize(resolvedProfile.toBoundObject(), new FileWriter(new // 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); } - private static void evaluatePath(@NonNull MetapathExpression path, @NonNull INodeContext nodeContext, + private static void evaluatePath(@NonNull MetapathExpression path, @NonNull IItem nodeContext, @NonNull DynamicContext dynamicContext) { // System.out.println("Path: " + path.getPath()); // System.out.println("Compiled Path: " + path.toString()); @@ -116,7 +128,7 @@ private static void evaluatePath(@NonNull MetapathExpression path, @NonNull INod ISequence result = path.evaluate(nodeContext, dynamicContext); // System.out.println("Result: "); AtomicInteger count = new AtomicInteger(); - result.asStream().forEachOrdered(x -> { + result.stream().forEachOrdered(x -> { count.incrementAndGet(); }); // System.out.println(String.format(" %d items", count.get())); 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 266f1020..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.model.common.util.ObjectUtils; +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 e00cf7a1..0426a447 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,14 @@ 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.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.model.IBoundObject; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.DefaultBindingContext; +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,8 +52,12 @@ class ReadWriteTest { private static final Logger LOGGER = LogManager.getLogger(ReadWriteTest.class); + private static final int WARMUP_ITERATIONS = 4; + private static final int ITERATIONS = WARMUP_ITERATIONS + 5; + // private static final int ITERATIONS = 1; + @NonNull - private static CLASS measureDeserializer( + private static CLASS measureDeserializer( @NonNull String format, @NonNull Path file, @NonNull IDeserializer deserializer, @@ -65,6 +71,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 +80,15 @@ private static CLASS measureDeserializer( if (LOGGER.isInfoEnabled()) { LOGGER.info(String.format("%s read in %d milliseconds from %s", format, timeElapsed, file)); } - totalTime += timeElapsed; + + // skip initial executions, if possible, to allow for JVM warmup + if (i >= WARMUP_ITERATIONS) { + totalTime += timeElapsed; + ++totalIterations; + } } - long average = totalTime / iterations - 1; - if (iterations > 1 && LOGGER.isInfoEnabled()) { + if (totalIterations > 1 && LOGGER.isInfoEnabled()) { + long average = totalTime / totalIterations; LOGGER.info(String.format("%s read in %d milliseconds (on average) from %s", format, average, file)); } @@ -85,13 +97,15 @@ private static CLASS measureDeserializer( return retval; } - private static void measureSerializer( + private static void measureSerializer( @NonNull CLASS root, @NonNull String format, @NonNull Path file, @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,33 +114,38 @@ 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) { + + // skip initial executions, if possible, to allow for JVM warmup + if (i >= WARMUP_ITERATIONS) { totalTime += timeElapsed; + ++totalIterations; } } - long average = totalTime / (iterations == 1 ? 1 : iterations - 1); - if (iterations > 1 && LOGGER.isInfoEnabled()) { + if (totalIterations > 1 && LOGGER.isInfoEnabled()) { + long average = totalTime / totalIterations; LOGGER.info(String.format("%s written in %d milliseconds (on average) to %s", format, average, file)); } } - private static void chainReadWrite( + private static void chainReadWrite( @NonNull Path xmlSource, @NonNull Class clazz, @NonNull Path tempDir, int iterations) throws IOException { - IBindingContext context = IBindingContext.instance(); CLASS obj; // XML { + IBindingContext context = new DefaultBindingContext(); IDeserializer deserializer = context.newDeserializer(Format.XML, clazz); deserializer.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS); obj = measureDeserializer("XML", xmlSource, deserializer, iterations); - + } + { + IBindingContext context = new DefaultBindingContext(); Path out = ObjectUtils.notNull(tempDir.resolve("out.xml")); ISerializer serializer = context.newSerializer(Format.XML, clazz); measureSerializer(obj, "XML", out, serializer, iterations); @@ -135,23 +154,33 @@ private static void chainReadWrite( // JSON { Path out = ObjectUtils.notNull(tempDir.resolve("out.json")); - ISerializer serializer = context.newSerializer(Format.JSON, clazz); - measureSerializer(obj, "JSON", out, serializer, iterations); - - IDeserializer deserializer = context.newDeserializer(Format.JSON, clazz); - deserializer.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS); - obj = measureDeserializer("JSON", out, deserializer, iterations); + { + IBindingContext context = new DefaultBindingContext(); + ISerializer serializer = context.newSerializer(Format.JSON, clazz); + measureSerializer(obj, "JSON", out, serializer, iterations); + } + { + IBindingContext context = new DefaultBindingContext(); + IDeserializer deserializer = context.newDeserializer(Format.JSON, clazz); + deserializer.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS); + obj = measureDeserializer("JSON", out, deserializer, iterations); + } } // YAML { Path out = ObjectUtils.notNull(tempDir.resolve("out.yaml")); - ISerializer serializer = context.newSerializer(Format.YAML, clazz); - measureSerializer(obj, "YAML", out, serializer, iterations); - - IDeserializer deserializer = context.newDeserializer(Format.YAML, clazz); - deserializer.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS); - measureDeserializer("YAML", out, deserializer, iterations); + { + IBindingContext context = new DefaultBindingContext(); + ISerializer serializer = context.newSerializer(Format.YAML, clazz); + measureSerializer(obj, "YAML", out, serializer, iterations); + } + { + IBindingContext context = new DefaultBindingContext(); + IDeserializer deserializer = context.newDeserializer(Format.YAML, clazz); + deserializer.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS); + measureDeserializer("YAML", out, deserializer, iterations); + } } } @@ -169,6 +198,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 38c602be..95ea0186 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,11 +31,11 @@ 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.model.common.metapath.DynamicContext; -import gov.nist.secauto.metaschema.model.common.metapath.StaticContext; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +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; @@ -73,7 +73,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"; @@ -85,7 +85,7 @@ class ProfileResolutionTests { @BeforeAll static void setup() throws SaxonApiException { - DynamicContext context = new StaticContext().newDynamicContext(); + DynamicContext context = new DynamicContext(OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); context.setDocumentLoader(new DefaultBoundLoader(OscalBindingContext.instance())); profileResolver = new ProfileResolver(); profileResolver.setDynamicContext(context); @@ -109,17 +109,17 @@ public static ProfileResolver getProfileResolver() { private static Catalog resolveProfile(@NonNull Path profileFile) throws FileNotFoundException, IOException, ProfileResolutionException { - return (Catalog) getProfileResolver().resolveProfile(profileFile).getValue(); + return (Catalog) INodeItem.toValue(getProfileResolver().resolve(profileFile)); } private static Catalog resolveProfile(@NonNull File profileFile) throws FileNotFoundException, IOException, ProfileResolutionException { - return (Catalog) getProfileResolver().resolveProfile(profileFile).getValue(); + return (Catalog) INodeItem.toValue(getProfileResolver().resolve(profileFile)); } private static Catalog resolveProfile(@NonNull URL profileUrl) throws IOException, ProfileResolutionException, URISyntaxException { - return (Catalog) getProfileResolver().resolveProfile(profileUrl).getValue(); + return (Catalog) INodeItem.toValue(getProfileResolver().resolve(profileUrl)); } /** @@ -182,7 +182,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 f3ed5b00..b2874122 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.model.common.IRootAssemblyDefinition; -import gov.nist.secauto.metaschema.model.common.metapath.item.DefaultNodeItemFactory; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly; import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.control.AbstractParameter; @@ -180,11 +179,10 @@ public static IDocumentNodeItem newImportedCatalog() { .build()) .build()); - return DefaultNodeItemFactory.instance().newDocumentNodeItem( - IRootAssemblyDefinition.toRootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class))), - importedCatalog, - ObjectUtils.notNull(Paths.get("").toUri())); + return INodeItemFactory.instance().newDocumentNodeItem( + ObjectUtils.requireNonNull( + (IBoundDefinitionModelAssembly) OscalBindingContext.instance().getBoundDefinitionForClass(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 a99b9aa5..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.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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; @@ -74,7 +74,9 @@ void test() throws IOException { OscalBindingContext.instance() .newSerializer(Format.YAML, Catalog.class) - .serialize(ObjectUtils.requireNonNull((Catalog) importedCatalogDocumentItem.getValue()), System.out); + .serialize( + (Catalog) INodeItem.toValue(importedCatalogDocumentItem), + System.out); } } diff --git a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionVisitorTest.java b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionVisitorTest.java index fdd0bc58..bc879c45 100644 --- a/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionVisitorTest.java +++ b/src/test/java/gov/nist/secauto/oscal/lib/profile/resolver/selection/ControlSelectionVisitorTest.java @@ -28,8 +28,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.CatalogGroup; import gov.nist.secauto.oscal.lib.model.Control; import gov.nist.secauto.oscal.lib.model.control.catalog.IControlContainer; 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 c294a587..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 @@ -29,7 +29,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.oscal.lib.model.Matching; import gov.nist.secauto.oscal.lib.model.control.catalog.IControl; import gov.nist.secauto.oscal.lib.model.control.profile.IProfileSelectControlById; @@ -157,7 +157,7 @@ private IControlSelectionFilter newMultipleSelectionFilter() { } /** - * Test the filtering of an empty set of match criteria + * Test the filtering of an empty set of match criteria. */ @Test @SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT") @@ -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 3240c060..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,8 +28,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import gov.nist.secauto.metaschema.binding.io.Format; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; +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; @@ -95,6 +96,8 @@ void test() throws IOException { selected); OscalBindingContext.instance().newSerializer(Format.YAML, Catalog.class) - .serialize((Catalog) importedCatalogDocumentItem.getValue(), System.out); + .serialize( + (Catalog) INodeItem.toValue(importedCatalogDocumentItem), + System.out); } } 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 dbc6da5a..fd884d3c 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,15 @@ package gov.nist.secauto.oscal.lib.profile.resolver.selection; -import gov.nist.secauto.metaschema.binding.model.IAssemblyClassBinding; -import gov.nist.secauto.metaschema.model.common.IRootAssemblyDefinition; -import gov.nist.secauto.metaschema.model.common.metapath.item.DefaultNodeItemFactory; -import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem; -import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem; -import gov.nist.secauto.metaschema.model.common.util.CollectionUtil; -import gov.nist.secauto.metaschema.model.common.util.ObjectUtils; +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.util.CollectionUtil; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly; import gov.nist.secauto.oscal.lib.OscalBindingContext; +import gov.nist.secauto.oscal.lib.OscalModelConstants; import gov.nist.secauto.oscal.lib.model.Catalog; import gov.nist.secauto.oscal.lib.model.IncludeAll; import gov.nist.secauto.oscal.lib.model.Profile; @@ -65,12 +66,11 @@ private static IDocumentNodeItem newImportedCatalog() { .title("Control 2") .build()); - return DefaultNodeItemFactory.instance().newDocumentNodeItem( - IRootAssemblyDefinition.toRootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Catalog.class))), - importedCatalog, - ObjectUtils.notNull(Paths.get("").toUri())); + return INodeItemFactory.instance().newDocumentNodeItem( + ObjectUtils.requireNonNull( + (IBoundDefinitionModelAssembly) OscalBindingContext.instance().getBoundDefinitionForClass(Catalog.class)), + ObjectUtils.notNull(Paths.get("").toUri()), + importedCatalog); } @SuppressWarnings("null") @@ -78,12 +78,6 @@ private static IDocumentNodeItem newImportedCatalog() { void test() throws ProfileResolutionException { URI cwd = Paths.get("").toUri(); - // 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( @@ -91,25 +85,34 @@ void test() throws ProfileResolutionException { .withId("control1") .build())); profileImport.setHref(cwd); + + // setup the profile + Profile profile = new Profile(); + profile.addImport(profileImport); - IDocumentNodeItem profileDocumentItem = DefaultNodeItemFactory.instance().newDocumentNodeItem( - IRootAssemblyDefinition.toRootAssemblyDefinition( - ObjectUtils.notNull( - (IAssemblyClassBinding) OscalBindingContext.instance().getClassBinding(Profile.class))), - profile, - cwd); + IDocumentNodeItem profileDocumentItem = INodeItemFactory.instance().newDocumentNodeItem( + ObjectUtils.requireNonNull( + (IBoundDefinitionModelAssembly) OscalBindingContext.instance().getBoundDefinitionForClass(Profile.class)), + cwd, + profile); + // setup the imported catalog + IDocumentNodeItem importedCatalogDocumentItem = newImportedCatalog(); // setup the resolved catalog Catalog resolvedCatalog = new Catalog(); + for (IRootAssemblyNodeItem profileRootItem : CollectionUtil + .toIterable(profileDocumentItem.getModelItemsByName(OscalModelConstants.QNAME_PROFILE).stream() + .map(rootItem -> (IRootAssemblyNodeItem) rootItem))) { + for (IAssemblyNodeItem importItem : CollectionUtil.toIterable( + profileRootItem.getModelItemsByName(OscalModelConstants.QNAME_IMPORT).stream() + .map(item -> (IAssemblyNodeItem) item))) { - for (IRequiredValueModelNodeItem importItem : CollectionUtil.toIterable( - profileDocumentItem.getModelItemsByName("profile").stream() - .flatMap(root -> root.getModelItemsByName("import").stream()))) { + Import catalogImport = new Import(profileRootItem, importItem); + catalogImport.resolve(importedCatalogDocumentItem, resolvedCatalog); + } - Import catalogImport = new Import(profileDocumentItem, importItem); - catalogImport.resolve(importedCatalogDocumentItem, resolvedCatalog); } - } + } } diff --git a/src/test/resources/log4j2-test.xml b/src/test/resources/log4j2-test.xml index ed84e7c9..e347850b 100644 --- a/src/test/resources/log4j2-test.xml +++ b/src/test/resources/log4j2-test.xml @@ -13,14 +13,14 @@ - + - + - + diff --git a/src/test/resources/profile-test-helper.xsl b/src/test/resources/profile-test-helper.xsl new file mode 100644 index 00000000..ae3e0a26 --- /dev/null +++ b/src/test/resources/profile-test-helper.xsl @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ... + + + + ... + + + + + + ... + + + + ... + + + + + + + + + + \ No newline at end of file