Skip to content

Commit 8fdc495

Browse files
Refactor meta-constraints context handling (#400)
* Cleaned up context processing for meta-constraints. Ensuing the constraint static context is used instead of the module static context. * Added debug hook. * Added module QName to the module item's signature. * Added module QName to the module item's signature. * Ensure imported modules are also registered when an module is registered.
1 parent 5d519af commit 8fdc495

File tree

6 files changed

+32
-25
lines changed

6 files changed

+32
-25
lines changed

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/ModuleNodeItemImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,6 @@ public String stringValue() {
5555

5656
@Override
5757
protected String getValueSignature() {
58-
return null;
58+
return getModule().getLocationHint();
5959
}
6060
}

core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ExternalConstraintsModulePostProcessor.java

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55

66
package gov.nist.secauto.metaschema.core.model.constraint;
77

8-
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
9-
import gov.nist.secauto.metaschema.core.metapath.StaticContext;
108
import gov.nist.secauto.metaschema.core.metapath.item.node.IModuleNodeItem;
119
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory;
1210
import gov.nist.secauto.metaschema.core.model.IModule;
@@ -61,22 +59,16 @@ public void processModule(IModule module) {
6159
ConstraintComposingVisitor visitor = new ConstraintComposingVisitor();
6260
IModuleNodeItem moduleItem = INodeItemFactory.instance().newModuleNodeItem(module);
6361

64-
StaticContext staticContext = StaticContext.builder()
65-
.defaultModelNamespace(module.getXmlNamespace())
66-
.build();
67-
DynamicContext dynamicContext = new DynamicContext(staticContext);
68-
6962
for (IConstraintSet set : getRegisteredConstraintSets()) {
7063
assert set != null;
71-
applyConstraintsForModule(moduleItem, set, visitor, dynamicContext);
64+
applyConstraintsForModule(moduleItem, set, visitor);
7265
}
7366
}
7467

7568
private static void applyConstraintsForModule(
7669
@NonNull IModuleNodeItem moduleItem,
7770
@NonNull IConstraintSet set,
78-
@NonNull ConstraintComposingVisitor visitor,
79-
@NonNull DynamicContext dynamicContext) {
80-
set.applyConstraintsForModule(moduleItem, dynamicContext, visitor);
71+
@NonNull ConstraintComposingVisitor visitor) {
72+
set.applyConstraintsForModule(moduleItem, visitor);
8173
}
8274
}

core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraintSet.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
package gov.nist.secauto.metaschema.core.model.constraint;
77

8-
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
98
import gov.nist.secauto.metaschema.core.metapath.item.node.IModuleNodeItem;
109
import gov.nist.secauto.metaschema.core.model.IModelElementVisitor;
1110
import gov.nist.secauto.metaschema.core.model.ISource;
@@ -37,13 +36,10 @@ public interface IConstraintSet {
3736
*
3837
* @param moduleItem
3938
* the module node item to apply applicable constraints to
40-
* @param dynamicContext
41-
* used to resolve Metapath targeting expressions
4239
* @param visitor
4340
* the visitor used to apply constraints to target definitions
4441
*/
4542
void applyConstraintsForModule(
4643
@NonNull IModuleNodeItem moduleItem,
47-
@NonNull DynamicContext dynamicContext,
4844
@NonNull IModelElementVisitor<ITargetedConstraints, Void> visitor);
4945
}

core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/MetaConstraintSet.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,14 @@ public Collection<? extends IConstraintSet> getImportedConstraintSets() {
5757
@Override
5858
public void applyConstraintsForModule(
5959
IModuleNodeItem moduleItem,
60-
DynamicContext dynamicContext,
6160
IModelElementVisitor<ITargetedConstraints, Void> visitor) {
61+
6262
for (IConstraintSet imported : imports) {
63-
imported.applyConstraintsForModule(moduleItem, dynamicContext, visitor);
63+
imported.applyConstraintsForModule(moduleItem, visitor);
6464
}
6565

66+
// generate a dynamic context using the external constraint set's static context
67+
DynamicContext dynamicContext = new DynamicContext(getSource().getStaticContext());
6668
for (Context context : contexts) {
6769
context.applyConstraintsForModule(moduleItem, dynamicContext, visitor, ISequence.of(moduleItem));
6870
}
@@ -142,26 +144,25 @@ void applyConstraintsForModule(
142144
@NonNull DynamicContext dynamicContext,
143145
@NonNull IModelElementVisitor<ITargetedConstraints, Void> visitor,
144146
@NonNull ISequence<? extends INodeItem> targetedItems) {
145-
Set<IDefinition> definitionConstraints = new HashSet<>();
147+
Set<IDefinition> targetedDefinitions = new HashSet<>();
146148

147149
for (INodeItem nodeItem : targetedItems) {
148150
for (IMetapathExpression metapath : metapaths) {
149151
ISequence<? extends IDefinitionNodeItem<?, ?>> items = ISequence.of(ObjectUtils.notNull(
150-
metapath.evaluate(nodeItem, dynamicContext).stream()
152+
evaluateItem(metapath, nodeItem, dynamicContext).stream()
151153
.filter(item -> filterNonDefinitionItem(item, metapath))
152154
.map(item -> (IDefinitionNodeItem<?, ?>) item)))
153155
.reusable();
154156
assert items != null;
155157
if (!items.isEmpty()) {
156158
// build a map to ensure the constraint is only applied once to each
157159
// underlying definition
158-
Set<IDefinition> targetedDefinitions = items.stream()
160+
items.stream()
159161
.map(IDefinitionNodeItem::getDefinition)
160162
// ensure the definition only gets processed if the module being processed is
161163
// the containing module
162164
.filter(definition -> definition.getContainingModule().equals(moduleItem.getModule()))
163-
.collect(Collectors.toUnmodifiableSet());
164-
definitionConstraints.addAll(targetedDefinitions);
165+
.forEach(definition -> targetedDefinitions.add(definition));
165166

166167
// process child contexts, which will be applied depth first
167168
for (Context context : childContexts) {
@@ -172,13 +173,20 @@ void applyConstraintsForModule(
172173
}
173174

174175
// apply the constraints for this context
175-
definitionConstraints.forEach(definition -> {
176+
targetedDefinitions.forEach(definition -> {
176177
getTargetedConstraints().forEach(constraints -> {
177178
definition.accept(visitor, constraints);
178179
});
179180
});
180181
}
181182

183+
private ISequence<?> evaluateItem(
184+
@NonNull IMetapathExpression metapath,
185+
@NonNull INodeItem nodeItem,
186+
@NonNull DynamicContext dynamicContext) {
187+
return metapath.evaluate(nodeItem, dynamicContext).reusable();
188+
}
189+
182190
private static boolean filterNonDefinitionItem(IItem item, @NonNull IMetapathExpression metapath) {
183191
boolean retval = item instanceof IDefinitionNodeItem;
184192
if (!retval) {

core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ScopedConstraintSet.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,14 @@ public Set<IConstraintSet> getImportedConstraintSets() {
101101
@Override
102102
public void applyConstraintsForModule(
103103
IModuleNodeItem moduleItem,
104-
DynamicContext dynamicContext,
105104
IModelElementVisitor<ITargetedConstraints, Void> visitor) {
106105
IEnhancedQName qname = moduleItem.getModule().getQName();
107106
List<IScopedContraints> scopes = getScopedContraints().getOrDefault(qname, CollectionUtil.emptyList());
108107

109108
Map<IDefinition, Set<ITargetedConstraints>> definitionConstraints = new HashMap<>();
110109

110+
DynamicContext dynamicContext = new DynamicContext(getSource().getStaticContext());
111+
111112
for (IScopedContraints scoped : scopes) {
112113
for (ITargetedConstraints targeted : scoped.getTargetedContraints()) {
113114
for (IMetapathExpression metapath : targeted.getTargets()) {

databind/src/main/java/gov/nist/secauto/metaschema/databind/DefaultBindingContext.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,19 @@ public IBindingModuleLoader newModuleLoader() {
117117
public final IBoundModule registerModule(@NonNull Class<? extends IBoundModule> clazz) {
118118
IModuleLoaderStrategy strategy = getModuleLoaderStrategy();
119119
IBoundModule module = strategy.loadModule(clazz, this);
120+
registerImportedModules(module);
120121
return strategy.registerModule(module, this);
121122
}
122123

124+
private void registerImportedModules(@NonNull IBoundModule module) {
125+
IModuleLoaderStrategy strategy = getModuleLoaderStrategy();
126+
module.getImportedModules().stream()
127+
.forEachOrdered(parentModule -> {
128+
registerImportedModules(ObjectUtils.notNull(parentModule));
129+
strategy.registerModule(ObjectUtils.notNull(parentModule), this);
130+
});
131+
}
132+
123133
/**
124134
* Get the binding matchers that are associated with this class.
125135
*

0 commit comments

Comments
 (0)