diff --git a/core/pom.xml b/core/pom.xml
index 64a77386a..1a8aebcd0 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -145,6 +145,11 @@
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+ io.hosuabyinject-resources-junit-jupiter
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/DefaultConfiguration.java b/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/DefaultConfiguration.java
index 1e32fb11a..a806bcbfe 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/DefaultConfiguration.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/DefaultConfiguration.java
@@ -34,8 +34,8 @@
import edu.umd.cs.findbugs.annotations.NonNull;
/**
- * Provides a basic configuration management implementation that allows mutable access to
- * configuration state.
+ * Provides a basic configuration management implementation that allows mutable
+ * access to configuration state.
*
* @param
* the type of managed features
@@ -112,16 +112,6 @@ public IMutableConfiguration applyConfiguration(@NonNull IConfiguration or
return this;
}
- @SuppressWarnings("unchecked")
- @Override
- public V get(T feature) {
- V value = (V) featureValues.get(feature);
- if (value == null) {
- value = (V) feature.getDefault();
- }
- return value;
- }
-
@Override
public IMutableConfiguration set(T feature, Object value) {
Class> featureValueClass = feature.getValueClass();
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/IConfiguration.java b/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/IConfiguration.java
index 44abc0027..31f8e2bd8 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/IConfiguration.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/IConfiguration.java
@@ -31,8 +31,8 @@
import edu.umd.cs.findbugs.annotations.NonNull;
/**
- * The base interface for getting the configuration of processors and parsers in this library. This
- * provides an immutable view of the current configuration.
+ * The base interface for getting the configuration of processors and parsers in
+ * this library. This provides an immutable view of the current configuration.
*
* @param
* the type of the feature set
@@ -59,8 +59,15 @@ public interface IConfiguration> {
* the requested feature
* @return the value of the feature
*/
+ @SuppressWarnings("unchecked")
@NonNull
- V get(@NonNull T feature);
+ default V get(@NonNull T feature) {
+ V value = (V) getFeatureValues().get(feature);
+ if (value == null) {
+ value = (V) feature.getDefault();
+ }
+ return value;
+ }
/**
* Get the mapping of each feature mapped to its value.
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/IConfigurationFeature.java b/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/IConfigurationFeature.java
index 80d6c6523..cb3522ce3 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/IConfigurationFeature.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/IConfigurationFeature.java
@@ -32,7 +32,8 @@
* The common interface that all configuration features must implement.
*
* This approach is inspired by the configuration implementation in the
- * Jackson databind library.
+ * Jackson databind
+ * library.
*
* @param
* the value type of the feature
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicContext.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicContext.java
index 70180978c..75105a67a 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicContext.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicContext.java
@@ -32,14 +32,15 @@
import gov.nist.secauto.metaschema.core.metapath.function.DefaultFunction.CallingContext;
import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
+import gov.nist.secauto.metaschema.core.model.IUriResolver;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
import java.io.IOException;
+import java.io.InputStream;
import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Path;
import java.time.Clock;
import java.time.ZoneId;
import java.time.ZonedDateTime;
@@ -49,7 +50,6 @@
import java.util.concurrent.ConcurrentHashMap;
import edu.umd.cs.findbugs.annotations.NonNull;
-import edu.umd.cs.findbugs.annotations.Nullable;
public class DynamicContext { // NOPMD - intentional data class
@NonNull
@@ -131,6 +131,19 @@ public void cacheResult(@NonNull CallingContext callingContext, @NonNull ISequen
assert old == null;
}
+ @NonNull
+ public ISequence> getVariableValue(String name) {
+ return ObjectUtils.requireNonNull(letVariableMap.get(name));
+ }
+
+ public void setVariableValue(String name, ISequence> boundValue) {
+ letVariableMap.put(name, boundValue);
+ }
+
+ public void clearVariableValue(String name) {
+ letVariableMap.remove(name);
+ }
+
private class CachingLoader implements IDocumentLoader {
@NonNull
private final IDocumentLoader proxy;
@@ -140,86 +153,83 @@ public CachingLoader(@NonNull IDocumentLoader proxy) {
}
@Override
- public @Nullable EntityResolver getEntityResolver() {
- return new ContextEntityResolver();
+ public IUriResolver getUriResolver() {
+ return new ContextUriResolver();
}
@Override
- public void setEntityResolver(@NonNull EntityResolver resolver) {
+ public void setUriResolver(@NonNull IUriResolver resolver) {
// we delegate to the document loader proxy, so the resolver should be set there
throw new UnsupportedOperationException("Set the resolver on the proxy");
}
+ @NonNull
protected IDocumentLoader getProxiedDocumentLoader() {
return proxy;
}
@Override
- public @NonNull IDocumentNodeItem loadAsNodeItem(@NonNull InputSource source) throws IOException {
- String systemId = source.getSystemId();
- URI uri = ObjectUtils.notNull(URI.create(systemId));
+ public IDocumentNodeItem loadAsNodeItem(Path path) throws IOException {
+ URI uri = path.toUri();
+ IDocumentNodeItem retval = availableDocuments.get(uri);
+ if (retval == null) {
+ retval = getProxiedDocumentLoader().loadAsNodeItem(path);
+ availableDocuments.put(uri, retval);
+ }
+ return retval;
+ }
+
+ @Override
+ public IDocumentNodeItem loadAsNodeItem(URL url) throws IOException, URISyntaxException {
+ URI uri = ObjectUtils.notNull(url.toURI());
+ IDocumentNodeItem retval = availableDocuments.get(uri);
+ if (retval == null) {
+ retval = getProxiedDocumentLoader().loadAsNodeItem(uri);
+ availableDocuments.put(uri, retval);
+ }
+ return retval;
+ }
+
+ @Override
+ public IDocumentNodeItem loadAsNodeItem(URI uri) throws IOException {
IDocumentNodeItem retval = availableDocuments.get(uri);
if (retval == null) {
- retval = getProxiedDocumentLoader().loadAsNodeItem(source);
+ retval = getProxiedDocumentLoader().loadAsNodeItem(uri);
availableDocuments.put(uri, retval);
}
return retval;
}
- public class ContextEntityResolver implements EntityResolver {
+ @Override
+ public @NonNull IDocumentNodeItem loadAsNodeItem(
+ @NonNull InputStream is,
+ @NonNull URI documentUri) throws IOException {
+ throw new UnsupportedOperationException();
+ // return getProxiedDocumentLoader().loadAsNodeItem(is, documentUri);
+ }
+
+ public class ContextUriResolver implements IUriResolver {
/**
- * Provides an {@link InputSource} for the provided {@code systemId} after attempting to resolve
- * this system identifier.
+ * {@inheritDoc}
*
- * This implementation of an {@link EntityResolver} will perform the following operations in order:
- *
- *
Resolves the {@code systemId} against the base URI provided by the
- * {@link StaticContext#getBaseUri()} method, if this method returns a non-{@code null} result, to
- * get a localized resource identifier.
- *
It will then delegate to the EntityResolver provided by the
- * {@link IDocumentLoader#getEntityResolver()} method, if the result is not-{@code null}, to get the
- * {@link InputSource}.
- *
If no InputSource is provided by the previous step, then an InputSource will be created from
- * the URI resolved in the first step, if possible.
- *
If an InputSource is still not provided, then an InputSource will be created from the
- * provided {@code systemId}.
- *
- * Based on the XPath 3.1 fn:doc
+ * Based on the XPath 3.1
+ * fn:doc
* function.
*
* @param uri
@@ -115,8 +115,8 @@ public static IDocumentNodeItem fnDoc(@NonNull IStringItem uri, @NonNull Dynamic
}
try {
- return context.getDocumentLoader().loadAsNodeItem(ObjectUtils.notNull(documentUri.toURL()));
- } catch (IOException | URISyntaxException ex) {
+ return context.getDocumentLoader().loadAsNodeItem(ObjectUtils.notNull(documentUri));
+ } catch (IOException ex) {
throw new DocumentFunctionException(DocumentFunctionException.ERROR_RETRIEVING_RESOURCE, String
.format("Unable to retrieve the resource identified by the URI '%s'.", documentUri.toString()), ex);
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java
index 920910605..b1ea60637 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java
@@ -32,12 +32,13 @@ public interface IItem {
/**
* Get the item's "wrapped" value. This "wrapped" value may be:
*
- *
In the case of an Assembly, a Java object representing the fields and flags of the
- * assembly.
- *
In the case of a Field with flags, a Java object representing the field value and flags of
- * the field.
+ *
In the case of an Assembly, a Java object representing the fields and
+ * flags of the assembly.
+ *
In the case of a Field with flags, a Java object representing the field
+ * value and flags of the field.
*
In the case of a Field without flags or a flag, a Java type managed by a
- * {@link IDataTypeAdapter} or a primitive type provided by the Java standard library.
+ * {@link IDataTypeAdapter} or a primitive type provided by the Java standard
+ * library.
*
*
* @return the value or {@code null} if the item has no available value
@@ -47,7 +48,8 @@ public interface IItem {
/**
* Determine if the item has an associated value.
*
- * @return {@code true} if the item has a non-{@code null} value or {@code false} otherwise
+ * @return {@code true} if the item has a non-{@code null} value or
+ * {@code false} otherwise
*/
default boolean hasValue() {
return getValue() != null;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java
index 797dd84a7..978d2f926 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java
@@ -55,7 +55,8 @@ default String asString() {
}
/**
- * Get a new {@link IStringItem} based on the the textual value of the item's "wrapped" value.
+ * Get a new {@link IStringItem} based on the the textual value of the item's
+ * "wrapped" value.
*
* @return a new string item
*/
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IDecimalItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IDecimalItem.java
index d5ff92089..cd266ed77 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IDecimalItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IDecimalItem.java
@@ -69,4 +69,7 @@ static IDecimalItem valueOf(@NonNull String value) {
throws InvalidValueForCastFunctionException {
return MetaschemaDataTypeProvider.DECIMAL.cast(item);
}
+
+ @Override
+ BigDecimal getValue();
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IIntegerItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IIntegerItem.java
index d19080d74..7ab5bb7da 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IIntegerItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IIntegerItem.java
@@ -33,7 +33,7 @@
import edu.umd.cs.findbugs.annotations.NonNull;
-public interface IIntegerItem extends IDecimalItem {
+public interface IIntegerItem extends INumericItem {
@SuppressWarnings("null")
@NonNull
@@ -59,7 +59,8 @@ static IIntegerItem valueOf(long value) {
* an integer value
* @return the item
* @throws NumberFormatException
- * if the provided value is not a valid representation of a {@link BigInteger}
+ * if the provided value is not a valid representation of a
+ * {@link BigInteger}
*/
@NonNull
static IIntegerItem valueOf(@NonNull String value) {
@@ -98,4 +99,7 @@ default IIntegerItem ceiling() {
default IIntegerItem floor() {
return this;
}
+
+ @Override
+ BigInteger getValue();
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/DocumentNodeItemImpl.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/DocumentNodeItemImpl.java
index 4e2459ce7..fd3fd69d1 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/DocumentNodeItemImpl.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/DocumentNodeItemImpl.java
@@ -60,7 +60,8 @@ public IRootAssemblyNodeItem getRootAssemblyNodeItem() {
}
@Override
- public @NonNull URI getDocumentUri() {
+ @NonNull
+ public URI getDocumentUri() {
return documentUri;
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDocumentNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDocumentNodeItem.java
index c056cba71..04e3ee9e9 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDocumentNodeItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDocumentNodeItem.java
@@ -36,7 +36,7 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
-public interface IDocumentNodeItem extends INodeItem {
+public interface IDocumentNodeItem extends INodeItem, IFeatureNoDataItem {
@Override
default NodeItemType getNodeItemType() {
return NodeItemType.DOCUMENT;
@@ -101,9 +101,4 @@ default RESULT accept(@NonNull INodeItemVisitor
- * If the provided node item is a document, this method get the first child node item's value, since
- * a document doesn't have a value.
+ * If the provided node item is a document, this method get the first child node
+ * item's value, since a document doesn't have a value.
*
* @param
* the type of the bound object to return
@@ -87,15 +81,17 @@ static CLASS toValue(@NonNull INodeItem item) {
/**
* Retrieve the parent node item if it exists.
*
- * @return the parent node item, or {@code null} if this node item has no known parent
+ * @return the parent node item, or {@code null} if this node item has no known
+ * parent
*/
INodeItem getParentNodeItem();
/**
- * Retrieve the parent content node item if it exists. A content node is a non-document node.
+ * Retrieve the parent content node item if it exists. A content node is a
+ * non-document node.
*
- * @return the parent content node item, or {@code null} if this node item has no known parent
- * content node item
+ * @return the parent content node item, or {@code null} if this node item has
+ * no known parent content node item
*/
IModelNodeItem, ?> getParentContentNodeItem();
@@ -140,8 +136,8 @@ default Stream extends INodeItem> getPathStream() {
}
/**
- * Get a stream of all ancestors of this node item. The stream is ordered from closest to farthest
- * ancestor.
+ * Get a stream of all ancestors of this node item. The stream is ordered from
+ * closest to farthest ancestor.
*
* @return a stream of ancestor node items
*/
@@ -151,8 +147,8 @@ default Stream extends INodeItem> ancestor() {
}
/**
- * Get a stream of this and all ancestors of this node item. The stream is ordered from self, then
- * closest to farthest ancestor.
+ * Get a stream of this and all ancestors of this node item. The stream is
+ * ordered from self, then closest to farthest ancestor.
*
* @return a stream of this node followed by all ancestor node items
*/
@@ -162,8 +158,8 @@ default Stream extends INodeItem> ancestorOrSelf() {
}
/**
- * Get a stream of the ancestors of the provided {@code item}. The stream is ordered from the
- * closest to farthest ancestor.
+ * Get a stream of the ancestors of the provided {@code item}. The stream is
+ * ordered from the closest to farthest ancestor.
*
* @param item
* the target item to get ancestors for
@@ -177,8 +173,8 @@ static Stream extends INodeItem> ancestorsOf(@NonNull INodeItem item) {
}
/**
- * Get a stream of all descendant model items of this node item. The stream is ordered from closest
- * to farthest descendants in a depth-first order.
+ * Get a stream of all descendant model items of this node item. The stream is
+ * ordered from closest to farthest descendants in a depth-first order.
*
* @return a stream of descendant node items
*/
@@ -188,8 +184,9 @@ default Stream extends INodeItem> descendant() {
}
/**
- * Get a stream of all descendant model items of the provided {@code item}. The stream is ordered
- * from closest to farthest descendants in a depth-first order.
+ * Get a stream of all descendant model items of the provided {@code item}. The
+ * stream is ordered from closest to farthest descendants in a depth-first
+ * order.
*
* @param item
* the target item to get descendants for
@@ -207,8 +204,9 @@ static Stream extends INodeItem> decendantsOf(@NonNull INodeItem item) {
}
/**
- * Get a stream of this node, followed by all descendant model items of this node item. The stream
- * is ordered from closest to farthest descendants in a depth-first order.
+ * Get a stream of this node, followed by all descendant model items of this
+ * node item. The stream is ordered from closest to farthest descendants in a
+ * depth-first order.
*
* @return a stream of this node and descendant node items
*/
@@ -218,10 +216,11 @@ default Stream extends INodeItem> descendantOrSelf() {
}
/**
- * Get the flags and value data associated this node. The resulting collection is expected to be
- * ordered, with the results in document order.
+ * Get the flags and value data associated this node. The resulting collection
+ * is expected to be ordered, with the results in document order.
*
- * The resulting collection may be modified, but such modification is not thread safe
+ * The resulting collection may be modified, but such modification is not thread
+ * safe
*
* @return a collection of flags
*/
@@ -233,7 +232,8 @@ default Stream extends INodeItem> descendantOrSelf() {
*
* @param name
* the effective name of the flag
- * @return the flag with the matching effective name or {@code null} if no match was found
+ * @return the flag with the matching effective name or {@code null} if no match
+ * was found
*/
@Nullable
IFlagNodeItem getFlagByName(@NonNull String name);
@@ -250,32 +250,38 @@ default Stream extends IFlagNodeItem> flags() {
}
/**
- * Get the model items (i.e., fields, assemblies) and value data associated this node. A given model
- * instance can be multi-valued, so the value of each instance will be a list. The resulting
- * collection is expected to be ordered, with the results in document order.
+ * Get the model items (i.e., fields, assemblies) and value data associated this
+ * node. A given model instance can be multi-valued, so the value of each
+ * instance will be a list. The resulting collection is expected to be ordered,
+ * with the results in document order.
*
- * The resulting collection may be modified, but such modification is not thread safe
+ * The resulting collection may be modified, but such modification is not thread
+ * safe
*
- * @return a collection of list(s), with each list containing the items for a given model instance
+ * @return a collection of list(s), with each list containing the items for a
+ * given model instance
*/
@NonNull
Collection extends List extends IModelNodeItem, ?>>> getModelItems();
/**
- * Get the collection of model items associated with the instance having the provided {@code name}.
+ * Get the collection of model items associated with the instance having the
+ * provided {@code name}.
*
- * The resulting collection may be modified, but such modification is not thread safe
+ * The resulting collection may be modified, but such modification is not thread
+ * safe
*
* @param name
* the instance name to get model items for
- * @return the sequence of items associated with the named model instance, or an empty list if an
- * instance with that name is not present
+ * @return the sequence of items associated with the named model instance, or an
+ * empty list if an instance with that name is not present
*/
@NonNull
List extends IModelNodeItem, ?>> getModelItemsByName(@NonNull String name);
/**
- * Get the model items (i.e., fields, assemblies) and value data associated this node as a stream.
+ * Get the model items (i.e., fields, assemblies) and value data associated this
+ * node as a stream.
*
* @return the stream of model items or an empty stream if none exist
*/
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IResourceLoader.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IResourceLoader.java
index a61dbcd2c..d8ebc9d3e 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IResourceLoader.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IResourceLoader.java
@@ -26,15 +26,6 @@
package gov.nist.secauto.metaschema.core.model;
-import gov.nist.secauto.metaschema.core.model.util.InputSourceUtils;
-
-import org.xml.sax.EntityResolver;
-import org.xml.sax.InputSource;
-
-import java.io.IOException;
-import java.net.URI;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
/**
@@ -47,23 +38,9 @@ public interface IResourceLoader {
* @return the entity resolver
*/
@Nullable
- default EntityResolver getEntityResolver() {
- // by default, do not support an entity resolver extension mechanism
- // Subclasses can override this behavior
+ default IUriResolver getUriResolver() {
+ // by default, do not support external URI resolution. Subclasses can override
+ // this behavior
return null;
}
-
- /**
- * Create a new input source based on the provided URI.
- *
- * @param uri
- * the resource to use as input
- * @return the created input source
- * @throws IOException
- * if an error occurred while accessing the resource identified by the URI
- */
- @NonNull
- default InputSource toInputSource(@NonNull URI uri) throws IOException {
- return InputSourceUtils.toInputSource(uri, getEntityResolver());
- }
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IUriResolver.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IUriResolver.java
new file mode 100644
index 000000000..0cd3507c1
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IUriResolver.java
@@ -0,0 +1,44 @@
+/*
+ * Portions of this software was developed by employees of the National Institute
+ * of Standards and Technology (NIST), an agency of the Federal Government and is
+ * being made available as a public service. Pursuant to title 17 United States
+ * Code Section 105, works of NIST employees are not subject to copyright
+ * protection in the United States. This software may be subject to foreign
+ * copyright. Permission in the United States and in foreign countries, to the
+ * extent that NIST may hold copyright, to use, copy, modify, create derivative
+ * works, and distribute this software and its documentation without fee is hereby
+ * granted on a non-exclusive basis, provided that this notice and disclaimer
+ * of warranty appears in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
+ * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
+ * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
+ * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
+ * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT
+ * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
+ * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
+ * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
+ * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
+ * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
+ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
+ */
+
+package gov.nist.secauto.metaschema.core.model;
+
+import java.net.URI;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+public interface IUriResolver {
+ /**
+ * Resolve the provided URI, producing a resolved URI, which may point to a
+ * different resource than the provided URI.
+ *
+ * @param uri
+ * the URI to resolve
+ * @return the resulting URI
+ */
+ @NonNull
+ URI resolve(@NonNull URI uri);
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/util/InputSourceUtils.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/util/InputSourceUtils.java
index c7e75c867..77cf4f44f 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/util/InputSourceUtils.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/util/InputSourceUtils.java
@@ -36,6 +36,7 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
+// REFACTOR: remove
public final class InputSourceUtils {
private InputSourceUtils() {
// disable construction
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/json/JsonUtil.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/util/JsonUtil.java
similarity index 93%
rename from databind/src/main/java/gov/nist/secauto/metaschema/databind/io/json/JsonUtil.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/model/util/JsonUtil.java
index 458d3163c..878e9f3eb 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/json/JsonUtil.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/util/JsonUtil.java
@@ -24,7 +24,7 @@
* OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
*/
-package gov.nist.secauto.metaschema.databind.io.json;
+package gov.nist.secauto.metaschema.core.model.util;
import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.core.JsonParser;
@@ -32,13 +32,15 @@
import gov.nist.secauto.metaschema.core.util.CustomCollectors;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
-import gov.nist.secauto.metaschema.databind.model.IBoundNamedInstance;
-import gov.nist.secauto.metaschema.databind.model.IClassBinding;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.json.JSONObject;
+import org.json.JSONTokener;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -53,6 +55,16 @@ private JsonUtil() {
// disable construction
}
+ @NonNull
+ public static JSONObject toJsonObject(@NonNull InputStream schemaInputStream) {
+ return new JSONObject(new JSONTokener(schemaInputStream));
+ }
+
+ @NonNull
+ public static JSONObject toJsonObject(@NonNull Reader reader) {
+ return new JSONObject(new JSONTokener(reader));
+ }
+
/**
* Generate an informational string describing the token at the current location
* of the provided {@code parser}.
@@ -266,19 +278,4 @@ public static CharSequence generateLocationMessage(@NonNull JsonLocation locatio
.append(location.getColumnNr())
.append('\'');
}
-
- @SuppressWarnings("null")
- @NonNull
- public static String toLocationContext(
- @NonNull JsonParser parser,
- @NonNull IClassBinding classBinding,
- IBoundNamedInstance property) {
- return new StringBuilder()
- .append("property '")
- .append(property.getEffectiveName())
- .append("' on class '")
- .append(classBinding.getBoundClass().getName())
- .append('\'')
- .append(generateLocationMessage(parser)).toString();
- }
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/validation/AbstractContentValidator.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/validation/AbstractContentValidator.java
new file mode 100644
index 000000000..04a83179a
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/validation/AbstractContentValidator.java
@@ -0,0 +1,50 @@
+/*
+ * Portions of this software was developed by employees of the National Institute
+ * of Standards and Technology (NIST), an agency of the Federal Government and is
+ * being made available as a public service. Pursuant to title 17 United States
+ * Code Section 105, works of NIST employees are not subject to copyright
+ * protection in the United States. This software may be subject to foreign
+ * copyright. Permission in the United States and in foreign countries, to the
+ * extent that NIST may hold copyright, to use, copy, modify, create derivative
+ * works, and distribute this software and its documentation without fee is hereby
+ * granted on a non-exclusive basis, provided that this notice and disclaimer
+ * of warranty appears in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
+ * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
+ * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
+ * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
+ * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT
+ * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
+ * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
+ * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
+ * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
+ * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
+ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
+ */
+
+package gov.nist.secauto.metaschema.core.model.validation;
+
+import gov.nist.secauto.metaschema.core.resource.AbstractResourceLoader;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+
+public abstract class AbstractContentValidator
+ extends AbstractResourceLoader
+ implements IContentValidator {
+
+ @Override
+ public IValidationResult validate(URI uri) throws IOException {
+ URI resourceUri = resolve(uri);
+ URL resource = resourceUri.toURL();
+
+ try (InputStream is = ObjectUtils.notNull(resource.openStream())) {
+ return validate(is, resourceUri);
+ }
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/validation/IContentValidator.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/validation/IContentValidator.java
index a391a9820..3b086da7b 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/validation/IContentValidator.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/validation/IContentValidator.java
@@ -26,17 +26,18 @@
package gov.nist.secauto.metaschema.core.model.validation;
-import gov.nist.secauto.metaschema.core.model.IResourceLoader;
+import gov.nist.secauto.metaschema.core.model.util.JsonUtil;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import org.json.JSONObject;
-import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
@@ -45,9 +46,9 @@
import edu.umd.cs.findbugs.annotations.NonNull;
/**
- * A common interface for Metaschema related content validators.
+ * A common interface for validation of Metaschema module-based content.
*/
-public interface IContentValidator extends IResourceLoader {
+public interface IContentValidator {
/**
* Validate the resource at provided {@code path}.
*
@@ -59,12 +60,13 @@ public interface IContentValidator extends IResourceLoader {
*/
@NonNull
default IValidationResult validate(@NonNull Path path) throws IOException {
- InputSource source = toInputSource(ObjectUtils.notNull(path.toUri()));
- return validate(source);
+ try (InputStream is = ObjectUtils.notNull(Files.newInputStream(path))) {
+ return validate(is, ObjectUtils.notNull(path.toUri()));
+ }
}
/**
- * Validate the resource at provided {@code path}.
+ * Validate the resource at the provided {@code url}.
*
* @param url
* the resource to validate
@@ -76,21 +78,34 @@ default IValidationResult validate(@NonNull Path path) throws IOException {
*/
@NonNull
default IValidationResult validate(@NonNull URL url) throws IOException, URISyntaxException {
- InputSource source = toInputSource(ObjectUtils.notNull(url.toURI()));
- return validate(source);
+ return validate(ObjectUtils.notNull(url.toURI()));
}
+ /**
+ * Validate the resource identified by the provided {@code uri}.
+ *
+ * @param uri
+ * the resource to validate
+ * @return the result of the validation
+ * @throws IOException
+ * if an error occurred while performing validation
+ */
+ @NonNull
+ IValidationResult validate(@NonNull URI uri) throws IOException;
+
/**
* Validate the resource associated with the provided input stream {@code is}.
*
- * @param source
- * information about how to access the resource
+ * @param is
+ * an input stream to access the resource
+ * @param documentUri
+ * the URI of the resource to validate
* @return the result of the validation
* @throws IOException
* if an error occurred while performing validation
*/
@NonNull
- IValidationResult validate(@NonNull InputSource source) throws IOException;
+ IValidationResult validate(@NonNull InputStream is, @NonNull URI documentUri) throws IOException;
/**
* Validate the target using the provided XML schemas.
@@ -106,7 +121,7 @@ default IValidationResult validate(@NonNull URL url) throws IOException, URISynt
* if an error occurred while parsing the XML target or schema
*/
@NonNull
- static IValidationResult validateWithXmlSchema(@NonNull Path target, @NonNull List