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/oscal b/oscal index f24dd56d..d19aedf7 160000 --- a/oscal +++ b/oscal @@ -1 +1 @@ -Subproject commit f24dd56d5569ade8489924cf6fc2640dc297bfbe +Subproject commit d19aedf7d0e0fba3b780d56c080312379127d7a4 diff --git a/pom.xml b/pom.xml index ee7e6e1d..b6fbacd6 100644 --- a/pom.xml +++ b/pom.xml @@ -131,9 +131,9 @@ 13.0.10.Final 23.0.0 2.12.0 - 2.22.0 + 2.23.1 12.3 - 4.7.3 + 4.8.3 5.2.0 4.6.0 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 8ad9a826..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,6 +26,7 @@ package gov.nist.secauto.oscal.lib; +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; @@ -44,15 +45,19 @@ 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 String NS_OSCAL = "http://csrc.nist.gov/ns/oscal/1.0"; + 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; } @@ -63,6 +68,8 @@ public static OscalBindingContext instance() { * @param modulePostProcessors * a list of module post processors to call after loading a module */ + @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); 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/metapath/function/library/HasOscalNamespace.java b/src/main/java/gov/nist/secauto/oscal/lib/metapath/function/library/HasOscalNamespace.java index b4ef4004..5621dcfc 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 @@ -28,6 +28,7 @@ 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; @@ -43,19 +44,23 @@ 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.OscalBindingContext; +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") - .namespace(OscalBindingContext.NS_OSCAL) + .namespace(OscalModelConstants.NS_OSCAL) .argument(IArgument.builder() .name("namespace") .type(IStringItem.class) @@ -73,7 +78,48 @@ public final class HasOscalNamespace { @NonNull static final IFunction SIGNATURE_TWO_ARGS = IFunction.builder() .name("has-oscal-namespace") - .namespace(OscalBindingContext.NS_OSCAL) + .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(IAssemblyNodeItem.class) @@ -139,7 +185,7 @@ public static ISequence executeTwoArg( ObjectUtils.notNull(arguments.get(0))); // always not null, since the first item is required - IAssemblyNodeItem node = FunctionUtils.requireFirstItem(nodeSequence, true); + IAssemblyNodeItem node = FunctionUtils.asType(ObjectUtils.requireNonNull(nodeSequence.getFirstItem(true))); return ISequence.of(hasNamespace(node, namespaceArgs)); } @@ -156,11 +202,11 @@ public static IBooleanItem hasNamespace( URI nodeNamespace = null; // get the "ns" flag value - IFlagNodeItem ns = propOrPart.getFlagByName("ns"); + 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"); + IFlagInstance flag = definition.getFlagInstanceByName(NS_FLAG_QNAME); if (flag == null) { throw new MetapathException( String.format( @@ -180,7 +226,7 @@ public static IBooleanItem hasNamespace( } 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 009510f6..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 @@ -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 5a2604e2..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 @@ -28,6 +28,7 @@ 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; @@ -36,7 +37,7 @@ import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; -import gov.nist.secauto.oscal.lib.OscalBindingContext; +import gov.nist.secauto.oscal.lib.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; @@ -51,7 +52,7 @@ public final class ResolveProfile { @NonNull static final IFunction SIGNATURE_NO_ARG = IFunction.builder() .name("resolve-profile") - .namespace(OscalBindingContext.NS_OSCAL) + .namespace(OscalModelConstants.NS_OSCAL) .returnType(INodeItem.class) .focusDependent() .contextDependent() @@ -63,7 +64,36 @@ public final class ResolveProfile { @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name("resolve-profile") - .namespace(OscalBindingContext.NS_OSCAL) + .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) @@ -109,7 +139,7 @@ public static ISequence executeOneArg( 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(); } 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 efe45bec..c74a619a 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 @@ -46,6 +46,7 @@ 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; @@ -93,30 +94,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("modify/set-parameter"); + = MetapathExpression.compile("modify/set-parameter", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); @NonNull private static final MetapathExpression METAPATH_ALTER - = MetapathExpression.compile("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)"); + = MetapathExpression.compile("/(catalog|profile)", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); @NonNull private static final MetapathExpression CATALOG - = MetapathExpression.compile("/catalog"); + = MetapathExpression.compile("/catalog", + OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); public enum StructuringDirective { FLAT, @@ -156,7 +168,9 @@ public void setBoundLoader(@NonNull IBoundLoader loader) { public DynamicContext getDynamicContext() { synchronized (this) { if (dynamicContext == null) { - dynamicContext = StaticContext.builder().build().dynamicContext(); + dynamicContext = new DynamicContext(StaticContext.builder() + .defaultModelNamespace(OscalModelConstants.NS_URI_OSCAL) + .build()); dynamicContext.setDocumentLoader(getBoundLoader()); } assert dynamicContext != null; @@ -176,7 +190,7 @@ private static IRootAssemblyNodeItem getRoot( @NonNull IDocumentNodeItem document, @NonNull MetapathExpression rootPath) { ISequence result = rootPath.evaluate(document); - IItem item = FunctionUtils.getFirstItem(result, false); + IItem item = result.getFirstItem(false); return item == null ? null : FunctionUtils.asType(item); } @@ -319,7 +333,7 @@ private IIndexer resolveImports( // first verify there is at least one import @SuppressWarnings("unchecked") List profileImports - = (List) profileItem.getModelItemsByName("import"); + = (List) profileItem.getModelItemsByName(IMPORT_QNAME); if (profileImports.isEmpty()) { throw new ProfileResolutionException(String.format("Profile '%s' has no imports", profileItem.getBaseUri())); } @@ -466,7 +480,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(" -> ", " -> ", "")))); } } 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 c61faacd..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 @@ -52,15 +52,19 @@ 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))); } @@ -206,7 +210,7 @@ private static void handlePartSelection( @NonNull IAssemblyNodeItem groupOrControlItem, @NonNull IIndexer index, @NonNull SelectionStatus selectionStatus) { - CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream() + CHILD_PART_METAPATH.evaluate(groupOrControlItem).stream() .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(partItem -> { index.setSelectionStatus(ObjectUtils.requireNonNull(partItem), selectionStatus); @@ -226,6 +230,7 @@ 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; } 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 55e08dd6..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 @@ -41,6 +41,8 @@ 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; @@ -71,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); @@ -81,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(); @@ -131,11 +139,12 @@ 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() { + private ReferenceCountingVisitor() { // visit everything except parts, roles, locations, parties, parameters, and // resources, which are // handled differently by this visitor @@ -272,7 +281,7 @@ protected void visitParts( IAssemblyNodeItem groupOrControlItem, Context context) { // visits all descendant parts - CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream() + CHILD_PART_METAPATH.evaluate(groupOrControlItem).stream() .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(partItem -> { visitPart(ObjectUtils.notNull(partItem), groupOrControlItem, context); @@ -315,11 +324,11 @@ protected void resolveGroup( if (IIndexer.SelectionStatus.SELECTED.equals(context.getIndexer().getSelectionStatus(item))) { // process children - item.getModelItemsByName("title") + item.getModelItemsByName(OscalModelConstants.QNAME_TITLE) .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); - item.getModelItemsByName("prop") + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - item.getModelItemsByName("link") + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); // always visit parts @@ -333,11 +342,11 @@ protected void resolveControl( @NonNull IAssemblyNodeItem item, @NonNull Context context) { // process non-control, non-param children - item.getModelItemsByName("title") + item.getModelItemsByName(OscalModelConstants.QNAME_TITLE) .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); - item.getModelItemsByName("prop") + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - item.getModelItemsByName("link") + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); // always visit parts @@ -348,76 +357,76 @@ protected void resolveControl( private static void resolveRole(@NonNull IEntityItem entity, @NonNull Context context) { IModelNodeItem item = entity.getInstance(); - item.getModelItemsByName("prop") + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - item.getModelItemsByName("link") + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - ROLE_MARKUP_METAPATH.evaluate(item).asList() + ROLE_MARKUP_METAPATH.evaluate(item).getValue() .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); } private static void resolveParty(@NonNull IEntityItem entity, @NonNull Context context) { IModelNodeItem item = entity.getInstance(); - item.getModelItemsByName("prop") + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - item.getModelItemsByName("link") + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - PARTY_MARKUP_METAPATH.evaluate(item).asList() + PARTY_MARKUP_METAPATH.evaluate(item).getValue() .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); } public static void resolveLocation(@NonNull IEntityItem entity, @NonNull Context context) { IModelNodeItem item = entity.getInstance(); - item.getModelItemsByName("prop") + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - item.getModelItemsByName("link") + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - LOCATION_MARKUP_METAPATH.evaluate(item).asList() + LOCATION_MARKUP_METAPATH.evaluate(item).getValue() .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); } public static void resolveResource(@NonNull IEntityItem entity, @NonNull Context context) { IModelNodeItem item = entity.getInstance(); - item.getModelItemsByName("prop") + 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") + child.getModelItemsByName(OscalModelConstants.QNAME_TEXT) .forEach(citationChild -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) citationChild), context)); - child.getModelItemsByName("prop") + child.getModelItemsByName(OscalModelConstants.QNAME_PROP) .forEach(citationChild -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) citationChild), context)); - child.getModelItemsByName("link") + child.getModelItemsByName(OscalModelConstants.QNAME_LINK) .forEach(citationChild -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) citationChild), context)); } }); - RESOURCE_MARKUP_METAPATH.evaluate(item).asList() + RESOURCE_MARKUP_METAPATH.evaluate(item).getValue() .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); } public static void resolveParameter(@NonNull IEntityItem entity, @NonNull Context context) { IModelNodeItem item = entity.getInstance(); - item.getModelItemsByName("prop") + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - item.getModelItemsByName("link") + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - PARAM_MARKUP_METAPATH.evaluate(item).asList() + PARAM_MARKUP_METAPATH.evaluate(item).getValue() .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); } private static void resolvePart( @NonNull IAssemblyNodeItem item, @NonNull Context context) { - item.getModelItemsByName("title") + item.getModelItemsByName(OscalModelConstants.QNAME_TITLE) .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); - item.getModelItemsByName("prop") + item.getModelItemsByName(OscalModelConstants.QNAME_PROP) .forEach(child -> handleProperty(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - item.getModelItemsByName("link") + item.getModelItemsByName(OscalModelConstants.QNAME_LINK) .forEach(child -> handleLink(ObjectUtils.notNull((IAssemblyNodeItem) child), context)); - item.getModelItemsByName("prose") + item.getModelItemsByName(OscalModelConstants.QNAME_PROSE) .forEach(child -> handleMarkup(ObjectUtils.notNull((IFieldNodeItem) child), context)); // item.getModelItemsByName("part").forEach(child -> // visitor.visitPart(ObjectUtils.notNull(child), 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 96b4d225..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 @@ -31,6 +31,7 @@ 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,7 +45,9 @@ 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; @@ -103,7 +106,7 @@ protected SelectionState getSelectionState(@NonNull IModelNodeItem item) { } 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((IModelNodeItem) ObjectUtils.requireNonNull(child)).isSelected(); }) 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 5a82944b..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 @@ -43,6 +43,7 @@ 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. @@ -66,16 +67,21 @@ * 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(); @@ -145,7 +151,7 @@ private void handlePartSelection( SelectionStatus selectionStatus = selected ? SelectionStatus.SELECTED : SelectionStatus.UNSELECTED; IIndexer index = getIndexer(state); - CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream() + CHILD_PART_METAPATH.evaluate(groupOrControlItem).stream() .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(partItem -> { index.setSelectionStatus(ObjectUtils.requireNonNull(partItem), selectionStatus); 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 2486b934..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 @@ -30,6 +30,7 @@ import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.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)); @@ -79,14 +85,14 @@ public void visitCatalog(@NonNull IDocumentNodeItem catalogItem, @NonNull IIndex result.applyTo(catalog); catalogItem.modelItems().forEachOrdered(root -> { - root.getModelItemsByName("metadata").stream() + root.getModelItemsByName(OscalModelConstants.QNAME_METADATA).stream() .map(child -> (IAssemblyNodeItem) child) .forEachOrdered(child -> { assert child != null; visitMetadata(child, context); }); - root.getModelItemsByName("back-matter").stream() + root.getModelItemsByName(OscalModelConstants.QNAME_BACK_MATTER).stream() .map(child -> (IAssemblyNodeItem) child) .forEachOrdered(child -> { assert child != null; @@ -232,7 +238,7 @@ public DefaultResult visitControl( protected static void removePartsFromIndex(@NonNull IAssemblyNodeItem groupOrControlItem, @NonNull IIndexer index) { - CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream() + CHILD_PART_METAPATH.evaluate(groupOrControlItem).stream() .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(partItem -> { ControlPart part = ObjectUtils.requireNonNull((ControlPart) partItem.getValue()); 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 d8834b2c..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 @@ -32,6 +32,8 @@ 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; @@ -54,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( @@ -127,15 +131,13 @@ protected R visitControlContainer(IAssemblyNodeItem catalogOrGroupOrControl, R i // handle parameters if (isVisitedItemType(IEntityItem.ItemType.PARAMETER)) { - retval = catalogOrGroupOrControl.getModelItemsByName("param").stream() - .map(paramItem -> { - return visitParameter( - ObjectUtils.requireNonNull((IAssemblyNodeItem) 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; } @@ -143,7 +145,7 @@ protected R visitControlContainer(IAssemblyNodeItem catalogOrGroupOrControl, R i protected void visitParts(@NonNull IAssemblyNodeItem groupOrControlItem, T state) { // handle parts if (isVisitedItemType(IEntityItem.ItemType.PART)) { - CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream() + CHILD_PART_METAPATH.evaluate(groupOrControlItem).stream() .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(partItem -> { visitPart(ObjectUtils.requireNonNull(partItem), groupOrControlItem, state); @@ -230,11 +232,11 @@ protected void visitPart( // NOPMD noop default * the calling context information */ protected void visitMetadata(@NonNull IRootAssemblyNodeItem rootItem, T state) { - rootItem.getModelItemsByName("metadata").stream() + rootItem.getModelItemsByName(OscalModelConstants.QNAME_METADATA).stream() .map(metadataItem -> (IAssemblyNodeItem) metadataItem) .forEach(metadataItem -> { if (isVisitedItemType(IEntityItem.ItemType.ROLE)) { - metadataItem.getModelItemsByName("role").stream() + metadataItem.getModelItemsByName(OscalModelConstants.QNAME_ROLE).stream() .map(roleItem -> (IAssemblyNodeItem) roleItem) .forEachOrdered(roleItem -> { visitRole(ObjectUtils.requireNonNull(roleItem), metadataItem, state); @@ -242,7 +244,7 @@ protected void visitMetadata(@NonNull IRootAssemblyNodeItem rootItem, T state) { } if (isVisitedItemType(IEntityItem.ItemType.LOCATION)) { - metadataItem.getModelItemsByName("location").stream() + metadataItem.getModelItemsByName(OscalModelConstants.QNAME_LOCATION).stream() .map(locationItem -> (IAssemblyNodeItem) locationItem) .forEachOrdered(locationItem -> { visitLocation(ObjectUtils.requireNonNull(locationItem), metadataItem, state); @@ -250,7 +252,7 @@ protected void visitMetadata(@NonNull IRootAssemblyNodeItem rootItem, T state) { } if (isVisitedItemType(IEntityItem.ItemType.PARTY)) { - metadataItem.getModelItemsByName("party").stream() + metadataItem.getModelItemsByName(OscalModelConstants.QNAME_PARTY).stream() .map(partyItem -> (IAssemblyNodeItem) partyItem) .forEachOrdered(partyItem -> { visitParty(ObjectUtils.requireNonNull(partyItem), metadataItem, state); @@ -333,7 +335,7 @@ protected void visitParty( // NOPMD noop default */ protected void visitBackMatter(@NonNull IRootAssemblyNodeItem rootItem, T state) { if (isVisitedItemType(IEntityItem.ItemType.RESOURCE)) { - BACK_MATTER_RESOURCES_METAPATH.evaluate(rootItem).asStream() + BACK_MATTER_RESOURCES_METAPATH.evaluate(rootItem).stream() .map(item -> (IAssemblyNodeItem) item) .forEachOrdered(resourceItem -> { visitResource(ObjectUtils.requireNonNull(resourceItem), rootItem, state); 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 142a0518..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 @@ -29,6 +29,7 @@ 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; @@ -72,7 +73,7 @@ protected R visitGroupContainer( @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((IAssemblyNodeItem) groupItem), @@ -132,7 +133,7 @@ protected R visitControlContainer( @NonNull IAssemblyNodeItem catalogOrGroupOrControl, R initialResult, T state) { - return catalogOrGroupOrControl.getModelItemsByName("control").stream() + return catalogOrGroupOrControl.getModelItemsByName(OscalModelConstants.QNAME_CONTROL).stream() .map(control -> { return visitControlItem(ObjectUtils.requireNonNull((IAssemblyNodeItem) control), state); }) 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 420cb976..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 @@ -33,6 +33,7 @@ import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.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; 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 9758c109..7fd9bfa6 100644 --- a/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/IIndexer.java +++ b/src/main/java/gov/nist/secauto/oscal/lib/profile/resolver/support/IIndexer.java @@ -32,6 +32,7 @@ import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.CustomCollectors; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.oscal.lib.OscalBindingContext; import gov.nist.secauto.oscal.lib.model.metadata.IProperty; import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem.ItemType; @@ -58,8 +59,9 @@ enum SelectionStatus { UNKNOWN; } - MetapathExpression HAS_PROP_KEEP_METAPATH = MetapathExpression - .compile("prop[@name='keep' and has-oscal-namespace('" + IProperty.OSCAL_NAMESPACE + "')]/@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<>() { diff --git a/src/test/java/gov/nist/secauto/oscal/java/ExamplesTest.java b/src/test/java/gov/nist/secauto/oscal/java/ExamplesTest.java index 52062770..9b750a15 100644 --- a/src/test/java/gov/nist/secauto/oscal/java/ExamplesTest.java +++ b/src/test/java/gov/nist/secauto/oscal/java/ExamplesTest.java @@ -93,7 +93,9 @@ void testConstraintValidation() 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 = StaticContext.instance().dynamicContext(); + DynamicContext dynamicContext = new DynamicContext(StaticContext.builder() + .defaultModelNamespace(nodeItem.getNamespace()) + .build()); dynamicContext.setDocumentLoader(loader); FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler(); DefaultConstraintValidator validator = new DefaultConstraintValidator(handler); 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 a8f0334f..80b6dbaf 100644 --- a/src/test/java/gov/nist/secauto/oscal/java/MetaschemaVisitorTest.java +++ b/src/test/java/gov/nist/secauto/oscal/java/MetaschemaVisitorTest.java @@ -59,10 +59,10 @@ void test() throws FileNotFoundException, IOException, URISyntaxException { IBoundLoader loader = bindingContext.newBoundLoader(); URI baseUri = ObjectUtils.notNull(new File("").getAbsoluteFile().toURI()); - StaticContext staticContext = StaticContext.builder() + StaticContext staticContext = OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT.buildFrom() .baseUri(baseUri) .build(); - DynamicContext dynamicContext = staticContext.dynamicContext(); + DynamicContext dynamicContext = new DynamicContext(staticContext); dynamicContext.setDocumentLoader(loader); // File file = new @@ -76,7 +76,7 @@ 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); // OscalBindingContext.instance().newSerializer(Format.XML, // Catalog.class).serialize(resolvedProfile.toBoundObject(), new FileWriter(new @@ -128,7 +128,7 @@ private static void evaluatePath(@NonNull MetapathExpression path, @NonNull IIte 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/ReadWriteTest.java b/src/test/java/gov/nist/secauto/oscal/java/ReadWriteTest.java index 25de2ab5..5d247dc1 100644 --- a/src/test/java/gov/nist/secauto/oscal/java/ReadWriteTest.java +++ b/src/test/java/gov/nist/secauto/oscal/java/ReadWriteTest.java @@ -51,7 +51,9 @@ class ReadWriteTest { private static final Logger LOGGER = LogManager.getLogger(ReadWriteTest.class); - private static final int ITERATIONS = 10; + 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( @@ -78,13 +80,13 @@ private static CLASS measureDeserializer( LOGGER.info(String.format("%s read in %d milliseconds from %s", format, timeElapsed, file)); } - // allow for JVM warmup - if (iterations == 1 || i > 1) { + // skip initial executions, if possible, to allow for JVM warmup + if (i >= WARMUP_ITERATIONS) { totalTime += timeElapsed; ++totalIterations; } } - 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)); } @@ -100,6 +102,7 @@ private static void measureSerializer( @NonNull Path file, @NonNull ISerializer serializer, int iterations) throws IOException { + long totalTime = 0; int totalIterations = 0; for (int i = 0; i < iterations; i++) { @@ -111,14 +114,14 @@ private static void measureSerializer( LOGGER.info(String.format("%s written in %d milliseconds to %s", format, timeElapsed, file)); } - // allow for JVM warmup - if (iterations == 1 || i > 1) { + // skip initial executions, if possible, to allow for JVM warmup + if (i >= WARMUP_ITERATIONS) { totalTime += timeElapsed; ++totalIterations; } } - 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)); } 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 bb27e8b6..f9f075ea 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 @@ -86,7 +86,7 @@ class ProfileResolutionTests { @BeforeAll static void setup() throws SaxonApiException { - DynamicContext context = StaticContext.instance().dynamicContext(); + DynamicContext context = new DynamicContext(OscalBindingContext.OSCAL_STATIC_METAPATH_CONTEXT); context.setDocumentLoader(new DefaultBoundLoader(OscalBindingContext.instance())); profileResolver = new ProfileResolver(); profileResolver.setDynamicContext(context); 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 41b39296..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 @@ -34,6 +34,7 @@ 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; @@ -77,9 +78,6 @@ private static IDocumentNodeItem newImportedCatalog() { void test() throws ProfileResolutionException { URI cwd = Paths.get("").toUri(); - // setup the imported catalog - IDocumentNodeItem importedCatalogDocumentItem = newImportedCatalog(); - ProfileImport profileImport = new ProfileImport(); profileImport.setIncludeAll(new IncludeAll()); profileImport.setExcludeControls(Collections.singletonList( @@ -98,14 +96,16 @@ void test() throws ProfileResolutionException { (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("profile").stream() + .toIterable(profileDocumentItem.getModelItemsByName(OscalModelConstants.QNAME_PROFILE).stream() .map(rootItem -> (IRootAssemblyNodeItem) rootItem))) { for (IAssemblyNodeItem importItem : CollectionUtil.toIterable( - profileRootItem.getModelItemsByName("import").stream() + profileRootItem.getModelItemsByName(OscalModelConstants.QNAME_IMPORT).stream() .map(item -> (IAssemblyNodeItem) item))) { Import catalogImport = new Import(profileRootItem, importItem);