diff --git a/core/src/main/antlr4/Metapath10.g4 b/core/src/main/antlr4/Metapath10.g4
index ecfb5f43d..1b25cc13f 100644
--- a/core/src/main/antlr4/Metapath10.g4
+++ b/core/src/main/antlr4/Metapath10.g4
@@ -148,7 +148,7 @@ parenthesizeditemtype : OP itemtype CP ;
// Error in the spec. EQName also includes acceptable keywords.
-eqname : NCName | QName | URIQualifiedName
+eqname : URIQualifiedName | NCName | QName
| KW_ANCESTOR
| KW_ANCESTOR_OR_SELF
| KW_AND
diff --git a/core/src/main/antlr4/Metapath10Lexer.g4 b/core/src/main/antlr4/Metapath10Lexer.g4
index 43ebf1b40..879194d59 100644
--- a/core/src/main/antlr4/Metapath10Lexer.g4
+++ b/core/src/main/antlr4/Metapath10Lexer.g4
@@ -117,7 +117,7 @@ DecimalLiteral : '.' FragDigits | FragDigits '.' [0-9]*;
DoubleLiteral : ('.' FragDigits | FragDigits ('.' [0-9]*)?) [eE] [+-]? FragDigits;
StringLiteral : '"' (~["] | FragEscapeQuot)* '"' | '\'' (~['] | FragEscapeApos)* '\'';
URIQualifiedName : BracedURILiteral NCName;
-BracedURILiteral : 'Q' '{' [^{}]* '}';
+BracedURILiteral : 'Q' '{' ~[{}]* '}';
// Error in spec: EscapeQuot and EscapeApos are not terminals!
fragment FragEscapeQuot : '""';
fragment FragEscapeApos : '\'\'';
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMAssemblyNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMAssemblyNodeItem.java
index 09cf2017c..ee85de9d4 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMAssemblyNodeItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMAssemblyNodeItem.java
@@ -5,30 +5,54 @@
package gov.nist.secauto.metaschema.core.mdm;
+import gov.nist.secauto.metaschema.core.mdm.impl.DefinitionAssemblyNodeItem;
import gov.nist.secauto.metaschema.core.mdm.impl.IDMModelNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem;
import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
import gov.nist.secauto.metaschema.core.model.IAssemblyInstance;
import gov.nist.secauto.metaschema.core.model.IFieldInstance;
-import gov.nist.secauto.metaschema.core.model.IResourceLocation;
import edu.umd.cs.findbugs.annotations.NonNull;
/**
- * An assembly node item implementation that is backed by a simple Metaschema
- * module-based data model.
+ * Represents a Metapath assembly node item that is backed by a simple
+ * Metaschema module-based data model.
+ *
+ * The {@link #newInstance(IAssemblyDefinition, StaticContext)} method can be
+ * used to create a node from an {@link IAssemblyDefinition} that is orphaned
+ * from a document model.
+ *
+ * Child nodes can be created using the
+ * {@link #newFlag(gov.nist.secauto.metaschema.core.model.IFlagInstance, IAnyAtomicItem)},
+ * {@link #newAssembly(IAssemblyInstance)}, and
+ * {@link #newField(IFieldInstance, IAnyAtomicItem)} methods. These children are
+ * added to this assembly.
*/
public interface IDMAssemblyNodeItem
extends IAssemblyNodeItem, IDMModelNodeItem {
+ /**
+ * Create new assembly node item that is detached from a parent node item.
+ *
+ * @param definition
+ * the Metaschema field definition describing the assembly
+ * @param staticContext
+ * the atomic field value
+ * @return the new field node item
+ */
+ @NonNull
+ static IDMAssemblyNodeItem newInstance(
+ @NonNull IAssemblyDefinition definition,
+ @NonNull StaticContext staticContext) {
+ return new DefinitionAssemblyNodeItem(definition, staticContext);
+ }
+
/**
* Create and add a new field to the underlying data model.
*
* @param instance
* the Metaschema field instance describing the field
- * @param resourceLocation
- * information about the location of the field within the containing
- * resource
* @param value
* the atomic field value
* @return the new field node item
@@ -36,7 +60,6 @@ public interface IDMAssemblyNodeItem
@NonNull
IDMFieldNodeItem newField(
@NonNull IFieldInstance instance,
- @NonNull IResourceLocation resourceLocation,
@NonNull IAnyAtomicItem value);
/**
@@ -44,13 +67,9 @@ IDMFieldNodeItem newField(
*
* @param instance
* the Metaschema assembly instance describing the assembly
- * @param resourceLocation
- * information about the location of the assembly within the containing
- * resource
* @return the new assembly node item
*/
@NonNull
IDMAssemblyNodeItem newAssembly(
- @NonNull IAssemblyInstance instance,
- @NonNull IResourceLocation resourceLocation);
+ @NonNull IAssemblyInstance instance);
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMDocumentNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMDocumentNodeItem.java
index 275b5a341..3bd5fa672 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMDocumentNodeItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMDocumentNodeItem.java
@@ -5,18 +5,20 @@
package gov.nist.secauto.metaschema.core.mdm;
-import gov.nist.secauto.metaschema.core.mdm.impl.DocumentImpl;
+import gov.nist.secauto.metaschema.core.mdm.impl.DocumentNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
-import gov.nist.secauto.metaschema.core.model.IResourceLocation;
import java.net.URI;
import edu.umd.cs.findbugs.annotations.NonNull;
/**
- * A document node item implementation that is backed by a simple Metaschema
- * module-based data model.
+ * Represents a Metapath document node item that is backed by a simple
+ * Metaschema module-based data model.
+ *
+ * The {@link #newInstance(URI, IAssemblyDefinition)} method can be used to
+ * create a new document-based data model.
*/
public interface IDMDocumentNodeItem
extends IDocumentNodeItem {
@@ -28,21 +30,14 @@ public interface IDMDocumentNodeItem
*
* @param resource
* the base URI of the document resource
- * @param resourceLocation
- * information about the (intended) location of the document resource
* @param rootAssembly
* the assembly that is at the root of the node tree for this document
- * @param rootAssemblyLocation
- * information about the (intended) location of the root assembly
- * resource
* @return the document node item
*/
@NonNull
static IDMDocumentNodeItem newInstance(
@NonNull URI resource,
- @NonNull IResourceLocation resourceLocation,
- @NonNull IAssemblyDefinition rootAssembly,
- @NonNull IResourceLocation rootAssemblyLocation) {
- return new DocumentImpl(resource, resourceLocation, rootAssembly, rootAssemblyLocation);
+ @NonNull IAssemblyDefinition rootAssembly) {
+ return new DocumentNodeItem(resource, rootAssembly);
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMFieldNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMFieldNodeItem.java
index f26e3680f..504f407eb 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMFieldNodeItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMFieldNodeItem.java
@@ -5,16 +5,44 @@
package gov.nist.secauto.metaschema.core.mdm;
+import gov.nist.secauto.metaschema.core.mdm.impl.DefinitionFieldNodeItem;
import gov.nist.secauto.metaschema.core.mdm.impl.IDMModelNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.StaticContext;
+import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
+import gov.nist.secauto.metaschema.core.metapath.item.node.IAtomicValuedNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.IFieldNodeItem;
+import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
import gov.nist.secauto.metaschema.core.model.IFieldInstance;
+import edu.umd.cs.findbugs.annotations.NonNull;
+
/**
- * A field node item implementation that is backed by a simple Metaschema
+ * Represents a Metapath field node item that is backed by a simple Metaschema
* module-based data model.
+ *
+ * The {@link #newInstance(IFieldDefinition, IAnyAtomicItem, StaticContext)}
+ * method can be used to create a node from an {@link IAssemblyDefinition} that
+ * is orphaned from a document model.
*/
public interface IDMFieldNodeItem
- extends IFieldNodeItem, IDMModelNodeItem {
- // no additional methods
+ extends IFieldNodeItem, IDMModelNodeItem, IAtomicValuedNodeItem, IDMNodeItem {
+ /**
+ * Create new field node item that is detached from a parent node item.
+ *
+ * @param definition
+ * the Metaschema field definition describing the field
+ * @param value
+ * the field's initial value
+ * @param staticContext
+ * the atomic field value
+ * @return the new field node item
+ */
+ @NonNull
+ static IDMFieldNodeItem newInstance(
+ @NonNull IFieldDefinition definition,
+ @NonNull IAnyAtomicItem value,
+ @NonNull StaticContext staticContext) {
+ return new DefinitionFieldNodeItem(definition, value, staticContext);
+ }
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMFlagNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMFlagNodeItem.java
new file mode 100644
index 000000000..455ed5c60
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMFlagNodeItem.java
@@ -0,0 +1,17 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.mdm;
+
+import gov.nist.secauto.metaschema.core.metapath.item.node.IAtomicValuedNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.item.node.IFlagNodeItem;
+
+/**
+ * Represents a Metapath flag node item that is backed by a simple Metaschema
+ * module-based data model.
+ */
+public interface IDMFlagNodeItem extends IFlagNodeItem, IDMNodeItem, IAtomicValuedNodeItem {
+ // no additional methods
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMNodeItem.java
new file mode 100644
index 000000000..269fd4d2d
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMNodeItem.java
@@ -0,0 +1,26 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.mdm;
+
+import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
+import gov.nist.secauto.metaschema.core.model.IResourceLocation;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * Represents a Metapath node item that is backed by a simple Metaschema
+ * module-based data model.
+ */
+public interface IDMNodeItem extends INodeItem {
+ /**
+ * Provides a means to change the location information for the node item.
+ *
+ * @param location
+ * information about the location of the node within the containing
+ * resource
+ */
+ void setLocation(@NonNull IResourceLocation location);
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMRootAssemblyNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMRootAssemblyNodeItem.java
index 03cab04ce..13854b75a 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMRootAssemblyNodeItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/IDMRootAssemblyNodeItem.java
@@ -8,8 +8,8 @@
import gov.nist.secauto.metaschema.core.metapath.item.node.IRootAssemblyNodeItem;
/**
- * A root assembly node item implementation that is backed by a simple
- * Metaschema module-based data model.
+ * Represents a Metapath root assembly node item implementation that is backed
+ * by a simple Metaschema module-based data model.
*/
public interface IDMRootAssemblyNodeItem
extends IDMAssemblyNodeItem, IRootAssemblyNodeItem {
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMAssemblyNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMAssemblyNodeItem.java
index 6eda28488..7be95ecb6 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMAssemblyNodeItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMAssemblyNodeItem.java
@@ -8,12 +8,9 @@
import gov.nist.secauto.metaschema.core.mdm.IDMAssemblyNodeItem;
import gov.nist.secauto.metaschema.core.mdm.IDMFieldNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
-import gov.nist.secauto.metaschema.core.metapath.item.node.AbstractNodeItem;
-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.IAssemblyInstance;
import gov.nist.secauto.metaschema.core.model.IFieldInstance;
-import gov.nist.secauto.metaschema.core.model.IFlagInstance;
-import gov.nist.secauto.metaschema.core.model.IResourceLocation;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
@@ -27,22 +24,22 @@
import edu.umd.cs.findbugs.annotations.NonNull;
+/**
+ * This abstract Metapath assmebly node item implementation supports creating a
+ * Metaschema module-based data model.
+ */
public abstract class AbstractDMAssemblyNodeItem
- extends AbstractNodeItem
+ extends AbstractDMModelNodeItem
implements IDMAssemblyNodeItem {
@NonNull
- private final Map flags = new ConcurrentHashMap<>();
- @NonNull
private final Map>> modelItems
= new ConcurrentHashMap<>();
+ /**
+ * Construct a new node item.
+ */
protected AbstractDMAssemblyNodeItem() {
- // nothing to do
- }
-
- @Override
- public Object getValue() {
- return this;
+ // only allow extending classes to create instances
}
@Override
@@ -55,26 +52,6 @@ protected String getValueSignature() {
return "";
}
- @Override
- public Collection extends IFlagNodeItem> getFlags() {
- return ObjectUtils.notNull(flags.values());
- }
-
- @Override
- public IFlagNodeItem getFlagByName(IEnhancedQName name) {
- return flags.get(name);
- }
-
- @Override
- public IFlagNodeItem newFlag(
- @NonNull IFlagInstance instance,
- @NonNull IResourceLocation resourceLocation,
- @NonNull IAnyAtomicItem value) {
- IFlagNodeItem flag = new FlagImpl(instance, this, resourceLocation, value);
- flags.put(instance.getQName(), flag);
- return flag;
- }
-
@Override
public Collection>> getModelItems() {
return ObjectUtils.notNull(modelItems.values());
@@ -87,21 +64,21 @@ public IFlagNodeItem newFlag(
}
@Override
- public IDMFieldNodeItem newField(IFieldInstance instance, IResourceLocation resourceLocation, IAnyAtomicItem value) {
+ public IDMFieldNodeItem newField(IFieldInstance instance, IAnyAtomicItem value) {
List> result = modelItems.computeIfAbsent(
instance.getQName(),
- name -> Collections.synchronizedList(new LinkedList>()));
- IDMFieldNodeItem field = new FieldImpl(instance, this, resourceLocation, value);
+ name -> Collections.synchronizedList(new LinkedList<>()));
+ IDMFieldNodeItem field = new ChildFieldNodeItem(instance, this, value);
result.add(field);
return field;
}
@Override
- public IDMAssemblyNodeItem newAssembly(IAssemblyInstance instance, IResourceLocation resourceLocation) {
+ public IDMAssemblyNodeItem newAssembly(IAssemblyInstance instance) {
List> result = modelItems.computeIfAbsent(
instance.getQName(),
- name -> Collections.synchronizedList(new LinkedList>()));
- IDMAssemblyNodeItem assembly = new AssemblyImpl(instance, this, resourceLocation);
+ name -> Collections.synchronizedList(new LinkedList<>()));
+ IDMAssemblyNodeItem assembly = new ChildAssemblyNodeItem(instance, this);
result.add(assembly);
return assembly;
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/FieldImpl.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMFieldNodeItem.java
similarity index 50%
rename from core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/FieldImpl.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMFieldNodeItem.java
index 329efcfc9..6468b84b0 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/FieldImpl.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMFieldNodeItem.java
@@ -7,38 +7,35 @@
import gov.nist.secauto.metaschema.core.mdm.IDMFieldNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
-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.metapath.item.node.IModelNodeItem;
import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
import gov.nist.secauto.metaschema.core.model.IFieldInstance;
-import gov.nist.secauto.metaschema.core.model.IFlagInstance;
-import gov.nist.secauto.metaschema.core.model.IResourceLocation;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
-import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
import edu.umd.cs.findbugs.annotations.NonNull;
-public class FieldImpl
- extends AbstractDMInstanceNodeItem
+/**
+ * This abstract Metapath field node item implementation supports creating a
+ * Metaschema module-based data model.
+ */
+public abstract class AbstractDMFieldNodeItem
+ extends AbstractDMModelNodeItem
implements IDMFieldNodeItem {
@NonNull
private IAnyAtomicItem value;
- @NonNull
- private final Map flags = new ConcurrentHashMap<>();
- public FieldImpl(
- @NonNull IFieldInstance instance,
- @NonNull IAssemblyNodeItem parent,
- @NonNull IResourceLocation resourceLocation,
- @NonNull IAnyAtomicItem value) {
- super(instance, parent, resourceLocation);
+ /**
+ * Construct a new node item.
+ *
+ * @param value
+ * the initial field value
+ */
+ protected AbstractDMFieldNodeItem(@NonNull IAnyAtomicItem value) {
+ // only allow extending classes to create instances
this.value = value;
}
@@ -47,19 +44,29 @@ public IAnyAtomicItem toAtomicItem() {
return value;
}
+ /**
+ * Change the field's value to the provided value.
+ *
+ * @param value
+ * the new field value
+ */
public void setValue(@NonNull IAnyAtomicItem value) {
this.value = getValueItemType().cast(value);
}
+ /**
+ * Change the field's value to the provided value.
+ *
+ * This method expects the provided value to align with the object type
+ * supported by the underlying atomic type.
+ *
+ * @param value
+ * the new field value
+ */
public void setValue(@NonNull Object value) {
this.value = getValueItemType().newItem(value);
}
- @Override
- public Object getValue() {
- return toAtomicItem().getValue();
- }
-
@Override
public String stringValue() {
return toAtomicItem().asString();
@@ -70,21 +77,6 @@ protected String getValueSignature() {
return toAtomicItem().toSignature();
}
- @Override
- public int getPosition() {
- return getParentNodeItem().getModelItemsByName(getQName()).indexOf(this);
- }
-
- @Override
- public Collection extends IFlagNodeItem> getFlags() {
- return ObjectUtils.notNull(flags.values());
- }
-
- @Override
- public IFlagNodeItem getFlagByName(IEnhancedQName name) {
- return flags.get(name);
- }
-
@Override
public Collection extends List extends IModelNodeItem, ?>>> getModelItems() {
// no model items
@@ -97,13 +89,4 @@ public IFlagNodeItem getFlagByName(IEnhancedQName name) {
return CollectionUtil.emptyList();
}
- @Override
- public IFlagNodeItem newFlag(
- @NonNull IFlagInstance instance,
- @NonNull IResourceLocation resourceLocation,
- @NonNull IAnyAtomicItem value) {
- IFlagNodeItem flag = new FlagImpl(instance, this, resourceLocation, value);
- flags.put(instance.getQName(), flag);
- return flag;
- }
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMFlagNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMFlagNodeItem.java
new file mode 100644
index 000000000..7b8adca2d
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMFlagNodeItem.java
@@ -0,0 +1,91 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.mdm.impl;
+
+import gov.nist.secauto.metaschema.core.mdm.IDMFlagNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
+import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem;
+import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
+import gov.nist.secauto.metaschema.core.util.CollectionUtil;
+
+import java.util.Collection;
+import java.util.List;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * This abstract Metapath flag node item implementation supports creating a
+ * Metaschema module-based data model.
+ */
+public abstract class AbstractDMFlagNodeItem
+ extends AbstractDMNodeItem
+ implements IDMFlagNodeItem {
+ @NonNull
+ private IAnyAtomicItem value;
+
+ /**
+ * Construct a new node item.
+ *
+ * @param value
+ * the initial field value
+ */
+ protected AbstractDMFlagNodeItem(
+ @NonNull IAnyAtomicItem value) {
+ // only allow extending classes to create instances
+ this.value = value;
+ }
+
+ @Override
+ public IAnyAtomicItem toAtomicItem() {
+ return value;
+ }
+
+ /**
+ * Change the field's value to the provided value.
+ *
+ * @param value
+ * the new field value
+ */
+ public void setValue(@NonNull IAnyAtomicItem value) {
+ this.value = getValueItemType().cast(value);
+ }
+
+ /**
+ * Change the field's value to the provided value.
+ *
+ * This method expects the provided value to align with the object type
+ * supported by the underlying atomic type.
+ *
+ * @param value
+ * the new field value
+ */
+ public void setValue(@NonNull Object value) {
+ this.value = getValueItemType().newItem(value);
+ }
+
+ @Override
+ public String stringValue() {
+ return toAtomicItem().asString();
+ }
+
+ @Override
+ protected String getValueSignature() {
+ return toAtomicItem().toSignature();
+ }
+
+ @Override
+ public Collection extends List extends IModelNodeItem, ?>>> getModelItems() {
+ // no model items
+ return CollectionUtil.emptyList();
+ }
+
+ @Override
+ public List extends IModelNodeItem, ?>> getModelItemsByName(IEnhancedQName name) {
+ // no model items
+ return CollectionUtil.emptyList();
+ }
+
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMInstanceNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMInstanceNodeItem.java
deleted file mode 100644
index 6d372c501..000000000
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMInstanceNodeItem.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * SPDX-FileCopyrightText: none
- * SPDX-License-Identifier: CC0-1.0
- */
-
-package gov.nist.secauto.metaschema.core.mdm.impl;
-
-import gov.nist.secauto.metaschema.core.metapath.StaticContext;
-import gov.nist.secauto.metaschema.core.metapath.item.node.AbstractInstanceNodeItem;
-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.model.IDefinition;
-import gov.nist.secauto.metaschema.core.model.IModelDefinition;
-import gov.nist.secauto.metaschema.core.model.INamedInstance;
-import gov.nist.secauto.metaschema.core.model.IResourceLocation;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-
-public abstract class AbstractDMInstanceNodeItem<
- D extends IDefinition,
- I extends INamedInstance,
- P extends IModelNodeItem extends IModelDefinition, ? extends INamedInstance>>
- extends AbstractInstanceNodeItem
- implements INodeItem {
- @NonNull
- private final IResourceLocation resourceLocation;
-
- protected AbstractDMInstanceNodeItem(
- @NonNull I instance,
- @NonNull P parent,
- @NonNull IResourceLocation resourceLocation) {
- super(instance, parent);
- this.resourceLocation = resourceLocation;
- }
-
- @Override
- public IResourceLocation getLocation() {
- return resourceLocation;
- }
-
- @Override
- public StaticContext getStaticContext() {
- return getParentNodeItem().getStaticContext();
- }
-}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMModelNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMModelNodeItem.java
new file mode 100644
index 000000000..3c34dfcec
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMModelNodeItem.java
@@ -0,0 +1,67 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.mdm.impl;
+
+import gov.nist.secauto.metaschema.core.mdm.IDMFlagNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
+import gov.nist.secauto.metaschema.core.model.IFlagInstance;
+import gov.nist.secauto.metaschema.core.model.IModelDefinition;
+import gov.nist.secauto.metaschema.core.model.INamedModelInstance;
+import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * This abstract Metapath node item implementation supports creating a
+ * Metaschema module-based data model that supports child flags.
+ *
+ * @param
+ * the Java type of the definition associated with a Metaschema module
+ * @param
+ * the Java type of the instance associated with a Metaschema module
+ */
+public abstract class AbstractDMModelNodeItem
+ extends AbstractDMNodeItem
+ implements IDMModelNodeItem {
+ @NonNull
+ private final Map flags = new ConcurrentHashMap<>();
+
+ /**
+ * Construct a new node item.
+ */
+ protected AbstractDMModelNodeItem() {
+ // only allow extending classes to create instances
+ }
+
+ @Override
+ public Object getValue() {
+ return this;
+ }
+
+ @Override
+ public Collection extends IDMFlagNodeItem> getFlags() {
+ return ObjectUtils.notNull(flags.values());
+ }
+
+ @Override
+ public IDMFlagNodeItem getFlagByName(IEnhancedQName name) {
+ return flags.get(name);
+ }
+
+ @Override
+ public IDMFlagNodeItem newFlag(
+ @NonNull IFlagInstance instance,
+ @NonNull IAnyAtomicItem value) {
+ IDMFlagNodeItem flag = new ChildFlagNodeItem(instance, this, value);
+ flags.put(instance.getQName(), flag);
+ return flag;
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMNodeItem.java
new file mode 100644
index 000000000..8fd526db7
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AbstractDMNodeItem.java
@@ -0,0 +1,40 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.mdm.impl;
+
+import gov.nist.secauto.metaschema.core.mdm.IDMNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.item.node.AbstractNodeItem;
+import gov.nist.secauto.metaschema.core.model.IResourceLocation;
+
+import edu.umd.cs.findbugs.annotations.Nullable;
+
+/**
+ * This abstract Metapath assmebly node item implementation supports creating a
+ * Metaschema module-based data model.
+ */
+public abstract class AbstractDMNodeItem
+ extends AbstractNodeItem
+ implements IDMNodeItem {
+ @Nullable
+ private IResourceLocation resourceLocation; // null
+
+ /**
+ * Construct a new node item.
+ */
+ protected AbstractDMNodeItem() {
+ // only allow extending classes to create instances
+ }
+
+ @Override
+ public IResourceLocation getLocation() {
+ return resourceLocation;
+ }
+
+ @Override
+ public void setLocation(IResourceLocation location) {
+ this.resourceLocation = location;
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AssemblyImpl.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/ChildAssemblyNodeItem.java
similarity index 64%
rename from core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AssemblyImpl.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/ChildAssemblyNodeItem.java
index 7c4e047c7..a3725c7d3 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/AssemblyImpl.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/ChildAssemblyNodeItem.java
@@ -6,34 +6,36 @@
package gov.nist.secauto.metaschema.core.mdm.impl;
import gov.nist.secauto.metaschema.core.mdm.IDMAssemblyNodeItem;
-import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
import gov.nist.secauto.metaschema.core.model.IAssemblyInstance;
-import gov.nist.secauto.metaschema.core.model.IResourceLocation;
import edu.umd.cs.findbugs.annotations.NonNull;
-public class AssemblyImpl
- extends AbstractDMAssemblyNodeItem {
+/**
+ * A Metapath assembly node item that is the child of another assembly node
+ * item.
+ */
+public class ChildAssemblyNodeItem
+ extends AbstractDMAssemblyNodeItem
+ implements IFeatureChildNodeItem {
@NonNull
private final IAssemblyInstance instance;
@NonNull
private final IDMAssemblyNodeItem parent;
- @NonNull
- private final IResourceLocation resourceLocation;
- public AssemblyImpl(
+ /**
+ * Construct a new node item.
+ *
+ * @param instance
+ * the Metaschema module instance associated with this node
+ * @param parent
+ * the parent node item containing this node item
+ */
+ public ChildAssemblyNodeItem(
@NonNull IAssemblyInstance instance,
- @NonNull IDMAssemblyNodeItem parent,
- @NonNull IResourceLocation resourceLocation) {
+ @NonNull IDMAssemblyNodeItem parent) {
this.instance = instance;
this.parent = parent;
- this.resourceLocation = resourceLocation;
- }
-
- @Override
- public IResourceLocation getLocation() {
- return resourceLocation;
}
@Override
@@ -62,9 +64,4 @@ public IAssemblyDefinition getDefinition() {
public IAssemblyInstance getInstance() {
return instance;
}
-
- @Override
- public StaticContext getStaticContext() {
- return getParentNodeItem().getStaticContext();
- }
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/ChildFieldNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/ChildFieldNodeItem.java
new file mode 100644
index 000000000..2e585321a
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/ChildFieldNodeItem.java
@@ -0,0 +1,75 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.mdm.impl;
+
+import gov.nist.secauto.metaschema.core.mdm.IDMFieldNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
+import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem;
+import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
+import gov.nist.secauto.metaschema.core.model.IFieldInstance;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * A Metapath assembly node item that is the child of an assembly node item.
+ */
+public class ChildFieldNodeItem
+ extends AbstractDMFieldNodeItem
+ implements IDMFieldNodeItem, IFeatureChildNodeItem {
+ @NonNull
+ private final IFieldInstance instance;
+ @NonNull
+ private final IAssemblyNodeItem parent;
+
+ /**
+ * Construct a new node item.
+ *
+ * @param instance
+ * the Metaschema module instance associated with this node
+ * @param parent
+ * the parent node item containing this node item
+ * @param value
+ * the initial field value
+ */
+ public ChildFieldNodeItem(
+ @NonNull IFieldInstance instance,
+ @NonNull IAssemblyNodeItem parent,
+ @NonNull IAnyAtomicItem value) {
+ super(value);
+ this.instance = instance;
+ this.parent = parent;
+ }
+
+ @Override
+ public Object getValue() {
+ return this;
+ }
+
+ @Override
+ public int getPosition() {
+ return getParentNodeItem().getModelItemsByName(getQName()).indexOf(this);
+ }
+
+ @Override
+ public IAssemblyNodeItem getParentNodeItem() {
+ return parent;
+ }
+
+ @Override
+ public IAssemblyNodeItem getParentContentNodeItem() {
+ return getParentNodeItem();
+ }
+
+ @Override
+ public IFieldDefinition getDefinition() {
+ return instance.getDefinition();
+ }
+
+ @Override
+ public IFieldInstance getInstance() {
+ return instance;
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/ChildFlagNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/ChildFlagNodeItem.java
new file mode 100644
index 000000000..96f4e88eb
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/ChildFlagNodeItem.java
@@ -0,0 +1,64 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.mdm.impl;
+
+import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
+import gov.nist.secauto.metaschema.core.model.IFlagDefinition;
+import gov.nist.secauto.metaschema.core.model.IFlagInstance;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * A Metapath assembly node item that is the child of an assembly or field node
+ * item.
+ */
+public class ChildFlagNodeItem
+ extends AbstractDMFlagNodeItem
+ implements IFeatureChildNodeItem> {
+ @NonNull
+ private final IFlagInstance instance;
+ @NonNull
+ private final IDMModelNodeItem, ?> parent;
+
+ /**
+ * Construct a new node item.
+ *
+ * @param instance
+ * the Metaschema module instance associated with this node
+ * @param parent
+ * the parent node item containing this node item
+ * @param value
+ * the initial field value
+ */
+ public ChildFlagNodeItem(
+ @NonNull IFlagInstance instance,
+ @NonNull IDMModelNodeItem, ?> parent,
+ @NonNull IAnyAtomicItem value) {
+ super(value);
+ this.instance = instance;
+ this.parent = parent;
+ }
+
+ @Override
+ public IDMModelNodeItem, ?> getParentNodeItem() {
+ return parent;
+ }
+
+ @Override
+ public Object getValue() {
+ return this;
+ }
+
+ @Override
+ public IFlagDefinition getDefinition() {
+ return getInstance().getDefinition();
+ }
+
+ @Override
+ public IFlagInstance getInstance() {
+ return instance;
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DefinitionAssemblyNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DefinitionAssemblyNodeItem.java
new file mode 100644
index 000000000..365bf92f0
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DefinitionAssemblyNodeItem.java
@@ -0,0 +1,75 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.mdm.impl;
+
+import gov.nist.secauto.metaschema.core.metapath.StaticContext;
+import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
+import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
+import gov.nist.secauto.metaschema.core.model.IAssemblyInstance;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * A Metapath assembly node item that is orphaned from a document-based data
+ * model.
+ */
+public class DefinitionAssemblyNodeItem
+ extends AbstractDMAssemblyNodeItem {
+ @NonNull
+ private final IAssemblyDefinition definition;
+ @NonNull
+ private final StaticContext staticContext;
+
+ /**
+ * Construct a new node item.
+ *
+ * @param definition
+ * the Metaschema module definition associated with this node
+ * @param staticContext
+ * the static context to use when evaluating Metapath expressions
+ * against this node
+ */
+ public DefinitionAssemblyNodeItem(
+ @NonNull IAssemblyDefinition definition,
+ @NonNull StaticContext staticContext) {
+ this.definition = definition;
+ this.staticContext = staticContext;
+ }
+
+ @Override
+ public int getPosition() {
+ return 1;
+ }
+
+ @Override
+ public INodeItem getParentNodeItem() {
+ // always null
+ return null;
+ }
+
+ @Override
+ public IAssemblyNodeItem getParentContentNodeItem() {
+ // always null
+ return null;
+ }
+
+ @Override
+ public IAssemblyDefinition getDefinition() {
+ return definition;
+ }
+
+ @Override
+ public IAssemblyInstance getInstance() {
+ // always null
+ return null;
+ }
+
+ @Override
+ public StaticContext getStaticContext() {
+ return staticContext;
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DefinitionFieldNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DefinitionFieldNodeItem.java
new file mode 100644
index 000000000..94334e89e
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DefinitionFieldNodeItem.java
@@ -0,0 +1,79 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.mdm.impl;
+
+import gov.nist.secauto.metaschema.core.metapath.StaticContext;
+import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
+import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
+import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
+import gov.nist.secauto.metaschema.core.model.IFieldInstance;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * A Metapath field node item that is orphaned from a document-based data model.
+ */
+public class DefinitionFieldNodeItem
+ extends AbstractDMFieldNodeItem {
+ @NonNull
+ private final IFieldDefinition definition;
+ @NonNull
+ private final StaticContext staticContext;
+
+ /**
+ * Construct a new node item.
+ *
+ * @param definition
+ * the Metaschema module definition associated with this node
+ * @param value
+ * the initial field value
+ * @param staticContext
+ * the static context to use when evaluating Metapath expressions
+ * against this node
+ */
+ public DefinitionFieldNodeItem(
+ @NonNull IFieldDefinition definition,
+ @NonNull IAnyAtomicItem value,
+ @NonNull StaticContext staticContext) {
+ super(value);
+ this.definition = definition;
+ this.staticContext = staticContext;
+ }
+
+ @Override
+ public int getPosition() {
+ return 1;
+ }
+
+ @Override
+ public INodeItem getParentNodeItem() {
+ // always null
+ return null;
+ }
+
+ @Override
+ public IAssemblyNodeItem getParentContentNodeItem() {
+ // always null
+ return null;
+ }
+
+ @Override
+ public IFieldDefinition getDefinition() {
+ return definition;
+ }
+
+ @Override
+ public IFieldInstance getInstance() {
+ // always null
+ return null;
+ }
+
+ @Override
+ public StaticContext getStaticContext() {
+ return staticContext;
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DocumentImpl.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DocumentNodeItem.java
similarity index 70%
rename from core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DocumentImpl.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DocumentNodeItem.java
index 822233e9a..2fdfb4f1a 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DocumentImpl.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/DocumentNodeItem.java
@@ -12,7 +12,6 @@
import gov.nist.secauto.metaschema.core.metapath.item.node.IFlagNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem;
import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
-import gov.nist.secauto.metaschema.core.model.IResourceLocation;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
@@ -24,21 +23,30 @@
import edu.umd.cs.findbugs.annotations.NonNull;
-public class DocumentImpl implements IDMDocumentNodeItem {
+/**
+ * A Metapath document node item that is the top of a document-based data model.
+ */
+public class DocumentNodeItem
+ extends AbstractDMNodeItem
+ implements IDMDocumentNodeItem {
@NonNull
private final RootAssembly root;
@NonNull
- private final IResourceLocation resourceLocation;
- @NonNull
private final ISource source;
- public DocumentImpl(
+ /**
+ * Construct a new node item.
+ *
+ * @param resource
+ * the Metaschema module instance resource this document is from
+ * @param root
+ * the root Metaschema module assembly definition that represents the
+ * root node of this document
+ */
+ public DocumentNodeItem(
@NonNull URI resource,
- @NonNull IResourceLocation resourceLocation,
- @NonNull IAssemblyDefinition root,
- @NonNull IResourceLocation assemblyLocation) {
- this.root = new RootAssembly(root, assemblyLocation);
- this.resourceLocation = resourceLocation;
+ @NonNull IAssemblyDefinition root) {
+ this.root = new RootAssembly(root);
this.source = ISource.externalSource(resource);
}
@@ -71,11 +79,6 @@ public IFlagNodeItem getFlagByName(IEnhancedQName name) {
: CollectionUtil.emptyList();
}
- @Override
- public IResourceLocation getLocation() {
- return resourceLocation;
- }
-
@Override
public String stringValue() {
return "";
@@ -92,13 +95,8 @@ public Object getValue() {
}
@Override
- public String toSignature() {
- return ObjectUtils.notNull(new StringBuilder()
- .append(getType().toSignature())
- .append('\u2ABB')
- .append(getMetapath())
- .append('\u2ABC')
- .toString());
+ protected String getValueSignature() {
+ return null;
}
@Override
@@ -111,29 +109,20 @@ private class RootAssembly
implements IDMRootAssemblyNodeItem {
@NonNull
private final IAssemblyDefinition definition;
- @NonNull
- private final IResourceLocation resourceLocation;
public RootAssembly(
- @NonNull IAssemblyDefinition definition,
- @NonNull IResourceLocation location) {
+ @NonNull IAssemblyDefinition definition) {
this.definition = definition;
- this.resourceLocation = location;
}
@Override
public IEnhancedQName getQName() {
- return definition.getRootQName();
- }
-
- @Override
- public IResourceLocation getLocation() {
- return resourceLocation;
+ return ObjectUtils.requireNonNull(definition.getRootQName(), "the definition is expected to have a root QName.");
}
@Override
public IDocumentNodeItem getDocumentNodeItem() {
- return DocumentImpl.this;
+ return DocumentNodeItem.this;
}
@Override
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/FlagImpl.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/FlagImpl.java
deleted file mode 100644
index 1335777a3..000000000
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/FlagImpl.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SPDX-FileCopyrightText: none
- * SPDX-License-Identifier: CC0-1.0
- */
-
-package gov.nist.secauto.metaschema.core.mdm.impl;
-
-import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
-import gov.nist.secauto.metaschema.core.metapath.item.node.IFlagNodeItem;
-import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem;
-import gov.nist.secauto.metaschema.core.model.IFlagDefinition;
-import gov.nist.secauto.metaschema.core.model.IFlagInstance;
-import gov.nist.secauto.metaschema.core.model.IResourceLocation;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-
-public class FlagImpl
- extends AbstractDMInstanceNodeItem>
- implements IFlagNodeItem {
- @NonNull
- private IAnyAtomicItem value;
-
- public FlagImpl(
- @NonNull IFlagInstance instance,
- @NonNull IModelNodeItem, ?> parent,
- @NonNull IResourceLocation resourceLocation,
- @NonNull IAnyAtomicItem value) {
- super(instance, parent, resourceLocation);
- this.value = value;
- }
-
- @Override
- public IAnyAtomicItem toAtomicItem() {
- return value;
- }
-
- @Override
- public Object getValue() {
- return this;
- }
-
- @Override
- public String stringValue() {
- return toAtomicItem().asString();
- }
-
- @Override
- protected String getValueSignature() {
- return toAtomicItem().toSignature();
- }
-}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/IDMAtomicValuedNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/IDMAtomicValuedNodeItem.java
deleted file mode 100644
index 6fa3c2af8..000000000
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/IDMAtomicValuedNodeItem.java
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * SPDX-FileCopyrightText: none
- * SPDX-License-Identifier: CC0-1.0
- */
-
-package gov.nist.secauto.metaschema.core.mdm.impl;
-
-import gov.nist.secauto.metaschema.core.metapath.item.node.IAtomicValuedNodeItem;
-
-public interface IDMAtomicValuedNodeItem extends IAtomicValuedNodeItem {
- @Override
- default String stringValue() {
- return toAtomicItem().asString();
- }
-}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/IDMModelNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/IDMModelNodeItem.java
index f0df08fdc..96df47136 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/IDMModelNodeItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/IDMModelNodeItem.java
@@ -5,21 +5,46 @@
package gov.nist.secauto.metaschema.core.mdm.impl;
+import gov.nist.secauto.metaschema.core.mdm.IDMFlagNodeItem;
+import gov.nist.secauto.metaschema.core.mdm.IDMNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
-import gov.nist.secauto.metaschema.core.metapath.item.node.IFlagNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem;
import gov.nist.secauto.metaschema.core.model.IFlagInstance;
import gov.nist.secauto.metaschema.core.model.IModelDefinition;
import gov.nist.secauto.metaschema.core.model.INamedModelInstance;
-import gov.nist.secauto.metaschema.core.model.IResourceLocation;
import edu.umd.cs.findbugs.annotations.NonNull;
+/**
+ * Represents a Metapath node item that is backed by a simple Metaschema
+ * module-based data model.
+ *
+ * Implementations of this interface are expected to support child flag node
+ * items.
+ *
+ * Child flags can be created using the
+ * {@link #newFlag(gov.nist.secauto.metaschema.core.model.IFlagInstance, IAnyAtomicItem)}
+ * method. These children are added to this assembly.
+ *
+ * @param
+ * the Java type of the definition associated with a Metaschema module
+ * @param
+ * the Java type of the instance associated with a Metaschema module
+ */
public interface IDMModelNodeItem
- extends IModelNodeItem {
+ extends IModelNodeItem, IDMNodeItem, IDefinitionNodeItem {
+ /**
+ * Create and add a new flag to the underlying data model.
+ *
+ * @param instance
+ * the Metaschema flag instance describing the field
+ * @param value
+ * the atomic flag value
+ * @return the new flag node item
+ */
@NonNull
- IFlagNodeItem newFlag(
+ IDMFlagNodeItem newFlag(
@NonNull IFlagInstance instance,
- @NonNull IResourceLocation resourceLocation,
@NonNull IAnyAtomicItem value);
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/IFeatureChildNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/IFeatureChildNodeItem.java
new file mode 100644
index 000000000..61417aed7
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/mdm/impl/IFeatureChildNodeItem.java
@@ -0,0 +1,36 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.mdm.impl;
+
+import gov.nist.secauto.metaschema.core.mdm.IDMNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.StaticContext;
+import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem;
+import gov.nist.secauto.metaschema.core.model.IModelDefinition;
+import gov.nist.secauto.metaschema.core.model.INamedInstance;
+
+/**
+ * This feature identifies the implementing class as a node item that has a node
+ * item parent, providing default methods required by all child node items.
+ *
+ * @param
+ * the Java type of the parent node item
+ */
+public interface IFeatureChildNodeItem
>
+ extends IDMNodeItem {
+
+ @Override
+ P getParentNodeItem();
+
+ @Override
+ default P getParentContentNodeItem() {
+ return getParentNodeItem();
+ }
+
+ @Override
+ default StaticContext getStaticContext() {
+ return getParentNodeItem().getStaticContext();
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IMetapathExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IMetapathExpression.java
index 9a2a15799..14329df84 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IMetapathExpression.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IMetapathExpression.java
@@ -8,6 +8,7 @@
import gov.nist.secauto.metaschema.core.metapath.MetapathExpression.ConversionFunction;
import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils;
import gov.nist.secauto.metaschema.core.metapath.function.library.FnBoolean;
+import gov.nist.secauto.metaschema.core.metapath.impl.LazyCompilationMetapathExpression;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
@@ -21,6 +22,9 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
+/**
+ * Supports compiling and executing Metapath expressions.
+ */
public interface IMetapathExpression {
/**
@@ -136,6 +140,23 @@ static IMetapathExpression compile(@NonNull String path, @NonNull StaticContext
return MetapathExpression.compile(path, staticContext);
}
+ /**
+ * Gets a new Metapath expression that is compiled on use.
+ *
+ * Lazy compilation may cause additional {@link MetapathException} errors at
+ * evaluation time, since compilation errors are not raised until evaluation.
+ *
+ * @param path
+ * the metapath expression
+ * @param staticContext
+ * the static evaluation context
+ * @return the expression object
+ */
+ @NonNull
+ static IMetapathExpression lazyCompile(@NonNull String path, @NonNull StaticContext staticContext) {
+ return new LazyCompilationMetapathExpression(path, staticContext);
+ }
+
/**
* Get the original Metapath expression as a string.
*
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/FailingErrorListener.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/FailingErrorListener.java
index 94dcb57c4..4b9300644 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/FailingErrorListener.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/FailingErrorListener.java
@@ -22,6 +22,6 @@ public class FailingErrorListener
@Override
public void syntaxError(Recognizer, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
String msg, RecognitionException ex) {
- throw new ParseCancellationException("line " + line + ":" + charPositionInLine + " " + msg);
+ throw new ParseCancellationException("line " + line + ":" + charPositionInLine + " " + msg, ex);
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/KindNodeTest.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/KindNodeTest.java
index ba5d5ee47..113d9c1ac 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/KindNodeTest.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/KindNodeTest.java
@@ -28,10 +28,10 @@ public class KindNodeTest
private final IItemType type;
/**
- * Construct a new expanded QName-based literal expression.
+ * Construct a new kind test expression.
*
- * @param name
- * the literal value
+ * @param type
+ * the expected item type to test against
*/
public KindNodeTest(@NonNull IItemType type) {
this.type = type;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/WildcardNodeTest.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/WildcardNodeTest.java
index 33d06978a..0c942077a 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/WildcardNodeTest.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/WildcardNodeTest.java
@@ -24,6 +24,7 @@
* wildcard name
* test.
*/
+@SuppressWarnings("PMD.TestClassWithoutTestCases")
public class WildcardNodeTest implements INodeTestExpression {
@Nullable
private final Predicate> matcher;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOneOrMore.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOneOrMore.java
index 0399ffa31..d44207078 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOneOrMore.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOneOrMore.java
@@ -72,7 +72,7 @@ private static ISequence> execute(@NonNull IFunction function,
*/
@NonNull
public static ISequence> fnOneOrMore(@NonNull ISequence> sequence) {
- if (sequence.size() < 1) {
+ if (sequence.isEmpty()) {
throw new InvalidArgumentFunctionException(
InvalidArgumentFunctionException.INVALID_ARGUMENT_ONE_OR_MORE,
String.format("fn:one-or-more called with the sequence '%s' containing less than one item.",
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/IFeatureCollectionFunctionItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/IFeatureCollectionFunctionItem.java
index ebcc5ae02..e4563276a 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/IFeatureCollectionFunctionItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/IFeatureCollectionFunctionItem.java
@@ -16,6 +16,10 @@
import edu.umd.cs.findbugs.annotations.NonNull;
+/**
+ * Provides default methods for node items that represent collections of
+ * Metapath items and sequences.
+ */
public interface IFeatureCollectionFunctionItem extends IFunction {
/**
* The function properties.
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/LazyCompilationMetapathExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/LazyCompilationMetapathExpression.java
new file mode 100644
index 000000000..eca627b1f
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/LazyCompilationMetapathExpression.java
@@ -0,0 +1,68 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.metapath.impl;
+
+import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
+import gov.nist.secauto.metaschema.core.metapath.MetapathException;
+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.ISequence;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+import nl.talsmasoftware.lazy4j.Lazy;
+
+/**
+ * An implementation of a Metapath expression that is compiled when evaluated.
+ *
+ * Lazy compilation may cause additional {@link MetapathException} errors at
+ * evaluation time, since compilation errors are not raised until evaluation.
+ */
+public class LazyCompilationMetapathExpression implements IMetapathExpression {
+ @NonNull
+ private final String path;
+ @NonNull
+ private final StaticContext staticContext;
+ @NonNull
+ private final Lazy compiledMetapath;
+
+ /**
+ * Construct a new lazy-compiled Metapath expression.
+ *
+ * @param path
+ * the metapath expression
+ * @param staticContext
+ * the static evaluation context
+ */
+ public LazyCompilationMetapathExpression(
+ @NonNull String path,
+ @NonNull StaticContext staticContext) {
+ this.path = path;
+ this.staticContext = staticContext;
+ this.compiledMetapath = ObjectUtils.notNull(Lazy.lazy(() -> IMetapathExpression.compile(path, staticContext)));
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ @Override
+ public StaticContext getStaticContext() {
+ return staticContext;
+ }
+
+ @NonNull
+ private IMetapathExpression getCompiledMetapath() {
+ return ObjectUtils.notNull(compiledMetapath.get());
+ }
+
+ @Override
+ public ISequence evaluate(IItem focus, DynamicContext dynamicContext) {
+ return getCompiledMetapath().evaluate(focus, dynamicContext);
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractGlobalDefinitionNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractGlobalDefinitionNodeItem.java
index 2c0a62470..16e50f847 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractGlobalDefinitionNodeItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractGlobalDefinitionNodeItem.java
@@ -13,7 +13,9 @@
* Represents a node item based on a global definition from a Metaschema.
*
* @param
- * the definition type
+ * the Java type of the associated Metaschema module definition
+ * @param
+ * the Java type of the associated Metaschema module instance
*/
public abstract class AbstractGlobalDefinitionNodeItem
extends AbstractDefinitionNodeItem {
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDefinitionNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDefinitionNodeItem.java
index 4dec59e28..b531267c8 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDefinitionNodeItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDefinitionNodeItem.java
@@ -9,6 +9,15 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
+/**
+ * Represents a Metapath node item that is based on an underlying Metaschema
+ * module definition and instance.
+ *
+ * @param
+ * the Java type of the definition associated with a Metaschema module
+ * @param
+ * the Java type of the instance associated with a Metaschema module
+ */
public interface IDefinitionNodeItem extends INodeItem {
/**
* Get the name of this node.
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/package-info.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/package-info.java
index cda49f921..4d1871000 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/package-info.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/package-info.java
@@ -4,8 +4,8 @@
* represented using a Metaschema model.
*
* The factory
- * {@link gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory}
- * can be used to create instances of various node item objects.
+ * {@link gov.nist.secauto.metaschema.databind.model.impl.INodeItemFactory} can
+ * be used to create instances of various node item objects.
*/
package gov.nist.secauto.metaschema.core.metapath.item.node;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/ISource.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/ISource.java
index 2c1c8a76e..8efee288c 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/ISource.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/ISource.java
@@ -8,6 +8,7 @@
import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.model.constraint.impl.InternalModelSource;
import gov.nist.secauto.metaschema.core.model.constraint.impl.StaticContextSource;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.net.URI;
@@ -47,6 +48,21 @@ static ISource moduleSource(@NonNull IModule module) {
return InternalModelSource.instance(module);
}
+ /**
+ * Get the descriptor for a
+ * {@link gov.nist.secauto.metaschema.core.model.ISource.SourceLocation#EXTERNAL}
+ * source for the provided resource.
+ *
+ * @param location
+ * the resource used as the source
+ *
+ * @return the source descriptor
+ */
+ @NonNull
+ static ISource externalSource(@NonNull String location) {
+ return externalSource(ObjectUtils.notNull(URI.create(location)));
+ }
+
/**
* Get the descriptor for a
* {@link gov.nist.secauto.metaschema.core.model.ISource.SourceLocation#EXTERNAL}
@@ -62,7 +78,8 @@ static ISource externalSource(@NonNull URI location) {
return StaticContextSource.instance(
StaticContext.builder()
.baseUri(location)
- .build());
+ .build(),
+ true);
}
/**
@@ -76,15 +93,20 @@ static ISource externalSource(@NonNull URI location) {
* @param staticContext
* the static Metapath context to use for compiling Metapath
* expressions in this source
+ * @param useCached
+ * if {@code true} use a previously cached source, otherwise create a
+ * new one
*
* @return the source descriptor
*/
@NonNull
- static ISource externalSource(@NonNull StaticContext staticContext) {
+ static ISource externalSource(
+ @NonNull StaticContext staticContext,
+ boolean useCached) {
if (staticContext.getBaseUri() == null) {
throw new IllegalArgumentException("The static content must define a baseUri identifing the source resource.");
}
- return StaticContextSource.instance(staticContext);
+ return StaticContextSource.instance(staticContext, useCached);
}
/**
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConfigurableMessageConstraintBuilder.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConfigurableMessageConstraintBuilder.java
index 0d1867d81..452bceace 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConfigurableMessageConstraintBuilder.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConfigurableMessageConstraintBuilder.java
@@ -24,6 +24,7 @@ public abstract class AbstractConfigurableMessageConstraintBuilder<
T extends AbstractConfigurableMessageConstraintBuilder,
R extends IConfigurableMessageConstraint>
extends AbstractConstraintBuilder {
+ @Nullable
private String message;
/**
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintBuilder.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintBuilder.java
index 1ab6d3fa9..8161dbf0c 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintBuilder.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintBuilder.java
@@ -7,6 +7,7 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.IConstraint.Level;
@@ -42,7 +43,7 @@ public abstract class AbstractConstraintBuilder<
@NonNull
private Level level = IConstraint.DEFAULT_LEVEL;
@NonNull
- private String target = IConstraint.DEFAULT_TARGET_METAPATH;
+ private IMetapathExpression target = IConstraint.DEFAULT_TARGET_METAPATH;
@NonNull
private Map> properties = new LinkedHashMap<>(); // NOPMD not thread safe
private MarkupMultiline remarks;
@@ -131,7 +132,7 @@ public T level(@NonNull Level level) {
* @return this builder
*/
@NonNull
- public T target(@NonNull String target) {
+ public T target(@NonNull IMetapathExpression target) {
this.target = target;
return getThis();
}
@@ -283,7 +284,7 @@ protected Level getLevel() {
* @return the target Metapath expression
*/
@NonNull
- protected String getTarget() {
+ protected IMetapathExpression getTarget() {
return target;
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintValidationHandler.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintValidationHandler.java
index 678c22cab..f5a1f2a20 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintValidationHandler.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintValidationHandler.java
@@ -87,7 +87,7 @@ protected String newCardinalityMinimumViolationMessage(
"The cardinality '%d' is below the required minimum '%d' for items matching '%s'.",
testedItems.size(),
constraint.getMinOccurs(),
- constraint.getTarget()))
+ constraint.getTarget().getPath()))
: constraint.generateMessage(target, dynamicContext);
}
@@ -284,7 +284,7 @@ protected String newExpectViolationMessage(
@NonNull DynamicContext dynamicContext) {
return constraint.getMessage() == null
? ObjectUtils.notNull(String.format("Expect constraint '%s' did not match the data at path '%s'",
- constraint.getTest(),
+ constraint.getTest().getPath(),
toPath(target)))
: constraint.generateMessage(target, dynamicContext);
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractTargetedConstraints.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractTargetedConstraints.java
index d010cf162..b2666ef28 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractTargetedConstraints.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractTargetedConstraints.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.core.model.constraint;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.ISource;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -21,7 +22,7 @@ public abstract class AbstractTargetedConstraints
@NonNull
private final ISource source;
@NonNull
- private final String targetExpression;
+ private final IMetapathExpression target;
@NonNull
private final T constraints;
@@ -37,10 +38,10 @@ public abstract class AbstractTargetedConstraints
*/
protected AbstractTargetedConstraints(
@NonNull ISource source,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull T constraints) {
this.source = source;
- this.targetExpression = target;
+ this.target = target;
this.constraints = constraints;
}
@@ -50,8 +51,8 @@ public ISource getSource() {
}
@Override
- public String getTargetExpression() {
- return targetExpression;
+ public IMetapathExpression getTarget() {
+ return target;
}
@Override
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AssemblyTargetedConstraints.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AssemblyTargetedConstraints.java
index e50f5b592..233273f6c 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AssemblyTargetedConstraints.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AssemblyTargetedConstraints.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.core.model.constraint;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.impl.AbstractDefinitionTargetedConstraints;
@@ -15,7 +16,7 @@
* A set of constraints targeting a {@link IAssemblyDefinition} based on a
* target Metapath expression.
*
- * @see #getTargetExpression()
+ * @see #getTarget()
*/
public class AssemblyTargetedConstraints
extends AbstractDefinitionTargetedConstraints
@@ -33,7 +34,7 @@ public class AssemblyTargetedConstraints
*/
public AssemblyTargetedConstraints(
@NonNull ISource source,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull IModelConstrained constraints) {
super(source, target, constraints);
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidator.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidator.java
index 0fadac1dc..3f6f414c4 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidator.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidator.java
@@ -392,7 +392,7 @@ private static String toErrorMessage(
String id = constraint.getId();
if (id == null) {
builder.append(" targeting the metapath '")
- .append(constraint.getTarget())
+ .append(constraint.getTarget().getPath())
.append('\'');
} else {
builder.append(" with id '")
@@ -677,10 +677,7 @@ private void validateExpect(
@NonNull ISequence extends INodeItem> targets,
@NonNull DynamicContext dynamicContext) {
try {
- IMetapathExpression metapath = IMetapathExpression.compile(
- constraint.getTest(),
- dynamicContext.getStaticContext());
-
+ IMetapathExpression metapath = constraint.getTest();
IConstraintValidationHandler handler = getConstraintValidationHandler();
targets.stream()
.forEachOrdered(item -> {
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ExternalConstraintsModulePostProcessor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ExternalConstraintsModulePostProcessor.java
index acd3a89ff..26c27eaf5 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ExternalConstraintsModulePostProcessor.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ExternalConstraintsModulePostProcessor.java
@@ -92,8 +92,7 @@ private static void applyConstraints(
@NonNull DynamicContext dynamicContext) {
for (ITargetedConstraints targeted : set.getTargetedConstraintsForModule(module)) {
// apply targeted constraints
- String targetExpression = targeted.getTargetExpression();
- IMetapathExpression metapath = IMetapathExpression.compile(targetExpression, dynamicContext.getStaticContext());
+ IMetapathExpression metapath = targeted.getTarget();
ISequence> items = metapath.evaluate(moduleItem, dynamicContext);
assert items != null;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FieldTargetedConstraints.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FieldTargetedConstraints.java
index 4078630ab..24e0c0e4d 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FieldTargetedConstraints.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FieldTargetedConstraints.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.core.model.constraint;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.impl.AbstractDefinitionTargetedConstraints;
@@ -15,7 +16,7 @@
* A set of constraints targeting a {@link IFieldDefinition} based on a target
* Metapath expression.
*
- * @see #getTargetExpression()
+ * @see #getTarget()
*/
public class FieldTargetedConstraints
extends AbstractDefinitionTargetedConstraints {
@@ -32,7 +33,7 @@ public class FieldTargetedConstraints
*/
public FieldTargetedConstraints(
@NonNull ISource source,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull IValueConstrained constraints) {
super(source, target, constraints);
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FlagTargetedConstraints.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FlagTargetedConstraints.java
index 1981ed572..7bf15a9ac 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FlagTargetedConstraints.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FlagTargetedConstraints.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.core.model.constraint;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IFlagDefinition;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.impl.AbstractDefinitionTargetedConstraints;
@@ -15,7 +16,7 @@
* A set of constraints targeting a {@link IFlagDefinition} based on a target
* Metapath expression.
*
- * @see #getTargetExpression()
+ * @see #getTarget()
*/
public class FlagTargetedConstraints
extends AbstractDefinitionTargetedConstraints {
@@ -32,7 +33,7 @@ public class FlagTargetedConstraints
*/
public FlagTargetedConstraints(
@NonNull ISource source,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull IValueConstrained constraints) {
super(source, target, constraints);
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraint.java
index b70d13e57..473817e5c 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraint.java
@@ -7,6 +7,7 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem;
@@ -90,10 +91,10 @@ enum Level {
Level DEFAULT_LEVEL = Level.ERROR;
/**
- * The default target Metapath expression to use if no target is provided.
+ * The compiled default target Metapath to use if no target is provided.
*/
@NonNull
- String DEFAULT_TARGET_METAPATH = ".";
+ IMetapathExpression DEFAULT_TARGET_METAPATH = IMetapathExpression.contextNode();
/**
* Get a string that identifies the provided constraint using the most specific
@@ -111,7 +112,7 @@ static String getConstraintIdentity(@NonNull IConstraint constraint) {
} else if (constraint.getFormalName() != null) {
identity = String.format("with the formal name '%s'", constraint.getFormalName());
} else {
- identity = String.format("targeting '%s'", constraint.getTarget());
+ identity = String.format("targeting '%s'", constraint.getTarget().getPath());
}
return ObjectUtils.notNull(identity);
}
@@ -155,7 +156,7 @@ static String getConstraintIdentity(@NonNull IConstraint constraint) {
* @return a Metapath expression
*/
@NonNull
- String getTarget();
+ IMetapathExpression getTarget();
/**
* Based on the provided {@code contextNodeItem}, find all nodes matching the
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IExpectConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IExpectConstraint.java
index 16b9e563e..db770ef77 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IExpectConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IExpectConstraint.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.core.model.constraint;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.constraint.impl.DefaultExpectConstraint;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
@@ -28,7 +29,7 @@ default Type getType() {
* @return the test metapath expression to use
*/
@NonNull
- String getTest();
+ IMetapathExpression getTest();
@Override
default R accept(IConstraintVisitor visitor, T state) {
@@ -50,7 +51,7 @@ static Builder builder() {
*/
final class Builder
extends AbstractConfigurableMessageConstraintBuilder {
- private String test;
+ private IMetapathExpression test;
private Builder() {
// disable construction
@@ -64,7 +65,7 @@ private Builder() {
* @return this builder
*/
@NonNull
- public Builder test(@NonNull String test) {
+ public Builder test(@NonNull IMetapathExpression test) {
this.test = test;
return this;
}
@@ -81,7 +82,7 @@ protected void validate() {
ObjectUtils.requireNonNull(getTest());
}
- private String getTest() {
+ private IMetapathExpression getTest() {
return test;
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IIndex.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IIndex.java
index 06d4d5ace..45914b155 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IIndex.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IIndex.java
@@ -160,7 +160,7 @@ private static String buildKeyItem(
@NonNull INodeItem item,
@NonNull IKeyField keyField,
@NonNull DynamicContext dynamicContext) {
- IMetapathExpression keyMetapath = keyField.getTargetMetapath();
+ IMetapathExpression keyMetapath = keyField.getTarget();
IItem keyItem;
try {
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IKeyField.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IKeyField.java
index 54e91447d..8c0396c5b 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IKeyField.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IKeyField.java
@@ -7,7 +7,6 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.impl.DefaultKeyField;
import java.util.regex.Pattern;
@@ -33,18 +32,15 @@ public interface IKeyField {
* an optional used to extract a portion of the resulting key value
* @param remarks
* optional remarks describing the intent of the constraint
- * @param source
- * the descriptor for the resource containing the constraint
* @return the new key field
*/
@SuppressWarnings("PMD.ShortMethodName")
@NonNull
static IKeyField of(
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@Nullable Pattern pattern,
- @Nullable MarkupMultiline remarks,
- @NonNull ISource source) {
- return new DefaultKeyField(target, pattern, remarks, source);
+ @Nullable MarkupMultiline remarks) {
+ return new DefaultKeyField(target, pattern, remarks);
}
/**
@@ -54,15 +50,7 @@ static IKeyField of(
* @return the Metapath expression identifying the key value target
*/
@NonNull
- String getTarget();
-
- /**
- * Get the compiled Metapath expression for the {@link #getTarget()}.
- *
- * @return the compiled Metapath expression
- */
- @NonNull
- IMetapathExpression getTargetMetapath();
+ IMetapathExpression getTarget();
/**
* A pattern to use to retrieve the value. If non-{@code null}, the first
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ITargetedConstraints.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ITargetedConstraints.java
index e2ca5c5bb..81ab656d1 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ITargetedConstraints.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ITargetedConstraints.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.core.model.constraint;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
import gov.nist.secauto.metaschema.core.model.IFlagDefinition;
@@ -31,7 +32,7 @@ public interface ITargetedConstraints extends IValueConstrained {
* @return the uncompiled Metapath expression
*/
@NonNull
- String getTargetExpression();
+ IMetapathExpression getTarget();
/**
* Apply the constraint to the provided definition.
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractConfigurableMessageConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractConfigurableMessageConstraint.java
index 68357c50f..8eb801a02 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractConfigurableMessageConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractConfigurableMessageConstraint.java
@@ -71,7 +71,7 @@ protected AbstractConfigurableMessageConstraint(
@Nullable MarkupLine description,
@NonNull ISource source,
@NonNull Level level,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull Map> properties,
@Nullable String message,
@Nullable MarkupMultiline remarks) {
@@ -97,8 +97,17 @@ public String generateMessage(@NonNull INodeItem item, @NonNull DynamicContext c
return ObjectUtils.notNull(ReplacementScanner.replaceTokens(message, METAPATH_VALUE_TEMPLATE_PATTERN, match -> {
String metapath = ObjectUtils.notNull(match.group(2));
try {
- IMetapathExpression expr = IMetapathExpression.compile(metapath, context.getStaticContext());
- return expr.evaluateAs(item, IMetapathExpression.ResultType.STRING, context);
+ IMetapathExpression expr = IMetapathExpression.compile(
+ metapath,
+ // need to use the static context of the source to resolve prefixes, etc., since
+ // this is where the message is defined
+ getSource().getStaticContext());
+ return expr.evaluateAs(
+ item,
+ IMetapathExpression.ResultType.STRING,
+ // here we are using the static context of the instance, since this is how
+ // variables and nodes are resolved.
+ context);
} catch (MetapathException ex) {
throw new MetapathException(
String.format("Unable to evaluate the message replacement expression '%s' in constraint '%s'. %s",
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractConstraint.java
index 66f0f8599..108a9b113 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractConstraint.java
@@ -23,7 +23,6 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
-import nl.talsmasoftware.lazy4j.Lazy;
/**
* The base class for all constraint implementations.
@@ -44,7 +43,7 @@ public abstract class AbstractConstraint implements IConstraint { // NOPMD - int
@NonNull
private final Map> properties;
@NonNull
- private final Lazy targetMetapath;
+ private final IMetapathExpression target;
/**
* Construct a new Metaschema constraint.
@@ -73,7 +72,7 @@ protected AbstractConstraint(
@Nullable MarkupLine description,
@NonNull ISource source,
@NonNull Level level,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull Map> properties,
@Nullable MarkupMultiline remarks) {
Objects.requireNonNull(target);
@@ -84,10 +83,7 @@ protected AbstractConstraint(
this.level = ObjectUtils.requireNonNull(level, "level");
this.properties = properties;
this.remarks = remarks;
- this.targetMetapath = ObjectUtils.notNull(
- Lazy.lazy(() -> IMetapathExpression.compile(
- target,
- source.getStaticContext())));
+ this.target = target;
}
@Override
@@ -117,8 +113,8 @@ public Level getLevel() {
}
@Override
- public final String getTarget() {
- return getTargetMetapath().getPath();
+ public final IMetapathExpression getTarget() {
+ return target;
}
@Override
@@ -131,21 +127,11 @@ public MarkupMultiline getRemarks() {
return remarks;
}
- /**
- * Get the compiled Metapath expression for the target.
- *
- * @return the compiled Metapath expression
- */
- @NonNull
- public final IMetapathExpression getTargetMetapath() {
- return ObjectUtils.notNull(targetMetapath.get());
- }
-
@Override
@NonNull
public ISequence extends IDefinitionNodeItem, ?>> matchTargets(
@NonNull IDefinitionNodeItem, ?> item,
@NonNull DynamicContext dynamicContext) {
- return item.hasValue() ? getTargetMetapath().evaluate(item, dynamicContext) : ISequence.empty();
+ return item.hasValue() ? getTarget().evaluate(item, dynamicContext) : ISequence.empty();
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractDefinitionTargetedConstraints.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractDefinitionTargetedConstraints.java
index 853607051..d589bde2a 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractDefinitionTargetedConstraints.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractDefinitionTargetedConstraints.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.core.model.constraint.impl;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
import gov.nist.secauto.metaschema.core.model.IDefinition;
import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
@@ -45,7 +46,7 @@ public abstract class AbstractDefinitionTargetedConstraints<
*/
protected AbstractDefinitionTargetedConstraints(
@NonNull ISource source,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull S constraints) {
super(source, target, constraints);
}
@@ -89,7 +90,7 @@ private void wrongDefinitionTypeTargeted(@NonNull IDefinition definition) {
definition.getModelType().name().toLowerCase(Locale.ROOT),
definition.getEffectiveName(),
definition.getContainingModule().getQName().toString(),
- getTargetExpression(),
+ getTarget(),
getSource().getLocationHint()));
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractKeyConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractKeyConstraint.java
index c7fcb1647..daa6e1550 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractKeyConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractKeyConstraint.java
@@ -7,6 +7,7 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.ConstraintInitializationException;
@@ -61,7 +62,7 @@ protected AbstractKeyConstraint(
@Nullable MarkupLine description,
@NonNull ISource source,
@NonNull Level level,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull Map> properties,
@NonNull List keyFields,
@Nullable String message,
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/ConstraintComposingVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/ConstraintComposingVisitor.java
index 5ade00e26..9a06f43d8 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/ConstraintComposingVisitor.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/ConstraintComposingVisitor.java
@@ -68,7 +68,7 @@ private static void illegalTargetError(
"Invalid target '%s' for constraints targeting '%s' in '%s'. A document node is an" +
" invalid constraint target. Constraints can only apply to an assembly, field, or flag definition.",
item.getMetapath(),
- context.getTargetExpression(),
+ context.getTarget(),
context.getSource().getLocationHint()));
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultAllowedValuesConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultAllowedValuesConstraint.java
index 3b5650a08..f84944154 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultAllowedValuesConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultAllowedValuesConstraint.java
@@ -7,6 +7,7 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.IAllowedValue;
@@ -70,7 +71,7 @@ public DefaultAllowedValuesConstraint( // NOPMD necessary
@Nullable MarkupLine description,
@NonNull ISource source,
@NonNull Level level,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull Map> properties,
@NonNull Map allowedValues,
boolean allowedOther,
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultCardinalityConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultCardinalityConstraint.java
index 3db8a01a4..478db95c6 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultCardinalityConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultCardinalityConstraint.java
@@ -7,6 +7,7 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.ConstraintInitializationException;
@@ -70,7 +71,7 @@ public DefaultCardinalityConstraint(
@Nullable MarkupLine description,
@NonNull ISource source,
@NonNull Level level,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull Map> properties,
@Nullable Integer minOccurs,
@Nullable Integer maxOccurs,
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultExpectConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultExpectConstraint.java
index a1c00f953..744bdd46f 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultExpectConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultExpectConstraint.java
@@ -12,14 +12,12 @@
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.IExpectConstraint;
-import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.util.Map;
import java.util.Set;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
-import nl.talsmasoftware.lazy4j.Lazy;
/**
* Represents an expect constraint.
@@ -31,7 +29,7 @@ public final class DefaultExpectConstraint
extends AbstractConfigurableMessageConstraint
implements IExpectConstraint {
@NonNull
- private final Lazy testMetapath;
+ private final IMetapathExpression test;
/**
* Construct a new expect constraint.
@@ -66,30 +64,17 @@ public DefaultExpectConstraint(
@Nullable MarkupLine description,
@NonNull ISource source,
@NonNull Level level,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull Map> properties,
- @NonNull String test,
+ @NonNull IMetapathExpression test,
@Nullable String message,
@Nullable MarkupMultiline remarks) {
super(id, formalName, description, source, level, target, properties, message, remarks);
- this.testMetapath = ObjectUtils.notNull(
- Lazy.lazy(() -> IMetapathExpression.compile(
- test,
- source.getStaticContext())));
- }
-
- /**
- * Get the compiled Metapath expression for the test.
- *
- * @return the compiled Metapath expression
- */
- @NonNull
- public IMetapathExpression getTestMetapath() {
- return ObjectUtils.notNull(testMetapath.get());
+ this.test = test;
}
@Override
- public String getTest() {
- return getTestMetapath().getPath();
+ public IMetapathExpression getTest() {
+ return test;
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultIndexConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultIndexConstraint.java
index c5fb4a241..7a8e6ee74 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultIndexConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultIndexConstraint.java
@@ -7,6 +7,7 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.ConstraintInitializationException;
@@ -69,7 +70,7 @@ public DefaultIndexConstraint(
@Nullable MarkupLine description,
@NonNull ISource source,
@NonNull Level level,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull Map> properties,
@NonNull String name,
@NonNull List keyFields,
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultIndexHasKeyConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultIndexHasKeyConstraint.java
index 3ac34f5d6..1303764b7 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultIndexHasKeyConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultIndexHasKeyConstraint.java
@@ -7,6 +7,7 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.ConstraintInitializationException;
@@ -67,7 +68,7 @@ public DefaultIndexHasKeyConstraint(
@Nullable MarkupLine description,
@NonNull ISource source,
@NonNull Level level,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull Map> properties,
@NonNull String indexName,
@NonNull List keyFields,
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultKeyField.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultKeyField.java
index 9be2c9feb..3a8f35d1e 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultKeyField.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultKeyField.java
@@ -7,22 +7,19 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.IKeyField;
-import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.util.regex.Pattern;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
-import nl.talsmasoftware.lazy4j.Lazy;
public class DefaultKeyField implements IKeyField {
@Nullable
private final Pattern pattern;
@NonNull
- private final Lazy target;
+ private final IMetapathExpression target;
@Nullable
private final MarkupMultiline remarks;
@@ -36,16 +33,13 @@ public class DefaultKeyField implements IKeyField {
* an optional used to extract a portion of the resulting key value
* @param remarks
* optional remarks describing the intent of the constraint
- * @param source
- * the descriptor for the resource containing the constraint
*/
public DefaultKeyField(
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@Nullable Pattern pattern,
- @Nullable MarkupMultiline remarks,
- @NonNull ISource source) {
+ @Nullable MarkupMultiline remarks) {
this.pattern = pattern;
- this.target = ObjectUtils.notNull(Lazy.lazy(() -> IMetapathExpression.compile(target, source.getStaticContext())));
+ this.target = target;
this.remarks = remarks;
}
@@ -55,13 +49,8 @@ public Pattern getPattern() {
}
@Override
- public String getTarget() {
- return getTargetMetapath().getPath();
- }
-
- @Override
- public IMetapathExpression getTargetMetapath() {
- return ObjectUtils.notNull(target.get());
+ public IMetapathExpression getTarget() {
+ return target;
}
@Override
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultMatchesConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultMatchesConstraint.java
index 952769386..0f581c8e5 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultMatchesConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultMatchesConstraint.java
@@ -8,6 +8,7 @@
import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.ConstraintInitializationException;
@@ -68,7 +69,7 @@ public DefaultMatchesConstraint(
@Nullable MarkupLine description,
@NonNull ISource source,
@NonNull Level level,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull Map> properties,
@Nullable Pattern pattern,
@Nullable IDataTypeAdapter> dataType,
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultUniqueConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultUniqueConstraint.java
index 4293feb1b..1bd9f3f23 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultUniqueConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultUniqueConstraint.java
@@ -7,6 +7,7 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.IKeyField;
@@ -60,7 +61,7 @@ public DefaultUniqueConstraint(
@Nullable MarkupLine description,
@NonNull ISource source,
@NonNull Level level,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull Map> properties,
@NonNull List keyFields,
@Nullable String message,
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/StaticContextSource.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/StaticContextSource.java
index 0e0262039..601aa438b 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/StaticContextSource.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/StaticContextSource.java
@@ -38,10 +38,22 @@ public final class StaticContextSource implements ISource {
* @param staticContext
* the static Metapath context to use for compiling Metapath
* expressions in this source
+ * @param useCached
+ * if {@code true} use a previously cached source, otherwise create a
+ * new one
* @return the source
*/
@NonNull
- public static ISource instance(@NonNull StaticContext staticContext) {
+ public static ISource instance(
+ @NonNull StaticContext staticContext,
+ boolean useCached) {
+ return useCached
+ ? retrieveFromCache(staticContext)
+ : new StaticContextSource(staticContext);
+ }
+
+ @NonNull
+ private static StaticContextSource retrieveFromCache(@NonNull StaticContext staticContext) {
SOURCE_LOCK.lock();
try {
return ObjectUtils.notNull(sources.computeIfAbsent(
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/XmlConstraintLoader.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/XmlConstraintLoader.java
index 35b0a3f37..47bcd0fb9 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/XmlConstraintLoader.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/XmlConstraintLoader.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.core.model.xml;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.model.AbstractLoader;
@@ -173,7 +174,7 @@ protected List parseScopedConstraints(
builder.useWildcardWhenNamespaceNotDefaulted(true);
- ISource source = ISource.externalSource(resource);
+ ISource source = ISource.externalSource(builder.build(), false);
for (Scope scope : constraints.getScopeList()) {
assert scope != null;
@@ -214,7 +215,9 @@ private static void handleScopedAssembly(
state.getRight().add(new AssemblyTargetedConstraints(
source,
- ObjectUtils.requireNonNull(assembly.getTarget()),
+ IMetapathExpression.lazyCompile(
+ ObjectUtils.requireNonNull(assembly.getTarget()),
+ source.getStaticContext()),
constraints));
}
@@ -229,7 +232,9 @@ private static void handleScopedField( // NOPMD false positive
state.getRight().add(new FieldTargetedConstraints(
source,
- ObjectUtils.requireNonNull(field.getTarget()),
+ IMetapathExpression.lazyCompile(
+ ObjectUtils.requireNonNull(field.getTarget()),
+ source.getStaticContext()),
constraints));
}
@@ -244,7 +249,9 @@ private static void handleScopedFlag( // NOPMD false positive
state.getRight().add(new FlagTargetedConstraints(
source,
- ObjectUtils.requireNonNull(flag.getTarget()),
+ IMetapathExpression.lazyCompile(
+ ObjectUtils.requireNonNull(flag.getTarget()),
+ source.getStaticContext()),
constraints));
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/XmlMetaConstraintLoader.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/XmlMetaConstraintLoader.java
index f12b8578b..f3e0b70d0 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/XmlMetaConstraintLoader.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/XmlMetaConstraintLoader.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.core.model.xml;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.model.AbstractLoader;
import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
@@ -66,7 +67,7 @@ protected List parseResource(URI resource, Deque visitedRes
ObjectUtils.notNull(binding.getPrefix()), ObjectUtils.notNull(binding.getUri())));
builder.useWildcardWhenNamespaceNotDefaulted(true);
- ISource source = ISource.externalSource(resource);
+ ISource source = ISource.externalSource(builder.build(), true);
List targetedConstraints = ObjectUtils.notNull(constraints.getContextList().stream()
.flatMap(context -> parseContext(ObjectUtils.notNull(context), null, source).getTargetedConstraints().stream())
@@ -151,7 +152,12 @@ public Context(
public List getTargetedConstraints() {
return Stream.concat(
getMetapaths().stream()
- .map(metapath -> new MetaTargetedContraints(source, ObjectUtils.notNull(metapath), constraints)),
+ .map(metapath -> new MetaTargetedContraints(
+ source,
+ IMetapathExpression.lazyCompile(
+ ObjectUtils.requireNonNull(metapath),
+ source.getStaticContext()),
+ constraints)),
childContexts.stream()
.flatMap(child -> child.getTargetedConstraints().stream()))
.collect(Collectors.toList());
@@ -172,7 +178,7 @@ private static class MetaTargetedContraints
protected MetaTargetedContraints(
@NonNull ISource source,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull IModelConstrained constraints) {
super(source, target, constraints);
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ConstraintXmlSupport.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ConstraintXmlSupport.java
index bb5aa223c..b03298c89 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ConstraintXmlSupport.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ConstraintXmlSupport.java
@@ -438,7 +438,7 @@ public Void visitAllowedValues(IAllowedValuesConstraint constraint, DefineAssemb
if (Boolean.compare(IAllowedValuesConstraint.ALLOW_OTHER_DEFAULT, constraint.isAllowedOther()) != 0) {
bean.setAllowOther(constraint.isAllowedOther());
}
- bean.setTarget(constraint.getTarget());
+ bean.setTarget(constraint.getTarget().getPath());
bean.setExtensible(constraint.getExtensible());
for (Map.Entry entry : constraint.getAllowedValues().entrySet()) {
@@ -494,7 +494,7 @@ public Void visitExpectConstraint(IExpectConstraint constraint, DefineAssemblyCo
assert bean != null;
applyCommonValues(constraint, bean);
- bean.setTest(constraint.getTest());
+ bean.setTest(constraint.getTest().getPath());
String message = constraint.getMessage();
if (message != null) {
@@ -550,7 +550,7 @@ private static void applyKeyField(@NonNull IKeyField keyField, @NonNull KeyField
bean.setPattern(pattern);
}
- bean.setTarget(keyField.getTarget());
+ bean.setTarget(keyField.getTarget().getPath());
MarkupMultiline remarks = keyField.getRemarks();
if (remarks != null) {
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ModelFactory.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ModelFactory.java
index e13724971..d28bb4869 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ModelFactory.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ModelFactory.java
@@ -6,6 +6,7 @@
package gov.nist.secauto.metaschema.core.model.xml.impl;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.AbstractConstraintBuilder;
@@ -63,8 +64,10 @@ private ModelFactory() {
}
@NonNull
- private static String target(@Nullable String target) {
- return target == null ? IConstraint.DEFAULT_TARGET_METAPATH : target;
+ private static IMetapathExpression metapath(@Nullable String target, @NonNull ISource source) {
+ return target == null
+ ? IConstraint.DEFAULT_TARGET_METAPATH
+ : IMetapathExpression.lazyCompile(target, source.getStaticContext());
}
@NonNull
@@ -145,7 +148,7 @@ private static Map toAllowedValues(
public static IAllowedValuesConstraint newAllowedValuesConstraint(
@NonNull TargetedAllowedValuesConstraintType xmlObject,
@NonNull ISource source) {
- return newAllowedValuesConstraint(xmlObject, target(xmlObject.getTarget()), source);
+ return newAllowedValuesConstraint(xmlObject, metapath(xmlObject.getTarget(), source), source);
}
/**
@@ -167,7 +170,7 @@ public static IAllowedValuesConstraint newAllowedValuesConstraint(
@NonNull
private static IAllowedValuesConstraint newAllowedValuesConstraint(
@NonNull AllowedValuesType xmlObject,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull ISource source) {
IAllowedValuesConstraint.Builder builder = IAllowedValuesConstraint.builder();
@@ -192,7 +195,7 @@ private static IAllowedValuesConstraint newAllowedValuesConstraint(
@NonNull
private static > T applyToBuilder(
@NonNull ConstraintType xmlObject,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull ISource source,
@NonNull T builder) {
@@ -218,7 +221,7 @@ private static IAllowedValuesConstraint newAllowedValuesConstraint(
public static IMatchesConstraint newMatchesConstraint(
@NonNull TargetedMatchesConstraintType xmlObject,
@NonNull ISource source) {
- return newMatchesConstraint(xmlObject, target(xmlObject.getTarget()), source);
+ return newMatchesConstraint(xmlObject, metapath(xmlObject.getTarget(), source), source);
}
/**
@@ -240,7 +243,7 @@ public static IMatchesConstraint newMatchesConstraint(
@NonNull
private static IMatchesConstraint newMatchesConstraint(
@NonNull MatchesConstraintType xmlObject,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull ISource source) {
IMatchesConstraint.Builder builder = IMatchesConstraint.builder();
@@ -270,10 +273,9 @@ private static void buildKeyFields(
@NonNull ISource source) {
for (KeyConstraintType.KeyField xmlKeyField : xmlObject.getKeyFieldList()) {
IKeyField keyField = IKeyField.of(
- ObjectUtils.requireNonNull(xmlKeyField.getTarget()),
+ metapath(ObjectUtils.requireNonNull(xmlKeyField.getTarget()), source),
xmlKeyField.isSetPattern() ? xmlKeyField.getPattern() : null, // NOPMD - intentional
- xmlKeyField.isSetRemarks() ? remarks(ObjectUtils.notNull(xmlKeyField.getRemarks())) : null,
- source);
+ xmlKeyField.isSetRemarks() ? remarks(ObjectUtils.notNull(xmlKeyField.getRemarks())) : null);
builder.keyField(keyField);
}
}
@@ -293,7 +295,7 @@ public static IUniqueConstraint newUniqueConstraint(
@NonNull ISource source) {
IUniqueConstraint.Builder builder = IUniqueConstraint.builder();
- applyToBuilder(xmlObject, target(xmlObject.getTarget()), source, builder);
+ applyToBuilder(xmlObject, metapath(xmlObject.getTarget(), source), source, builder);
if (xmlObject.isSetMessage()) {
builder.message(ObjectUtils.notNull(xmlObject.getMessage()));
@@ -323,7 +325,7 @@ public static IIndexConstraint newIndexConstraint(
@NonNull ISource source) {
IIndexConstraint.Builder builder = IIndexConstraint.builder(ObjectUtils.requireNonNull(xmlObject.getName()));
- applyToBuilder(xmlObject, target(xmlObject.getTarget()), source, builder);
+ applyToBuilder(xmlObject, metapath(xmlObject.getTarget(), source), source, builder);
if (xmlObject.isSetMessage()) {
builder.message(ObjectUtils.notNull(xmlObject.getMessage()));
@@ -351,7 +353,7 @@ public static IIndexConstraint newIndexConstraint(
public static IIndexHasKeyConstraint newIndexHasKeyConstraint(
@NonNull TargetedIndexHasKeyConstraintType xmlObject,
@NonNull ISource source) {
- return newIndexHasKeyConstraint(xmlObject, target(xmlObject.getTarget()), source);
+ return newIndexHasKeyConstraint(xmlObject, metapath(xmlObject.getTarget(), source), source);
}
/**
@@ -373,7 +375,7 @@ public static IIndexHasKeyConstraint newIndexHasKeyConstraint(
@NonNull
private static IIndexHasKeyConstraint newIndexHasKeyConstraint(
@NonNull IndexHasKeyConstraintType xmlObject,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull ISource source) {
IIndexHasKeyConstraint.Builder builder
= IIndexHasKeyConstraint.builder(ObjectUtils.requireNonNull(xmlObject.getName()));
@@ -406,7 +408,7 @@ private static IIndexHasKeyConstraint newIndexHasKeyConstraint(
public static IExpectConstraint newExpectConstraint(
@NonNull TargetedExpectConstraintType xmlObject,
@NonNull ISource source) {
- return newExpectConstraint(xmlObject, target(xmlObject.getTarget()), source);
+ return newExpectConstraint(xmlObject, metapath(xmlObject.getTarget(), source), source);
}
/**
@@ -428,7 +430,7 @@ public static IExpectConstraint newExpectConstraint(
@NonNull
private static IExpectConstraint newExpectConstraint(
@NonNull ExpectConstraintType xmlObject,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull ISource source) {
IExpectConstraint.Builder builder = IExpectConstraint.builder();
@@ -443,7 +445,10 @@ private static IExpectConstraint newExpectConstraint(
builder.remarks(remarks(ObjectUtils.notNull(xmlObject.getRemarks())));
}
- builder.test(ObjectUtils.requireNonNull(xmlObject.getTest()));
+ builder.test(
+ IMetapathExpression.lazyCompile(
+ ObjectUtils.requireNonNull(xmlObject.getTest()),
+ source.getStaticContext()));
return builder.build();
}
@@ -464,7 +469,7 @@ public static ICardinalityConstraint newCardinalityConstraint(
ICardinalityConstraint.Builder builder = ICardinalityConstraint.builder();
- applyToBuilder(xmlObject, target(xmlObject.getTarget()), source, builder);
+ applyToBuilder(xmlObject, metapath(xmlObject.getTarget(), source), source, builder);
if (xmlObject.isSetMessage()) {
builder.message(ObjectUtils.notNull(xmlObject.getMessage()));
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnHasChildrenTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnHasChildrenTest.java
index ad89574e0..76e94165c 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnHasChildrenTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnHasChildrenTest.java
@@ -62,7 +62,7 @@ private static Stream provideValues() { // NOPMD - false positive
void test(boolean expected, @NonNull String metapath) {
DynamicContext dynamicContext = newDynamicContext();
- INodeItem node = MockedDocumentGenerator.generateDocumentNodeItem(getContext());
+ INodeItem node = MockedDocumentGenerator.generateDocumentNodeItem();
Boolean result = IMetapathExpression.compile(metapath, dynamicContext.getStaticContext())
.evaluateAs(node, IMetapathExpression.ResultType.BOOLEAN, dynamicContext);
assertEquals(expected, result);
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnInnermostTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnInnermostTest.java
index 17746b27d..ffa773f76 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnInnermostTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnInnermostTest.java
@@ -52,7 +52,7 @@ private static Stream provideValues() { // NOPMD - false positive
@MethodSource("provideValues")
void test(@NonNull String expectedValueMetapath, @NonNull String actualValuesMetapath) {
DynamicContext dynamicContext = newDynamicContext();
- INodeItem node = MockedDocumentGenerator.generateDocumentNodeItem(getContext());
+ INodeItem node = MockedDocumentGenerator.generateDocumentNodeItem();
ISequence extends INodeItem> expected
= IMetapathExpression.compile(expectedValueMetapath, dynamicContext.getStaticContext())
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnLocalNameTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnLocalNameTest.java
index 6a0647477..375d88863 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnLocalNameTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnLocalNameTest.java
@@ -66,7 +66,7 @@ void test(@Nullable IEnhancedQName expected, @NonNull String metapath) {
IStringItem result = IMetapathExpression.compile(metapath, dynamicContext.getStaticContext())
.evaluateAs(
- MockedDocumentGenerator.generateDocumentNodeItem(getContext()),
+ MockedDocumentGenerator.generateDocumentNodeItem(),
IMetapathExpression.ResultType.ITEM,
dynamicContext);
assertNotNull(result);
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNameTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNameTest.java
index 5b9a376d9..0937e6a89 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNameTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNameTest.java
@@ -65,7 +65,7 @@ void test(@Nullable IEnhancedQName expected, @NonNull String metapath) {
IStringItem result = IMetapathExpression.compile(metapath, dynamicContext.getStaticContext())
.evaluateAs(
- MockedDocumentGenerator.generateDocumentNodeItem(getContext()),
+ MockedDocumentGenerator.generateDocumentNodeItem(),
IMetapathExpression.ResultType.ITEM,
dynamicContext);
assertNotNull(result);
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNamespaceUriTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNamespaceUriTest.java
index 632738974..23c3b2b52 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNamespaceUriTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNamespaceUriTest.java
@@ -66,7 +66,7 @@ void test(@Nullable IEnhancedQName expected, @NonNull String metapath) {
IStringItem result = IMetapathExpression.compile(metapath, dynamicContext.getStaticContext())
.evaluateAs(
- MockedDocumentGenerator.generateDocumentNodeItem(getContext()),
+ MockedDocumentGenerator.generateDocumentNodeItem(),
IMetapathExpression.ResultType.ITEM,
dynamicContext);
assertNotNull(result);
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOutermostTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOutermostTest.java
index e54963f98..72e8791c9 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOutermostTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOutermostTest.java
@@ -59,7 +59,7 @@ private static Stream provideValues() { // NOPMD - false positive
@MethodSource("provideValues")
void test(@NonNull String expectedValueMetapath, @NonNull String actualValuesMetapath) {
DynamicContext dynamicContext = newDynamicContext();
- INodeItem node = MockedDocumentGenerator.generateDocumentNodeItem(getContext());
+ INodeItem node = MockedDocumentGenerator.generateDocumentNodeItem();
ISequence extends INodeItem> expected
= IMetapathExpression.compile(expectedValueMetapath, dynamicContext.getStaticContext())
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnRootTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnRootTest.java
index e8d4c330f..fabe74d4e 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnRootTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnRootTest.java
@@ -55,7 +55,7 @@ private static Stream provideValues() { // NOPMD - false positive
void test(@NonNull String metapath) {
DynamicContext dynamicContext = newDynamicContext();
- INodeItem root = MockedDocumentGenerator.generateDocumentNodeItem(getContext());
+ INodeItem root = MockedDocumentGenerator.generateDocumentNodeItem();
INodeItem result = IMetapathExpression.compile(metapath, dynamicContext.getStaticContext())
.evaluateAs(root, IMetapathExpression.ResultType.ITEM, dynamicContext);
INodeItem rootResult
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/impl/MockedDocumentGenerator.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/impl/MockedDocumentGenerator.java
index 3b1b39aa4..8ac532550 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/impl/MockedDocumentGenerator.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/impl/MockedDocumentGenerator.java
@@ -14,51 +14,107 @@
import gov.nist.secauto.metaschema.core.model.IAssemblyInstance;
import gov.nist.secauto.metaschema.core.model.IFieldInstance;
import gov.nist.secauto.metaschema.core.model.IFlagInstance;
-import gov.nist.secauto.metaschema.core.model.IResourceLocation;
+import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
-import gov.nist.secauto.metaschema.core.testing.MockedModelTestSupport;
-
-import org.jmock.Mockery;
+import gov.nist.secauto.metaschema.core.testing.model.MockedModelTestSupport;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.net.URI;
import edu.umd.cs.findbugs.annotations.NonNull;
+/**
+ * Supports generating a simple Metapath node item-based document model for use
+ * in unit tests.
+ */
public class MockedDocumentGenerator {
+ /**
+ * The document base URI used by documents generated by the
+ * {@link #generateDocumentNodeItem()} method.
+ */
+ @NonNull
+ public static final URI BASE_URI = ObjectUtils.notNull(URI.create("https://example.com/resource"));
+ /**
+ * The namespace used by Metaschema module definitions generated by the
+ * {@link #generateDocumentNodeItem()} method.
+ */
@NonNull
public static final String NS = "http://example.com/ns";
+ /**
+ * The qualified name for the root node ({@code /Q{http://example.com/ns}root})
+ * of a document generated by the {@link #generateDocumentNodeItem()} method.
+ */
@NonNull
public static final IEnhancedQName ROOT_QNAME = IEnhancedQName.of(NS, "root");
+ /**
+ * The qualified name for the assembly child node
+ * ({@code /Q{http://example.com/ns}root/Q{http://example.com/ns}assembly}) of a
+ * document generated by the {@link #generateDocumentNodeItem()} method.
+ */
@NonNull
public static final IEnhancedQName ASSEMBLY_QNAME = IEnhancedQName.of(NS, "assembly");
+ /**
+ * The qualified name for the field child node
+ * ({@code /Q{http://example.com/ns}root/Q{http://example.com/ns}field}) of a
+ * document generated by the {@link #generateDocumentNodeItem()} method.
+ */
@NonNull
public static final IEnhancedQName FIELD_QNAME = IEnhancedQName.of(NS, "field");
+ /**
+ * The qualified name for the flag child node
+ * ({@code /Q{http://example.com/ns}root/Q{http://example.com/ns}assembly/@field-flag})
+ * of a document generated by the {@link #generateDocumentNodeItem()} method.
+ */
@NonNull
public static final IEnhancedQName ASSEMBLY_FLAG_QNAME = IEnhancedQName.of("assembly-flag");
+ /**
+ * The qualified name for the flag child node
+ * ({@code /Q{http://example.com/ns}root/Q{http://example.com/ns}field/@field-flag})
+ * of a document generated by the {@link #generateDocumentNodeItem()} method.
+ */
@NonNull
public static final IEnhancedQName FIELD_FLAG_QNAME = IEnhancedQName.of("field-flag");
- public static IDMDocumentNodeItem generateDocumentNodeItem(@NonNull Mockery context) {
- MockedModelTestSupport mocking = new MockedModelTestSupport(context);
- IResourceLocation resourceLocation = mocking.mock(IResourceLocation.class);
+ /**
+ * Generate a simple Metaschema-based document model.
+ *
+ * @return the document node item for this model
+ */
+ public static IDMDocumentNodeItem generateDocumentNodeItem() {
+ MockedModelTestSupport mocking = new MockedModelTestSupport();
- IAssemblyDefinition rootDefinition = mocking.assembly().qname(ROOT_QNAME).rootQName(ROOT_QNAME).toDefinition();
- IAssemblyInstance assemblyInstance = mocking.assembly().qname(ASSEMBLY_QNAME).toInstance(rootDefinition);
- IFlagInstance assemblyFlag = mocking.flag().qname(ASSEMBLY_FLAG_QNAME).toInstance(assemblyInstance.getDefinition());
- IFieldInstance fieldInstance = mocking.field().qname(FIELD_QNAME).toInstance(rootDefinition);
- IFlagInstance fieldFlag = mocking.flag().qname(FIELD_FLAG_QNAME).toInstance(fieldInstance.getDefinition());
+ ISource moduleSource = ISource.externalSource("https://example.com/module");
+
+ IAssemblyDefinition rootDefinition = mocking.assembly()
+ .qname(ROOT_QNAME)
+ .rootQName(ROOT_QNAME)
+ .source(moduleSource)
+ .toDefinition();
+ IAssemblyInstance assemblyInstance = mocking.assembly()
+ .qname(ASSEMBLY_QNAME)
+ .source(moduleSource)
+ .toInstance(rootDefinition);
+ IFlagInstance assemblyFlag = mocking.flag()
+ .qname(ASSEMBLY_FLAG_QNAME)
+ .source(moduleSource)
+ .toInstance(assemblyInstance.getDefinition());
+ IFieldInstance fieldInstance = mocking.field()
+ .qname(FIELD_QNAME)
+ .source(moduleSource)
+ .toInstance(rootDefinition);
+ IFlagInstance fieldFlag = mocking.flag()
+ .qname(FIELD_FLAG_QNAME)
+ .source(moduleSource)
+ .toInstance(fieldInstance.getDefinition());
IDMDocumentNodeItem document = IDMDocumentNodeItem.newInstance(
- URI.create("https://example.com/resource"),
- resourceLocation,
- rootDefinition,
- resourceLocation);
+ BASE_URI,
+ rootDefinition);
IDMRootAssemblyNodeItem root = document.getRootAssemblyNodeItem();
- IDMAssemblyNodeItem assembly = root.newAssembly(assemblyInstance, resourceLocation);
- assembly.newFlag(assemblyFlag, resourceLocation, IStringItem.valueOf("assembly-flag"));
- IDMFieldNodeItem field = root.newField(fieldInstance, resourceLocation, IStringItem.valueOf("field"));
- field.newFlag(fieldFlag, resourceLocation, IStringItem.valueOf("field-flag"));
-
+ IDMAssemblyNodeItem assembly = root.newAssembly(assemblyInstance);
+ assembly.newFlag(assemblyFlag, IStringItem.valueOf("assembly-flag"));
+ IDMFieldNodeItem field = root.newField(fieldInstance, IStringItem.valueOf("field"));
+ field.newFlag(fieldFlag, IStringItem.valueOf("field-flag"));
return document;
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/node/DefaultNodeItemFactoryTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/node/DefaultNodeItemFactoryTest.java
index bd81cfab3..950cba715 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/node/DefaultNodeItemFactoryTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/node/DefaultNodeItemFactoryTest.java
@@ -1,27 +1,22 @@
package gov.nist.secauto.metaschema.core.metapath.item.node;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.allOf;
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.Matchers.equalTo;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
+import gov.nist.secauto.metaschema.core.mdm.IDMAssemblyNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.StaticContext;
+import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
-import gov.nist.secauto.metaschema.core.model.IFieldInstance;
+import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
-import gov.nist.secauto.metaschema.core.testing.MockedModelTestSupport;
+import gov.nist.secauto.metaschema.core.testing.model.MockedModelTestSupport;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
-import org.hamcrest.FeatureMatcher;
-import org.hamcrest.Matcher;
-import org.jmock.Expectations;
import org.junit.jupiter.api.Test;
-import java.net.URI;
import java.util.Collection;
import java.util.List;
-import java.util.function.Function;
import java.util.stream.Collectors;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -29,104 +24,41 @@
class DefaultNodeItemFactoryTest
extends MockedModelTestSupport {
@NonNull
- private static final URI NS_URI = ObjectUtils.notNull(URI.create("http://example.com/ns"));
- @NonNull
- private static final String NS = ObjectUtils.notNull(NS_URI.toASCIIString());
-
- @Test
- void testGenerateFlags() {
- DefaultNodeItemFactory nodeFactory = DefaultNodeItemFactory.instance();
-
- IAssemblyDefinition parent = assembly()
- .namespace(NS_URI)
- .name("assembly1")
- .toDefinition();
-
- IFieldInstance fieldInstance = field()
- .namespace(NS_URI)
- .name("field1")
- .flags(List.of(
- flag().namespace(NS_URI).name("flag1")))
- .toInstance(parent);
-
- Object fieldValue = "test value";
-
- // setup the value calls
- getContext().checking(new Expectations() {
- { // NOPMD - intentional
- allowing(fieldInstance.getDefinition().getFlagInstanceByName(IEnhancedQName.of(NS, "flag1").getIndexPosition()))
- .getValue(fieldValue);
- will(returnValue("flag1 value"));
- }
- });
-
- IAssemblyNodeItem parentItem = INodeItemFactory.instance().newAssemblyNodeItem(parent);
- IFieldNodeItem field = new FieldInstanceNodeItemImpl(fieldInstance, parentItem, 2, fieldValue, nodeFactory);
-
- Collection extends IFlagNodeItem> flagItems = field.getFlags();
- assertThat(flagItems, containsInAnyOrder(
- allOf(
- match("name", IFlagNodeItem::getQName, equalTo(IEnhancedQName.of(NS, "flag1"))),
- match("value", IFlagNodeItem::getValue, equalTo("flag1 value"))))); // NOPMD
- }
+ private static final String NS = ObjectUtils.notNull("http://example.com/ns");
@Test
void testGenerateModelItems() {
IAssemblyDefinition assembly = assembly()
- .namespace(NS_URI)
+ .namespace(NS)
.name("assembly1")
+ .source(ISource.externalSource("http://example.com/module"))
.flags(List.of(
- flag().namespace(NS_URI).name("flag1")))
+ flag().namespace(NS).name("flag1")))
.modelInstances(List.of(
- field().namespace(NS_URI).name("field1")))
+ field().namespace(NS).name("field1")))
.toDefinition();
- Object assemblyValue = "assembly value";
- Object flagValue = "flag1 value";
- Object fieldValue = "field1 value";
-
// Setup the value calls
- getContext().checking(new Expectations() {
- { // NOPMD - intentional
- allowing(assembly.getFlagInstanceByName(IEnhancedQName.of(NS, "flag1").getIndexPosition()))
- .getValue(assemblyValue);
- will(returnValue(flagValue));
- allowing(assembly.getNamedModelInstanceByName(IEnhancedQName.of(NS, "field1").getIndexPosition()))
- .getValue(assemblyValue);
- will(returnValue(fieldValue));
- allowing(assembly.getNamedModelInstanceByName(IEnhancedQName.of(NS, "field1").getIndexPosition()))
- .getItemValues(fieldValue);
- will(returnValue(List.of(fieldValue)));
- }
- });
-
- IAssemblyNodeItem parentItem = INodeItemFactory.instance().newAssemblyNodeItem(assembly, null, assemblyValue);
+ StaticContext staticContext = StaticContext.instance();
+ IDMAssemblyNodeItem parentItem = IDMAssemblyNodeItem.newInstance(assembly, staticContext);
+ assembly.getFlagInstances()
+ .forEach(flag -> parentItem.newFlag(flag, IStringItem.valueOf(flag.getName() + " value")));
+ assembly.getFieldInstances()
+ .forEach(field -> {
+ parentItem.newField(field, IStringItem.valueOf(field.getName() + " value"));
+ });
Collection extends IFlagNodeItem> flagItems = parentItem.getFlags();
Collection extends IModelNodeItem, ?>> modelItems = parentItem.modelItems()
.collect(Collectors.toUnmodifiableList());
assertAll(
- () -> assertThat(flagItems, containsInAnyOrder(
- allOf(
- match("name", IFlagNodeItem::getQName, equalTo(IEnhancedQName.of(NS, "flag1"))),
- match("value", IFlagNodeItem::getValue, equalTo("flag1 value"))))),
- () -> assertThat(modelItems, containsInAnyOrder(
- allOf(
- match("name", IModelNodeItem::getQName,
- equalTo(IEnhancedQName.of(NS, "field1"))),
- match("value", IModelNodeItem::getValue,
- equalTo("field1 value"))))));
- }
-
- private static FeatureMatcher match(
- @NonNull String label,
- @NonNull Function lambda,
- Matcher matcher) {
- return new FeatureMatcher<>(matcher, label, label) {
- @Override
- protected R featureValueOf(T actual) {
- return lambda.apply(actual);
- }
- };
+ () -> assertThat(flagItems).extracting(IFlagNodeItem::getQName)
+ .isEqualTo(List.of(IEnhancedQName.of(NS, "flag1"))),
+ () -> assertThat(flagItems).extracting(flag -> flag.toAtomicItem().asString())
+ .isEqualTo(List.of("flag1 value")),
+ () -> assertThat(modelItems).extracting(IModelNodeItem::getQName)
+ .isEqualTo(List.of(IEnhancedQName.of(NS, "field1"))),
+ () -> assertThat(modelItems).extracting(field -> field.toAtomicItem().asString())
+ .isEqualTo(List.of("field1 value")));
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/node/MockNodeItemFactory.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/node/MockNodeItemFactory.java
index aa6352f9a..10831650c 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/node/MockNodeItemFactory.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/node/MockNodeItemFactory.java
@@ -3,26 +3,22 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.withSettings;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
import gov.nist.secauto.metaschema.core.model.IFlagDefinition;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
+import gov.nist.secauto.metaschema.core.testing.model.mocking.AbstractMockitoFactory;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
-import org.mockito.Answers;
-import org.mockito.Mockito;
-
import java.net.URI;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -31,20 +27,8 @@
// TODO: Integrate with classes in gov.nist.secauto.metaschema.core.testing
@SuppressWarnings("checkstyle:MissingJavadocMethodCheck")
@SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT")
-public class MockNodeItemFactory {
- @SuppressWarnings("null")
- @NonNull
- protected T newMock(@NonNull Class clazz, @NonNull String name) {
- String mockName = new StringBuilder()
- .append(clazz.getSimpleName())
- .append('-')
- .append(name)
- .append('-')
- .append(UUID.randomUUID().toString())
- .toString();
- return Mockito.mock(clazz, withSettings().name(mockName).defaultAnswer(Answers.CALLS_REAL_METHODS));
- }
-
+public class MockNodeItemFactory
+ extends AbstractMockitoFactory {
@NonNull
public IDocumentNodeItem document(
URI documentURI,
@@ -52,9 +36,9 @@ public IDocumentNodeItem document(
List flags,
List> modelItems) {
String qname = ObjectUtils.requireNonNull(rootName.toString());
- IDocumentNodeItem document = newMock(IDocumentNodeItem.class, qname);
- IRootAssemblyNodeItem root = newMock(IRootAssemblyNodeItem.class, qname);
- IAssemblyDefinition definition = newMock(IAssemblyDefinition.class, qname);
+ IDocumentNodeItem document = mock(IDocumentNodeItem.class, qname);
+ IRootAssemblyNodeItem root = mock(IRootAssemblyNodeItem.class, qname);
+ IAssemblyDefinition definition = mock(IAssemblyDefinition.class, qname);
// doAnswer(invocation -> Stream.of(root)).when(document).modelItems();
doReturn(root).when(document).getRootAssemblyNodeItem();
@@ -136,8 +120,8 @@ protected void handleChildren(
@NonNull
public IFlagNodeItem flag(@NonNull IEnhancedQName name, @NonNull IAnyAtomicItem value) {
- IFlagNodeItem flag = newMock(IFlagNodeItem.class, ObjectUtils.notNull(name.toString()));
- IFlagDefinition definition = newMock(IFlagDefinition.class, ObjectUtils.notNull(name.toString()));
+ IFlagNodeItem flag = mock(IFlagNodeItem.class, ObjectUtils.notNull(name.toString()));
+ IFlagDefinition definition = mock(IFlagDefinition.class, ObjectUtils.notNull(name.toString()));
doReturn(name).when(flag).getQName();
doReturn(true).when(flag).hasValue();
@@ -163,8 +147,8 @@ public IFieldNodeItem field(
@NonNull IEnhancedQName name,
@NonNull IAnyAtomicItem value,
List flags) {
- IFieldNodeItem field = newMock(IFieldNodeItem.class, ObjectUtils.notNull(name.toString()));
- IFieldDefinition definition = newMock(IFieldDefinition.class, ObjectUtils.notNull(name.toString()));
+ IFieldNodeItem field = mock(IFieldNodeItem.class, ObjectUtils.notNull(name.toString()));
+ IFieldDefinition definition = mock(IFieldDefinition.class, ObjectUtils.notNull(name.toString()));
doReturn(name).when(field).getQName();
doReturn(true).when(field).hasValue();
@@ -184,8 +168,8 @@ public IAssemblyNodeItem assembly(
@NonNull IEnhancedQName name,
List flags,
List> modelItems) {
- IAssemblyNodeItem assembly = newMock(IAssemblyNodeItem.class, ObjectUtils.notNull(name.toString()));
- IAssemblyDefinition definition = newMock(IAssemblyDefinition.class, ObjectUtils.notNull(name.toString()));
+ IAssemblyNodeItem assembly = mock(IAssemblyNodeItem.class, ObjectUtils.notNull(name.toString()));
+ IAssemblyDefinition definition = mock(IAssemblyDefinition.class, ObjectUtils.notNull(name.toString()));
doReturn(name).when(assembly).getQName();
doReturn(false).when(assembly).hasValue();
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractConfigurableMessageConstraintTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractConfigurableMessageConstraintTest.java
new file mode 100644
index 000000000..54e3694a0
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/model/constraint/impl/AbstractConfigurableMessageConstraintTest.java
@@ -0,0 +1,139 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.model.constraint.impl;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
+import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
+import gov.nist.secauto.metaschema.core.metapath.StaticContext;
+import gov.nist.secauto.metaschema.core.metapath.function.library.impl.MockedDocumentGenerator;
+import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
+import gov.nist.secauto.metaschema.core.model.ISource;
+import gov.nist.secauto.metaschema.core.model.constraint.DefaultConstraintValidator;
+import gov.nist.secauto.metaschema.core.model.constraint.FindingCollectingConstraintValidationHandler;
+import gov.nist.secauto.metaschema.core.model.constraint.IExpectConstraint;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import org.junit.jupiter.api.Test;
+
+import java.net.URI;
+
+class AbstractConfigurableMessageConstraintTest
+ extends ExpressionTestBase {
+
+ @Test
+ void testDifferentNS() {
+ StaticContext constraintContext = StaticContext.builder()
+ .defaultModelNamespace(NS)
+ .baseUri(ObjectUtils.notNull(URI.create("https://example.com/other")))
+ .build();
+
+ IExpectConstraint expect = IExpectConstraint.builder()
+ .target(IMetapathExpression.compile("assembly", constraintContext))
+ .test(IMetapathExpression.compile("ancestor::root", constraintContext))
+ .source(ISource.externalSource(constraintContext, false))
+ .build();
+
+ IDocumentNodeItem document = MockedDocumentGenerator.generateDocumentNodeItem();
+ document.getRootAssemblyNodeItem().getDefinition().addConstraint(expect);
+
+ FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler();
+ DefaultConstraintValidator validator = new DefaultConstraintValidator(handler);
+ validator.validate(
+ document,
+ new DynamicContext(document.getStaticContext()));
+
+ assertAll(
+ () -> assertTrue(handler.isPassing()),
+ () -> assertEquals(0, handler.getFindings().size()));
+ }
+
+ @Test
+ void testWildCard() {
+ StaticContext constraintContext = StaticContext.builder()
+ .defaultModelNamespace(NS)
+ .baseUri(ObjectUtils.notNull(URI.create("https://example.com/other")))
+ .build();
+
+ IExpectConstraint expect = IExpectConstraint.builder()
+ .target(IMetapathExpression.compile("assembly", constraintContext))
+ .test(IMetapathExpression.compile("ancestor::*:root", constraintContext))
+ .source(ISource.externalSource(constraintContext, false))
+ .build();
+
+ IDocumentNodeItem document = MockedDocumentGenerator.generateDocumentNodeItem();
+ document.getRootAssemblyNodeItem().getDefinition().addConstraint(expect);
+
+ FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler();
+ DefaultConstraintValidator validator = new DefaultConstraintValidator(handler);
+ validator.validate(
+ document,
+ new DynamicContext(document.getStaticContext()));
+
+ assertAll(
+ () -> assertTrue(handler.isPassing()),
+ () -> assertEquals(0, handler.getFindings().size()));
+ }
+
+ @Test
+ void testPrefix() {
+ StaticContext constraintContext = StaticContext.builder()
+ .defaultModelNamespace(NS)
+ .baseUri(ObjectUtils.notNull(URI.create("https://example.com/other")))
+ .namespace("ns", MockedDocumentGenerator.NS)
+ .build();
+
+ IExpectConstraint expect = IExpectConstraint.builder()
+ .target(IMetapathExpression.compile("ns:assembly", constraintContext))
+ .test(IMetapathExpression.compile("ancestor::ns:root", constraintContext))
+ .source(ISource.externalSource(constraintContext, false))
+ .build();
+
+ IDocumentNodeItem document = MockedDocumentGenerator.generateDocumentNodeItem();
+ document.getRootAssemblyNodeItem().getDefinition().addConstraint(expect);
+
+ FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler();
+ DefaultConstraintValidator validator = new DefaultConstraintValidator(handler);
+ validator.validate(
+ document,
+ new DynamicContext(document.getStaticContext()));
+
+ assertAll(
+ () -> assertTrue(handler.isPassing()),
+ () -> assertEquals(0, handler.getFindings().size()));
+ }
+
+ @Test
+ void testQualifiedName() {
+ StaticContext constraintContext = StaticContext.builder()
+ .defaultModelNamespace(NS)
+ .baseUri(ObjectUtils.notNull(URI.create("https://example.com/other")))
+ .build();
+
+ IExpectConstraint expect = IExpectConstraint.builder()
+ .target(IMetapathExpression.compile("Q{" + MockedDocumentGenerator.NS + "}assembly", constraintContext))
+ .test(IMetapathExpression.compile("ancestor::Q{" + MockedDocumentGenerator.NS + "}root", constraintContext))
+ .source(ISource.externalSource(constraintContext, false))
+ .build();
+
+ IDocumentNodeItem document = MockedDocumentGenerator.generateDocumentNodeItem();
+ document.getRootAssemblyNodeItem().getDefinition().addConstraint(expect);
+
+ FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler();
+ DefaultConstraintValidator validator = new DefaultConstraintValidator(handler);
+ validator.validate(
+ document,
+ new DynamicContext(document.getStaticContext()));
+
+ assertAll(
+ () -> assertTrue(handler.isPassing()),
+ () -> assertEquals(0, handler.getFindings().size()));
+ }
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/AssemblyBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/AssemblyBuilder.java
deleted file mode 100644
index 3f8da001d..000000000
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/AssemblyBuilder.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * SPDX-FileCopyrightText: none
- * SPDX-License-Identifier: CC0-1.0
- */
-
-package gov.nist.secauto.metaschema.core.testing;
-
-import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
-import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute;
-import gov.nist.secauto.metaschema.core.model.IFlagInstance;
-import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute;
-import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
-import gov.nist.secauto.metaschema.core.util.CollectionUtil;
-import gov.nist.secauto.metaschema.core.util.ObjectUtils;
-
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-import edu.umd.cs.findbugs.annotations.Nullable;
-
-public final class AssemblyBuilder
- extends AbstractModelBuilder
- implements IModelInstanceBuilder {
-
- private String rootNamespace = "";
- private String rootName;
- private List flags;
- private List extends IModelInstanceBuilder> modelInstances;
-
- private AssemblyBuilder(@NonNull Mockery ctx) {
- super(ctx);
- }
-
- /**
- * Create a new builder using the provided mocking context.
- *
- * @param ctx
- * the mocking context
- * @return the new builder
- */
- @NonNull
- public static AssemblyBuilder builder(@NonNull Mockery ctx) {
- return new AssemblyBuilder(ctx).reset();
- }
-
- @Override
- public AssemblyBuilder reset() {
- this.flags = CollectionUtil.emptyList();
- this.modelInstances = CollectionUtil.emptyList();
- return this;
- }
-
- /**
- * Apply the provided root namespace for use by this builder.
- *
- * @param name
- * the namespace to use
- * @return this builder
- */
- @NonNull
- public AssemblyBuilder rootNamespace(@NonNull String name) {
- this.rootNamespace = name;
- return this;
- }
-
- /**
- * Apply the provided root namespace for use by this builder.
- *
- * @param name
- * the namespace to use
- * @return this builder
- */
- @NonNull
- public AssemblyBuilder rootNamespace(@NonNull URI name) {
- return rootNamespace(ObjectUtils.notNull(name.toASCIIString()));
- }
-
- /**
- * Apply the provided root name for use by this builder.
- *
- * @param name
- * the name to use
- * @return this builder
- */
- @NonNull
- public AssemblyBuilder rootName(@NonNull String name) {
- this.rootName = name;
- return this;
- }
-
- /**
- * Apply the provided root qualified name for use by this builder.
- *
- * @param qname
- * the qualified name to use
- * @return this builder
- */
- @NonNull
- public AssemblyBuilder rootQName(@NonNull IEnhancedQName qname) {
- this.rootName = qname.getLocalName();
- this.rootNamespace = qname.getNamespace();
- return this;
- }
-
- /**
- * Use the provided flag instances for built fields.
- *
- * @param flags
- * the flags to use
- * @return this builder
- */
- public AssemblyBuilder flags(@Nullable List flags) {
- this.flags = flags == null ? CollectionUtil.emptyList() : flags;
- return this;
- }
-
- /**
- * Use the provided model instances for built fields.
- *
- * @param modelInstances
- * the model instances to use
- * @return this builder
- */
- public AssemblyBuilder modelInstances(@Nullable List extends IModelInstanceBuilder> modelInstances) {
- this.modelInstances = modelInstances == null ? CollectionUtil.emptyList() : modelInstances;
- return this;
- }
-
- @Override
- @NonNull
- public IAssemblyInstanceAbsolute toInstance(
- @NonNull IAssemblyDefinition parent) {
- IAssemblyDefinition def = toDefinition();
- return toInstance(parent, def);
- }
-
- /**
- * Build a mocked assembly instance, using the provided definition, as a child
- * of the provided parent.
- *
- * @param parent
- * the parent containing the new instance
- * @param definition
- * the definition to base the instance on
- * @return the new mocked instance
- */
- @NonNull
- public IAssemblyInstanceAbsolute toInstance(
- @NonNull IAssemblyDefinition parent,
- @NonNull IAssemblyDefinition definition) {
- validate();
-
- IAssemblyInstanceAbsolute retval = mock(IAssemblyInstanceAbsolute.class);
- applyNamedInstance(retval, definition, parent);
- return retval;
- }
-
- /**
- * Build a mocked assembly definition.
- *
- * @return the new mocked definition
- */
- @NonNull
- public IAssemblyDefinition toDefinition() {
- validate();
-
- IAssemblyDefinition retval = mock(IAssemblyDefinition.class);
- applyDefinition(retval);
-
- Map flags = this.flags.stream()
- .map(builder -> builder.toInstance(retval))
- .collect(Collectors.toUnmodifiableMap(
- IFlagInstance::getQName,
- Function.identity()));
-
- Map modelInstances = this.modelInstances.stream()
- .map(builder -> builder.toInstance(retval))
- .collect(Collectors.toUnmodifiableMap(
- INamedModelInstanceAbsolute::getQName,
- Function.identity()));
-
- getContext().checking(new Expectations() {
- {
- if (rootName != null) {
- allowing(retval).getRootQName();
- will(returnValue(IEnhancedQName.of(ObjectUtils.notNull(rootNamespace), ObjectUtils.notNull(rootName))));
- }
-
- allowing(retval).getFlagInstances();
- will(returnValue(flags.values()));
- flags.forEach((key, value) -> {
- allowing(retval).getFlagInstanceByName(with(key.getIndexPosition()));
- will(returnValue(value));
- });
- allowing(retval).getModelInstances();
- will(returnValue(modelInstances.values()));
- modelInstances.forEach((key, value) -> {
- allowing(retval).getNamedModelInstanceByName(with(key.getIndexPosition()));
- will(returnValue(value));
- });
- }
- });
-
- return retval;
- }
-}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/FieldBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/FieldBuilder.java
deleted file mode 100644
index 25adead9f..000000000
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/FieldBuilder.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * SPDX-FileCopyrightText: none
- * SPDX-License-Identifier: CC0-1.0
- */
-
-package gov.nist.secauto.metaschema.core.testing;
-
-import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
-import gov.nist.secauto.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
-import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
-import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
-import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute;
-import gov.nist.secauto.metaschema.core.model.IFlagInstance;
-import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
-import gov.nist.secauto.metaschema.core.util.CollectionUtil;
-
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-import edu.umd.cs.findbugs.annotations.Nullable;
-
-public final class FieldBuilder
- extends AbstractModelBuilder
- implements IModelInstanceBuilder {
-
- private IDataTypeAdapter> dataTypeAdapter;
- private Object defaultValue = null;
- private List flags;
-
- private FieldBuilder(@NonNull Mockery ctx) {
- super(ctx);
- }
-
- /**
- * Create a new builder using the provided mocking context.
- *
- * @param ctx
- * the mocking context
- * @return the new builder
- */
- @NonNull
- public static FieldBuilder builder(@NonNull Mockery ctx) {
- return new FieldBuilder(ctx).reset();
- }
-
- @Override
- public FieldBuilder reset() {
- this.dataTypeAdapter = MetaschemaDataTypeProvider.DEFAULT_DATA_TYPE;
- this.defaultValue = null;
- this.flags = CollectionUtil.emptyList();
- return this;
- }
-
- /**
- * Apply the provided data type adapter to built fields.
- *
- * @param dataTypeAdapter
- * the data type adapter to use
- * @return this builder
- */
- public FieldBuilder dataTypeAdapter(@NonNull IDataTypeAdapter> dataTypeAdapter) {
- this.dataTypeAdapter = dataTypeAdapter;
- return this;
- }
-
- /**
- * Apply the provided data type adapter to built fields.
- *
- * @param defaultValue
- * the default value to use
- * @return this builder
- */
- public FieldBuilder defaultValue(@NonNull Object defaultValue) {
- this.defaultValue = defaultValue;
- return this;
- }
-
- /**
- * Use the provided flag instances for built fields.
- *
- * @param flags
- * the flags to use
- * @return this builder
- */
- public FieldBuilder flags(@Nullable List flags) {
- this.flags = flags == null ? CollectionUtil.emptyList() : flags;
- return this;
- }
-
- /**
- * Build a mocked field instance, based on a mocked definition, as a child of
- * the provided parent.
- *
- * @param parent
- * the parent containing the new instance
- * @return the new mocked instance
- */
- @Override
- @NonNull
- public IFieldInstanceAbsolute toInstance(
- @NonNull IAssemblyDefinition parent) {
- IFieldDefinition def = toDefinition();
- return toInstance(parent, def);
- }
-
- /**
- * Build a mocked field instance, using the provided definition, as a child of
- * the provided parent.
- *
- * @param parent
- * the parent containing the new instance
- * @param definition
- * the definition to base the instance on
- * @return the new mocked instance
- */
- @NonNull
- public IFieldInstanceAbsolute toInstance(
- @NonNull IAssemblyDefinition parent,
- @NonNull IFieldDefinition definition) {
- validate();
-
- IFieldInstanceAbsolute retval = mock(IFieldInstanceAbsolute.class);
- applyNamedInstance(retval, definition, parent);
- return retval;
- }
-
- /**
- * Build a mocked field definition.
- *
- * @return the new mocked definition
- */
- @NonNull
- public IFieldDefinition toDefinition() {
- validate();
-
- IFieldDefinition retval = mock(IFieldDefinition.class);
- applyDefinition(retval);
-
- Map flags = this.flags.stream()
- .map(builder -> builder.toInstance(retval))
- .collect(Collectors.toUnmodifiableMap(
- IFlagInstance::getQName,
- Function.identity()));
-
- getContext().checking(new Expectations() {
- {
- allowing(retval).getJavaTypeAdapter();
- will(returnValue(dataTypeAdapter));
- allowing(retval).getDefaultValue();
- will(returnValue(defaultValue));
- allowing(retval).getFlagInstances();
- will(returnValue(flags.values()));
- flags.forEach((key, value) -> {
- allowing(retval).getFlagInstanceByName(with(key.getIndexPosition()));
- will(returnValue(value));
- });
- }
- });
-
- return retval;
- }
-}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/FlagBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/FlagBuilder.java
deleted file mode 100644
index 32c902b77..000000000
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/FlagBuilder.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * SPDX-FileCopyrightText: none
- * SPDX-License-Identifier: CC0-1.0
- */
-
-package gov.nist.secauto.metaschema.core.testing;
-
-import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
-import gov.nist.secauto.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
-import gov.nist.secauto.metaschema.core.model.IFlagDefinition;
-import gov.nist.secauto.metaschema.core.model.IFlagInstance;
-import gov.nist.secauto.metaschema.core.model.IModelDefinition;
-
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-
-/**
- * A builder that generates mock flag definitions and instances.
- */
-public final class FlagBuilder
- extends AbstractModelBuilder {
-
- private IDataTypeAdapter> dataTypeAdapter;
- private Object defaultValue = null;
- private boolean required;
-
- private FlagBuilder(@NonNull Mockery ctx) {
- super(ctx);
- }
-
- /**
- * Create a new builder using the provided mocking context.
- *
- * @param ctx
- * the mocking context
- * @return the new builder
- */
- @NonNull
- public static FlagBuilder builder(@NonNull Mockery ctx) {
- return new FlagBuilder(ctx).reset();
- }
-
- @Override
- public FlagBuilder reset() {
- this.dataTypeAdapter = MetaschemaDataTypeProvider.DEFAULT_DATA_TYPE;
- this.defaultValue = null;
- this.required = IFlagInstance.DEFAULT_FLAG_REQUIRED;
- return this;
- }
-
- /**
- * Apply the provided required setting to built flags.
- *
- * @param required
- * {@code true} if the flag is required or {@code false} otherwise
- * @return this builder
- */
- public FlagBuilder required(boolean required) {
- this.required = required;
- return this;
- }
-
- /**
- * Apply the provided data type adapter to built flags.
- *
- * @param dataTypeAdapter
- * the data type adapter to use
- * @return this builder
- */
- public FlagBuilder dataTypeAdapter(@NonNull IDataTypeAdapter> dataTypeAdapter) {
- this.dataTypeAdapter = dataTypeAdapter;
- return this;
- }
-
- /**
- * Apply the provided data type adapter to built flags.
- *
- * @param defaultValue
- * the default value to use
- * @return this builder
- */
- public FlagBuilder defaultValue(@NonNull Object defaultValue) {
- this.defaultValue = defaultValue;
- return this;
- }
-
- /**
- * Build a mocked flag instance, based on a mocked definition, as a child of the
- * provided parent.
- *
- * @param parent
- * the parent containing the new instance
- * @return the new mocked instance
- */
- @NonNull
- public IFlagInstance toInstance(@NonNull IModelDefinition parent) {
- IFlagDefinition def = toDefinition();
- return toInstance(parent, def);
- }
-
- /**
- * Build a mocked flag instance, using the provided definition, as a child of
- * the provided parent.
- *
- * @param parent
- * the parent containing the new instance
- * @param definition
- * the definition to base the instance on
- * @return the new mocked instance
- */
- @NonNull
- public IFlagInstance toInstance(
- @NonNull IModelDefinition parent,
- @NonNull IFlagDefinition definition) {
- validate();
-
- IFlagInstance retval = mock(IFlagInstance.class);
-
- applyNamedInstance(retval, definition, parent);
-
- getContext().checking(new Expectations() {
- {
- allowing(retval).isRequired();
- will(returnValue(required));
- }
- });
-
- return retval;
- }
-
- /**
- * Build a mocked flag definition.
- *
- * @return the new mocked definition
- */
- @NonNull
- public IFlagDefinition toDefinition() {
- validate();
-
- IFlagDefinition retval = mock(IFlagDefinition.class);
- applyDefinition(retval);
-
- getContext().checking(new Expectations() {
- {
- allowing(retval).getJavaTypeAdapter();
- will(returnValue(dataTypeAdapter));
- allowing(retval).getDefaultValue();
- will(returnValue(defaultValue));
- }
- });
- return retval;
- }
-}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/IModelInstanceBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/IModelInstanceBuilder.java
deleted file mode 100644
index 39bba6bd2..000000000
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/IModelInstanceBuilder.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SPDX-FileCopyrightText: none
- * SPDX-License-Identifier: CC0-1.0
- */
-
-package gov.nist.secauto.metaschema.core.testing;
-
-import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
-import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-
-public interface IModelInstanceBuilder {
- /**
- * Generate an instance of the implementing type using the provided parent.
- *
- * @param parent
- * the parent assembly definition containing the instance
- * @return the new instance
- */
- @NonNull
- INamedModelInstanceAbsolute toInstance(@NonNull IAssemblyDefinition parent);
-}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/MockedModelTestSupport.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/MockedModelTestSupport.java
deleted file mode 100644
index 96d17b74b..000000000
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/MockedModelTestSupport.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * SPDX-FileCopyrightText: none
- * SPDX-License-Identifier: CC0-1.0
- */
-
-package gov.nist.secauto.metaschema.core.testing;
-
-import org.jmock.Mockery;
-import org.jmock.junit5.JUnit5Mockery;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-
-public class MockedModelTestSupport implements IModuleMockFactory {
- @RegisterExtension
- @NonNull
- Mockery context;
-
- /**
- * Construct a new model mock factory using the default JUnit-based mocking
- * context.
- */
- public MockedModelTestSupport() {
- this(new JUnit5Mockery());
- }
-
- /**
- * Construct a new model mock factory using the provided mocking context.
- */
- public MockedModelTestSupport(@NonNull Mockery context) {
- this.context = context;
- }
-
- @Override
- public Mockery getContext() {
- return context;
- }
-
- @Override
- public T mock(Class clazz, String name) {
- return new MockFactory(getContext()).mock(clazz, name);
- }
-}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/AbstractModelBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/AbstractMetaschemaBuilder.java
similarity index 52%
rename from core/src/test/java/gov/nist/secauto/metaschema/core/testing/AbstractModelBuilder.java
rename to core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/AbstractMetaschemaBuilder.java
index 67c2a47cf..fd1fbe737 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/AbstractModelBuilder.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/AbstractMetaschemaBuilder.java
@@ -3,7 +3,9 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.testing;
+package gov.nist.secauto.metaschema.core.testing.model;
+
+import static org.mockito.Mockito.doReturn;
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.IDefinition;
@@ -11,15 +13,12 @@
import gov.nist.secauto.metaschema.core.model.IModelElement;
import gov.nist.secauto.metaschema.core.model.INamedInstance;
import gov.nist.secauto.metaschema.core.model.INamedModelElement;
+import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
+import gov.nist.secauto.metaschema.core.testing.model.mocking.AbstractMockitoFactory;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-
-import java.net.URI;
-
import edu.umd.cs.findbugs.annotations.NonNull;
/**
@@ -28,89 +27,64 @@
* @param
* the Java type of this builder
*/
-public abstract class AbstractModelBuilder>
- extends MockFactory {
+abstract class AbstractMetaschemaBuilder>
+ extends AbstractMockitoFactory
+ implements IMetaschemaBuilder {
private String namespace = "";
private String name;
+ private ISource source;
/**
- * Construct a new builder using the provided mocking context.
- *
- * @param ctx
- * the mocking context
+ * Construct a new builder.
*/
- protected AbstractModelBuilder(@NonNull Mockery ctx) {
- super(ctx);
+ protected AbstractMetaschemaBuilder() {
+ // allow extending classes to construct
}
- /**
- * Reset the builder back to a default state.
- *
- * @return this builder
- */
- @NonNull
- @SuppressWarnings("unchecked")
+ @Override
public T reset() {
this.name = null;
this.namespace = null;
- return (T) this;
+ return ObjectUtils.asType(this);
}
- /**
- * Apply the provided namespace for use by this builder.
- *
- * @param name
- * the namespace to use
- * @return this builder
- */
- @SuppressWarnings("unchecked")
+ @Override
@NonNull
public T namespace(@NonNull String name) {
this.namespace = name;
- return (T) this;
+ return ObjectUtils.asType(this);
}
- /**
- * Apply the provided namespace for use by this builder.
- *
- * @param name
- * the namespace to use
- * @return this builder
- */
- @SuppressWarnings("unchecked")
- @NonNull
- public T namespace(@NonNull URI name) {
- return namespace(name.toASCIIString());
- }
-
- /**
- * Apply the provided name for use by this builder.
- *
- * @param name
- * the name to use
- * @return this builder
- */
- @SuppressWarnings("unchecked")
+ @Override
@NonNull
public T name(@NonNull String name) {
this.name = name;
- return (T) this;
+ return ObjectUtils.asType(this);
}
- /**
- * Apply the provided qualified name for use by this builder.
- *
- * @param qname
- * the qualified name to use
- * @return this builder
- */
- @SuppressWarnings("unchecked")
+ @Override
@NonNull
public T qname(@NonNull IEnhancedQName qname) {
this.name = qname.getLocalName();
this.namespace = qname.getNamespace();
- return (T) this;
+ return ObjectUtils.asType(this);
+ }
+
+ @Override
+ @NonNull
+ public T source(@NonNull ISource source) {
+ this.source = source;
+ return ObjectUtils.asType(this);
+ }
+
+ /**
+ * Get the currently configured source.
+ *
+ * @return the source or {@code null} if no source is configured
+ */
+ protected ISource getSource() {
+ return source;
}
/**
@@ -119,6 +93,7 @@ public T qname(@NonNull IEnhancedQName qname) {
*/
protected void validate() {
ObjectUtils.requireNonEmpty(name, "name");
+ ObjectUtils.requireNonNull(source, "source");
}
/**
@@ -131,12 +106,17 @@ protected void applyDefinition(@NonNull IDefinition definition) {
applyModelElement(definition);
applyNamed(definition);
applyAttributable(definition);
- getContext().checking(new Expectations() {
- {
- allowing(definition).getDefinitionQName();
- will(returnValue(IEnhancedQName.of(ObjectUtils.notNull(namespace), ObjectUtils.notNull(name))));
- }
- });
+
+ IEnhancedQName qname = IEnhancedQName.of(ObjectUtils.notNull(namespace), ObjectUtils.notNull(name));
+
+ doReturn(qname).when(definition).getDefinitionQName();
+ doReturn(null).when(definition).getRemarks();
+ doReturn(CollectionUtil.emptyMap()).when(definition).getProperties();
+ doReturn(null).when(definition).getInlineInstance();
+
+ // doReturn().when(definition).getConstraintSupport();
+ // doReturn().when(definition).getContainingModule();
+ // doReturn().when(definition).getModelType();
}
/**
@@ -159,18 +139,11 @@ protected void applyNamedInstance(
applyModelElement(instance);
applyNamed(instance);
applyAttributable(instance);
- getContext().checking(new Expectations() {
- {
- allowing(instance).getQName();
- will(returnValue(IEnhancedQName.of(ObjectUtils.notNull(namespace), ObjectUtils.notNull(name))));
- allowing(instance).getDefinition();
- will(returnValue(definition));
- allowing(instance).getContainingDefinition();
- will(returnValue(parent));
- allowing(instance).getParentContainer();
- will(returnValue(parent));
- }
- });
+
+ doReturn(name).when(instance).getName();
+ doReturn(definition).when(instance).getDefinition();
+ doReturn(parent).when(instance).getContainingDefinition();
+ doReturn(parent).when(instance).getParentContainer();
}
/**
@@ -181,22 +154,12 @@ protected void applyNamedInstance(
* the named model element to apply mocking expectations for
*/
protected void applyNamed(@NonNull INamedModelElement element) {
- getContext().checking(new Expectations() {
- {
- allowing(element).getName();
- will(returnValue(name));
- allowing(element).getUseName();
- will(returnValue(null));
- allowing(element).getQName();
- will(returnValue(IEnhancedQName.of(ObjectUtils.notNull(namespace), ObjectUtils.notNull(name))));
- allowing(element).getEffectiveName();
- will(returnValue(name));
- allowing(element).getFormalName();
- will(returnValue(null));
- allowing(element).getDescription();
- will(returnValue(null));
- }
- });
+ IEnhancedQName qname = IEnhancedQName.of(ObjectUtils.notNull(namespace), ObjectUtils.notNull(name));
+
+ doReturn(qname).when(element).getQName();
+ doReturn(name).when(element).getName();
+ doReturn(null).when(element).getFormalName();
+ doReturn(null).when(element).getDescription();
}
/**
@@ -207,12 +170,7 @@ protected void applyNamed(@NonNull INamedModelElement element) {
* the element to apply mocking expectations for
*/
protected void applyAttributable(@NonNull IAttributable element) {
- getContext().checking(new Expectations() {
- {
- allowing(element).getProperties();
- will(returnValue(CollectionUtil.emptyMap()));
- }
- });
+ doReturn(CollectionUtil.emptyMap()).when(element).getProperties();
}
/**
@@ -222,11 +180,6 @@ protected void applyAttributable(@NonNull IAttributable element) {
* the model element to apply mocking expectations for
*/
protected void applyModelElement(@NonNull IModelElement element) {
- getContext().checking(new Expectations() {
- {
- allowing(element).getRemarks();
- will(returnValue(null));
- }
- });
+ doReturn(null).when(element).getRemarks();
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/AbstractModelBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/AbstractModelBuilder.java
new file mode 100644
index 000000000..9be8f1a87
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/AbstractModelBuilder.java
@@ -0,0 +1,53 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.testing.model;
+
+import gov.nist.secauto.metaschema.core.util.CollectionUtil;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import java.util.List;
+
+import edu.umd.cs.findbugs.annotations.Nullable;
+
+/**
+ * A base class for Metaschema module-based model builders for model elements
+ * that support flag children.
+ *
+ * @param
+ * the Java type of this builder
+ */
+abstract class AbstractModelBuilder>
+ extends AbstractMetaschemaBuilder {
+ private List flags = CollectionUtil.emptyList();
+
+ @Override
+ public T reset() {
+ super.reset();
+ this.flags = CollectionUtil.emptyList();
+ return ObjectUtils.asType(this);
+ }
+
+ /**
+ * Get the configured flags.
+ *
+ * @return the list of flag builders
+ */
+ protected List getFlags() {
+ return flags;
+ }
+
+ /**
+ * Use the provided flag instances for definitions produced by this builder.
+ *
+ * @param flags
+ * the flags to use
+ * @return this builder
+ */
+ public T flags(@Nullable List flags) {
+ this.flags = flags == null ? CollectionUtil.emptyList() : flags;
+ return ObjectUtils.asType(this);
+ }
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/AssemblyBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/AssemblyBuilder.java
new file mode 100644
index 000000000..6620c8a2f
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/AssemblyBuilder.java
@@ -0,0 +1,184 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.testing.model;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+
+import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
+import gov.nist.secauto.metaschema.core.model.IAssemblyInstance;
+import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute;
+import gov.nist.secauto.metaschema.core.model.IFieldInstance;
+import gov.nist.secauto.metaschema.core.model.IFlagInstance;
+import gov.nist.secauto.metaschema.core.model.INamedModelElement;
+import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute;
+import gov.nist.secauto.metaschema.core.model.ISource;
+import gov.nist.secauto.metaschema.core.model.ModelType;
+import gov.nist.secauto.metaschema.core.model.constraint.AssemblyConstraintSet;
+import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
+import gov.nist.secauto.metaschema.core.util.CollectionUtil;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
+
+final class AssemblyBuilder
+ extends AbstractModelBuilder
+ implements IAssemblyBuilder {
+
+ private String rootNamespace = "";
+ private String rootName;
+
+ private List extends IModelBuilder>> modelInstances;
+
+ AssemblyBuilder() {
+ // prevent direct instantiation
+ }
+
+ @Override
+ public AssemblyBuilder reset() {
+ super.reset();
+ this.modelInstances = CollectionUtil.emptyList();
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public AssemblyBuilder rootNamespace(@NonNull String name) {
+ this.rootNamespace = name;
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public AssemblyBuilder rootName(@NonNull String name) {
+ this.rootName = name;
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public AssemblyBuilder rootQName(@NonNull IEnhancedQName qname) {
+ this.rootName = qname.getLocalName();
+ this.rootNamespace = qname.getNamespace();
+ return this;
+ }
+
+ @Override
+ public AssemblyBuilder modelInstances(@Nullable List extends IModelBuilder>> modelInstances) {
+ this.modelInstances = modelInstances == null ? CollectionUtil.emptyList() : modelInstances;
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public IAssemblyInstanceAbsolute toInstance(@NonNull IAssemblyDefinition parent) {
+ IAssemblyDefinition def = toDefinition();
+ return toInstance(parent, def);
+ }
+
+ /**
+ * Build a mocked assembly instance, using the provided definition, as a child
+ * of the provided parent.
+ *
+ * @param parent
+ * the parent containing the new instance
+ * @param definition
+ * the definition to base the instance on
+ * @return the new mocked instance
+ */
+ @Override
+ @NonNull
+ public IAssemblyInstanceAbsolute toInstance(
+ @NonNull IAssemblyDefinition parent,
+ @NonNull IAssemblyDefinition definition) {
+ validate();
+
+ IAssemblyInstanceAbsolute retval = mock(IAssemblyInstanceAbsolute.class);
+ applyNamedInstance(retval, definition, parent);
+ return retval;
+ }
+
+ /**
+ * Build a mocked assembly definition.
+ *
+ * @return the new mocked definition
+ */
+ @Override
+ @NonNull
+ public IAssemblyDefinition toDefinition() {
+ validate();
+
+ // already validated as non-null
+ ISource source = ObjectUtils.notNull(getSource());
+
+ IAssemblyDefinition retval = mock(IAssemblyDefinition.class);
+ applyDefinition(retval);
+
+ Map flags = getFlags().stream()
+ .map(builder -> builder.source(source).toInstance(retval))
+ .collect(Collectors.toUnmodifiableMap(
+ IFlagInstance::getQName,
+ Function.identity()));
+
+ if (rootName != null) {
+ doReturn(ModelType.ASSEMBLY).when(retval).getModelType();
+
+ IEnhancedQName rootQName = IEnhancedQName.of(ObjectUtils.notNull(rootNamespace), ObjectUtils.notNull(rootName));
+ doReturn(rootQName).when(retval).getRootQName();
+ }
+
+ doReturn(new AssemblyConstraintSet(source)).when(retval).getConstraintSupport();
+
+ doReturn(flags.values()).when(retval).getFlagInstances();
+ flags.entrySet().forEach(entry -> {
+ assert entry != null;
+ doReturn(entry.getValue()).when(retval).getFlagInstanceByName(eq(entry.getKey().getIndexPosition()));
+ });
+
+ Map modelInstances = this.modelInstances.stream()
+ .map(builder -> builder.source(source).toInstance(retval))
+ .collect(Collectors.toUnmodifiableMap(
+ INamedModelInstanceAbsolute::getQName,
+ Function.identity()));
+
+ doReturn(modelInstances.values()).when(retval).getModelInstances();
+ doReturn(CollectionUtil.emptyMap()).when(retval).getChoiceGroupInstances();
+ doReturn(CollectionUtil.emptyList()).when(retval).getChoiceInstances();
+ modelInstances.forEach((key, value) -> {
+ doReturn(value).when(retval).getNamedModelInstanceByName(eq(key.getIndexPosition()));
+
+ if (value instanceof IAssemblyInstance) {
+ doReturn(value).when(retval).getAssemblyInstanceByName(eq(key.getIndexPosition()));
+ } else if (value instanceof IFieldInstance) {
+ doReturn(value).when(retval).getFieldInstanceByName(eq(key.getIndexPosition()));
+ }
+ });
+ doReturn(
+ modelInstances.values().stream()
+ .flatMap(value -> value instanceof IAssemblyInstance ? Stream.of(value) : null)
+ .collect(Collectors.toList()))
+ .when(retval).getAssemblyInstances();
+ doReturn(
+ modelInstances.values().stream()
+ .flatMap(value -> value instanceof IFieldInstance ? Stream.of(value) : null)
+ .collect(Collectors.toList()))
+ .when(retval).getFieldInstances();
+ return retval;
+ }
+
+ @Override
+ protected void applyNamed(INamedModelElement element) {
+ super.applyNamed(element);
+ doReturn(ModelType.ASSEMBLY).when(element).getModelType();
+ }
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/FieldBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/FieldBuilder.java
new file mode 100644
index 000000000..d5bdbb25c
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/FieldBuilder.java
@@ -0,0 +1,111 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.testing.model;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+
+import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
+import gov.nist.secauto.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
+import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
+import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
+import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute;
+import gov.nist.secauto.metaschema.core.model.IFlagInstance;
+import gov.nist.secauto.metaschema.core.model.INamedModelElement;
+import gov.nist.secauto.metaschema.core.model.ModelType;
+import gov.nist.secauto.metaschema.core.model.constraint.ValueConstraintSet;
+import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+final class FieldBuilder
+ extends AbstractModelBuilder
+ implements IFieldBuilder {
+
+ private IDataTypeAdapter> dataTypeAdapter;
+ private Object defaultValue = null;
+
+ FieldBuilder() {
+ // prevent direct instantiation
+ }
+
+ @Override
+ public FieldBuilder reset() {
+ this.dataTypeAdapter = MetaschemaDataTypeProvider.DEFAULT_DATA_TYPE;
+ this.defaultValue = null;
+ return this;
+ }
+
+ @Override
+ public FieldBuilder dataTypeAdapter(@NonNull IDataTypeAdapter> dataTypeAdapter) {
+ this.dataTypeAdapter = dataTypeAdapter;
+ return this;
+ }
+
+ @Override
+ public FieldBuilder defaultValue(@NonNull Object defaultValue) {
+ this.defaultValue = defaultValue;
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public IFieldInstanceAbsolute toInstance(
+ @NonNull IAssemblyDefinition parent) {
+ IFieldDefinition def = toDefinition();
+ return toInstance(parent, def);
+ }
+
+ @Override
+ @NonNull
+ public IFieldInstanceAbsolute toInstance(
+ @NonNull IAssemblyDefinition parent,
+ @NonNull IFieldDefinition definition) {
+ validate();
+
+ IFieldInstanceAbsolute retval = mock(IFieldInstanceAbsolute.class);
+ applyNamedInstance(retval, definition, parent);
+ return retval;
+ }
+
+ @Override
+ @NonNull
+ public IFieldDefinition toDefinition() {
+ validate();
+
+ IFieldDefinition retval = mock(IFieldDefinition.class);
+ applyDefinition(retval);
+
+ Map flags = getFlags().stream()
+ .map(builder -> builder.toInstance(retval))
+ .collect(Collectors.toUnmodifiableMap(
+ IFlagInstance::getQName,
+ Function.identity()));
+
+ doReturn(new ValueConstraintSet(ObjectUtils.notNull(getSource()))).when(retval).getConstraintSupport();
+ doReturn(dataTypeAdapter).when(retval).getJavaTypeAdapter();
+ doReturn(defaultValue).when(retval).getDefaultValue();
+
+ doReturn(flags.values()).when(retval).getFlagInstances();
+ flags.entrySet().forEach(entry -> {
+ assert entry != null;
+ doReturn(entry.getValue()).when(retval).getFlagInstanceByName(eq(entry.getKey().getIndexPosition()));
+ });
+
+ return retval;
+ }
+
+ @Override
+ protected void applyNamed(INamedModelElement element) {
+ super.applyNamed(element);
+ doReturn(ModelType.FIELD).when(element).getModelType();
+ }
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/FlagBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/FlagBuilder.java
new file mode 100644
index 000000000..ae994784b
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/FlagBuilder.java
@@ -0,0 +1,103 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.testing.model;
+
+import static org.mockito.Mockito.doReturn;
+
+import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
+import gov.nist.secauto.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
+import gov.nist.secauto.metaschema.core.model.IFlagDefinition;
+import gov.nist.secauto.metaschema.core.model.IFlagInstance;
+import gov.nist.secauto.metaschema.core.model.IModelDefinition;
+import gov.nist.secauto.metaschema.core.model.INamedModelElement;
+import gov.nist.secauto.metaschema.core.model.ModelType;
+import gov.nist.secauto.metaschema.core.model.constraint.ValueConstraintSet;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * A builder that generates mock flag definitions and instances.
+ */
+final class FlagBuilder
+ extends AbstractMetaschemaBuilder
+ implements IFlagBuilder {
+
+ private IDataTypeAdapter> dataTypeAdapter;
+ private Object defaultValue = null;
+ private boolean required;
+
+ FlagBuilder() {
+ // prevent direct instantiation
+ }
+
+ @Override
+ public FlagBuilder reset() {
+ this.dataTypeAdapter = MetaschemaDataTypeProvider.DEFAULT_DATA_TYPE;
+ this.defaultValue = null;
+ this.required = IFlagInstance.DEFAULT_FLAG_REQUIRED;
+ return this;
+ }
+
+ @Override
+ public FlagBuilder required(boolean required) {
+ this.required = required;
+ return this;
+ }
+
+ @Override
+ public FlagBuilder dataTypeAdapter(@NonNull IDataTypeAdapter> dataTypeAdapter) {
+ this.dataTypeAdapter = dataTypeAdapter;
+ return this;
+ }
+
+ @Override
+ public FlagBuilder defaultValue(@NonNull Object defaultValue) {
+ this.defaultValue = defaultValue;
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public IFlagInstance toInstance(
+ @NonNull IModelDefinition parent,
+ @NonNull IFlagDefinition definition) {
+ validate();
+
+ IFlagInstance retval = mock(IFlagInstance.class);
+
+ applyNamedInstance(retval, definition, parent);
+
+ doReturn(required).when(retval).isRequired();
+ return retval;
+ }
+
+ /**
+ * Build a mocked flag definition.
+ *
+ * @return the new mocked definition
+ */
+ @Override
+ @NonNull
+ public IFlagDefinition toDefinition() {
+ validate();
+
+ IFlagDefinition retval = mock(IFlagDefinition.class);
+ applyDefinition(retval);
+
+ doReturn(new ValueConstraintSet(ObjectUtils.notNull(getSource()))).when(retval).getConstraintSupport();
+ doReturn(dataTypeAdapter).when(retval).getJavaTypeAdapter();
+ doReturn(defaultValue).when(retval).getDefaultValue();
+
+ return retval;
+ }
+
+ @Override
+ protected void applyNamed(INamedModelElement element) {
+ super.applyNamed(element);
+ doReturn(ModelType.FLAG).when(element).getModelType();
+ }
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IAssemblyBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IAssemblyBuilder.java
new file mode 100644
index 000000000..ba5e8bfc7
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IAssemblyBuilder.java
@@ -0,0 +1,110 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.testing.model;
+
+import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
+import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute;
+import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import java.net.URI;
+import java.util.List;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
+
+/**
+ * Represents a Metaschema module-based model builder for producing assembly
+ * definitions and instances.
+ */
+public interface IAssemblyBuilder extends IModelBuilder {
+
+ /**
+ * Create a new builder using the provided mocking context.
+ *
+ * @return the new builder
+ */
+ @NonNull
+ static IAssemblyBuilder builder() {
+ return new AssemblyBuilder().reset();
+ }
+
+ /**
+ * Apply the provided root namespace for use by this builder.
+ *
+ * @param name
+ * the namespace to use
+ * @return this builder
+ */
+ @NonNull
+ IAssemblyBuilder rootNamespace(@NonNull String name);
+
+ /**
+ * Apply the provided root namespace for use by this builder.
+ *
+ * @param name
+ * the namespace to use
+ * @return this builder
+ */
+ @NonNull
+ default IAssemblyBuilder rootNamespace(@NonNull URI name) {
+ return rootNamespace(ObjectUtils.notNull(name.toASCIIString()));
+ }
+
+ /**
+ * Apply the provided root name for use by this builder.
+ *
+ * @param name
+ * the name to use
+ * @return this builder
+ */
+ @NonNull
+ IAssemblyBuilder rootName(@NonNull String name);
+
+ /**
+ * Apply the provided root qualified name for use by this builder.
+ *
+ * @param qname
+ * the qualified name to use
+ * @return this builder
+ */
+ @NonNull
+ IAssemblyBuilder rootQName(@NonNull IEnhancedQName qname);
+
+ /**
+ * Use the provided model instances for built fields.
+ *
+ * @param modelInstances
+ * the model instances to use
+ * @return this builder
+ */
+ IAssemblyBuilder modelInstances(@Nullable List extends IModelBuilder>> modelInstances);
+
+ @Override
+ @NonNull
+ IAssemblyInstanceAbsolute toInstance(@NonNull IAssemblyDefinition parent);
+
+ /**
+ * Build a mocked assembly instance, using the provided definition, as a child
+ * of the provided parent.
+ *
+ * @param parent
+ * the parent containing the new instance
+ * @param definition
+ * the definition to base the instance on
+ * @return the new mocked instance
+ */
+ @NonNull
+ IAssemblyInstanceAbsolute toInstance(@NonNull IAssemblyDefinition parent, @NonNull IAssemblyDefinition definition);
+
+ /**
+ * Build a mocked assembly definition.
+ *
+ * @return the new mocked definition
+ */
+ @NonNull
+ IAssemblyDefinition toDefinition();
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IFieldBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IFieldBuilder.java
new file mode 100644
index 000000000..f7822f29d
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IFieldBuilder.java
@@ -0,0 +1,81 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.testing.model;
+
+import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
+import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
+import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
+import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * Represents a Metaschema module-based model builder for producing field
+ * definitions and instances.
+ */
+public interface IFieldBuilder extends IModelBuilder {
+
+ /**
+ * Create a new builder using the provided mocking context.
+ *
+ * @return the new builder
+ */
+ @NonNull
+ static IFieldBuilder builder() {
+ return new FieldBuilder().reset();
+ }
+
+ /**
+ * Apply the provided data type adapter to built fields.
+ *
+ * @param dataTypeAdapter
+ * the data type adapter to use
+ * @return this builder
+ */
+ IFieldBuilder dataTypeAdapter(@NonNull IDataTypeAdapter> dataTypeAdapter);
+
+ /**
+ * Apply the provided data type adapter to built fields.
+ *
+ * @param defaultValue
+ * the default value to use
+ * @return this builder
+ */
+ IFieldBuilder defaultValue(@NonNull Object defaultValue);
+
+ /**
+ * Build a mocked field instance, based on a mocked definition, as a child of
+ * the provided parent.
+ *
+ * @param parent
+ * the parent containing the new instance
+ * @return the new mocked instance
+ */
+ @Override
+ @NonNull
+ IFieldInstanceAbsolute toInstance(@NonNull IAssemblyDefinition parent);
+
+ /**
+ * Build a mocked field instance, using the provided definition, as a child of
+ * the provided parent.
+ *
+ * @param parent
+ * the parent containing the new instance
+ * @param definition
+ * the definition to base the instance on
+ * @return the new mocked instance
+ */
+ @NonNull
+ IFieldInstanceAbsolute toInstance(@NonNull IAssemblyDefinition parent, @NonNull IFieldDefinition definition);
+
+ /**
+ * Build a mocked field definition.
+ *
+ * @return the new mocked definition
+ */
+ @NonNull
+ IFieldDefinition toDefinition();
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IFlagBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IFlagBuilder.java
new file mode 100644
index 000000000..d4b7157c0
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IFlagBuilder.java
@@ -0,0 +1,92 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.testing.model;
+
+import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
+import gov.nist.secauto.metaschema.core.model.IFlagDefinition;
+import gov.nist.secauto.metaschema.core.model.IFlagInstance;
+import gov.nist.secauto.metaschema.core.model.IModelDefinition;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * Represents a Metaschema module-based model builder for producing flag
+ * definitions and instances.
+ */
+public interface IFlagBuilder extends IMetaschemaBuilder {
+
+ /**
+ * Create a new builder using the provided mocking context.
+ *
+ * @return the new builder
+ */
+ @NonNull
+ static IFlagBuilder builder() {
+ return new FlagBuilder().reset();
+ }
+
+ /**
+ * Apply the provided required setting to built flags.
+ *
+ * @param required
+ * {@code true} if the flag is required or {@code false} otherwise
+ * @return this builder
+ */
+ IFlagBuilder required(boolean required);
+
+ /**
+ * Apply the provided data type adapter to built flags.
+ *
+ * @param dataTypeAdapter
+ * the data type adapter to use
+ * @return this builder
+ */
+ IFlagBuilder dataTypeAdapter(@NonNull IDataTypeAdapter> dataTypeAdapter);
+
+ /**
+ * Apply the provided data type adapter to built flags.
+ *
+ * @param defaultValue
+ * the default value to use
+ * @return this builder
+ */
+ IFlagBuilder defaultValue(@NonNull Object defaultValue);
+
+ /**
+ * Build a mocked flag instance, based on a mocked definition, as a child of the
+ * provided parent.
+ *
+ * @param parent
+ * the parent containing the new instance
+ * @return the new mocked instance
+ */
+ @NonNull
+ default IFlagInstance toInstance(@NonNull IModelDefinition parent) {
+ IFlagDefinition def = toDefinition();
+ return toInstance(parent, def);
+ }
+
+ /**
+ * Build a mocked flag instance, using the provided definition, as a child of
+ * the provided parent.
+ *
+ * @param parent
+ * the parent containing the new instance
+ * @param definition
+ * the definition to base the instance on
+ * @return the new mocked instance
+ */
+ @NonNull
+ IFlagInstance toInstance(@NonNull IModelDefinition parent, @NonNull IFlagDefinition definition);
+
+ /**
+ * Build a mocked flag definition.
+ *
+ * @return the new mocked definition
+ */
+ @NonNull
+ IFlagDefinition toDefinition();
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IMetaschemaBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IMetaschemaBuilder.java
new file mode 100644
index 000000000..5e32c71f2
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IMetaschemaBuilder.java
@@ -0,0 +1,83 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.testing.model;
+
+import gov.nist.secauto.metaschema.core.model.ISource;
+import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import java.net.URI;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * Represents a Metaschema module-based model builder.
+ *
+ * @param
+ * the Java type of the implementation of this builder
+ */
+public interface IMetaschemaBuilder> {
+ /**
+ * Reset the builder back to a default state.
+ *
+ * @return this builder
+ */
+ @NonNull
+ T reset();
+
+ /**
+ * Apply the provided namespace for use by this builder.
+ *
+ * @param name
+ * the namespace to use
+ * @return this builder
+ */
+ @NonNull
+ T namespace(@NonNull String name);
+
+ /**
+ * Apply the provided namespace for use by this builder.
+ *
+ * @param name
+ * the namespace to use
+ * @return this builder
+ */
+ @NonNull
+ default T namespace(@NonNull URI name) {
+ return namespace(ObjectUtils.notNull(name.toASCIIString()));
+ }
+
+ /**
+ * Apply the provided name for use by this builder.
+ *
+ * @param name
+ * the name to use
+ * @return this builder
+ */
+ @NonNull
+ T name(@NonNull String name);
+
+ /**
+ * Apply the provided qualified name for use by this builder.
+ *
+ * @param qname
+ * the qualified name to use
+ * @return this builder
+ */
+ @NonNull
+ T qname(@NonNull IEnhancedQName qname);
+
+ /**
+ * Apply the provided source information for use by this builder.
+ *
+ * @param source
+ * the source information
+ * @return this builder
+ */
+ @NonNull
+ T source(@NonNull ISource source);
+
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IModelBuilder.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IModelBuilder.java
new file mode 100644
index 000000000..786a358d5
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IModelBuilder.java
@@ -0,0 +1,42 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.testing.model;
+
+import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
+import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute;
+
+import java.util.List;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
+
+/**
+ * Represents a Metaschema module-based model builder, that supports flag
+ * children.
+ *
+ * @param
+ * the Java type of the implementation of this builder
+ */
+public interface IModelBuilder> extends IMetaschemaBuilder {
+ /**
+ * Use the provided flag instances for built fields.
+ *
+ * @param flags
+ * the flag builders to add
+ * @return this builder
+ */
+ T flags(@Nullable List flags);
+
+ /**
+ * Generate an instance of the implementing type using the provided parent.
+ *
+ * @param parent
+ * the parent assembly definition containing the instance
+ * @return the new instance
+ */
+ @NonNull
+ INamedModelInstanceAbsolute toInstance(@NonNull IAssemblyDefinition parent);
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/IModuleMockFactory.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IModuleMockFactory.java
similarity index 50%
rename from core/src/test/java/gov/nist/secauto/metaschema/core/testing/IModuleMockFactory.java
rename to core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IModuleMockFactory.java
index fc6a9e624..96b04063f 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/IModuleMockFactory.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/IModuleMockFactory.java
@@ -3,25 +3,25 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.testing;
+package gov.nist.secauto.metaschema.core.testing.model;
-import org.jmock.Mockery;
+import gov.nist.secauto.metaschema.core.testing.model.mocking.IMockFactory;
import edu.umd.cs.findbugs.annotations.NonNull;
+/**
+ * Represents a factory used to produce Metaschema module-based definitions and
+ * instances.
+ */
public interface IModuleMockFactory extends IMockFactory {
- @Override
- @NonNull
- Mockery getContext();
-
/**
* Get a new flag builder.
*
* @return the builder
*/
@NonNull
- default FlagBuilder flag() {
- return FlagBuilder.builder(getContext());
+ default IFlagBuilder flag() {
+ return IFlagBuilder.builder();
}
/**
@@ -30,8 +30,8 @@ default FlagBuilder flag() {
* @return the builder
*/
@NonNull
- default FieldBuilder field() {
- return FieldBuilder.builder(getContext());
+ default IFieldBuilder field() {
+ return IFieldBuilder.builder();
}
/**
@@ -40,7 +40,7 @@ default FieldBuilder field() {
* @return the builder
*/
@NonNull
- default AssemblyBuilder assembly() {
- return AssemblyBuilder.builder(getContext());
+ default IAssemblyBuilder assembly() {
+ return IAssemblyBuilder.builder();
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/MockedModelTestSupport.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/MockedModelTestSupport.java
new file mode 100644
index 000000000..678cde82e
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/MockedModelTestSupport.java
@@ -0,0 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.testing.model;
+
+import gov.nist.secauto.metaschema.core.testing.model.mocking.AbstractMockitoFactory;
+
+/**
+ * Provides the ability to generate mocked Metaschema module definitions and
+ * instances, along with other mocked data.
+ */
+public class MockedModelTestSupport
+ extends AbstractMockitoFactory
+ implements IModuleMockFactory {
+ /**
+ * Construct a new model mock factory using the default JUnit-based mocking
+ * context.
+ */
+ public MockedModelTestSupport() {
+ // do nothing
+ }
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/MockFactory.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/mocking/AbstractJMockFactory.java
similarity index 83%
rename from core/src/test/java/gov/nist/secauto/metaschema/core/testing/MockFactory.java
rename to core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/mocking/AbstractJMockFactory.java
index a496940a1..1ac4a193d 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/MockFactory.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/mocking/AbstractJMockFactory.java
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.testing;
+package gov.nist.secauto.metaschema.core.testing.model.mocking;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
@@ -14,7 +14,7 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
-public class MockFactory implements IMockFactory {
+public class AbstractJMockFactory implements IMockFactory {
@NonNull
private final Mockery context;
@@ -25,11 +25,11 @@ public class MockFactory implements IMockFactory {
* @param ctx
* the mocking context
*/
- public MockFactory(@NonNull Mockery ctx) {
+ public AbstractJMockFactory(@NonNull Mockery ctx) {
this.context = ctx;
}
- @Override
+ @NonNull
public Mockery getContext() {
return context;
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/mocking/AbstractMockitoFactory.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/mocking/AbstractMockitoFactory.java
new file mode 100644
index 000000000..bb957adb2
--- /dev/null
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/mocking/AbstractMockitoFactory.java
@@ -0,0 +1,45 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.testing.model.mocking;
+
+import static org.mockito.Mockito.withSettings;
+
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import org.mockito.Answers;
+import org.mockito.Mockito;
+
+import java.util.UUID;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
+
+public class AbstractMockitoFactory
+ implements IMockFactory {
+
+ protected AbstractMockitoFactory() {
+ // allow construction by extending classes
+ }
+
+ @Override
+ @NonNull
+ public T mock(@NonNull Class clazz, @Nullable String name) {
+ StringBuilder builder = new StringBuilder()
+ .append(clazz.getSimpleName());
+ if (name != null) {
+ builder
+ .append('-')
+ .append(name);
+ }
+ builder
+ .append('-')
+ .append(UUID.randomUUID().toString())
+ .toString();
+ return ObjectUtils.notNull(Mockito.mock(clazz, withSettings()
+ .name(builder.toString())
+ .defaultAnswer(Answers.CALLS_REAL_METHODS)));
+ }
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/IMockFactory.java b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/mocking/IMockFactory.java
similarity index 84%
rename from core/src/test/java/gov/nist/secauto/metaschema/core/testing/IMockFactory.java
rename to core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/mocking/IMockFactory.java
index 42f85a713..cbb41330a 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/testing/IMockFactory.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/testing/model/mocking/IMockFactory.java
@@ -3,22 +3,12 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.testing;
-
-import org.jmock.Mockery;
+package gov.nist.secauto.metaschema.core.testing.model.mocking;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
public interface IMockFactory {
- /**
- * Get the mocking context.
- *
- * @return the mocking context
- */
- @NonNull
- Mockery getContext();
-
/**
* Create a mock for the given class.
*
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/impl/AnnotationGenerator.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/impl/AnnotationGenerator.java
index 7c3efe340..8fcb78df0 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/impl/AnnotationGenerator.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/impl/AnnotationGenerator.java
@@ -116,7 +116,7 @@ private static void buildConstraint(Class> annotationType, AnnotationSpec.Buil
annotation.addMember("level", "$T.$L", IConstraint.Level.class, constraint.getLevel());
- String target = constraint.getTarget();
+ String target = constraint.getTarget().getPath();
if (!target.equals(getDefaultValue(annotationType, "target"))) {
annotation.addMember("target", "$S", target);
}
@@ -291,7 +291,7 @@ private static void buildKeyFields(
for (IKeyField key : keyFields) {
AnnotationSpec.Builder keyAnnotation = AnnotationSpec.builder(KeyField.class);
- String target = key.getTarget();
+ String target = key.getTarget().getPath();
if (!target.equals(getDefaultValue(KeyField.class, "target"))) {
keyAnnotation.addMember("target", "$S", target);
}
@@ -348,7 +348,7 @@ private static void applyExpectConstraints(
buildConstraint(Expect.class, constraintAnnotation, constraint);
- constraintAnnotation.addMember("test", "$S", constraint.getTest());
+ constraintAnnotation.addMember("test", "$S", constraint.getTest().getPath());
if (constraint.getMessage() != null) {
constraintAnnotation.addMember("message", "$S", constraint.getMessage());
@@ -433,7 +433,9 @@ private static void checkCardinalities(
} else {
warn.log(String.format(
"Definition '%s' has min-occurs=%d cardinality constraint targeting '%s' that is not a model instance",
- definition.getName(), constraint.getMinOccurs(), constraint.getTarget()));
+ definition.getName(),
+ constraint.getMinOccurs(),
+ constraint.getTarget().getPath()));
}
}
}
@@ -452,14 +454,18 @@ private static void checkMinOccurs(
logBuilder.log(String.format(
"Definition '%s' has min-occurs=%d cardinality constraint targeting '%s' that is redundant with a"
+ " targeted instance named '%s' that requires min-occurs=%d",
- definition.getName(), minOccurs, constraint.getTarget(),
+ definition.getName(),
+ minOccurs,
+ constraint.getTarget().getPath(),
modelInstance.getName(),
modelInstance.getMinOccurs()));
} else if (minOccurs < modelInstance.getMinOccurs()) {
logBuilder.log(String.format(
"Definition '%s' has min-occurs=%d cardinality constraint targeting '%s' that conflicts with a"
+ " targeted instance named '%s' that requires min-occurs=%d",
- definition.getName(), minOccurs, constraint.getTarget(),
+ definition.getName(),
+ minOccurs,
+ constraint.getTarget().getPath(),
modelInstance.getName(),
modelInstance.getMinOccurs()));
}
@@ -480,14 +486,18 @@ private static void checkMaxOccurs(
logBuilder.log(String.format(
"Definition '%s' has max-occurs=%d cardinality constraint targeting '%s' that is redundant with a"
+ " targeted instance named '%s' that requires max-occurs=%d",
- definition.getName(), maxOccurs, constraint.getTarget(),
+ definition.getName(),
+ maxOccurs,
+ constraint.getTarget().getPath(),
modelInstance.getName(),
modelInstance.getMaxOccurs()));
} else if (maxOccurs < modelInstance.getMaxOccurs()) {
logBuilder.log(String.format(
"Definition '%s' has max-occurs=%d cardinality constraint targeting '%s' that conflicts with a"
+ " targeted instance named '%s' that requires max-occurs=%d",
- definition.getName(), maxOccurs, constraint.getTarget(),
+ definition.getName(),
+ maxOccurs,
+ constraint.getTarget().getPath(),
modelInstance.getName(),
modelInstance.getMaxOccurs()));
}
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/annotations/AllowedValues.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/annotations/AllowedValues.java
index e2ee240dc..a6c5fde90 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/annotations/AllowedValues.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/annotations/AllowedValues.java
@@ -72,7 +72,7 @@
* @return the target metapath
*/
@NonNull
- String target() default IConstraint.DEFAULT_TARGET_METAPATH;
+ String target() default ".";
/**
* An optional set of properties associated with these allowed values.
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/annotations/Expect.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/annotations/Expect.java
index da5c93e9c..a37243c0c 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/annotations/Expect.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/annotations/Expect.java
@@ -71,7 +71,7 @@
* @return the target metapath
*/
@NonNull
- String target() default IConstraint.DEFAULT_TARGET_METAPATH;
+ String target() default ".";
/**
* An optional set of properties associated with these allowed values.
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/ConstraintFactory.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/ConstraintFactory.java
index 5bd11da9a..70a6b1579 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/ConstraintFactory.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/ConstraintFactory.java
@@ -9,6 +9,7 @@
import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.AbstractConfigurableMessageConstraintBuilder;
import gov.nist.secauto.metaschema.core.model.constraint.AbstractConstraintBuilder;
@@ -56,8 +57,12 @@ static MarkupMultiline toRemarks(@NonNull String remarks) {
}
@NonNull
- static String toMetapath(@NonNull String metapath) {
- return metapath.isBlank() ? IConstraint.DEFAULT_TARGET_METAPATH : metapath;
+ static IMetapathExpression toMetapath(
+ @NonNull String metapath,
+ @NonNull ISource source) {
+ return metapath.isBlank()
+ ? IConstraint.DEFAULT_TARGET_METAPATH
+ : IMetapathExpression.lazyCompile(metapath, source.getStaticContext());
}
@NonNull
@@ -85,8 +90,11 @@ static String toMetapath(@NonNull String metapath) {
}
@NonNull
- static > T applyTarget(@NonNull T builder, @NonNull String target) {
- builder.target(toMetapath(target));
+ static > T applyTarget(
+ @NonNull T builder,
+ @NonNull String target,
+ @NonNull ISource source) {
+ builder.target(toMetapath(target, source));
return builder;
}
@@ -166,7 +174,7 @@ static IAllowedValuesConstraint newAllowedValuesConstraint(
builder
.source(source)
.level(constraint.level());
- applyTarget(builder, constraint.target());
+ applyTarget(builder, constraint.target(), source);
applyProperties(builder, constraint.properties());
applyRemarks(builder, constraint.remarks());
@@ -186,7 +194,7 @@ static IMatchesConstraint newMatchesConstraint(Matches constraint, @NonNull ISou
builder
.source(source)
.level(constraint.level());
- applyTarget(builder, constraint.target());
+ applyTarget(builder, constraint.target(), source);
applyProperties(builder, constraint.properties());
applyMessage(builder, constraint.message());
applyRemarks(builder, constraint.remarks());
@@ -212,10 +220,9 @@ static IMatchesConstraint newMatchesConstraint(Matches constraint, @NonNull ISou
for (KeyField keyField : keyFields) {
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops") // ok
IKeyField field = IKeyField.of(
- toMetapath(keyField.target()),
+ toMetapath(keyField.target(), source),
toPattern(keyField.pattern()),
- toRemarks(keyField.remarks()),
- source);
+ toRemarks(keyField.remarks()));
builder.keyField(field);
}
return builder;
@@ -230,7 +237,7 @@ static IUniqueConstraint newUniqueConstraint(@NonNull IsUnique constraint, @NonN
builder
.source(source)
.level(constraint.level());
- applyTarget(builder, constraint.target());
+ applyTarget(builder, constraint.target(), source);
applyProperties(builder, constraint.properties());
applyMessage(builder, constraint.message());
applyRemarks(builder, constraint.remarks());
@@ -249,7 +256,7 @@ static IIndexConstraint newIndexConstraint(@NonNull Index constraint, @NonNull I
builder
.source(source)
.level(constraint.level());
- applyTarget(builder, constraint.target());
+ applyTarget(builder, constraint.target(), source);
applyProperties(builder, constraint.properties());
applyMessage(builder, constraint.message());
applyRemarks(builder, constraint.remarks());
@@ -270,7 +277,7 @@ static IIndexHasKeyConstraint newIndexHasKeyConstraint(
builder
.source(source)
.level(constraint.level());
- applyTarget(builder, constraint.target());
+ applyTarget(builder, constraint.target(), source);
applyProperties(builder, constraint.properties());
applyMessage(builder, constraint.message());
applyRemarks(builder, constraint.remarks());
@@ -289,12 +296,12 @@ static IExpectConstraint newExpectConstraint(@NonNull Expect constraint, @NonNul
builder
.source(source)
.level(constraint.level());
- applyTarget(builder, constraint.target());
+ applyTarget(builder, constraint.target(), source);
applyProperties(builder, constraint.properties());
applyMessage(builder, constraint.message());
applyRemarks(builder, constraint.remarks());
- builder.test(toMetapath(constraint.test()));
+ builder.test(toMetapath(constraint.test(), source));
return builder.build();
}
@@ -314,7 +321,7 @@ static ICardinalityConstraint newCardinalityConstraint(@NonNull HasCardinality c
builder
.source(source)
.level(constraint.level());
- applyTarget(builder, constraint.target());
+ applyTarget(builder, constraint.target(), source);
applyProperties(builder, constraint.properties());
applyMessage(builder, constraint.message());
applyRemarks(builder, constraint.remarks());
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/BindingConstraintLoader.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/BindingConstraintLoader.java
index 6555b80ad..6e1e4404b 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/BindingConstraintLoader.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/BindingConstraintLoader.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.databind.model.metaschema;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.model.AbstractLoader;
@@ -154,7 +155,7 @@ protected List parseResource(@NonNull URI resource, @NonNull Deq
ObjectUtils.notNull(binding.getPrefix()),
ObjectUtils.notNull(binding.getUri())));
- ISource source = ISource.externalSource(builder.build());
+ ISource source = ISource.externalSource(builder.build(), false);
List targetedConstraints = ObjectUtils.notNull(CollectionUtil.listOrEmpty(obj.getContexts())
.stream()
@@ -235,7 +236,9 @@ private static AssemblyTargetedConstraints handleScopedAssembly(
ConstraintBindingSupport.parse(constraints, obj, source);
return new AssemblyTargetedConstraints(
source,
- ObjectUtils.requireNonNull(obj.getTarget()),
+ IMetapathExpression.lazyCompile(
+ ObjectUtils.requireNonNull(obj.getTarget()),
+ source.getStaticContext()),
constraints);
}
@@ -247,7 +250,9 @@ private static FieldTargetedConstraints handleScopedField(
return new FieldTargetedConstraints(
source,
- ObjectUtils.requireNonNull(obj.getTarget()),
+ IMetapathExpression.lazyCompile(
+ ObjectUtils.requireNonNull(obj.getTarget()),
+ source.getStaticContext()),
constraints);
}
@@ -259,7 +264,9 @@ private static FlagTargetedConstraints handleScopedFlag(
return new FlagTargetedConstraints(
source,
- ObjectUtils.requireNonNull(obj.getTarget()),
+ IMetapathExpression.lazyCompile(
+ ObjectUtils.requireNonNull(obj.getTarget()),
+ source.getStaticContext()),
constraints);
}
@@ -268,18 +275,24 @@ private Context parseContext(
@Nullable Context parent,
@NonNull ISource source) {
- List metapaths;
+ List metapaths;
if (parent == null) {
metapaths = ObjectUtils.notNull(CollectionUtil.listOrEmpty(contextObj.getMetapaths()).stream()
.map(MetaschemaMetapath::getTarget)
+ .map(metapath -> IMetapathExpression.lazyCompile(
+ ObjectUtils.requireNonNull(metapath),
+ source.getStaticContext()))
.collect(Collectors.toList()));
} else {
- List parentMetapaths = parent.getMetapaths().stream()
+ List parentMetapaths = parent.getMetapaths().stream()
.collect(Collectors.toList());
metapaths = ObjectUtils.notNull(CollectionUtil.listOrEmpty(contextObj.getMetapaths()).stream()
.map(MetaschemaMetapath::getTarget)
.flatMap(childPath -> parentMetapaths.stream()
- .map(parentPath -> parentPath + '/' + childPath))
+ .map(parentPath -> parentPath.getPath() + '/' + childPath))
+ .map(metapath -> IMetapathExpression.lazyCompile(
+ ObjectUtils.requireNonNull(metapath),
+ source.getStaticContext()))
.collect(Collectors.toList()));
}
@@ -301,7 +314,7 @@ private Context parseContext(
private static class Context {
@NonNull
- private final List metapaths;
+ private final List metapaths;
@NonNull
private final List childContexts = new LinkedList<>();
@NonNull
@@ -309,13 +322,16 @@ private static class Context {
public Context(
@NonNull ISource source,
- @NonNull List metapaths,
+ @NonNull List metapaths,
@NonNull IModelConstrained constraints) {
this.metapaths = metapaths;
this.targetedConstraints = ObjectUtils.notNull(Lazy.lazy(() -> {
Stream paths = getMetapaths().stream()
- .map(metapath -> new MetaTargetedContraints(source, ObjectUtils.notNull(metapath), constraints));
+ .map(metapath -> new MetaTargetedContraints(
+ source,
+ ObjectUtils.notNull(metapath),
+ constraints));
Stream childPaths = childContexts.stream()
.flatMap(child -> child.getTargetedConstraints().stream());
@@ -334,7 +350,7 @@ public void addAll(@NonNull Collection childContexts) {
}
@NonNull
- public List getMetapaths() {
+ public List getMetapaths() {
return metapaths;
}
}
@@ -345,7 +361,7 @@ private static class MetaTargetedContraints
protected MetaTargetedContraints(
@NonNull ISource source,
- @NonNull String target,
+ @NonNull IMetapathExpression target,
@NonNull IModelConstrained constraints) {
super(source, target, constraints);
}
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ConstraintBindingSupport.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ConstraintBindingSupport.java
index 4568c591a..901dd582d 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ConstraintBindingSupport.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ConstraintBindingSupport.java
@@ -8,6 +8,7 @@
import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.AbstractConfigurableMessageConstraintBuilder;
@@ -243,7 +244,7 @@ private static IExpectConstraint newExpect(
@NonNull FlagExpect obj,
@NonNull ISource source) {
IExpectConstraint.Builder builder = IExpectConstraint.builder()
- .test(target(ObjectUtils.requireNonNull(obj.getTest())));
+ .test(metapath(ObjectUtils.requireNonNull(obj.getTest()), source));
applyConfigurableCommonValues(obj, null, source, builder);
String message = obj.getMessage();
@@ -259,7 +260,7 @@ private static IExpectConstraint newExpect(
@NonNull TargetedExpectConstraint obj,
@NonNull ISource source) {
IExpectConstraint.Builder builder = IExpectConstraint.builder()
- .test(target(ObjectUtils.requireNonNull(obj.getTest())));
+ .test(metapath(ObjectUtils.requireNonNull(obj.getTest()), source));
applyConfigurableCommonValues(obj, obj.getTarget(), source, builder);
return builder.build();
@@ -274,10 +275,9 @@ private static IExpectConstraint newExpect(
assert value != null;
IKeyField keyField = IKeyField.of(
- target(ObjectUtils.requireNonNull(value.getTarget())),
+ metapath(ObjectUtils.requireNonNull(value.getTarget()), source),
pattern(value.getPattern()),
- ModelSupport.remarks(value.getRemarks()),
- source);
+ ModelSupport.remarks(value.getRemarks()));
builder.keyField(keyField);
}
return builder;
@@ -437,17 +437,21 @@ private static IUniqueConstraint newUnique(
builder.remarks(ObjectUtils.notNull(remarks.getRemark()));
}
- builder.target(target(target));
+ builder.target(metapath(target, source));
builder.level(level(constraint.getLevel()));
builder.source(source);
return builder;
}
@NonNull
- private static String target(@Nullable String target) {
- return target == null
+ private static IMetapathExpression metapath(
+ @Nullable String metapath,
+ @NonNull ISource source) {
+ return metapath == null
? IConstraint.DEFAULT_TARGET_METAPATH
- : target;
+ : IMetapathExpression.lazyCompile(
+ metapath,
+ source.getStaticContext());
}
@NonNull
diff --git a/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/AbstractGenerationState.java b/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/AbstractGenerationState.java
index 1dc51b273..ef8796d87 100644
--- a/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/AbstractGenerationState.java
+++ b/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/AbstractGenerationState.java
@@ -93,7 +93,7 @@ protected static AllowedValueCollection getContextIndependentEnumeratedValues(
closed = true;
}
- if (!IMetapathExpression.contextNode().getPath().equals(constraint.getTarget())) {
+ if (!IMetapathExpression.contextNode().getPath().equals(constraint.getTarget().getPath())) {
values = CollectionUtil.emptyList();
break;
}