getExecutionStack() {
+ return new ArrayDeque<>(this.sharedState.executionStack);
}
/**
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicMetapathException.java
index 95d8512b7..881055430 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicMetapathException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicMetapathException.java
@@ -5,12 +5,17 @@
package gov.nist.secauto.metaschema.core.metapath;
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
+
/**
* MPDY: Exceptions related to the Metapath dynamic context and dynamic
* evaluation.
*/
public class DynamicMetapathException
- extends AbstractCodedMetapathException {
+ extends MetapathException {
+ @NonNull
+ private static final String PREFIX = "MPDY";
/**
* the serial version UID.
@@ -25,7 +30,7 @@ public class DynamicMetapathException
* context that is
* absent.
*/
- public static final int DYNAMIC_CONTEXT_ABSENT = 2;
+ protected static final int DYNAMIC_CONTEXT_ABSENT = 2;
/**
* err:MPDY0050: It
@@ -40,7 +45,7 @@ public class DynamicMetapathException
* "/" or "//" in a path expression is an abbreviation for an initial step that
* includes the clause treat as document-node()
.
*/
- public static final int TREAT_DOES_NOT_MATCH_TYPE = 50;
+ protected static final int TREAT_DOES_NOT_MATCH_TYPE = 50;
/**
* Constructs a new exception with the provided {@code code}, {@code message},
@@ -51,8 +56,10 @@ public class DynamicMetapathException
* @param message
* the exception message
*/
- public DynamicMetapathException(int code, String message) {
- super(code, message);
+ public DynamicMetapathException(
+ int code,
+ @Nullable String message) {
+ super(IErrorCode.of(PREFIX, code), message);
}
/**
@@ -66,8 +73,11 @@ public DynamicMetapathException(int code, String message) {
* @param cause
* the original exception cause
*/
- public DynamicMetapathException(int code, String message, Throwable cause) {
- super(code, message, cause);
+ public DynamicMetapathException(
+ int code,
+ @Nullable String message,
+ @Nullable Throwable cause) {
+ super(IErrorCode.of(PREFIX, code), message, cause);
}
/**
@@ -79,12 +89,9 @@ public DynamicMetapathException(int code, String message, Throwable cause) {
* @param cause
* the original exception cause
*/
- public DynamicMetapathException(int code, Throwable cause) {
- super(code, cause);
- }
-
- @Override
- public String getCodePrefix() {
- return "MPDY";
+ public DynamicMetapathException(
+ int code,
+ @Nullable Throwable cause) {
+ super(IErrorCode.of(PREFIX, code), cause);
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IErrorCode.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IErrorCode.java
new file mode 100644
index 000000000..cee843679
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IErrorCode.java
@@ -0,0 +1,49 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.metapath;
+
+import gov.nist.secauto.metaschema.core.metapath.impl.ErrorCodeImpl;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * Provides an error code that identifies the type of message.
+ *
+ * Implementations of this interface are expected to be immutable.
+ */
+public interface IErrorCode {
+ @SuppressWarnings("PMD.ShortMethodName")
+ @NonNull
+ static IErrorCode of(@NonNull String prefix, int code) {
+ return new ErrorCodeImpl(prefix, code);
+ }
+
+ /**
+ * Get the error code prefix, which indicates what type of error it is.
+ *
+ * @return the error code prefix
+ */
+ @NonNull
+ String getPrefix();
+
+ /**
+ * Get the error code value.
+ *
+ * @return the error code value
+ */
+ int getCode();
+
+ /**
+ * Get a combination of the error code family and value.
+ *
+ * @return the full error code.
+ */
+ @NonNull
+ default String getCodeAsString() {
+ return ObjectUtils.notNull(String.format("%s%04d", getPrefix(), getCode()));
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IExpression.java
index da67b4365..2bf1f6f1a 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IExpression.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IExpression.java
@@ -30,7 +30,7 @@ public interface IExpression {
* @return the expression text
*/
@NonNull
- String getText();
+ String getPath();
/**
* Retrieve the child expressions associated with this expression.
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 14329df84..8dfa5ce69 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
@@ -5,10 +5,10 @@
package gov.nist.secauto.metaschema.core.metapath;
-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.impl.MetapathExpression;
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;
@@ -25,7 +25,7 @@
/**
* Supports compiling and executing Metapath expressions.
*/
-public interface IMetapathExpression {
+public interface IMetapathExpression extends IExpression {
/**
* Identifies the expected type for a Metapath evaluation result.
@@ -86,18 +86,27 @@ public Class> expectedClass() {
* if the provided sequence is incompatible with the expected result
* type
*/
+ // TODO: trace exceptions thrown to ensure the Javadoc matches; should be static
+ // type error
@Nullable
public T convert(@NonNull ISequence> sequence) {
try {
return ObjectUtils.asNullableType(converter.convert(sequence));
} catch (ClassCastException ex) {
- throw new InvalidTypeMetapathException(null,
- String.format("Unable to cast to expected result type '%s' using expected type '%s'.",
- name(),
- expectedClass().getName()),
+ throw new InvalidTypeMetapathException(
+ null,
+ String.format("Unable to cast type '%s' to expected result type '%s'.",
+ expectedClass().getName(),
+ name()),
ex);
}
}
+
+ @FunctionalInterface
+ interface ConversionFunction {
+ @Nullable
+ Object convert(@NonNull ISequence> sequence);
+ }
}
/**
@@ -107,7 +116,7 @@ public T convert(@NonNull ISequence> sequence) {
*/
@NonNull
static IMetapathExpression contextNode() {
- return MetapathExpression.CONTEXT_NODE;
+ return MetapathExpression.CONTEXT_METAPATH;
}
/**
@@ -116,12 +125,12 @@ static IMetapathExpression contextNode() {
* @param path
* the metapath expression
* @return the compiled expression object
- * @throws MetapathException
+ * @throws InvalidMetapathGrammarException
* if an error occurred while compiling the Metapath expression
*/
@NonNull
static IMetapathExpression compile(@NonNull String path) {
- return MetapathExpression.compile(path, StaticContext.instance());
+ return compile(path, StaticContext.instance());
}
/**
@@ -132,7 +141,7 @@ static IMetapathExpression compile(@NonNull String path) {
* @param staticContext
* the static evaluation context
* @return the compiled expression object
- * @throws MetapathException
+ * @throws InvalidMetapathGrammarException
* if an error occurred while compiling the Metapath expression
*/
@NonNull
@@ -162,6 +171,7 @@ static IMetapathExpression lazyCompile(@NonNull String path, @NonNull StaticCont
*
* @return the expression
*/
+ @Override
@NonNull
String getPath();
@@ -308,4 +318,5 @@ default ISequence evaluate(
ISequence evaluate(
@Nullable IItem focus,
@NonNull DynamicContext dynamicContext);
+
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/InvalidMetapathGrammarException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/InvalidMetapathGrammarException.java
new file mode 100644
index 000000000..029d18a9e
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/InvalidMetapathGrammarException.java
@@ -0,0 +1,55 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.metapath;
+
+/**
+ * An exception to be raised when a Metapath is not a valid instance of the
+ * Metapath grammar.
+ *
+ * This exception is associated with the
+ * {@link StaticMetapathException#INVALID_PATH_GRAMMAR} error code.
+ */
+public class InvalidMetapathGrammarException
+ extends StaticMetapathException {
+
+ /**
+ * the serial version UID.
+ */
+ private static final long serialVersionUID = 2L;
+
+ /**
+ * Constructs a new exception with the provided {@code message} and
+ * {@code cause}.
+ *
+ * @param message
+ * the exception message
+ * @param cause
+ * the original exception cause
+ */
+ public InvalidMetapathGrammarException(String message, Throwable cause) {
+ super(INVALID_PATH_GRAMMAR, message, cause);
+ }
+
+ /**
+ * Constructs a new exception with the provided {@code message} and no cause.
+ *
+ * @param message
+ * the exception message
+ */
+ public InvalidMetapathGrammarException(String message) {
+ super(INVALID_PATH_GRAMMAR, message);
+ }
+
+ /**
+ * Constructs a new exception with no message and the provided {@code cause}.
+ *
+ * @param cause
+ * the original exception cause
+ */
+ public InvalidMetapathGrammarException(Throwable cause) {
+ super(INVALID_PATH_GRAMMAR, cause);
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/InvalidTreatTypeDynamicMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/InvalidTreatTypeDynamicMetapathException.java
new file mode 100644
index 000000000..01c15be30
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/InvalidTreatTypeDynamicMetapathException.java
@@ -0,0 +1,55 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.metapath;
+
+import java.util.Deque;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
+
+public class InvalidTreatTypeDynamicMetapathException
+ extends DynamicMetapathException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a new exception with the provided {@code message} and no cause.
+ *
+ * @param message
+ * the exception message
+ */
+ public InvalidTreatTypeDynamicMetapathException(
+ @NonNull Deque evaluationStack,
+ @Nullable String message) {
+ super(TREAT_DOES_NOT_MATCH_TYPE, message);
+ }
+
+ /**
+ * Constructs a new exception with the provided {@code message} and
+ * {@code cause}.
+ *
+ * @param message
+ * the exception message
+ * @param cause
+ * the original exception cause
+ */
+ public InvalidTreatTypeDynamicMetapathException(
+ @Nullable String message,
+ @Nullable Throwable cause) {
+ super(TREAT_DOES_NOT_MATCH_TYPE, message, cause);
+ }
+
+ /**
+ * Constructs a new exception with the provided {@code cause} and no message.
+ *
+ * @param cause
+ * the original exception cause
+ */
+ public InvalidTreatTypeDynamicMetapathException(
+ @Nullable Throwable cause) {
+ super(TREAT_DOES_NOT_MATCH_TYPE, cause);
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathException.java
index 78c8ad6b1..6f211ee0c 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathException.java
@@ -5,57 +5,156 @@
package gov.nist.secauto.metaschema.core.metapath;
+import java.util.ArrayDeque;
+import java.util.Collections;
+import java.util.Deque;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
+
/**
* {@code MetapathException} is the superclass of all exceptions that can be
* thrown during the compilation and evaluation of a Metapath.
*/
public class MetapathException
extends RuntimeException {
-
/**
* the serial version UID.
*/
private static final long serialVersionUID = 1L;
-
/**
- * Constructs a new Metapath exception with a {@code null} message and no cause.
+ * The error prefix which identifies what kind of error it is.
*/
- public MetapathException() {
- // no message
- }
+ @NonNull
+ private final IErrorCode errorCode;
+
+ @Nullable
+ private Deque evaluationStack = null;
/**
- * Constructs a new Metapath exception with the provided {@code message} and no
- * cause.
+ * Constructs a new Metapath exception with the provided {@code code} and
+ * {@code message} and no cause.
*
+ * @param errorCode
+ * the error code that identifies the type of error
* @param message
* the exception message
*/
- public MetapathException(String message) {
+ protected MetapathException(
+ @NonNull IErrorCode errorCode,
+ @Nullable String message) {
super(message);
+ this.errorCode = errorCode;
}
/**
* Constructs a new Metapath exception with a {@code null} message and the
- * provided {@code cause}.
+ * provided {@code code} and {@code cause}.
*
+ * @param errorCode
+ * the error code that identifies the type of error
* @param cause
* the exception cause
*/
- public MetapathException(Throwable cause) {
+ protected MetapathException(
+ @NonNull IErrorCode errorCode,
+ @Nullable Throwable cause) {
super(cause);
+ this.errorCode = errorCode;
}
/**
- * Constructs a new Metapath exception with the provided {@code message} and
- * {@code cause}.
+ * Constructs a new Metapath exception with the provided {@code code},
+ * {@code message} and {@code cause}.
*
+ * @param errorCode
+ * the error code that identifies the type of error
* @param message
* the exception message
* @param cause
* the exception cause
*/
- public MetapathException(String message, Throwable cause) {
+ protected MetapathException(
+ @NonNull IErrorCode errorCode,
+ @Nullable String message,
+ @Nullable Throwable cause) {
super(message, cause);
+ this.errorCode = errorCode;
+ }
+
+ public MetapathException registerEvaluationContext(@NonNull DynamicContext dynamicContext) {
+ if (evaluationStack == null) {
+ evaluationStack = dynamicContext.getExecutionStack();
+ }
+ return this;
+ }
+
+ public MetapathException registerEvaluationContext(@NonNull IMetapathExpression metapath) {
+ if (evaluationStack == null) {
+ evaluationStack = new ArrayDeque<>(Collections.singleton(metapath));
+ }
+ return this;
+ }
+
+ @Nullable
+ protected Deque getEvaluationStack() {
+ return evaluationStack;
+ }
+
+ @Override
+ public final String getMessage() {
+ String message = getMessageText();
+ return String.format(
+ "%s%s",
+ getErrorCode().toString(),
+ message == null ? "" : ": " + message);
+ }
+
+ /**
+ * Get the message text without the error code prefix.
+ *
+ * @return the message text or {@code null}
+ */
+ @Nullable
+ public String getMessageText() {
+ Deque evaluationStack = getEvaluationStack();
+
+ // assert evaluationStack != null
+ // && !evaluationStack.isEmpty() : "The evaluation stack must contain at least
+ // one entry";
+ return super.getMessage();
+
+ // TODO: get function call context
+ // evaluationStack.stream()
+ // .filter(null)
+ // .findFirst();
+
+ // new FunctionMetapathError(
+ // dynamicContext.getExecutionStack(),
+ // ex.getErrorCode(),
+ // String.format("Unable to execute function '%s'. %s",
+ // toSignature(),
+ // ex.getLocalizedMessage()),
+ // ex);
+
+ // TODO: get expression context, which should be the head
+
+ // IMetapathExpression head = (IMetapathExpression)
+ // getEvaluationStack().peekLast();
+ // return String.format(
+ // "An error occurred while evaluating the expression '%s'%s",
+ // head.getPath(),
+ // message == null ? "" : ": " + message);
}
+
+ /**
+ * Get the error code, which indicates what type of error it is.
+ *
+ * @return the error code
+ */
+ @NonNull
+ public final IErrorCode getErrorCode() {
+ return errorCode;
+ }
+
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java
index e8eb9250b..bed824d6a 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java
@@ -24,7 +24,6 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
-import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@@ -455,7 +454,7 @@ private static void checkForUnknownPrefix(@NonNull String prefix) {
@NonNull
public IFunction lookupFunction(@NonNull String name, int arity) {
IEnhancedQName qname = parseFunctionName(name);
- return functionResolver.getFunction(qname, arity);
+ return lookupFunction(qname, arity);
}
/**
@@ -471,10 +470,8 @@ public IFunction lookupFunction(@NonNull String name, int arity) {
* a matching function was not found
*/
@NonNull
- public static IFunction lookupFunction(@NonNull IEnhancedQName qname, int arity) {
- return FunctionService.getInstance().getFunction(
- Objects.requireNonNull(qname, "name"),
- arity);
+ public IFunction lookupFunction(@NonNull IEnhancedQName qname, int arity) {
+ return functionResolver.getFunction(qname, arity);
}
/**
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticMetapathException.java
index 8e911952e..4c08bc7d9 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticMetapathException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticMetapathException.java
@@ -5,20 +5,29 @@
package gov.nist.secauto.metaschema.core.metapath;
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
+
/**
* MPST: Exceptions related to the Metapath static context and static
* evaluation.
*/
+// TODO: review use of this exception
+// TODO: include a reference to the Metapath expression?
+// TODO: Move this to a StaticMetapathException that extends this class; align
+// signatures with DynamicMetapathError
@SuppressWarnings("PMD.DataClass")
public class StaticMetapathException
- extends AbstractCodedMetapathException {
+ extends MetapathException {
+ @NonNull
+ private static final String PREFIX = "MPST";
/**
* err:MPST0003: It
* is a static
* error if an expression is not a valid instance of the Metapath grammar.
*/
// TODO: need a Metapath grammar link
- public static final int INVALID_PATH_GRAMMAR = 3;
+ protected static final int INVALID_PATH_GRAMMAR = 3;
/**
* err:MPST0008: It
@@ -132,8 +141,11 @@ public class StaticMetapathException
* @param cause
* the original exception cause
*/
- public StaticMetapathException(int code, String message, Throwable cause) {
- super(code, message, cause);
+ public StaticMetapathException(
+ int code,
+ @Nullable String message,
+ @Nullable Throwable cause) {
+ super(IErrorCode.of(PREFIX, code), message, cause);
}
/**
@@ -145,8 +157,10 @@ public StaticMetapathException(int code, String message, Throwable cause) {
* @param message
* the exception message
*/
- public StaticMetapathException(int code, String message) {
- super(code, message);
+ public StaticMetapathException(
+ int code,
+ @Nullable String message) {
+ super(IErrorCode.of(PREFIX, code), message, null);
}
/**
@@ -158,13 +172,9 @@ public StaticMetapathException(int code, String message) {
* @param cause
* the original exception cause
*/
- public StaticMetapathException(int code, Throwable cause) {
- super(code, cause);
- }
-
- @Override
- public String getCodePrefix() {
- return "MPST";
+ public StaticMetapathException(
+ int code,
+ @Nullable Throwable cause) {
+ super(IErrorCode.of(PREFIX, code), null, cause);
}
-
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpression.java
index cca59fd3b..3b9e1216c 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpression.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpression.java
@@ -31,7 +31,7 @@ public AbstractExpression(@NonNull String text) {
}
@Override
- public String getText() {
+ public String getPath() {
return text;
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCSTVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCSTVisitor.java
index 7244db40b..7ea611990 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCSTVisitor.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCSTVisitor.java
@@ -6,6 +6,7 @@
package gov.nist.secauto.metaschema.core.metapath.cst;
import gov.nist.secauto.metaschema.core.metapath.IExpression;
+import gov.nist.secauto.metaschema.core.metapath.InvalidMetapathGrammarException;
import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException;
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10;
@@ -63,9 +64,9 @@
import gov.nist.secauto.metaschema.core.metapath.cst.type.TypeTestSupport;
import gov.nist.secauto.metaschema.core.metapath.function.ComparisonFunctions;
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
-import gov.nist.secauto.metaschema.core.metapath.impl.AbstractKeySpecifier;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem;
import gov.nist.secauto.metaschema.core.metapath.item.function.IKeySpecifier;
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.AbstractKeySpecifier;
import gov.nist.secauto.metaschema.core.metapath.type.IAtomicOrUnionType;
import gov.nist.secauto.metaschema.core.metapath.type.IItemType;
import gov.nist.secauto.metaschema.core.metapath.type.ISequenceType;
@@ -1172,8 +1173,11 @@ private IAtomicOrUnionType> getTypeForCast(@NonNull String name) {
try {
type = getContext().lookupAtomicType(name);
} catch (StaticMetapathException ex) {
- if (StaticMetapathException.UNKNOWN_TYPE == ex.getCode()) {
- throw new StaticMetapathException(StaticMetapathException.CAST_UNKNOWN_TYPE, ex);
+ if (StaticMetapathException.UNKNOWN_TYPE == ex.getErrorCode().getCode()) {
+ throw new StaticMetapathException(
+ StaticMetapathException.CAST_UNKNOWN_TYPE,
+ String.format("Unknown type '%s'.", name),
+ ex);
}
throw ex;
}
@@ -1275,8 +1279,8 @@ protected IExpression handleArrowexpr(Metapath10.ArrowexprContext context) {
// function expression
result = visit(arrowCtx.parenthesizedexpr().expr());
} else {
- throw new StaticMetapathException(
- StaticMetapathException.INVALID_PATH_GRAMMAR,
+ // TODO: Is this the correct exception to throw here?
+ throw new InvalidMetapathGrammarException(
String.format("Unable to get function name using arrow specifier '%s'.", arrowCtx.getText()));
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/FunctionCallAccessor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/FunctionCallAccessor.java
index a13630fbb..b89bcccbf 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/FunctionCallAccessor.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/FunctionCallAccessor.java
@@ -81,7 +81,10 @@ protected ISequence> evaluate(DynamicContext dynamicContext, ISequence> focu
IItem collection = target.getFirstItem(true);
if (!(collection instanceof IFunction)) {
- throw new InvalidTypeMetapathException(collection, "The base expression did not evaluate to a function.");
+ throw new InvalidTypeMetapathException(
+ collection,
+ "The base expression did not evaluate to a function.")
+ .registerEvaluationContext(dynamicContext);
}
return ((IFunction) collection).execute(ObjectUtils.notNull(getArguments().stream()
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/NamedFunctionReference.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/NamedFunctionReference.java
index acc6f2f0f..9056f9cf4 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/NamedFunctionReference.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/NamedFunctionReference.java
@@ -82,7 +82,7 @@ public RESULT accept(IExpressionVisitor visit
@Override
protected ISequence> evaluate(DynamicContext dynamicContext, ISequence> focus) {
- IFunction function = dynamicContext.getFunction(name, arity);
+ IFunction function = dynamicContext.lookupFunction(name, arity);
return ISequence.of(function);
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/MapConstructor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/MapConstructor.java
index e080af521..b8253e5cf 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/MapConstructor.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/MapConstructor.java
@@ -60,8 +60,11 @@ protected ISequence> evaluate(DynamicContext dynamicContext, ISequence> focu
IAnyAtomicItem key = ISequence.of(keyExpression.accept(dynamicContext, focus).atomize())
.getFirstItem(true);
if (key == null) {
- throw new InvalidTypeMetapathException(null, String.format(
- "The expression '%s' did not result in a single key atomic value.", keyExpression.toCSTString()));
+ throw new InvalidTypeMetapathException(
+ null,
+ String.format("The expression '%s' did not result in a single key atomic value.",
+ keyExpression.toCSTString()))
+ .registerEvaluationContext(dynamicContext);
}
ICollectionValue value = item.getValueExpression().accept(dynamicContext, focus).toCollectionValue();
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Multiplication.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Multiplication.java
index f66648b6d..b11d01665 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Multiplication.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Multiplication.java
@@ -138,6 +138,7 @@ Map, OperationStrategy>> generateStrategies() {
* @throws InvalidTypeMetapathException
* for unsupported operand combinations.
*/
+ // TODO: Is this used?
@SuppressWarnings("PMD.CyclomaticComplexity")
@NonNull
public static IAnyAtomicItem multiply(
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractSearchPathExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractSearchPathExpression.java
index 2a29bccac..c551e04b6 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractSearchPathExpression.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractSearchPathExpression.java
@@ -78,7 +78,7 @@ protected Stream extends INodeItem> search(
= (Stream extends INodeItem>) expression.accept(dynamicContext, focus).stream();
Stream extends INodeItem> childMatches = focus.stream()
- .map(ItemUtils::checkItemIsNodeItemForStep)
+ .map(item -> ItemUtils.checkItemIsNodeItem(dynamicContext, item))
.flatMap(focusedNode -> {
Stream extends INodeItem> matches;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractStepExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractStepExpression.java
index f8de3891f..1d701aea2 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractStepExpression.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractStepExpression.java
@@ -67,7 +67,7 @@ protected ISequence extends RESULT_TYPE> evaluate(
DynamicContext dynamicContext,
ISequence> focus) {
return ISequence.of(ObjectUtils.notNull(focus.stream()
- .map(ItemUtils::checkItemIsNodeItemForStep)
+ .map(item -> ItemUtils.checkItemIsNodeItem(dynamicContext, item))
.flatMap(item -> {
assert item != null;
return match(item);
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/ContextItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/ContextItem.java
index 7afb5cbdc..93551a2d1 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/ContextItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/ContextItem.java
@@ -5,8 +5,8 @@
package gov.nist.secauto.metaschema.core.metapath.cst.path;
+import gov.nist.secauto.metaschema.core.metapath.ContextAbsentDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.IExpression;
import gov.nist.secauto.metaschema.core.metapath.cst.IExpressionVisitor;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
@@ -68,7 +68,8 @@ public RESULT accept(IExpressionVisitor visit
@Override
protected ISequence> evaluate(DynamicContext dynamicContext, ISequence> focus) {
if (focus.isEmpty()) {
- throw new DynamicMetapathException(DynamicMetapathException.DYNAMIC_CONTEXT_ABSENT, "The context is empty");
+ throw new ContextAbsentDynamicMetapathException("The context item is empty")
+ .registerEvaluationContext(dynamicContext);
}
return focus;
}
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 04c871097..fb96519db 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
@@ -50,7 +50,7 @@ public RESULT accept(IExpressionVisitor visit
@Override
protected ISequence extends INodeItem> evaluate(DynamicContext dynamicContext, ISequence> focus) {
return ISequence.of(filterStream(ObjectUtils.notNull(focus.stream()
- .map(ItemUtils::checkItemIsNodeItemForStep))));
+ .map(item -> ItemUtils.checkItemIsNodeItem(dynamicContext, item)))));
}
@SuppressWarnings("null")
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/NameNodeTest.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/NameNodeTest.java
index dac3654ea..feb2e847a 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/NameNodeTest.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/NameNodeTest.java
@@ -63,7 +63,7 @@ public RESULT accept(IExpressionVisitor visit
@Override
protected ISequence extends INodeItem> evaluate(DynamicContext dynamicContext, ISequence> focus) {
Stream nodes = ObjectUtils.notNull(focus.stream()
- .map(ItemUtils::checkItemIsNodeItemForStep));
+ .map(item -> ItemUtils.checkItemIsNodeItem(dynamicContext, item)));
return ISequence.of(filterStream(nodes));
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootDoubleSlashPath.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootDoubleSlashPath.java
index fe9ee3d73..3975f03bc 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootDoubleSlashPath.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootDoubleSlashPath.java
@@ -9,6 +9,7 @@
import gov.nist.secauto.metaschema.core.metapath.IExpression;
import gov.nist.secauto.metaschema.core.metapath.cst.IExpressionVisitor;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
+import gov.nist.secauto.metaschema.core.metapath.item.ItemUtils;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -42,7 +43,10 @@ public RESULT accept(IExpressionVisitor visit
}
@Override
- protected ISequence> evaluate(DynamicContext dynamicContext, ISequence> context) {
- return ISequence.of(search(getExpression(), dynamicContext, context));
+ protected ISequence> evaluate(DynamicContext dynamicContext, ISequence> focus) {
+ return ISequence.of(search(
+ getExpression(),
+ dynamicContext,
+ ItemUtils.getDocumentNodeItems(dynamicContext, focus)));
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashOnlyPath.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashOnlyPath.java
index 06aa685ed..e347213b6 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashOnlyPath.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashOnlyPath.java
@@ -6,15 +6,12 @@
package gov.nist.secauto.metaschema.core.metapath.cst.path;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.IExpression;
import gov.nist.secauto.metaschema.core.metapath.cst.IExpressionVisitor;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.ItemUtils;
-import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
-import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.util.List;
@@ -61,23 +58,6 @@ public RESULT accept(IExpressionVisitor visit
@Override
protected ISequence extends INodeItem> evaluate(DynamicContext dynamicContext, ISequence> focus) {
- return ISequence.of(ObjectUtils.notNull(focus.stream()
- .map(ItemUtils::checkItemIsNodeItemForStep)
- .map(RootSlashOnlyPath::findAndValidateDocumentRoot)));
- }
-
- private static INodeItem findAndValidateDocumentRoot(INodeItem item) {
- INodeItem root = Axis.ANCESTOR_OR_SELF.execute(ObjectUtils.notNull(item))
- .findFirst()
- .orElseThrow(() -> new DynamicMetapathException(
- DynamicMetapathException.TREAT_DOES_NOT_MATCH_TYPE,
- "Root node not found"));
-
- if (!(root instanceof IDocumentNodeItem)) {
- throw new DynamicMetapathException(
- DynamicMetapathException.TREAT_DOES_NOT_MATCH_TYPE,
- "The head of the tree is not a document node.");
- }
- return root;
+ return ItemUtils.getDocumentNodeItems(dynamicContext, focus);
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashPath.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashPath.java
index 3106093bb..762dedc09 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashPath.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashPath.java
@@ -47,7 +47,7 @@ public RESULT accept(IExpressionVisitor visit
@Override
protected ISequence> evaluate(DynamicContext dynamicContext, ISequence> focus) {
ISequence> roots = ObjectUtils.notNull(focus.stream()
- .map(ItemUtils::checkItemIsNodeItemForStep)
+ .map(item -> ItemUtils.checkItemIsNodeItem(dynamicContext, item))
// the previous checks for a null instance
.flatMap(item -> Axis.ANCESTOR_OR_SELF.execute(ObjectUtils.notNull(item)).limit(1))
.collect(CustomCollectors.toSequence()));
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Step.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Step.java
index d43580596..c3e918bed 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Step.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Step.java
@@ -115,7 +115,7 @@ protected ISequence> evaluate(DynamicContext dynamicContext, ISequence> focu
axisResult = ISequence.empty();
} else {
axisResult = ISequence.of(ObjectUtils.notNull(focus.stream()
- .map(ItemUtils::checkItemIsNodeItemForStep)
+ .map(item -> ItemUtils.checkItemIsNodeItem(dynamicContext, item))
.flatMap(item -> {
assert item != null;
return axis.execute(item);
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 109d484a6..730430aef 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
@@ -53,7 +53,7 @@ public RESULT accept(IExpressionVisitor visit
@Override
protected ISequence extends INodeItem> evaluate(DynamicContext dynamicContext, ISequence> focus) {
Stream stream = focus.stream()
- .map(ItemUtils::checkItemIsNodeItemForStep);
+ .map(item -> ItemUtils.checkItemIsNodeItem(dynamicContext, item));
if (matcher != null) {
stream = stream.filter(this::match);
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/type/Treat.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/type/Treat.java
index 05dfe3e9b..9047abbcb 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/type/Treat.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/type/Treat.java
@@ -6,8 +6,8 @@
package gov.nist.secauto.metaschema.core.metapath.cst.type;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.IExpression;
+import gov.nist.secauto.metaschema.core.metapath.InvalidTreatTypeDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.cst.AbstractExpression;
import gov.nist.secauto.metaschema.core.metapath.cst.IExpressionVisitor;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
@@ -64,8 +64,8 @@ public List extends IExpression> getChildren() {
protected ISequence> evaluate(DynamicContext dynamicContext, ISequence> focus) {
ISequence> retval = value.accept(dynamicContext, focus);
if (!type.matches(retval)) {
- throw new DynamicMetapathException(
- DynamicMetapathException.TREAT_DOES_NOT_MATCH_TYPE,
+ throw new InvalidTreatTypeDynamicMetapathException(
+ dynamicContext.getExecutionStack(),
String.format("The sequence '%s' does not match the sequence type '%s'.", retval, type.toSignature()));
}
return retval;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/ArithmeticFunctionException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/ArithmeticFunctionException.java
index 8c50a75fa..3d7336f04 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/ArithmeticFunctionException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/ArithmeticFunctionException.java
@@ -5,13 +5,17 @@
package gov.nist.secauto.metaschema.core.metapath.function;
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
/**
* Represents an error that occurred while performing mathematical operations.
*/
public class ArithmeticFunctionException
- extends AbstractCodedMetapathException {
+ extends FunctionMetapathError {
+ @NonNull
+ private static final String PREFIX = "FOAR";
/**
* err:FOAR0001:
@@ -46,7 +50,7 @@ public class ArithmeticFunctionException
* the exception message
*/
public ArithmeticFunctionException(int code, String message) {
- super(code, message);
+ super(IErrorCode.of(PREFIX, code), message);
}
/**
@@ -61,7 +65,7 @@ public ArithmeticFunctionException(int code, String message) {
* the original exception cause
*/
public ArithmeticFunctionException(int code, String message, Throwable cause) {
- super(code, message, cause);
+ super(IErrorCode.of(PREFIX, code), message, cause);
}
/**
@@ -74,12 +78,6 @@ public ArithmeticFunctionException(int code, String message, Throwable cause) {
* the original exception cause
*/
public ArithmeticFunctionException(int code, Throwable cause) {
- super(code, cause);
- }
-
- @Override
- public String getCodePrefix() {
- return "FOAR";
+ super(IErrorCode.of(PREFIX, code), cause);
}
-
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/CastFunctionException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/CastFunctionException.java
index 85d7ec943..b4c092642 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/CastFunctionException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/CastFunctionException.java
@@ -5,7 +5,7 @@
package gov.nist.secauto.metaschema.core.metapath.function;
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -14,7 +14,9 @@
* FOCA: Exceptions related to type casting.
*/
public class CastFunctionException
- extends AbstractCodedMetapathException {
+ extends FunctionMetapathError {
+ @NonNull
+ private static final String PREFIX = "FOCA";
/**
* err:FOCA0002:
@@ -52,7 +54,7 @@ public class CastFunctionException
* the exception message text
*/
public CastFunctionException(int code, @NonNull IAnyAtomicItem item, String message) {
- super(code, message);
+ super(IErrorCode.of(PREFIX, code), message);
this.item = item;
}
@@ -70,7 +72,7 @@ public CastFunctionException(int code, @NonNull IAnyAtomicItem item, String mess
* the original exception cause
*/
public CastFunctionException(int code, @NonNull IAnyAtomicItem item, String message, Throwable cause) {
- super(code, message, cause);
+ super(IErrorCode.of(PREFIX, code), message, cause);
this.item = item;
}
@@ -83,9 +85,4 @@ public CastFunctionException(int code, @NonNull IAnyAtomicItem item, String mess
public IAnyAtomicItem getItem() {
return item;
}
-
- @Override
- public String getCodePrefix() {
- return "FOCA";
- }
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DateTimeFunctionException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DateTimeFunctionException.java
index 0b99a50b7..a39b9a4b9 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DateTimeFunctionException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DateTimeFunctionException.java
@@ -5,13 +5,17 @@
package gov.nist.secauto.metaschema.core.metapath.function;
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
/**
* FODT: Exceptions related to Date/Time/Duration errors.
*/
public class DateTimeFunctionException
- extends AbstractCodedMetapathException {
+ extends FunctionMetapathError {
+ @NonNull
+ private static final String PREFIX = "FODT";
/**
* err:FODT0001:
@@ -49,7 +53,7 @@ public class DateTimeFunctionException
* the exception message
*/
public DateTimeFunctionException(int code, String message) {
- super(code, message);
+ super(IErrorCode.of(PREFIX, code), message);
}
/**
@@ -64,7 +68,7 @@ public DateTimeFunctionException(int code, String message) {
* the original exception cause
*/
public DateTimeFunctionException(int code, String message, Throwable cause) {
- super(code, message, cause);
+ super(IErrorCode.of(PREFIX, code), message, cause);
}
/**
@@ -77,12 +81,6 @@ public DateTimeFunctionException(int code, String message, Throwable cause) {
* the original exception cause
*/
public DateTimeFunctionException(int code, Throwable cause) {
- super(code, cause);
- }
-
- @Override
- public String getCodePrefix() {
- return "FODT";
+ super(IErrorCode.of(PREFIX, code), cause);
}
-
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DocumentFunctionException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DocumentFunctionException.java
index 1875cd071..c473d47b2 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DocumentFunctionException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DocumentFunctionException.java
@@ -5,14 +5,18 @@
package gov.nist.secauto.metaschema.core.metapath.function;
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
import gov.nist.secauto.metaschema.core.metapath.function.library.FnDoc;
+import edu.umd.cs.findbugs.annotations.NonNull;
+
/**
* FODC: Exceptions representing document related errors.
*/
public class DocumentFunctionException
- extends AbstractCodedMetapathException {
+ extends FunctionMetapathError {
+ @NonNull
+ private static final String PREFIX = "FODC";
/**
* err:FODC0002:
@@ -51,7 +55,7 @@ public class DocumentFunctionException
* the exception message
*/
public DocumentFunctionException(int code, String message) {
- super(code, message);
+ super(IErrorCode.of(PREFIX, code), message);
}
/**
@@ -66,7 +70,7 @@ public DocumentFunctionException(int code, String message) {
* the original exception cause
*/
public DocumentFunctionException(int code, String message, Throwable cause) {
- super(code, message, cause);
+ super(IErrorCode.of(PREFIX, code), message, cause);
}
/**
@@ -79,12 +83,6 @@ public DocumentFunctionException(int code, String message, Throwable cause) {
* the original exception cause
*/
public DocumentFunctionException(int code, Throwable cause) {
- super(code, cause);
- }
-
- @Override
- public String getCodePrefix() {
- return "FODC";
+ super(IErrorCode.of(PREFIX, code), cause);
}
-
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/FunctionMetapathError.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/FunctionMetapathError.java
new file mode 100644
index 000000000..afbb40cc7
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/FunctionMetapathError.java
@@ -0,0 +1,70 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.metapath.function;
+
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
+import gov.nist.secauto.metaschema.core.metapath.MetapathException;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
+
+// TODO: remove this intermediate exception?
+public class FunctionMetapathError
+ extends MetapathException {
+
+ /**
+ * the serial version UID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a new Metapath exception with the provided {@code code},
+ * {@code message}, and no cause.
+ *
+ * @param errorCode
+ * the error code that identifies the type of error
+ * @param message
+ * the exception message
+ */
+ public FunctionMetapathError(
+ @NonNull IErrorCode errorCode,
+ @Nullable String message) {
+ super(errorCode, message, null);
+ }
+
+ /**
+ * Constructs a new Metapath exception with the provided {@code code},
+ * {@code message}, and {@code cause}.
+ *
+ * @param errorCode
+ * the error code that identifies the type of error
+ * @param message
+ * the exception message
+ * @param cause
+ * the original exception cause
+ */
+ public FunctionMetapathError(
+ @NonNull IErrorCode errorCode,
+ @Nullable String message,
+ @Nullable Throwable cause) {
+ super(errorCode, message, cause);
+ }
+
+ /**
+ * Constructs a new Metapath exception with a {@code null} message and the
+ * provided {@code cause}.
+ *
+ * @param errorCode
+ * the error code that identifies the type of error
+ * @param cause
+ * the original exception cause
+ */
+ public FunctionMetapathError(
+ @NonNull IErrorCode errorCode,
+ @Nullable Throwable cause) {
+ super(errorCode, null, cause);
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/FunctionUtils.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/FunctionUtils.java
index 487249e26..78cc9ff76 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/FunctionUtils.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/FunctionUtils.java
@@ -55,6 +55,7 @@ private FunctionUtils() {
* cast to a numeric value
*
*/
+ @Deprecated(since = "3.0.0", forRemoval = true)
@Nullable
public static INumericItem toNumeric(@NonNull ISequence> sequence, boolean requireSingleton) {
IItem item = sequence.getFirstItem(requireSingleton);
@@ -71,6 +72,7 @@ public static INumericItem toNumeric(@NonNull ISequence> sequence, boolean req
* if the sequence contains more than one item, or the item cannot be
* cast to a numeric value
*/
+ @Deprecated(since = "3.0.0", forRemoval = true)
@NonNull
public static INumericItem toNumeric(@NonNull IItem item) {
// atomize
@@ -90,6 +92,7 @@ public static INumericItem toNumeric(@NonNull IItem item) {
* @throws TypeMetapathException
* if the item cannot be cast to a numeric value
*/
+ @Deprecated(since = "3.0.0", forRemoval = true)
@NonNull
public static INumericItem toNumeric(@NonNull IAnyAtomicItem item) {
try {
@@ -127,6 +130,7 @@ public static INumericItem toNumericOrNull(@Nullable IAnyAtomicItem item) {
* @throws ClassCastException
* if the item's type is not compatible with the requested type
*/
+ @Deprecated(since = "3.0.0", forRemoval = true)
@SuppressWarnings("unchecked")
@Nullable
public static TYPE asTypeOrNull(@Nullable IItem item) {
@@ -144,6 +148,7 @@ public static TYPE asTypeOrNull(@Nullable IItem item) {
* @throws ClassCastException
* if the item's type is not compatible with the requested type
*/
+ @Deprecated(since = "3.0.0", forRemoval = true)
@SuppressWarnings("unchecked")
@NonNull
public static TYPE asType(@NonNull IItem item) {
@@ -161,6 +166,7 @@ public static TYPE asType(@NonNull IItem item) {
* @throws ClassCastException
* if the sequence's type is not compatible with the requested type
*/
+ @Deprecated(since = "3.0.0", forRemoval = true)
@SuppressWarnings("unchecked")
@NonNull
public static ISequence asType(@NonNull ISequence> sequence) {
@@ -181,6 +187,7 @@ public static ISequence asType(@NonNull ISequence>
* if the provided item is {@code null} or if the item's type is not
* assignment compatible to the requested type
*/
+ @Deprecated(since = "3.0.0", forRemoval = true)
@NonNull
public static TYPE requireType(Class clazz, IItem item) {
if (item == null) {
@@ -215,6 +222,7 @@ public static TYPE requireType(Class clazz, IItem ite
* if the provided item is {@code null} or if the item's type is not
* assignment compatible to the requested type
*/
+ @Deprecated(since = "3.0.0", forRemoval = true)
@Nullable
public static TYPE requireTypeOrNull(Class clazz, @Nullable IItem item) {
if (item == null || clazz.isInstance(item)) {
@@ -234,6 +242,7 @@ public static TYPE requireTypeOrNull(Class clazz, @Nu
* the Metapath items to get the data types for
* @return a stream of data type classes
*/
+ @Deprecated(since = "3.0.0", forRemoval = true)
@NonNull
public static Stream> getTypes(@NonNull Stream extends IItem> items) {
return ObjectUtils.notNull(items.map(Object::getClass));
@@ -249,6 +258,7 @@ public static Stream> getTypes(@NonNull Stream extends IItem> items)
* the items to get Java type class for
* @return a list of corresponding Java type classes for the provided items
*/
+ @Deprecated(since = "3.0.0", forRemoval = true)
@SuppressWarnings("unchecked")
@NonNull
public static List> getTypes(@NonNull List items) {
@@ -269,6 +279,7 @@ public static List> getTypes(@NonNull List<
* the Metapath items to analyze
* @return a mapping of Metapath item class to count
*/
+ @Deprecated(since = "3.0.0", forRemoval = true)
@NonNull
public static Map, Integer> countTypes(
@NonNull Set> classes,
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/InvalidArgumentFunctionException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/InvalidArgumentFunctionException.java
index 35d2db9fd..6d3d02d65 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/InvalidArgumentFunctionException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/InvalidArgumentFunctionException.java
@@ -5,13 +5,17 @@
package gov.nist.secauto.metaschema.core.metapath.function;
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
/**
* FORG: Exceptions related to argument types.
*/
public class InvalidArgumentFunctionException
- extends AbstractCodedMetapathException {
+ extends FunctionMetapathError {
+ @NonNull
+ private static final String PREFIX = "FORG";
/**
* err:FOTY0012:
@@ -61,7 +63,7 @@ public class InvalidTypeFunctionException
* the item the exception applies to
*/
public InvalidTypeFunctionException(int code, @NonNull IItem item) {
- super(code, generateMessage(item));
+ super(IErrorCode.of(PREFIX, code), generateMessage(item));
}
/**
@@ -76,7 +78,7 @@ public InvalidTypeFunctionException(int code, @NonNull IItem item) {
* the original exception cause
*/
public InvalidTypeFunctionException(int code, @NonNull IItem item, Throwable cause) {
- super(code, generateMessage(item), cause);
+ super(IErrorCode.of(PREFIX, code), generateMessage(item), cause);
}
private static String generateMessage(@NonNull IItem item) {
@@ -91,9 +93,4 @@ private static String generateMessage(@NonNull IItem item) {
}
return retval;
}
-
- @Override
- public String getCodePrefix() {
- return "FOTY";
- }
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/JsonFunctionException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/JsonFunctionException.java
index 240e36098..3f9481ba0 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/JsonFunctionException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/JsonFunctionException.java
@@ -5,10 +5,14 @@
package gov.nist.secauto.metaschema.core.metapath.function;
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
public class JsonFunctionException
- extends AbstractCodedMetapathException {
+ extends FunctionMetapathError {
+ @NonNull
+ private static final String PREFIX = "FOJS";
/**
* err:FOJS0003:
@@ -39,7 +43,7 @@ public class JsonFunctionException
* the exception message
*/
public JsonFunctionException(int code, String message) {
- super(code, message);
+ super(IErrorCode.of(PREFIX, code), message);
}
/**
@@ -54,7 +58,7 @@ public JsonFunctionException(int code, String message) {
* the original exception cause
*/
public JsonFunctionException(int code, String message, Throwable cause) {
- super(code, message, cause);
+ super(IErrorCode.of(PREFIX, code), message, cause);
}
/**
@@ -67,11 +71,6 @@ public JsonFunctionException(int code, String message, Throwable cause) {
* the original exception cause
*/
public JsonFunctionException(int code, Throwable cause) {
- super(code, cause);
- }
-
- @Override
- public String getCodePrefix() {
- return "FOJS";
+ super(IErrorCode.of(PREFIX, code), cause);
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UnidentifiedFunctionError.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UnidentifiedFunctionError.java
index c229b573b..2a81e9ade 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UnidentifiedFunctionError.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UnidentifiedFunctionError.java
@@ -5,10 +5,15 @@
package gov.nist.secauto.metaschema.core.metapath.function;
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
public class UnidentifiedFunctionError
- extends AbstractCodedMetapathException {
+ extends FunctionMetapathError {
+ @NonNull
+ private static final IErrorCode ERROR_CODE = IErrorCode.of("FOER", 0);
/**
* the serial version UID.
@@ -24,8 +29,8 @@ public class UnidentifiedFunctionError
* @param cause
* the original exception cause
*/
- public UnidentifiedFunctionError(String message, Throwable cause) {
- super(0, message, cause);
+ public UnidentifiedFunctionError(@Nullable String message, @Nullable Throwable cause) {
+ super(ERROR_CODE, message, cause);
}
/**
@@ -35,8 +40,8 @@ public UnidentifiedFunctionError(String message, Throwable cause) {
* @param message
* the exception message
*/
- public UnidentifiedFunctionError(String message) {
- super(0, message);
+ public UnidentifiedFunctionError(@Nullable String message) {
+ super(ERROR_CODE, message);
}
/**
@@ -46,13 +51,7 @@ public UnidentifiedFunctionError(String message) {
* @param cause
* the original exception cause
*/
- public UnidentifiedFunctionError(Throwable cause) {
- super(0, cause);
- }
-
- @Override
- public String getCodePrefix() {
- return "FOER";
+ public UnidentifiedFunctionError(@Nullable Throwable cause) {
+ super(ERROR_CODE, cause);
}
-
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UriFunctionException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UriFunctionException.java
index e536ca5ab..d0d993796 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UriFunctionException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UriFunctionException.java
@@ -5,14 +5,18 @@
package gov.nist.secauto.metaschema.core.metapath.function;
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
import gov.nist.secauto.metaschema.core.metapath.function.library.FnResolveUri;
+import edu.umd.cs.findbugs.annotations.NonNull;
+
/**
* FONS: Exceptions related to function namespaces.
*/
public class UriFunctionException
- extends AbstractCodedMetapathException {
+ extends FunctionMetapathError {
+ @NonNull
+ private static final String PREFIX = "FONS";
/**
* err:FONS0004:
@@ -45,7 +49,7 @@ public class UriFunctionException
* the exception message
*/
public UriFunctionException(int code, String message) {
- super(code, message);
+ super(IErrorCode.of(PREFIX, code), message);
}
/**
@@ -60,7 +64,7 @@ public UriFunctionException(int code, String message) {
* the original exception cause
*/
public UriFunctionException(int code, String message, Throwable cause) {
- super(code, message, cause);
+ super(IErrorCode.of(PREFIX, code), message, cause);
}
/**
@@ -73,12 +77,6 @@ public UriFunctionException(int code, String message, Throwable cause) {
* the original exception cause
*/
public UriFunctionException(int code, Throwable cause) {
- super(code, cause);
- }
-
- @Override
- public String getCodePrefix() {
- return "FONS";
+ super(IErrorCode.of(PREFIX, code), cause);
}
-
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/impl/AbstractFunction.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/impl/AbstractFunction.java
index f3e5b301d..4773aac3f 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/impl/AbstractFunction.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/impl/AbstractFunction.java
@@ -5,8 +5,8 @@
package gov.nist.secauto.metaschema.core.metapath.function.impl;
+import gov.nist.secauto.metaschema.core.metapath.ContextAbsentDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.CalledContext;
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
@@ -136,14 +136,14 @@ public static List> convertArguments(
argument = argumentIterator.next();
} else if (!function.isArityUnbounded()) {
throw new InvalidTypeMetapathException(
- null,
- String.format("argument signature doesn't match '%s'", function.toSignature()));
+ function,
+ String.format("Argument signature doesn't match '%s'.", function.toSignature()));
}
assert argument != null;
assert parameter != null;
- retval.add(convertArgument(argument, parameter));
+ retval.add(convertArgument(argument, parameter, dynamicContext));
}
return CollectionUtil.unmodifiableList(retval);
}
@@ -151,7 +151,8 @@ public static List> convertArguments(
@NonNull
private static ISequence> convertArgument(
@NonNull IArgument argument,
- @NonNull ISequence> parameter) {
+ @NonNull ISequence> parameter,
+ @NonNull DynamicContext dynamicContext) {
ISequenceType sequenceType = argument.getSequenceType();
// apply occurrence
@@ -161,7 +162,7 @@ private static ISequence> convertArgument(
if (!result.isEmpty()) {
IItemType type = sequenceType.getType();
// this is not required to be an empty sequence
- result = convertSequence(argument, result, type);
+ result = convertSequence(argument, result, type, dynamicContext);
}
// verify resulting values
@@ -179,13 +180,16 @@ private static ISequence> convertArgument(
* the sequence to convert
* @param requiredSequenceType
* the expected item type for the sequence
+ * @param dynamicContext
+ * the dynamic evaluation context
* @return the converted sequence
*/
@NonNull
protected static ISequence> convertSequence(
@NonNull IArgument argument,
@NonNull ISequence> sequence,
- @NonNull IItemType requiredSequenceType) {
+ @NonNull IItemType requiredSequenceType,
+ @NonNull DynamicContext dynamicContext) {
Class extends IItem> requiredSequenceTypeClass = requiredSequenceType.getItemClass();
Stream extends IItem> stream = sequence.safeStream();
@@ -221,13 +225,9 @@ protected static ISequence> convertSequence(
@Nullable
private IItem getContextItem(@NonNull ISequence> focus) {
- IItem contextItem = isFocusDependent()
+ return isFocusDependent()
? focus.getFirstItem(true)
: null;
- if (isFocusDependent() && contextItem == null) {
- throw new DynamicMetapathException(DynamicMetapathException.DYNAMIC_CONTEXT_ABSENT, "The context is empty");
- }
- return contextItem;
}
@Override
@@ -238,6 +238,9 @@ public ISequence> execute(
try {
IItem contextItem = getContextItem(focus);
+ if (isFocusDependent() && contextItem == null) {
+ throw new ContextAbsentDynamicMetapathException("The context item is empty.");
+ }
List> convertedArguments = convertArguments(this, arguments, dynamicContext);
@@ -268,12 +271,7 @@ public ISequence> execute(
// toSignature(), convertedArguments.toString(), result.asList().toString()));
return result;
} catch (MetapathException ex) {
- // FIXME: avoid throwing a new exception for a function-related exception. Fix
- // this after refactoring the exception hierarchy.
- throw new MetapathException(String.format("Unable to execute function '%s'. %s",
- toSignature(),
- ex.getLocalizedMessage()),
- ex);
+ throw ex.registerEvaluationContext(dynamicContext);
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/impl/OperationFunctions.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/impl/OperationFunctions.java
index 0f2c13595..a52851d04 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/impl/OperationFunctions.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/impl/OperationFunctions.java
@@ -1132,14 +1132,17 @@ public static INumericItem opNumericMod(@NonNull INumericItem dividend, @NonNull
* @return the number with a reversed sign
*/
@NonNull
- public static INumericItem opNumericUnaryMinus(@NonNull INumericItem item) {
+ public static INumericItem opNumericUnaryMinus(
+ @NonNull INumericItem item) {
INumericItem retval;
if (item instanceof IIntegerItem) {
retval = ((IIntegerItem) item).negate();
} else if (item instanceof IDecimalItem) {
retval = ((IDecimalItem) item).negate();
} else {
- throw new InvalidTypeMetapathException(item, String.format("Unsupported numeric type '%s'.", item.getClass()));
+ throw new InvalidTypeMetapathException(
+ item,
+ String.format("Unsupported numeric type '%s'.", item.getClass()));
}
return retval;
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayGet.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayGet.java
index bfeed4e10..4b2fa7b92 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayGet.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayGet.java
@@ -14,8 +14,8 @@
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.IIntegerItem;
-import gov.nist.secauto.metaschema.core.metapath.item.function.ArrayException;
import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem;
+import gov.nist.secauto.metaschema.core.metapath.item.function.IndexOutOfBoundsArrayMetapathException;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.util.List;
@@ -78,12 +78,12 @@ private static ISequence> execute(@NonNull IFunction function,
* @param positionItem
* the integer position of the item to retrieve
* @return the retrieved item
- * @throws ArrayException
+ * @throws IndexOutOfBoundsArrayMetapathException
* if the position is not in the range of 1 to array:size
*/
@NonNull
public static T get(
- @NonNull List target,
+ @NonNull IArrayItem target,
@NonNull IIntegerItem positionItem) {
return get(target, positionItem.toIntValueExact());
}
@@ -99,18 +99,18 @@ public static T get(
* @param position
* the integer position of the item to retrieve
* @return the retrieved item
- * @throws ArrayException
+ * @throws IndexOutOfBoundsArrayMetapathException
* if the position is not in the range of 1 to array:size
*/
@NonNull
public static T get(
- @NonNull List target,
+ @NonNull IArrayItem target,
int position) {
try {
return ObjectUtils.requireNonNull(target.get(position - 1));
} catch (IndexOutOfBoundsException ex) {
- throw new ArrayException(
- ArrayException.INDEX_OUT_OF_BOUNDS,
+ throw new IndexOutOfBoundsArrayMetapathException(
+ target,
String.format("The index %d is outside the range of values for the array size '%d'.",
position,
target.size()),
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayInsertBefore.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayInsertBefore.java
index 6c0c48365..b13cc1a11 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayInsertBefore.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayInsertBefore.java
@@ -14,8 +14,9 @@
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.IIntegerItem;
-import gov.nist.secauto.metaschema.core.metapath.item.function.ArrayException;
import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem;
+import gov.nist.secauto.metaschema.core.metapath.item.function.IndexOutOfBoundsArrayMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.item.function.NegativeLengthArrayMetapathException;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.util.List;
@@ -91,7 +92,9 @@ private static ISequence> execute(@No
* @param member
* the Metapath item to insert into the identified array
* @return a new array containing the modification
- * @throws ArrayException
+ * @throws NegativeLengthArrayMetapathException
+ * if the position is negative
+ * @throws IndexOutOfBoundsArrayMetapathException
* if the position is not in the range of 1 to array:size
*/
@NonNull
@@ -115,7 +118,9 @@ public static IArrayItem insertBefore(
* @param member
* the Metapath item to insert into the identified array
* @return a new array containing the modification
- * @throws ArrayException
+ * @throws NegativeLengthArrayMetapathException
+ * if the position is negative
+ * @throws IndexOutOfBoundsArrayMetapathException
* if the position is not in the range of 1 to array:size
*/
@NonNull
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayPut.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayPut.java
index 2994eb6aa..88a3945b0 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayPut.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayPut.java
@@ -14,8 +14,9 @@
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.IIntegerItem;
-import gov.nist.secauto.metaschema.core.metapath.item.function.ArrayException;
import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem;
+import gov.nist.secauto.metaschema.core.metapath.item.function.IndexOutOfBoundsArrayMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.item.function.NegativeLengthArrayMetapathException;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.util.ArrayList;
@@ -92,7 +93,9 @@ private static ISequence extends IArrayItem> e
* @param member
* the Metapath item to replace the identified array member with
* @return a new array containing the modification
- * @throws ArrayException
+ * @throws NegativeLengthArrayMetapathException
+ * if the position is negative
+ * @throws IndexOutOfBoundsArrayMetapathException
* if the position is not in the range of 1 to array:size
*/
@NonNull
@@ -116,7 +119,9 @@ public static IArrayItem put(
* @param member
* the Metapath item to replace the identified array member with
* @return a new array containing the modification
- * @throws ArrayException
+ * @throws NegativeLengthArrayMetapathException
+ * if the position is negative
+ * @throws IndexOutOfBoundsArrayMetapathException
* if the position is not in the range of 1 to array:size
*/
@NonNull
@@ -128,8 +133,8 @@ public static IArrayItem put(
try {
copy.set(position - 1, member);
} catch (IndexOutOfBoundsException ex) {
- throw new ArrayException(
- ArrayException.INDEX_OUT_OF_BOUNDS,
+ throw new IndexOutOfBoundsArrayMetapathException(
+ array,
String.format("The position %d is outside the range of values for the array of size '%d'.",
position,
copy.size()),
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayRemove.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayRemove.java
index 1727539e3..25ca67687 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayRemove.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArrayRemove.java
@@ -13,8 +13,9 @@
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.IIntegerItem;
-import gov.nist.secauto.metaschema.core.metapath.item.function.ArrayException;
import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem;
+import gov.nist.secauto.metaschema.core.metapath.item.function.IndexOutOfBoundsArrayMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.item.function.NegativeLengthArrayMetapathException;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.util.Collection;
@@ -83,7 +84,9 @@ private static ISequence> execute(@NonNull IFunc
* @param positions
* the integer position of the items to remove
* @return a new array containing the modification
- * @throws ArrayException
+ * @throws NegativeLengthArrayMetapathException
+ * if the position is negative
+ * @throws IndexOutOfBoundsArrayMetapathException
* if the position is not in the range of 1 to array:size
*/
@NonNull
@@ -97,7 +100,7 @@ public static IArrayItem removeItems(
.map(IIntegerItem::toIntValueExact)
.peek(position -> {
if (position < 1 || position > size) {
- throw new ArrayException(ArrayException.INDEX_OUT_OF_BOUNDS,
+ throw new ArrayIndexOutOfBoundsException(
String.format("Index position '%d' is out of bounds for the array of size '%d'.", position, size));
}
})
@@ -115,7 +118,9 @@ public static IArrayItem removeItems(
* @param positions
* the integer position of the items to remove
* @return a new array containing the modification
- * @throws ArrayException
+ * @throws NegativeLengthArrayMetapathException
+ * if the position is negative
+ * @throws IndexOutOfBoundsArrayMetapathException
* if the position is not in the range of 1 to array:size
*/
@NonNull
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArraySubarray.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArraySubarray.java
index c1b30ed72..d11a321b8 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArraySubarray.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/ArraySubarray.java
@@ -14,8 +14,9 @@
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.IIntegerItem;
-import gov.nist.secauto.metaschema.core.metapath.item.function.ArrayException;
import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem;
+import gov.nist.secauto.metaschema.core.metapath.item.function.IndexOutOfBoundsArrayMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.item.function.NegativeLengthArrayMetapathException;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.util.ArrayList;
@@ -120,8 +121,8 @@ private static ISequence> executeThre
* @param startItem
* the integer position of the item to start with (inclusive)
* @return a new array item consisting of the items in the identified range
- * @throws ArrayException
- * if the position is not in the range of 1 to array:size
+ * @throws IndexOutOfBoundsArrayMetapathException
+ * if the start position is not in the range of 1 to array:size
*/
@SuppressWarnings("PMD.OnlyOneReturn")
@NonNull
@@ -145,9 +146,10 @@ public static IArrayItem subarray(
* the integer count of items to include starting with the item at the
* start position
* @return a new array item consisting of the items in the identified range
- * @throws ArrayException
- * if the length is negative or the position is not in the range of 1
- * to array:size
+ * @throws NegativeLengthArrayMetapathException
+ * if the length is negative
+ * @throws IndexOutOfBoundsArrayMetapathException
+ * if the start position is not in the range of 1 to array:size
*/
@SuppressWarnings("PMD.OnlyOneReturn")
@NonNull
@@ -169,9 +171,8 @@ public static IArrayItem subarray(
* @param start
* the integer position of the item to start with (inclusive)
* @return a new array item consisting of the items in the identified range
- * @throws ArrayException
- * if the length is negative or the position is not in the range of 1
- * to array:size
+ * @throws IndexOutOfBoundsArrayMetapathException
+ * if the start position is not in the range of 1 to array:size
*/
@NonNull
public static IArrayItem subarray(
@@ -194,9 +195,11 @@ public static IArrayItem subarray(
* the integer count of items to include starting with the item at the
* start position
* @return a new array item consisting of the items in the identified range
- * @throws ArrayException
- * if the length is negative or the position is not in the range of 1
- * to array:size
+ * @throws NegativeLengthArrayMetapathException
+ * if the length argument is negative
+ * @throws IndexOutOfBoundsArrayMetapathException
+ * if the position of the start argument is not a value in the range
+ * of 1 to array:size
*/
@NonNull
public static IArrayItem subarray(
@@ -204,16 +207,17 @@ public static IArrayItem subarray(
int start,
int length) {
if (length < 0) {
- throw new ArrayException(
- ArrayException.NEGATIVE_ARRAY_LENGTH, String.format("The length '%d' is negative.", length));
+ throw new NegativeLengthArrayMetapathException(
+ array,
+ String.format("The length '%d' is negative.", length));
}
List copy;
try {
copy = array.subList(start - 1, start - 1 + length);
} catch (IndexOutOfBoundsException ex) {
- throw new ArrayException(
- ArrayException.INDEX_OUT_OF_BOUNDS,
+ throw new IndexOutOfBoundsArrayMetapathException(
+ array,
String.format("The start + length (%d + %d) exceeds the array length '%d'.",
start,
length,
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnFunctionLookup.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnFunctionLookup.java
index c77bf369b..9c315f206 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnFunctionLookup.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnFunctionLookup.java
@@ -7,7 +7,6 @@
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
import gov.nist.secauto.metaschema.core.metapath.MetapathConstants;
-import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils;
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
@@ -65,11 +64,12 @@ private static ISequence execute(@NonNull IFunction function,
IFunction matchingFunction = null;
try {
- matchingFunction = StaticContext.lookupFunction(
+ matchingFunction = dynamicContext.lookupFunction(
name.toEnhancedQName(),
arity.toIntValueExact());
} catch (StaticMetapathException ex) {
- if (ex.getCode() != StaticMetapathException.NO_FUNCTION_MATCH) {
+ if (ex.getErrorCode().getCode() != StaticMetapathException.NO_FUNCTION_MATCH) {
+ // this is something other than a non-match
throw ex;
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpRecurseDepth.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpRecurseDepth.java
index b06e4b301..24a6cccb7 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpRecurseDepth.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpRecurseDepth.java
@@ -8,8 +8,6 @@
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.metapath.MetapathConstants;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
-import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils;
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
@@ -111,13 +109,8 @@ private static ISequence recurseDepth(
@NonNull ISequence initialContext,
@NonNull IStringItem recursionPath,
@NonNull DynamicContext dynamicContext) {
- IMetapathExpression recursionMetapath;
- try {
- recursionMetapath = IMetapathExpression.compile(recursionPath.asString(), dynamicContext.getStaticContext());
- } catch (MetapathException ex) {
- throw new StaticMetapathException(StaticMetapathException.INVALID_PATH_GRAMMAR, ex.getMessage(), ex);
- }
-
+ IMetapathExpression recursionMetapath
+ = IMetapathExpression.compile(recursionPath.asString(), dynamicContext.getStaticContext());
return recurseDepth(initialContext, recursionMetapath, dynamicContext);
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/regex/RegularExpressionMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/regex/RegularExpressionMetapathException.java
index db981e975..4d6dd2239 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/regex/RegularExpressionMetapathException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/regex/RegularExpressionMetapathException.java
@@ -5,10 +5,16 @@
package gov.nist.secauto.metaschema.core.metapath.function.regex;
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
+import gov.nist.secauto.metaschema.core.metapath.MetapathException;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
public class RegularExpressionMetapathException
- extends AbstractCodedMetapathException {
+ extends MetapathException {
+ @NonNull
+ private static final String PREFIX = "MPRX";
/**
* the serial version UID.
*/
@@ -64,8 +70,11 @@ public class RegularExpressionMetapathException
* @param cause
* the original exception cause
*/
- public RegularExpressionMetapathException(int code, String message, Throwable cause) {
- super(code, message, cause);
+ public RegularExpressionMetapathException(
+ int code,
+ @Nullable String message,
+ @Nullable Throwable cause) {
+ super(IErrorCode.of(PREFIX, code), message, cause);
}
/**
@@ -77,8 +86,10 @@ public RegularExpressionMetapathException(int code, String message, Throwable ca
* @param message
* the exception message
*/
- public RegularExpressionMetapathException(int code, String message) {
- super(code, message);
+ public RegularExpressionMetapathException(
+ int code,
+ @Nullable String message) {
+ super(IErrorCode.of(PREFIX, code), message);
}
/**
@@ -90,12 +101,9 @@ public RegularExpressionMetapathException(int code, String message) {
* @param cause
* the original exception cause
*/
- public RegularExpressionMetapathException(int code, Throwable cause) {
- super(code, cause);
- }
-
- @Override
- public String getCodePrefix() {
- return "MPRX";
+ public RegularExpressionMetapathException(
+ int code,
+ @Nullable Throwable cause) {
+ super(IErrorCode.of(PREFIX, code), cause);
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractMetapathExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractMetapathExpression.java
new file mode 100644
index 000000000..94b1e46bc
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractMetapathExpression.java
@@ -0,0 +1,67 @@
+/*
+ * 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.IExpression;
+import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
+import gov.nist.secauto.metaschema.core.metapath.StaticContext;
+import gov.nist.secauto.metaschema.core.metapath.cst.IExpressionVisitor;
+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.CollectionUtil;
+
+import java.util.List;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+public abstract class AbstractMetapathExpression implements IMetapathExpression {
+
+ @NonNull
+ private final String path;
+ @NonNull
+ private final StaticContext staticContext;
+
+ public AbstractMetapathExpression(
+ @NonNull String path,
+ @NonNull StaticContext context) {
+ this.path = path;
+ this.staticContext = context;
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ @Override
+ public StaticContext getStaticContext() {
+ return staticContext;
+ }
+
+ @NonNull
+ protected abstract IExpression getExpression();
+
+ @Override
+ public Class extends IItem> getBaseResultType() {
+ return getExpression().getStaticResultType();
+ }
+
+ @Override
+ public List extends IExpression> getChildren() {
+ return CollectionUtil.singletonList(getExpression());
+ }
+
+ @Override
+ public ISequence extends IItem> accept(DynamicContext dynamicContext, ISequence> focus) {
+ return getExpression().accept(dynamicContext, focus);
+ }
+
+ @Override
+ public RESULT accept(IExpressionVisitor visitor, CONTEXT context) {
+ return getExpression().accept(visitor, context);
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/ErrorCodeImpl.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/ErrorCodeImpl.java
new file mode 100644
index 000000000..460cea94e
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/ErrorCodeImpl.java
@@ -0,0 +1,66 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.metapath.impl;
+
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+public class ErrorCodeImpl implements IErrorCode {
+ /**
+ * The error prefix which identifies what kind of error it is.
+ */
+ @NonNull
+ private final String prefix;
+
+ /**
+ * The error code.
+ */
+ private final int code;
+
+ /**
+ * Construct a new error code.
+ *
+ * @param prefix
+ * the error code prefix, which indicates what type of error it is
+ * @param code
+ * the error code value, which indicates the specific error
+ */
+ public ErrorCodeImpl(@NonNull String prefix, int code) {
+ this.prefix = prefix;
+ this.code = code;
+ }
+
+ /**
+ * Get the error code prefix, which indicates what type of error it is.
+ *
+ * @return the error code prefix
+ */
+ @Override
+ public String getPrefix() {
+ return prefix;
+ }
+
+ /**
+ * Get the error code value.
+ *
+ * @return the error code value
+ */
+ @Override
+ public int getCode() {
+ return code;
+ }
+
+ /**
+ * Get a combination of the error code family and value.
+ *
+ * @return the full error code.
+ */
+ @Override
+ public final String toString() {
+ return getCodeAsString();
+ }
+}
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
index c7a8cb99c..b785a1a89 100644
--- 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
@@ -6,13 +6,18 @@
package gov.nist.secauto.metaschema.core.metapath.impl;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
+import gov.nist.secauto.metaschema.core.metapath.IExpression;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
+import gov.nist.secauto.metaschema.core.metapath.InvalidMetapathGrammarException;
import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.StaticContext;
+import gov.nist.secauto.metaschema.core.metapath.cst.IExpressionVisitor;
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 java.util.List;
+
import edu.umd.cs.findbugs.annotations.NonNull;
import nl.talsmasoftware.lazy4j.Lazy;
@@ -43,7 +48,15 @@ public LazyCompilationMetapathExpression(
@NonNull StaticContext staticContext) {
this.path = path;
this.staticContext = staticContext;
- this.compiledMetapath = ObjectUtils.notNull(Lazy.lazy(() -> IMetapathExpression.compile(path, staticContext)));
+ this.compiledMetapath = ObjectUtils.notNull(Lazy.lazy(() -> {
+ IMetapathExpression result;
+ try {
+ result = IMetapathExpression.compile(path, staticContext);
+ } catch (InvalidMetapathGrammarException ex) {
+ throw new InvalidMetapathGrammarException(ex);
+ }
+ return result;
+ }));
}
@Override
@@ -61,6 +74,26 @@ private IMetapathExpression getCompiledMetapath() {
return ObjectUtils.notNull(compiledMetapath.get());
}
+ @Override
+ public List extends IExpression> getChildren() {
+ return getCompiledMetapath().getChildren();
+ }
+
+ @Override
+ public Class extends IItem> getBaseResultType() {
+ return getCompiledMetapath().getBaseResultType();
+ }
+
+ @Override
+ public ISequence extends IItem> accept(DynamicContext dynamicContext, ISequence> focus) {
+ return getCompiledMetapath().accept(dynamicContext, focus);
+ }
+
+ @Override
+ public RESULT accept(IExpressionVisitor visitor, CONTEXT context) {
+ return getCompiledMetapath().accept(visitor, context);
+ }
+
@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/MetapathExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/MetapathExpression.java
similarity index 82%
rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathExpression.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/MetapathExpression.java
index dde1e1ecc..24359251d 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathExpression.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/MetapathExpression.java
@@ -3,8 +3,13 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.metapath;
+package gov.nist.secauto.metaschema.core.metapath.impl;
+import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
+import gov.nist.secauto.metaschema.core.metapath.IExpression;
+import gov.nist.secauto.metaschema.core.metapath.InvalidMetapathGrammarException;
+import gov.nist.secauto.metaschema.core.metapath.StaticContext;
+import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException;
import gov.nist.secauto.metaschema.core.metapath.antlr.FailingErrorListener;
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10;
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10Lexer;
@@ -39,22 +44,18 @@
@SuppressWarnings({
"PMD.CouplingBetweenObjects" // necessary since this class aggregates functionality
})
-class MetapathExpression implements IMetapathExpression {
+public class MetapathExpression
+ extends AbstractMetapathExpression {
/**
* The Metapath expression identifying the current context node.
*/
@NonNull
- public static final MetapathExpression CONTEXT_NODE
+ public static final MetapathExpression CONTEXT_METAPATH
= new MetapathExpression(".", ContextItem.instance(), StaticContext.instance());
private static final Logger LOGGER = LogManager.getLogger(MetapathExpression.class);
-
- @NonNull
- private final String path;
@NonNull
private final IExpression expression;
- @NonNull
- private final StaticContext staticContext;
/**
* Compiles a Metapath expression string using the provided static context.
@@ -64,7 +65,7 @@ class MetapathExpression implements IMetapathExpression {
* @param context
* the static evaluation context
* @return the compiled expression object
- * @throws MetapathException
+ * @throws InvalidMetapathGrammarException
* if an error occurred while compiling the Metapath expression
*/
@NonNull
@@ -72,7 +73,7 @@ public static MetapathExpression compile(@NonNull String path, @NonNull StaticCo
@NonNull
MetapathExpression retval;
if (".".equals(path)) {
- retval = CONTEXT_NODE;
+ retval = CONTEXT_METAPATH;
} else {
try {
Metapath10 parser = newParser(path);
@@ -83,14 +84,15 @@ public static MetapathExpression compile(@NonNull String path, @NonNull StaticCo
retval = new MetapathExpression(path, expr, context);
} catch (StaticMetapathException ex) {
String message = ex.getMessageText();
- throw new StaticMetapathException(
- ex.getCode(),
+ throw new InvalidMetapathGrammarException(
String.format("Unable to compile path '%s'.%s", path, message == null ? "" : " " + message),
ex);
- } catch (MetapathException | ParseCancellationException ex) {
+ } catch (ParseCancellationException ex) {
String msg = String.format("Unable to compile Metapath '%s'", path);
- LOGGER.atError().withThrowable(ex).log(msg);
- throw new StaticMetapathException(StaticMetapathException.INVALID_PATH_GRAMMAR, msg, ex);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.atDebug().withThrowable(ex).log(msg);
+ }
+ throw new InvalidMetapathGrammarException(msg, ex);
}
}
return retval;
@@ -151,14 +153,13 @@ protected MetapathExpression(
@NonNull String path,
@NonNull IExpression expr,
@NonNull StaticContext staticContext) {
- this.path = path;
+ super(path, staticContext);
this.expression = expr;
- this.staticContext = staticContext;
}
@Override
- public String getPath() {
- return path;
+ protected IExpression getExpression() {
+ return expression;
}
/**
@@ -171,11 +172,6 @@ protected IExpression getCSTNode() {
return expression;
}
- @Override
- public StaticContext getStaticContext() {
- return staticContext;
- }
-
@Override
public String toString() {
return getPath();
@@ -186,21 +182,11 @@ public String toString() {
public ISequence evaluate(
@Nullable IItem focus,
@NonNull DynamicContext dynamicContext) {
+ dynamicContext.pushExecutionStack(this);
try {
return ObjectUtils.asType(getCSTNode().accept(dynamicContext, ISequence.of(focus)).reusable());
- } catch (MetapathException ex) {
- throw new MetapathException(
- String.format("An error occurred while evaluating the expression '%s'. %s",
- getPath(),
- ex.getLocalizedMessage()),
- ex);
+ } finally {
+ dynamicContext.popExecutionStack(this);
}
}
-
- @FunctionalInterface
- interface ConversionFunction {
- @Nullable
- Object convert(@NonNull ISequence> sequence);
- }
-
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/ItemUtils.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/ItemUtils.java
index 02176212f..399db185f 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/ItemUtils.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/ItemUtils.java
@@ -5,12 +5,15 @@
package gov.nist.secauto.metaschema.core.metapath.item;
+import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
+import gov.nist.secauto.metaschema.core.metapath.InvalidTreatTypeDynamicMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.cst.path.Axis;
+import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentBasedNodeItem;
+import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
+import gov.nist.secauto.metaschema.core.metapath.type.InvalidTypeMetapathException;
import gov.nist.secauto.metaschema.core.metapath.type.TypeMetapathException;
-
-import java.util.Arrays;
-import java.util.Objects;
-import java.util.stream.Stream;
+import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
@@ -25,8 +28,10 @@ private ItemUtils() {
}
/**
- * Checks that the item is a node item.
+ * Checks that the item is an {@link INodeItem}.
*
+ * @param dynamicContext
+ * the dynamic evaluation context
* @param item
* the item to check
* @return the item cast to a {@link INodeItem}
@@ -35,18 +40,75 @@ private ItemUtils() {
*/
// FIXME: make this a method on the type implementation
@NonNull
- public static INodeItem checkItemIsNodeItemForStep(@Nullable IItem item) {
- if (item instanceof INodeItem) {
- return (INodeItem) item;
+ public static INodeItem checkItemIsNodeItem(
+ @NonNull DynamicContext dynamicContext,
+ @Nullable IItem item) {
+ return checkItemIsType(dynamicContext, item, INodeItem.class);
+ }
+
+ /**
+ * Checks that the item is an {@link IDocumentNodeItem}.
+ *
+ * @param dynamicContext
+ * the dynamic evaluation context
+ * @param item
+ * the item to check
+ * @return the item cast to a {@link INodeItem}
+ * @throws TypeMetapathException
+ * if the item is {@code null} or not an {@link INodeItem}
+ */
+ @NonNull
+ public static IDocumentBasedNodeItem checkItemIsDocumentNodeItem(
+ @NonNull DynamicContext dynamicContext,
+ @Nullable IItem item) {
+ return checkItemIsType(dynamicContext, item, IDocumentBasedNodeItem.class);
+ }
+
+ @NonNull
+ private static T checkItemIsType(
+ @NonNull DynamicContext dynamicContext,
+ @Nullable IItem item,
+ @NonNull Class itemClass) {
+ if (itemClass.isInstance(item)) {
+ return ObjectUtils.notNull(itemClass.cast(item));
}
if (item == null) {
- throw new TypeMetapathException(TypeMetapathException.NOT_A_NODE_ITEM_FOR_STEP,
- "Item is null.");
+ throw new TypeMetapathException(TypeMetapathException.NOT_A_NODE_ITEM_FOR_STEP, "Item is null.")
+ .registerEvaluationContext(dynamicContext);
}
- throw new TypeMetapathException(TypeMetapathException.NOT_A_NODE_ITEM_FOR_STEP,
- String.format(
- "The item of type '%s' is not a INodeItem.",
- item.getClass().getName()));
+ throw new TypeMetapathException(
+ TypeMetapathException.NOT_A_NODE_ITEM_FOR_STEP,
+ String.format("The item of type '%s' is not of the type '%s'.",
+ item.getClass().getName(),
+ itemClass.getName()))
+ .registerEvaluationContext(dynamicContext);
+ }
+
+ /**
+ * Get the ancestor document nodes for the provided items.
+ *
+ * The resulting sequence has items of the {@link IDocumentBasedNodeItem} to
+ * allow for both module and document querying.
+ *
+ * @param items
+ * the node items to get the document roots for
+ * @return the document root node items
+ */
+ @NonNull
+ public static ISequence getDocumentNodeItems(
+ @NonNull DynamicContext dynamicContext,
+ @NonNull ISequence> items) {
+ return ISequence.of(ObjectUtils.notNull(items.stream()
+ // ensures a non-null INodeItem instance
+ .map(item -> ItemUtils.checkItemIsNodeItem(dynamicContext, item))
+ .map(item -> Axis.ANCESTOR_OR_SELF.execute(ObjectUtils.notNull(item))
+ .findFirst().stream()
+ .filter(IDocumentBasedNodeItem.class::isInstance)
+ .map(firstItem -> ItemUtils.checkItemIsDocumentNodeItem(dynamicContext, firstItem))
+ .findFirst().orElseThrow(() -> new InvalidTreatTypeDynamicMetapathException(
+ dynamicContext.getExecutionStack(),
+ String.format("The node '%s' is not the descendant of a document node.",
+ item.getMetapath()))))));
}
/**
@@ -70,36 +132,11 @@ public static TYPE checkItemType(@NonNull IItem item, @NonNull Class Stream> interfacesFor(
- @NonNull Class extends T> seed,
- @NonNull Class base) {
- return ancestorsOrSelf(seed)
- .flatMap(clazz -> Stream.ofNullable(asSubclassOrNull(clazz, base)))
- .flatMap(clazz -> Stream.concat(
- Stream.of(clazz),
- Arrays.stream(seed.getInterfaces())
- .flatMap(cls -> Stream.ofNullable(asSubclassOrNull(cls, base)))));
- }
-
- private static Stream> ancestorsOrSelf(@NonNull Class seed) {
- return Stream.iterate(seed, Objects::nonNull, Class::getSuperclass);
- }
-
- @Nullable
- private static Class extends T> asSubclassOrNull(Class> clazz, Class base) {
- Class extends T> retval = null;
- try {
- retval = clazz.asSubclass(base);
- } catch (@SuppressWarnings("unused") ClassCastException ex) {
- // not a subclass, do nothing
- }
- return retval;
- }
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/AbstractUntypedAtomicItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/AbstractUntypedAtomicItem.java
index 90bf7cbc2..6d0b1a78b 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/AbstractUntypedAtomicItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/AbstractUntypedAtomicItem.java
@@ -5,8 +5,8 @@
package gov.nist.secauto.metaschema.core.metapath.item.atomic;
-import gov.nist.secauto.metaschema.core.metapath.impl.AbstractStringMapKey;
import gov.nist.secauto.metaschema.core.metapath.item.function.IMapKey;
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.AbstractStringMapKey;
import edu.umd.cs.findbugs.annotations.NonNull;
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 79c531bbe..07ad67aa1 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
@@ -67,9 +67,7 @@ static IIntegerItem valueOf(@NonNull String value) {
try {
return valueOf(MetaschemaDataTypeProvider.INTEGER.parse(value));
} catch (IllegalArgumentException ex) {
- throw new InvalidTypeMetapathException(null,
- ex.getMessage(),
- ex);
+ throw new InvalidTypeMetapathException(null, ex.getMessage(), ex);
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/INumericItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/INumericItem.java
index c85b620f1..8569b41ef 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/INumericItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/INumericItem.java
@@ -291,7 +291,5 @@ default INumericItem mod(@NonNull INumericItem divisor) {
* @return a new value with the sign reversed
*/
@NonNull
- default INumericItem negate() {
- return OperationFunctions.opNumericUnaryMinus(this);
- }
+ INumericItem negate();
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractMarkupItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractMarkupItem.java
index 6349ced1f..cb021f1b5 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractMarkupItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractMarkupItem.java
@@ -6,10 +6,10 @@
package gov.nist.secauto.metaschema.core.metapath.item.atomic.impl;
import gov.nist.secauto.metaschema.core.datatype.markup.IMarkupString;
-import gov.nist.secauto.metaschema.core.metapath.impl.AbstractStringMapKey;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.AbstractAnyAtomicItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IMarkupItem;
import gov.nist.secauto.metaschema.core.metapath.item.function.IMapKey;
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.AbstractStringMapKey;
import edu.umd.cs.findbugs.annotations.NonNull;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractStringItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractStringItem.java
index 2b8fe929f..25e6baa31 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractStringItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractStringItem.java
@@ -5,10 +5,10 @@
package gov.nist.secauto.metaschema.core.metapath.item.atomic.impl;
-import gov.nist.secauto.metaschema.core.metapath.impl.AbstractStringMapKey;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.AbstractAnyAtomicItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.item.function.IMapKey;
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.AbstractStringMapKey;
import java.util.regex.Pattern;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractUriItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractUriItem.java
index 7ee2947e7..391a92038 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractUriItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/AbstractUriItem.java
@@ -5,10 +5,10 @@
package gov.nist.secauto.metaschema.core.metapath.item.atomic.impl;
-import gov.nist.secauto.metaschema.core.metapath.impl.AbstractStringMapKey;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.AbstractAnyAtomicItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyUriItem;
import gov.nist.secauto.metaschema.core.metapath.item.function.IMapKey;
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.AbstractStringMapKey;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.net.URI;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/UuidItemImpl.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/UuidItemImpl.java
index 166eb6fb3..eac4dea9f 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/UuidItemImpl.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/impl/UuidItemImpl.java
@@ -7,11 +7,11 @@
import gov.nist.secauto.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
import gov.nist.secauto.metaschema.core.datatype.adapter.UuidAdapter;
-import gov.nist.secauto.metaschema.core.metapath.impl.AbstractStringMapKey;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.AbstractAnyAtomicItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IUuidItem;
import gov.nist.secauto.metaschema.core.metapath.item.function.IMapKey;
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.AbstractStringMapKey;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import java.util.UUID;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/ArrayException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/ArrayException.java
deleted file mode 100644
index 6ba0d8dc6..000000000
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/ArrayException.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * SPDX-FileCopyrightText: none
- * SPDX-License-Identifier: CC0-1.0
- */
-
-package gov.nist.secauto.metaschema.core.metapath.item.function;
-
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
-
-/**
- * Represents an error that occurred while performing mathematical operations.
- */
-public class ArrayException
- extends AbstractCodedMetapathException {
- /**
- * err:FOAY0001:
- * This error is raised when the $length argument to array:subarray is negative.
- */
- public static final int INDEX_OUT_OF_BOUNDS = 1;
- /**
- * err:FOAY0002:
- * This error is raised whenever numeric operations result in an overflow or
- * underflow.
- */
- public static final int NEGATIVE_ARRAY_LENGTH = 2;
-
- /**
- * the serial version UID.
- */
- private static final long serialVersionUID = 2L;
-
- /**
- * Constructs a new exception with the provided {@code code}, {@code message},
- * and no cause.
- *
- * @param code
- * the error code value
- * @param message
- * the exception message
- */
- public ArrayException(int code, String message) {
- super(code, message);
- }
-
- /**
- * Constructs a new exception with the provided {@code code}, {@code message},
- * and {@code cause}.
- *
- * @param code
- * the error code value
- * @param message
- * the exception message
- * @param cause
- * the original exception cause
- */
- public ArrayException(int code, String message, Throwable cause) {
- super(code, message, cause);
- }
-
- /**
- * Constructs a new exception with the provided {@code code}, no message, and
- * the {@code cause}.
- *
- * @param code
- * the error code value
- * @param cause
- * the original exception cause
- */
- public ArrayException(int code, Throwable cause) {
- super(code, cause);
- }
-
- @Override
- public String getCodePrefix() {
- return "FOAY";
- }
-
-}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java
index 796e64e34..2b75a9ecf 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java
@@ -6,13 +6,13 @@
package gov.nist.secauto.metaschema.core.metapath.item.function;
import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
-import gov.nist.secauto.metaschema.core.metapath.impl.AbstractArrayItem;
-import gov.nist.secauto.metaschema.core.metapath.impl.ArrayItemN;
import gov.nist.secauto.metaschema.core.metapath.item.ICollectionValue;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.IItemVisitor;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.AbstractArrayItem;
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.ArrayItemN;
import gov.nist.secauto.metaschema.core.metapath.type.IItemType;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IMapItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IMapItem.java
index 554b00729..82f0f7c7f 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IMapItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IMapItem.java
@@ -6,12 +6,12 @@
package gov.nist.secauto.metaschema.core.metapath.item.function;
import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
-import gov.nist.secauto.metaschema.core.metapath.impl.AbstractMapItem;
-import gov.nist.secauto.metaschema.core.metapath.impl.MapItemN;
import gov.nist.secauto.metaschema.core.metapath.item.ICollectionValue;
import gov.nist.secauto.metaschema.core.metapath.item.IItemVisitor;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.AbstractMapItem;
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.MapItemN;
import gov.nist.secauto.metaschema.core.metapath.type.IItemType;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IndexOutOfBoundsArrayMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IndexOutOfBoundsArrayMetapathException.java
new file mode 100644
index 000000000..45a4ab664
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IndexOutOfBoundsArrayMetapathException.java
@@ -0,0 +1,64 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.metapath.item.function;
+
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.ArrayMetapathException;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * err:FOAY0001:
+ * This error is raised when an integer used to select a member of an array is
+ * outside the range of values for that array.
+ */
+public class IndexOutOfBoundsArrayMetapathException
+ extends ArrayMetapathException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a new exception with the provided {@code item}, {@code message},
+ * and no cause.
+ *
+ * @param item
+ * the array item involved
+ * @param message
+ * the exception message
+ */
+ public IndexOutOfBoundsArrayMetapathException(@NonNull IArrayItem> item, String message) {
+ super(INDEX_OUT_OF_BOUNDS, item, message);
+ }
+
+ /**
+ * Constructs a new exception with the provided {@code item}, {@code message},
+ * and {@code cause}.
+ *
+ * @param item
+ * the array item involved
+ * @param message
+ * the exception message
+ * @param cause
+ * the original exception cause
+ */
+ public IndexOutOfBoundsArrayMetapathException(@NonNull IArrayItem> item, String message,
+ Throwable cause) {
+ super(INDEX_OUT_OF_BOUNDS, item, message, cause);
+ }
+
+ /**
+ * Constructs a new exception with the provided {@code item}, no message, and
+ * the {@code cause}.
+ *
+ * @param item
+ * the array item involved
+ * @param cause
+ * the original exception cause
+ */
+ public IndexOutOfBoundsArrayMetapathException(@NonNull IArrayItem> item, Throwable cause) {
+ super(INDEX_OUT_OF_BOUNDS, item, cause);
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/NegativeLengthArrayMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/NegativeLengthArrayMetapathException.java
new file mode 100644
index 000000000..3639a47c8
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/NegativeLengthArrayMetapathException.java
@@ -0,0 +1,64 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.metapath.item.function;
+
+import gov.nist.secauto.metaschema.core.metapath.item.function.impl.ArrayMetapathException;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * err:FOAY0001:
+ * This error is raised when an integer used to select a member of an array is
+ * outside the range of values for that array.
+ */
+public class NegativeLengthArrayMetapathException
+ extends ArrayMetapathException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a new exception with the provided {@code code}, {@code message},
+ * and no cause.
+ *
+ * @param item
+ * the array item involved
+ * @param message
+ * the exception message
+ */
+ public NegativeLengthArrayMetapathException(@NonNull IArrayItem> item, String message) {
+ super(NEGATIVE_ARRAY_LENGTH, item, message);
+ }
+
+ /**
+ * Constructs a new exception with the provided {@code code}, {@code message},
+ * and {@code cause}.
+ *
+ * @param item
+ * the array item involved
+ * @param message
+ * the exception message
+ * @param cause
+ * the original exception cause
+ */
+ public NegativeLengthArrayMetapathException(@NonNull IArrayItem> item, String message,
+ Throwable cause) {
+ super(NEGATIVE_ARRAY_LENGTH, item, message, cause);
+ }
+
+ /**
+ * Constructs a new exception with the provided {@code code}, no message, and
+ * the {@code cause}.
+ *
+ * @param item
+ * the array item involved
+ * @param cause
+ * the original exception cause
+ */
+ public NegativeLengthArrayMetapathException(@NonNull IArrayItem> item, Throwable cause) {
+ super(NEGATIVE_ARRAY_LENGTH, item, cause);
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractArrayItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractArrayItem.java
similarity index 96%
rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractArrayItem.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractArrayItem.java
index 4f4829d15..d78ca4497 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractArrayItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractArrayItem.java
@@ -3,11 +3,12 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.metapath.impl;
+package gov.nist.secauto.metaschema.core.metapath.item.function.impl;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils;
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
+import gov.nist.secauto.metaschema.core.metapath.impl.IFeatureCollectionFunctionItem;
import gov.nist.secauto.metaschema.core.metapath.item.ICollectionValue;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractKeySpecifier.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractKeySpecifier.java
similarity index 96%
rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractKeySpecifier.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractKeySpecifier.java
index 5d4f99d43..19c073a36 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractKeySpecifier.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractKeySpecifier.java
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.metapath.impl;
+package gov.nist.secauto.metaschema.core.metapath.item.function.impl;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
import gov.nist.secauto.metaschema.core.metapath.IExpression;
@@ -14,10 +14,10 @@
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
-import gov.nist.secauto.metaschema.core.metapath.item.function.ArrayException;
import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem;
import gov.nist.secauto.metaschema.core.metapath.item.function.IKeySpecifier;
import gov.nist.secauto.metaschema.core.metapath.item.function.IMapItem;
+import gov.nist.secauto.metaschema.core.metapath.item.function.IndexOutOfBoundsArrayMetapathException;
import gov.nist.secauto.metaschema.core.metapath.type.InvalidTypeMetapathException;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
@@ -174,8 +174,8 @@ protected Stream extends ICollectionValue> lookupInArray(
try {
return ObjectUtils.notNull(Stream.ofNullable(ArrayGet.get(targetItem, index)));
} catch (IndexOutOfBoundsException ex) {
- throw new ArrayException(
- ArrayException.INDEX_OUT_OF_BOUNDS,
+ throw new IndexOutOfBoundsArrayMetapathException(
+ targetItem,
String.format("The index '%d' is outside the range of values for the array size '%d'.",
index + 1,
targetItem.size()),
@@ -243,8 +243,8 @@ protected Stream lookupInArray(
try {
return Stream.ofNullable(ArrayGet.get(targetItem, index));
} catch (IndexOutOfBoundsException ex) {
- throw new ArrayException(
- ArrayException.INDEX_OUT_OF_BOUNDS,
+ throw new IndexOutOfBoundsArrayMetapathException(
+ targetItem,
String.format("The index %d is outside the range of values for the array size '%d'.",
index + 1,
targetItem.size()),
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractMapItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractMapItem.java
similarity index 96%
rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractMapItem.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractMapItem.java
index 59088e52c..58b886bfb 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractMapItem.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractMapItem.java
@@ -3,12 +3,13 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.metapath.impl;
+package gov.nist.secauto.metaschema.core.metapath.item.function.impl;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils;
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
import gov.nist.secauto.metaschema.core.metapath.function.library.MapGet;
+import gov.nist.secauto.metaschema.core.metapath.impl.IFeatureCollectionFunctionItem;
import gov.nist.secauto.metaschema.core.metapath.item.ICollectionValue;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractStringMapKey.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractStringMapKey.java
similarity index 78%
rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractStringMapKey.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractStringMapKey.java
index ae1f8481d..ee89d8aef 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractStringMapKey.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/AbstractStringMapKey.java
@@ -3,8 +3,9 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.metapath.impl;
+package gov.nist.secauto.metaschema.core.metapath.item.function.impl;
+import gov.nist.secauto.metaschema.core.metapath.impl.AbstractMapKey;
import gov.nist.secauto.metaschema.core.metapath.item.function.IMapKey;
import gov.nist.secauto.metaschema.core.metapath.item.function.IStringMapKey;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/ArrayItemN.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/ArrayItemN.java
similarity index 94%
rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/ArrayItemN.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/ArrayItemN.java
index 4f9f05dcb..20d266813 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/ArrayItemN.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/ArrayItemN.java
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.metapath.impl;
+package gov.nist.secauto.metaschema.core.metapath.item.function.impl;
import gov.nist.secauto.metaschema.core.metapath.item.ICollectionValue;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/ArrayMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/ArrayMetapathException.java
new file mode 100644
index 000000000..02e9e5b57
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/ArrayMetapathException.java
@@ -0,0 +1,101 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.metapath.item.function.impl;
+
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
+import gov.nist.secauto.metaschema.core.metapath.function.FunctionMetapathError;
+import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * Represents an error that occurred while performing mathematical operations.
+ */
+public class ArrayMetapathException
+ extends FunctionMetapathError {
+ @NonNull
+ private static final String PREFIX = "FOAY";
+ /**
+ * err:FOAY0001:
+ * This error is raised when an integer used to select a member of an array is
+ * outside the range of values for that array.
+ */
+ protected static final int INDEX_OUT_OF_BOUNDS = 1;
+ /**
+ * err:FOAY0001:
+ * This error is raised when the $length argument to array:subarray is negative.
+ */
+ public static final int NEGATIVE_ARRAY_LENGTH = 2;
+
+ /**
+ * the serial version UID.
+ */
+ private static final long serialVersionUID = 2L;
+
+ @NonNull
+ private final IArrayItem> item;
+
+ /**
+ * Constructs a new exception with the provided {@code code}, {@code message},
+ * and no cause.
+ *
+ * @param code
+ * the error code value
+ * @param item
+ * the array item involved
+ * @param message
+ * the exception message
+ */
+ public ArrayMetapathException(int code, @NonNull IArrayItem> item, String message) {
+ super(IErrorCode.of(PREFIX, code), message);
+ this.item = item;
+ }
+
+ /**
+ * Constructs a new exception with the provided {@code code}, {@code message},
+ * and {@code cause}.
+ *
+ * @param code
+ * the error code value
+ * @param item
+ * the array item involved
+ * @param message
+ * the exception message
+ * @param cause
+ * the original exception cause
+ */
+ public ArrayMetapathException(int code, @NonNull IArrayItem> item, String message, Throwable cause) {
+ super(IErrorCode.of(PREFIX, code), message, cause);
+ this.item = item;
+ }
+
+ /**
+ * Constructs a new exception with the provided {@code code}, no message, and
+ * the {@code cause}.
+ *
+ * @param code
+ * the error code value
+ * @param item
+ * the array item involved
+ * @param cause
+ * the original exception cause
+ */
+ public ArrayMetapathException(int code, @NonNull IArrayItem> item, Throwable cause) {
+ super(IErrorCode.of(PREFIX, code), cause);
+ this.item = item;
+ }
+
+ /**
+ * Get the array item involved in the exception.
+ *
+ * @return the array item
+ */
+ public IArrayItem> getArrayItem() {
+ return item;
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/ImmutableCollections.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/ImmutableCollections.java
similarity index 98%
rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/ImmutableCollections.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/ImmutableCollections.java
index 2860bb25f..c9d5b5623 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/ImmutableCollections.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/ImmutableCollections.java
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.metapath.impl;
+package gov.nist.secauto.metaschema.core.metapath.item.function.impl;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/MapItemN.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/MapItemN.java
similarity index 95%
rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/MapItemN.java
rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/MapItemN.java
index babf5f81a..0b61691c7 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/MapItemN.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/impl/MapItemN.java
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: CC0-1.0
*/
-package gov.nist.secauto.metaschema.core.metapath.impl;
+package gov.nist.secauto.metaschema.core.metapath.item.function.impl;
import gov.nist.secauto.metaschema.core.metapath.item.ICollectionValue;
import gov.nist.secauto.metaschema.core.metapath.item.function.IMapKey;
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractNodeItemVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractNodeItemVisitor.java
index fc55da58b..1ae212215 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractNodeItemVisitor.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractNodeItemVisitor.java
@@ -14,7 +14,8 @@
* @param
* the type of result produced by visitation
*/
-public abstract class AbstractNodeItemVisitor implements INodeItemVisitor {
+public abstract class AbstractNodeItemVisitor
+ implements INodeItemVisitor {
/**
* Visit the provided {@code item}.
*
@@ -59,6 +60,8 @@ protected RESULT visitFlags(@NonNull INodeItem item, CONTEXT context) {
* @param context
* provides contextual information for use by the visitor
* @return the result produced by visiting the item's child model items
+ * @throws EXCEPTION
+ * when an un-handled error was raised while visiting a child node
*/
protected RESULT visitModelChildren(@NonNull INodeItem item, CONTEXT context) {
RESULT result = defaultResult();
@@ -153,7 +156,6 @@ protected RESULT aggregateResult(RESULT first, RESULT second, CONTEXT context) {
public RESULT visitDocument(IDocumentNodeItem item, CONTEXT context) {
// this is the default behavior, which can be overridden
return visitModelChildren(item, context);
- // return visitAssembly(item.getRootAssemblyNodeItem(), context);
}
@Override
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/INodeItemVisitable.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/INodeItemVisitable.java
index 64dfd9823..856b925df 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/INodeItemVisitable.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/INodeItemVisitable.java
@@ -17,5 +17,7 @@ public interface INodeItemVisitable {
* a parameter used to pass contextual information between visitors
* @return the visitor result
*/
- RESULT accept(@NonNull INodeItemVisitor visitor, CONTEXT context);
+ RESULT accept(
+ @NonNull INodeItemVisitor visitor,
+ CONTEXT context);
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/InvalidTypeMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/InvalidTypeMetapathException.java
index 96a61f4e3..d7e54a11b 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/InvalidTypeMetapathException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/InvalidTypeMetapathException.java
@@ -34,8 +34,12 @@ public class InvalidTypeMetapathException
* @param cause
* the original exception cause
*/
- public InvalidTypeMetapathException(@NonNull IItem item, @NonNull Throwable cause) {
- super(INVALID_TYPE_ERROR, String.format("Invalid data type '%s'", item.getClass().getName()),
+ public InvalidTypeMetapathException(
+ @NonNull IItem item,
+ @NonNull Throwable cause) {
+ super(
+ INVALID_TYPE_ERROR,
+ String.format("Invalid data type '%s'", item.getClass().getName()),
cause);
this.item = item;
}
@@ -47,7 +51,8 @@ public InvalidTypeMetapathException(@NonNull IItem item, @NonNull Throwable caus
* @param item
* the item related to the invalid type error
*/
- public InvalidTypeMetapathException(@NonNull IItem item) {
+ public InvalidTypeMetapathException(
+ @NonNull IItem item) {
super(INVALID_TYPE_ERROR, String.format("Invalid data type '%s'", item.getClass().getName()));
this.item = item;
}
@@ -63,7 +68,10 @@ public InvalidTypeMetapathException(@NonNull IItem item) {
* @param cause
* the original exception cause
*/
- public InvalidTypeMetapathException(@Nullable IItem item, @Nullable String message, @NonNull Throwable cause) {
+ public InvalidTypeMetapathException(
+ @Nullable IItem item,
+ @Nullable String message,
+ @NonNull Throwable cause) {
super(INVALID_TYPE_ERROR, message, cause);
this.item = item;
}
@@ -77,7 +85,9 @@ public InvalidTypeMetapathException(@Nullable IItem item, @Nullable String messa
* @param message
* the exception message
*/
- public InvalidTypeMetapathException(@Nullable IItem item, @Nullable String message) {
+ public InvalidTypeMetapathException(
+ @Nullable IItem item,
+ @Nullable String message) {
super(INVALID_TYPE_ERROR, message);
this.item = item;
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/TypeMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/TypeMetapathException.java
index aed0b5b81..b491b7fdb 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/TypeMetapathException.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/TypeMetapathException.java
@@ -5,13 +5,24 @@
package gov.nist.secauto.metaschema.core.metapath.type;
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.IErrorCode;
+import gov.nist.secauto.metaschema.core.metapath.MetapathException;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
/**
* MPTY: Exceptions related to Metapath type errors.
*/
public class TypeMetapathException
- extends AbstractCodedMetapathException {
+ extends MetapathException {
+
+ /**
+ * the serial version UID.
+ */
+ private static final long serialVersionUID = 2L;
+ @NonNull
+ private static final String PREFIX = "MPTY";
/**
* err:MPTY0004: It
* is a type error
@@ -27,7 +38,8 @@ public class TypeMetapathException
* 2.5.5
* SequenceType Matching.
*/
- public static final int INVALID_TYPE_ERROR = 4;
+ // FIXME: differentiate static vs dynamic errors
+ protected static final int INVALID_TYPE_ERROR = 4;
/**
* err:MPTY0019: It
* is a type error
@@ -36,15 +48,11 @@ public class TypeMetapathException
*/
public static final int BASE_PATH_NOT_A_SEQUENCE = 19;
/**
- * The context item is not a node when evaluating an axis step.
+ * err:MPTY0020: The
+ * context item is not a node when evaluating an axis step.
*/
public static final int NOT_A_NODE_ITEM_FOR_STEP = 20;
- /**
- * the serial version UID.
- */
- private static final long serialVersionUID = 2L;
-
/**
* Constructs a new exception with the provided {@code code}, {@code message},
* and {@code cause}.
@@ -56,38 +64,27 @@ public class TypeMetapathException
* @param cause
* the original exception cause
*/
- public TypeMetapathException(int code, String message, Throwable cause) {
- super(code, message, cause);
+ protected TypeMetapathException(
+ int code,
+ @Nullable String message,
+ @Nullable Throwable cause) {
+ super(IErrorCode.of(PREFIX, code), message, cause);
}
/**
* Constructs a new exception with the provided {@code code}, {@code message},
* and no cause.
*
+ * @param evaluationStack
+ * the Metapath evaluation stack that lead to this exception
* @param code
* the error code value
* @param message
* the exception message
*/
- public TypeMetapathException(int code, String message) {
- super(code, message);
- }
-
- /**
- * Constructs a new exception with the provided {@code code}, no message, and
- * the {@code cause}.
- *
- * @param code
- * the error code value
- * @param cause
- * the original exception cause
- */
- public TypeMetapathException(int code, Throwable cause) {
- super(code, cause);
- }
-
- @Override
- public String getCodePrefix() {
- return "MPTY";
+ public TypeMetapathException(
+ int code,
+ @Nullable String message) {
+ super(IErrorCode.of(PREFIX, code), message);
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/impl/DynamicTypeSupport.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/impl/DynamicTypeSupport.java
index 7835c5402..6cfa1789b 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/impl/DynamicTypeSupport.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/impl/DynamicTypeSupport.java
@@ -104,7 +104,9 @@ private static boolean compareDefinition(
try {
IEnhancedQName expectedName = nameResolver.resolve(expected);
retval = definition.getDefinitionQName().equals(expectedName); // AT is ET
- } catch (@SuppressWarnings("unused") StaticMetapathException ex) {
+ } catch (StaticMetapathException ex) {
+ assert ex != null;
+
// fail the definition name test
retval = false;
}
@@ -134,5 +136,4 @@ private static boolean compareAtomicTypes(
private DynamicTypeSupport() {
// disable construction
}
-
}
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 f5a1f2a20..9b4b1b521 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
@@ -75,13 +75,16 @@ protected String toPath(@NonNull INodeItem item) {
* the Metapath dynamic execution context to use for Metapath
* evaluation
* @return the new message
+ * @throws ConstraintValidationException
+ * if the custom message contains a Metapath expression that is
+ * invalid or if the expression failed to evaluate
*/
@NonNull
protected String newCardinalityMinimumViolationMessage(
@NonNull ICardinalityConstraint constraint,
@NonNull INodeItem target,
@NonNull ISequence extends INodeItem> testedItems,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
return constraint.getMessage() == null
? ObjectUtils.notNull(String.format(
"The cardinality '%d' is below the required minimum '%d' for items matching '%s'.",
@@ -105,13 +108,16 @@ protected String newCardinalityMinimumViolationMessage(
* the Metapath dynamic execution context to use for Metapath
* evaluation
* @return the new message
+ * @throws ConstraintValidationException
+ * if the custom message contains a Metapath expression that is
+ * invalid or if the expression failed to evaluate
*/
@NonNull
protected String newCardinalityMaximumViolationMessage(
@NonNull ICardinalityConstraint constraint,
@NonNull INodeItem target,
@NonNull ISequence extends INodeItem> testedItems,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
return constraint.getMessage() == null
? ObjectUtils.notNull(String.format(
"The cardinality '%d' is greater than the required maximum '%d' at: %s.",
@@ -143,6 +149,9 @@ protected String newCardinalityMaximumViolationMessage(
* the Metapath dynamic execution context to use for Metapath
* evaluation
* @return the new message
+ * @throws ConstraintValidationException
+ * if the custom message contains a Metapath expression that is
+ * invalid or if the expression failed to evaluate
*/
@NonNull
protected String newIndexDuplicateKeyViolationMessage(
@@ -150,7 +159,7 @@ protected String newIndexDuplicateKeyViolationMessage(
@NonNull INodeItem node,
@NonNull INodeItem oldItem,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
// TODO: render the key paths
return constraint.getMessage() == null
? ObjectUtils.notNull(String.format("Index '%s' has duplicate key for items at paths '%s' and '%s'",
@@ -176,6 +185,9 @@ protected String newIndexDuplicateKeyViolationMessage(
* the Metapath dynamic execution context to use for Metapath
* evaluation
* @return the new message
+ * @throws ConstraintValidationException
+ * if the custom message contains a Metapath expression that is
+ * invalid or if the expression failed to evaluate
*/
@NonNull
protected String newUniqueKeyViolationMessage(
@@ -183,7 +195,7 @@ protected String newUniqueKeyViolationMessage(
@NonNull INodeItem node,
@NonNull INodeItem oldItem,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
return constraint.getMessage() == null
? ObjectUtils.notNull(String.format("Unique constraint violation at paths '%s' and '%s'",
toPath(oldItem),
@@ -209,6 +221,9 @@ protected String newUniqueKeyViolationMessage(
* the Metapath dynamic execution context to use for Metapath
* evaluation
* @return the new message
+ * @throws ConstraintValidationException
+ * if the custom message contains a Metapath expression that is
+ * invalid or if the expression failed to evaluate
*/
@NonNull
protected String newMatchPatternViolationMessage(
@@ -217,7 +232,7 @@ protected String newMatchPatternViolationMessage(
@NonNull INodeItem target,
@NonNull String value,
@NonNull Pattern pattern,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
return constraint.getMessage() == null
? ObjectUtils.notNull(String.format("Value '%s' did not match the pattern '%s' at path '%s'",
value,
@@ -244,6 +259,9 @@ protected String newMatchPatternViolationMessage(
* the Metapath dynamic execution context to use for Metapath
* evaluation
* @return the new message
+ * @throws ConstraintValidationException
+ * if the custom message contains a Metapath expression that is
+ * invalid or if the expression failed to evaluate
*/
@NonNull
protected String newMatchDatatypeViolationMessage(
@@ -252,7 +270,7 @@ protected String newMatchDatatypeViolationMessage(
@NonNull INodeItem target,
@NonNull String value,
@NonNull IDataTypeAdapter> adapter,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
return constraint.getMessage() == null
? ObjectUtils.notNull(String.format("Value '%s' did not conform to the data type '%s' at path '%s'",
value,
@@ -275,13 +293,16 @@ protected String newMatchDatatypeViolationMessage(
* the Metapath dynamic execution context to use for Metapath
* evaluation
* @return the new message
+ * @throws ConstraintValidationException
+ * if the custom message contains a Metapath expression that is
+ * invalid or if the expression failed to evaluate
*/
@NonNull
protected String newExpectViolationMessage(
@NonNull IExpectConstraint constraint,
@NonNull INodeItem node,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
return constraint.getMessage() == null
? ObjectUtils.notNull(String.format("Expect constraint '%s' did not match the data at path '%s'",
constraint.getTest().getPath(),
@@ -351,6 +372,9 @@ protected String newIndexDuplicateViolationMessage(
* the Metapath dynamic execution context to use for Metapath
* evaluation
* @return the new message
+ * @throws ConstraintValidationException
+ * if the custom message contains a Metapath expression that is
+ * invalid or if the expression failed to evaluate
*/
@NonNull
protected String newIndexMissMessage(
@@ -358,7 +382,7 @@ protected String newIndexMissMessage(
@NonNull INodeItem node,
@NonNull INodeItem target,
@NonNull List key,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
String keyValues = key.stream()
.collect(Collectors.joining(","));
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractKeyConstraintBuilder.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractKeyConstraintBuilder.java
index ff3d35e59..79fdc961b 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractKeyConstraintBuilder.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractKeyConstraintBuilder.java
@@ -12,6 +12,16 @@
import edu.umd.cs.findbugs.annotations.NonNull;
+/**
+ * Provides builder methods for the core data elements of an {@link IConstraint}
+ * that supports a custom message.
+ *
+ * @param
+ * the Java type of the implementing builder
+ * @param
+ * the Java type of the resulting built object
+ * @since 2.0.0
+ */
public abstract class AbstractKeyConstraintBuilder<
T extends AbstractKeyConstraintBuilder,
R extends IKeyConstraint>
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ConstraintValidationException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ConstraintValidationException.java
new file mode 100644
index 000000000..b13824091
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ConstraintValidationException.java
@@ -0,0 +1,53 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.model.constraint;
+
+import edu.umd.cs.findbugs.annotations.Nullable;
+
+public class ConstraintValidationException
+ extends Exception {
+
+ /**
+ * the serial version UID.
+ */
+ private static final long serialVersionUID = 2L;
+
+ /**
+ * Constructs a new exception with the specified detail message. The cause is
+ * not initialized, and may subsequently be initialized by a call to
+ * {@link #initCause}.
+ *
+ * @param message
+ * the detail message, which is saved for later retrieval by the
+ * {@link #getMessage()} method.
+ */
+ public ConstraintValidationException(@Nullable String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new exception with the specified cause.
+ *
+ * If the cause has a detail message (i.e.
+ * {@code (cause==null ? null : cause.toString())} then the message provided by
+ * the cause will be used.
+ *
+ * This constructor is useful for when this exception is raised as a wrapper of
+ * another exception.
+ *
+ * @param cause
+ * the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). A {@code null} value is permitted, and
+ * indicates that the cause is nonexistent or unknown.
+ */
+ public ConstraintValidationException(@Nullable Throwable cause) {
+ super(cause);
+ }
+
+ public ConstraintValidationException(@Nullable String message, @Nullable Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ConstraintValidationFinding.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ConstraintValidationFinding.java
index 6ec8c754c..ea3d4f981 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ConstraintValidationFinding.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ConstraintValidationFinding.java
@@ -182,6 +182,9 @@ public static Builder builder(@NonNull IConstraint constraint, @NonNull INodeIte
return new Builder(CollectionUtil.singletonList(constraint), node);
}
+ /**
+ * Implements a builder pattern for creating constraint findings.
+ */
public static final class Builder {
@NonNull
private final List extends IConstraint> 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 67b3ce176..d6618da9e 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
@@ -26,6 +26,8 @@
import gov.nist.secauto.metaschema.core.model.IFlagDefinition;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
+import gov.nist.secauto.metaschema.core.util.ExceptionUtils;
+import gov.nist.secauto.metaschema.core.util.ExceptionUtils.WrappedException;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import org.apache.commons.lang3.tuple.Pair;
@@ -70,8 +72,10 @@ public class DefaultConstraintValidator
@NonNull
private final IMutableConfiguration> configuration;
+ private final boolean exceptionOnError = false;
+
/**
- * Construct a new constraint validator instance.
+ * Construct a new constraint validation instance.
*
* @param handler
* the validation handler to use for handling constraint violations
@@ -138,8 +142,12 @@ protected IConstraintValidationHandler getConstraintValidationHandler() {
@Override
public void validate(
@NonNull INodeItem item,
- @NonNull DynamicContext dynamicContext) {
- item.accept(new Visitor(), dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
+ try {
+ item.accept(new Visitor(), dynamicContext);
+ } catch (WrappedException ex) {
+ ex.unwrapAndThrow(ConstraintValidationException.class);
+ }
}
/**
@@ -159,10 +167,14 @@ protected void validateFlag(
@NonNull DynamicContext dynamicContext) {
IFlagDefinition definition = item.getDefinition();
- validateExpect(definition.getExpectConstraints(), item, dynamicContext);
- validateAllowedValues(definition.getAllowedValuesConstraints(), item, dynamicContext);
- validateIndexHasKey(definition.getIndexHasKeyConstraints(), item, dynamicContext);
- validateMatches(definition.getMatchesConstraints(), item, dynamicContext);
+ try {
+ validateExpect(definition.getExpectConstraints(), item, dynamicContext);
+ validateAllowedValues(definition.getAllowedValuesConstraints(), item, dynamicContext);
+ validateIndexHasKey(definition.getIndexHasKeyConstraints(), item, dynamicContext);
+ validateMatches(definition.getMatchesConstraints(), item, dynamicContext);
+ } catch (ConstraintValidationException ex) {
+ throw ExceptionUtils.wrap(ex);
+ }
}
/**
@@ -182,10 +194,14 @@ protected void validateField(
@NonNull DynamicContext dynamicContext) {
IFieldDefinition definition = item.getDefinition();
- validateExpect(definition.getExpectConstraints(), item, dynamicContext);
- validateAllowedValues(definition.getAllowedValuesConstraints(), item, dynamicContext);
- validateIndexHasKey(definition.getIndexHasKeyConstraints(), item, dynamicContext);
- validateMatches(definition.getMatchesConstraints(), item, dynamicContext);
+ try {
+ validateExpect(definition.getExpectConstraints(), item, dynamicContext);
+ validateAllowedValues(definition.getAllowedValuesConstraints(), item, dynamicContext);
+ validateIndexHasKey(definition.getIndexHasKeyConstraints(), item, dynamicContext);
+ validateMatches(definition.getMatchesConstraints(), item, dynamicContext);
+ } catch (ConstraintValidationException ex) {
+ throw ExceptionUtils.wrap(ex);
+ }
}
/**
@@ -196,22 +212,25 @@ protected void validateField(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
- * @throws MetapathException
- * if an error occurred while evaluating a Metapath used in a
- * constraint
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
protected void validateAssembly(
@NonNull IAssemblyNodeItem item,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
IAssemblyDefinition definition = item.getDefinition();
- validateExpect(definition.getExpectConstraints(), item, dynamicContext);
- validateAllowedValues(definition.getAllowedValuesConstraints(), item, dynamicContext);
- validateIndexHasKey(definition.getIndexHasKeyConstraints(), item, dynamicContext);
- validateMatches(definition.getMatchesConstraints(), item, dynamicContext);
- validateHasCardinality(definition.getHasCardinalityConstraints(), item, dynamicContext);
- validateIndex(definition.getIndexConstraints(), item, dynamicContext);
- validateUnique(definition.getUniqueConstraints(), item, dynamicContext);
+ try {
+ validateExpect(definition.getExpectConstraints(), item, dynamicContext);
+ validateAllowedValues(definition.getAllowedValuesConstraints(), item, dynamicContext);
+ validateIndexHasKey(definition.getIndexHasKeyConstraints(), item, dynamicContext);
+ validateMatches(definition.getMatchesConstraints(), item, dynamicContext);
+ validateHasCardinality(definition.getHasCardinalityConstraints(), item, dynamicContext);
+ validateIndex(definition.getIndexConstraints(), item, dynamicContext);
+ validateUnique(definition.getUniqueConstraints(), item, dynamicContext);
+ } catch (ConstraintValidationException ex) {
+ throw ExceptionUtils.wrap(ex);
+ }
}
/**
@@ -225,19 +244,19 @@ protected void validateAssembly(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
- @SuppressWarnings("PMD.AvoidCatchingGenericException")
private void validateHasCardinality( // NOPMD false positive
@NonNull List extends ICardinalityConstraint> constraints,
@NonNull IAssemblyNodeItem item,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
for (ICardinalityConstraint constraint : constraints) {
assert constraint != null;
-
try {
ISequence extends IDefinitionNodeItem, ?>> targets = constraint.matchTargets(item, dynamicContext);
validateHasCardinality(constraint, item, targets, dynamicContext);
- } catch (RuntimeException ex) {
+ } catch (MetapathException ex) {
handleError(constraint, item, ex, dynamicContext);
}
}
@@ -255,12 +274,14 @@ private void validateHasCardinality( // NOPMD false positive
* @param targets
* the focus of Metapath evaluation for evaluating any constraint
* Metapath clauses
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
private void validateHasCardinality(
@NonNull ICardinalityConstraint constraint,
@NonNull IAssemblyNodeItem node,
@NonNull ISequence extends INodeItem> targets,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
int itemCount = targets.size();
IConstraintValidationHandler handler = getConstraintValidationHandler();
@@ -294,19 +315,20 @@ private void validateHasCardinality(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
- @SuppressWarnings("PMD.AvoidCatchingGenericException")
private void validateIndex(
@NonNull List extends IIndexConstraint> constraints,
@NonNull IAssemblyNodeItem item,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
for (IIndexConstraint constraint : constraints) {
assert constraint != null;
try {
ISequence extends IDefinitionNodeItem, ?>> targets = constraint.matchTargets(item, dynamicContext);
validateIndex(constraint, item, targets, dynamicContext);
- } catch (RuntimeException ex) {
+ } catch (MetapathException ex) {
handleError(constraint, item, ex, dynamicContext);
}
}
@@ -327,37 +349,50 @@ private void validateIndex(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
private void validateIndex(
@NonNull IIndexConstraint constraint,
@NonNull IAssemblyNodeItem node,
@NonNull ISequence extends INodeItem> targets,
- @NonNull DynamicContext dynamicContext) {
- String indexName = constraint.getName();
-
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
IConstraintValidationHandler handler = getConstraintValidationHandler();
- if (indexNameToIndexMap.containsKey(indexName)) {
+ if (indexNameToIndexMap.containsKey(constraint.getName())) {
handler.handleIndexDuplicateViolation(constraint, node, dynamicContext);
} else {
- IIndex index = IIndex.newInstance(constraint.getKeyFields());
- targets.stream()
- .forEachOrdered(item -> {
- assert item != null;
- if (item.hasValue()) {
- try {
- INodeItem oldItem = index.put(item, dynamicContext);
- if (oldItem == null) {
- handlePass(constraint, node, item, dynamicContext);
- } else {
- handler.handleIndexDuplicateKeyViolation(constraint, node, oldItem, item, dynamicContext);
- }
- } catch (MetapathException ex) {
- handler.handleKeyMatchError(constraint, node, item, ex, dynamicContext);
- }
- }
- });
- indexNameToIndexMap.put(indexName, index);
+ validateIndexEntries(constraint, node, targets, dynamicContext);
+ }
+ }
+
+ private void validateIndexEntries(
+ @NonNull IIndexConstraint constraint,
+ @NonNull IAssemblyNodeItem node,
+ @NonNull ISequence extends INodeItem> targets,
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
+ IIndex index = IIndex.newInstance(constraint.getKeyFields());
+ for (INodeItem item : targets) {
+ assert item != null;
+ if (item.hasValue()) {
+ INodeItem oldItem = null;
+ try {
+ oldItem = index.put(item, IIndex.toKey(item, index.getKeyFields(), dynamicContext));
+ } catch (IllegalArgumentException ex) {
+ // throw by IIndex.toKey
+ handleError(constraint, item, ex, dynamicContext);
+ }
+ try {
+ if (oldItem == null) {
+ handlePass(constraint, node, item, dynamicContext);
+ } else {
+ handler.handleIndexDuplicateKeyViolation(constraint, node, oldItem, item, dynamicContext);
+ }
+ } catch (MetapathException ex) {
+ handler.handleKeyMatchError(constraint, node, item, ex, dynamicContext);
+ }
+ }
}
+ indexNameToIndexMap.put(constraint.getName(), index);
}
private void handlePass(
@@ -374,9 +409,16 @@ private void handleError(
@NonNull IConstraint constraint,
@NonNull INodeItem node,
@NonNull Throwable ex,
- @NonNull DynamicContext dynamicContext) {
- getConstraintValidationHandler()
- .handleError(constraint, node, toErrorMessage(constraint, node, ex), ex, dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
+ if (exceptionOnError) {
+ if (ex instanceof ConstraintValidationException) {
+ throw (ConstraintValidationException) ex;
+ }
+ throw new ConstraintValidationException(ex);
+ } else {
+ getConstraintValidationHandler()
+ .handleError(constraint, node, toErrorMessage(constraint, node, ex), ex, dynamicContext);
+ }
}
@NonNull
@@ -418,19 +460,20 @@ private static String toErrorMessage(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
- @SuppressWarnings("PMD.AvoidCatchingGenericException")
private void validateUnique(
@NonNull List extends IUniqueConstraint> constraints,
@NonNull IAssemblyNodeItem item,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
for (IUniqueConstraint constraint : constraints) {
assert constraint != null;
try {
ISequence extends IDefinitionNodeItem, ?>> targets = constraint.matchTargets(item, dynamicContext);
validateUnique(constraint, item, targets, dynamicContext);
- } catch (RuntimeException ex) {
+ } catch (MetapathException ex) {
handleError(constraint, item, ex, dynamicContext);
}
}
@@ -451,32 +494,40 @@ private void validateUnique(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
private void validateUnique(
@NonNull IUniqueConstraint constraint,
@NonNull IAssemblyNodeItem node,
@NonNull ISequence extends INodeItem> targets,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
IConstraintValidationHandler handler = getConstraintValidationHandler();
IIndex index = IIndex.newInstance(constraint.getKeyFields());
- targets.stream()
- .forEachOrdered(item -> {
- assert item != null;
- if (item.hasValue()) {
- try {
- INodeItem oldItem = index.put(item, dynamicContext);
- if (oldItem == null) {
- handlePass(constraint, node, item, dynamicContext);
- } else {
- handler.handleUniqueKeyViolation(constraint, node, oldItem, item, dynamicContext);
- }
- } catch (MetapathException ex) {
- handler.handleKeyMatchError(constraint, node, item, ex, dynamicContext);
- throw ex;
- }
+
+ for (INodeItem item : targets) {
+ assert item != null;
+ if (item.hasValue()) {
+ INodeItem oldItem = null;
+ try {
+ oldItem = index.put(item, IIndex.toKey(item, index.getKeyFields(), dynamicContext));
+ } catch (IllegalArgumentException ex) {
+ // raised by IIndex.toKey
+ handleError(constraint, item, ex, dynamicContext);
+ }
+
+ try {
+ if (oldItem == null) {
+ handlePass(constraint, node, item, dynamicContext);
+ } else {
+ handler.handleUniqueKeyViolation(constraint, node, oldItem, item, dynamicContext);
}
- });
+ } catch (MetapathException ex) {
+ handleError(constraint, item, ex, dynamicContext);
+ }
+ }
+ }
}
/**
@@ -490,12 +541,13 @@ private void validateUnique(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
- @SuppressWarnings("PMD.AvoidCatchingGenericException")
- private void validateMatches( // NOPMD false positive
+ private void validateMatches(
@NonNull List extends IMatchesConstraint> constraints,
@NonNull IDefinitionNodeItem, ?> item,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
for (IMatchesConstraint constraint : constraints) {
assert constraint != null;
@@ -503,7 +555,7 @@ private void validateMatches( // NOPMD false positive
try {
ISequence extends IDefinitionNodeItem, ?>> targets = constraint.matchTargets(item, dynamicContext);
validateMatches(constraint, item, targets, dynamicContext);
- } catch (RuntimeException ex) {
+ } catch (MetapathException ex) {
handleError(constraint, item, ex, dynamicContext);
}
}
@@ -521,26 +573,27 @@ private void validateMatches( // NOPMD false positive
* @param targets
* the focus of Metapath evaluation for evaluating any constraint
* Metapath clauses
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
private void validateMatches(
@NonNull IMatchesConstraint constraint,
@NonNull INodeItem node,
@NonNull ISequence extends INodeItem> targets,
- @NonNull DynamicContext dynamicContext) {
- targets.stream()
- .forEachOrdered(item -> {
- assert item != null;
- if (item.hasValue()) {
- validateMatchesItem(constraint, node, item, dynamicContext);
- }
- });
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
+ for (INodeItem item : targets) {
+ assert item != null;
+ if (item.hasValue()) {
+ validateMatchesItem(constraint, node, item, dynamicContext);
+ }
+ }
}
private void validateMatchesItem(
@NonNull IMatchesConstraint constraint,
@NonNull INodeItem node,
@NonNull INodeItem item,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
String value = item.toAtomicItem().asString();
IConstraintValidationHandler handler = getConstraintValidationHandler();
@@ -578,12 +631,13 @@ private void validateMatchesItem(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
- @SuppressWarnings("PMD.AvoidCatchingGenericException")
private void validateIndexHasKey( // NOPMD false positive
@NonNull List extends IIndexHasKeyConstraint> constraints,
@NonNull IDefinitionNodeItem, ?> item,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
for (IIndexHasKeyConstraint constraint : constraints) {
assert constraint != null;
@@ -591,7 +645,7 @@ private void validateIndexHasKey( // NOPMD false positive
try {
ISequence extends IDefinitionNodeItem, ?>> targets = constraint.matchTargets(item, dynamicContext);
validateIndexHasKey(constraint, item, targets);
- } catch (RuntimeException ex) {
+ } catch (MetapathException ex) {
handleError(constraint, item, ex, dynamicContext);
}
}
@@ -636,19 +690,20 @@ private void validateIndexHasKey(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
- @SuppressWarnings("PMD.AvoidCatchingGenericException")
private void validateExpect(
@NonNull List extends IExpectConstraint> constraints,
@NonNull IDefinitionNodeItem, ?> item,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
for (IExpectConstraint constraint : constraints) {
assert constraint != null;
try {
ISequence extends IDefinitionNodeItem, ?>> targets = constraint.matchTargets(item, dynamicContext);
validateExpect(constraint, item, targets, dynamicContext);
- } catch (RuntimeException ex) {
+ } catch (MetapathException ex) {
handleError(constraint, item, ex, dynamicContext);
}
}
@@ -669,34 +724,31 @@ private void validateExpect(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
private void validateExpect(
@NonNull IExpectConstraint constraint,
@NonNull INodeItem node,
@NonNull ISequence extends INodeItem> targets,
- @NonNull DynamicContext dynamicContext) {
- try {
- IMetapathExpression metapath = constraint.getTest();
- IConstraintValidationHandler handler = getConstraintValidationHandler();
- targets.stream()
- .forEachOrdered(item -> {
- assert item != null;
-
- if (item.hasValue()) {
- try {
- ISequence> result = metapath.evaluate(item, dynamicContext);
- if (FnBoolean.fnBoolean(result).toBoolean()) {
- handlePass(constraint, node, item, dynamicContext);
- } else {
- handler.handleExpectViolation(constraint, node, item, dynamicContext);
- }
- } catch (MetapathException ex) {
- handleError(constraint, item, ex, dynamicContext);
- }
- }
- });
- } catch (MetapathException ex) {
- handleError(constraint, node, ex, dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
+ IMetapathExpression test = constraint.getTest();
+ IConstraintValidationHandler handler = getConstraintValidationHandler();
+ for (INodeItem item : targets) {
+ assert item != null;
+
+ if (item.hasValue()) {
+ try {
+ ISequence> result = test.evaluate(item, dynamicContext);
+ if (FnBoolean.fnBoolean(result).toBoolean()) {
+ handlePass(constraint, node, item, dynamicContext);
+ } else {
+ handler.handleExpectViolation(constraint, node, item, dynamicContext);
+ }
+ } catch (MetapathException ex) {
+ handleError(constraint, item, ex, dynamicContext);
+ }
+ }
}
}
@@ -711,18 +763,19 @@ private void validateExpect(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
- @SuppressWarnings("PMD.AvoidCatchingGenericException")
private void validateAllowedValues(
@NonNull List extends IAllowedValuesConstraint> constraints,
@NonNull IDefinitionNodeItem, ?> item,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
for (IAllowedValuesConstraint constraint : constraints) {
assert constraint != null;
try {
ISequence extends IDefinitionNodeItem, ?>> targets = constraint.matchTargets(item, dynamicContext);
validateAllowedValues(constraint, item, targets, dynamicContext);
- } catch (RuntimeException ex) {
+ } catch (MetapathException ex) {
handleError(constraint, item, ex, dynamicContext);
}
}
@@ -743,23 +796,24 @@ private void validateAllowedValues(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while validating a constraint
*/
- @SuppressWarnings("PMD.AvoidCatchingGenericException")
private void validateAllowedValues(
@NonNull IAllowedValuesConstraint constraint,
@NonNull IDefinitionNodeItem, ?> node,
@NonNull ISequence extends IDefinitionNodeItem, ?>> targets,
- @NonNull DynamicContext dynamicContext) {
- targets.stream().forEachOrdered(item -> {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
+ for (INodeItem item : targets) {
assert item != null;
if (item.hasValue()) {
try {
updateValueStatus(item, constraint, node);
- } catch (RuntimeException ex) {
+ } catch (ConstraintValidationException ex) {
handleError(constraint, item, ex, dynamicContext);
}
}
- });
+ }
}
/**
@@ -772,11 +826,14 @@ private void validateAllowedValues(
* @param node
* the original focus of Metapath evaluation for identifying the
* targets
+ * @throws ConstraintValidationException
+ * if an unexpected error occurred while registering the allowed
+ * values
*/
protected void updateValueStatus(
@NonNull INodeItem targetItem,
@NonNull IAllowedValuesConstraint allowedValues,
- @NonNull IDefinitionNodeItem, ?> node) {
+ @NonNull IDefinitionNodeItem, ?> node) throws ConstraintValidationException {
// constraint.getAllowedValues().containsKey(value)
@Nullable
@@ -786,7 +843,7 @@ protected void updateValueStatus(
valueMap.put(targetItem, valueStatus);
}
- valueStatus.registerAllowedValue(allowedValues, node);
+ valueStatus.registerAllowedValues(allowedValues, node);
}
/**
@@ -808,9 +865,8 @@ protected void handleAllowedValues(
}
}
- @SuppressWarnings("PMD.AvoidCatchingGenericException")
@Override
- public void finalizeValidation(DynamicContext dynamicContext) {
+ public void finalizeValidation(DynamicContext dynamicContext) throws ConstraintValidationException {
// key references
for (Map.Entry> entry : indexNameToKeyRefMap.entrySet()) {
String indexName = ObjectUtils.notNull(entry.getKey());
@@ -827,7 +883,7 @@ public void finalizeValidation(DynamicContext dynamicContext) {
assert item != null;
try {
validateKeyRef(constraint, node, item, indexName, index, dynamicContext);
- } catch (RuntimeException ex) {
+ } catch (MetapathException ex) {
handleError(constraint, item, ex, dynamicContext);
}
}
@@ -841,10 +897,16 @@ private void validateKeyRef(
@NonNull INodeItem item,
@NonNull String indexName,
@Nullable IIndex index,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
IConstraintValidationHandler handler = getConstraintValidationHandler();
try {
- List key = IIndex.toKey(item, constraint.getKeyFields(), dynamicContext);
+ List key;
+ try {
+ key = IIndex.toKey(item, constraint.getKeyFields(), dynamicContext);
+ } catch (IllegalArgumentException ex) {
+ handler.handleError(constraint, item, toErrorMessage(constraint, item, ex), ex, dynamicContext);
+ throw ex;
+ }
if (index == null) {
handler.handleMissingIndexViolation(
@@ -884,9 +946,9 @@ public ValueStatus(@NonNull INodeItem item) {
this.value = item.toAtomicItem().asString();
}
- public void registerAllowedValue(
+ public void registerAllowedValues(
@NonNull IAllowedValuesConstraint allowedValues,
- @NonNull IDefinitionNodeItem, ?> node) {
+ @NonNull IDefinitionNodeItem, ?> node) throws ConstraintValidationException {
IAllowedValuesConstraint.Extensible newExtensible = allowedValues.getExtensible();
if (newExtensible.ordinal() > extensible.ordinal()) {
// record the most restrictive value
@@ -894,10 +956,11 @@ public void registerAllowedValue(
} else if (IAllowedValuesConstraint.Extensible.NONE.equals(newExtensible)
&& IAllowedValuesConstraint.Extensible.NONE.equals(extensible)) {
// this is an error, where there are two none constraints that conflict
- throw new MetapathException(
- String.format(
+ // TODO: find a different exception type to use
+ throw new ConstraintValidationException(
+ ObjectUtils.notNull(String.format(
"Multiple constraints matching path '%s' have scope='none', which prevents extension. Involved" +
- " constraints are those: %s",
+ " constraints are: %s",
Stream.concat(
Stream.of(allowedValues),
constraints.stream()
@@ -906,14 +969,14 @@ public void registerAllowedValue(
constraint -> IAllowedValuesConstraint.Extensible.NONE.equals(constraint.getExtensible())))
.map(IConstraint::getConstraintIdentity)
.collect(Collectors.joining(", ", "{", "}")),
- item.getMetapath()));
+ item.getMetapath())));
} else if (allowedValues.getExtensible().ordinal() < extensible.ordinal()) {
- String msg = String.format(
+ String msg = ObjectUtils.notNull(String.format(
"An allowed values constraint with an extensibility scope '%s'"
+ " exceeds the allowed scope '%s' at path '%s'",
- allowedValues.getExtensible().name(), extensible.name(), item.getMetapath());
+ allowedValues.getExtensible().name(), extensible.name(), item.getMetapath()));
LOGGER.atError().log(msg);
- throw new MetapathException(msg);
+ throw new ConstraintValidationException(msg);
}
this.constraints.add(Pair.of(allowedValues, node));
if (!allowedValues.isAllowedOther()) {
@@ -1014,7 +1077,11 @@ public Void visitAssembly(@NonNull IAssemblyNodeItem item, DynamicContext contex
IAssemblyDefinition definition = item.getDefinition();
DynamicContext effectiveContext = handleLetStatements(item, definition.getLetExpressions(), context);
- validateAssembly(item, effectiveContext);
+ try {
+ validateAssembly(item, effectiveContext);
+ } catch (ConstraintValidationException ex) {
+ throw ExceptionUtils.wrap(ex);
+ }
super.visitAssembly(item, effectiveContext);
return null;
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultScopedContraints.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultScopedContraints.java
index f02a03be8..3e8f0e292 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultScopedContraints.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultScopedContraints.java
@@ -13,8 +13,8 @@
import edu.umd.cs.findbugs.annotations.NonNull;
/**
- * Represents a collection of constraints to apply to a given module identified
- * by the module's namespace and short name.
+ * A collection of constraints to apply to a given module identified by the
+ * module's namespace and short name.
*/
public class DefaultScopedContraints implements IScopedContraints {
@NonNull
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FindingCollectingConstraintValidationHandler.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FindingCollectingConstraintValidationHandler.java
index 259a4938c..a6d62d26c 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FindingCollectingConstraintValidationHandler.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/FindingCollectingConstraintValidationHandler.java
@@ -95,7 +95,7 @@ public void handleCardinalityMinimumViolation(
@NonNull ICardinalityConstraint constraint,
@NonNull INodeItem target,
@NonNull ISequence extends INodeItem> testedItems,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
addFinding(ConstraintValidationFinding.builder(constraint, target)
.severity(constraint.getLevel())
.kind(toKind(constraint.getLevel()))
@@ -110,7 +110,7 @@ public void handleCardinalityMaximumViolation(
@NonNull ICardinalityConstraint constraint,
@NonNull INodeItem target,
@NonNull ISequence extends INodeItem> testedItems,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
addFinding(ConstraintValidationFinding.builder(constraint, target)
.severity(constraint.getLevel())
.kind(toKind(constraint.getLevel()))
@@ -126,7 +126,7 @@ public void handleIndexDuplicateKeyViolation(
@NonNull INodeItem node,
@NonNull INodeItem oldItem,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
addFinding(ConstraintValidationFinding.builder(constraint, node)
.severity(constraint.getLevel())
.kind(toKind(constraint.getLevel()))
@@ -141,7 +141,7 @@ public void handleUniqueKeyViolation(
@NonNull INodeItem node,
@NonNull INodeItem oldItem,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
addFinding(ConstraintValidationFinding.builder(constraint, node)
.severity(constraint.getLevel())
.kind(toKind(constraint.getLevel()))
@@ -174,7 +174,7 @@ public void handleMatchPatternViolation(
@NonNull INodeItem target,
@NonNull String value,
@NonNull Pattern pattern,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
addFinding(ConstraintValidationFinding.builder(constraint, node)
.severity(constraint.getLevel())
.kind(toKind(constraint.getLevel()))
@@ -191,7 +191,7 @@ public void handleMatchDatatypeViolation(
@NonNull String value,
@NonNull IDataTypeAdapter> adapter,
@NonNull IllegalArgumentException cause,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
addFinding(ConstraintValidationFinding.builder(constraint, node)
.severity(constraint.getLevel())
.kind(toKind(constraint.getLevel()))
@@ -206,7 +206,7 @@ public void handleExpectViolation(
@NonNull IExpectConstraint constraint,
@NonNull INodeItem node,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
addFinding(ConstraintValidationFinding.builder(constraint, node)
.severity(constraint.getLevel())
.kind(toKind(constraint.getLevel()))
@@ -251,7 +251,7 @@ public void handleIndexMiss(
@NonNull INodeItem node,
@NonNull INodeItem target,
@NonNull List key,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
addFinding(ConstraintValidationFinding.builder(constraint, node)
.severity(constraint.getLevel())
.kind(toKind(constraint.getLevel()))
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConfigurableMessageConstraint.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConfigurableMessageConstraint.java
index af718b11d..fbb8863cd 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConfigurableMessageConstraint.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConfigurableMessageConstraint.java
@@ -39,7 +39,10 @@ public interface IConfigurableMessageConstraint extends IConstraint {
* @throws ConstraintInitializationException
* if a custom message is not defined, which will occur if this method
* is called while {@link #getMessage()} returns {@code null}
+ * @throws ConstraintValidationException
+ * if the custom message contains a Metapath expression that is
+ * invalid or if the expression failed to evaluate
*/
@NonNull
- String generateMessage(@NonNull INodeItem item, @NonNull DynamicContext context);
+ String generateMessage(@NonNull INodeItem item, @NonNull DynamicContext context) throws ConstraintValidationException;
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraintValidationHandler.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraintValidationHandler.java
index e6327feab..d7b749826 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraintValidationHandler.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraintValidationHandler.java
@@ -34,12 +34,15 @@ public interface IConstraintValidationHandler {
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if the constraint has a custom message that contains a Metapath
+ * expression that is invalid or if the expression failed to evaluate
*/
void handleCardinalityMinimumViolation(
@NonNull ICardinalityConstraint constraint,
@NonNull INodeItem target,
@NonNull ISequence extends INodeItem> testedItems,
- @NonNull DynamicContext dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException;
/**
* Handle a cardinality constraint maximum violation.
@@ -53,12 +56,15 @@ void handleCardinalityMinimumViolation(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if the constraint has a custom message that contains a Metapath
+ * expression that is invalid or if the expression failed to evaluate
*/
void handleCardinalityMaximumViolation(
@NonNull ICardinalityConstraint constraint,
@NonNull INodeItem target,
@NonNull ISequence extends INodeItem> testedItems,
- @NonNull DynamicContext dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException;
/**
* Handle a duplicate index violation.
@@ -94,13 +100,16 @@ void handleIndexDuplicateViolation(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if the constraint has a custom message that contains a Metapath
+ * expression that is invalid or if the expression failed to evaluate
*/
void handleIndexDuplicateKeyViolation(
@NonNull IIndexConstraint constraint,
@NonNull INodeItem node,
@NonNull INodeItem oldItem,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException;
/**
* Handle an unique key violation.
@@ -119,13 +128,16 @@ void handleIndexDuplicateKeyViolation(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if the constraint has a custom message that contains a Metapath
+ * expression that is invalid or if the expression failed to evaluate
*/
void handleUniqueKeyViolation(
@NonNull IUniqueConstraint constraint,
@NonNull INodeItem node,
@NonNull INodeItem oldItem,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException;
/**
* Handle an error that occurred while generating a key.
@@ -193,13 +205,16 @@ void handleMissingIndexViolation(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if the constraint has a custom message that contains a Metapath
+ * expression that is invalid or if the expression failed to evaluate
*/
void handleIndexMiss(
@NonNull IIndexHasKeyConstraint constraint,
@NonNull INodeItem node,
@NonNull INodeItem target,
@NonNull List key,
- @NonNull DynamicContext dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException;
/**
* Handle a match pattern violation.
@@ -220,6 +235,9 @@ void handleIndexMiss(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if the constraint has a custom message that contains a Metapath
+ * expression that is invalid or if the expression failed to evaluate
*/
void handleMatchPatternViolation(
@NonNull IMatchesConstraint constraint,
@@ -227,7 +245,7 @@ void handleMatchPatternViolation(
@NonNull INodeItem target,
@NonNull String value,
@NonNull Pattern pattern,
- @NonNull DynamicContext dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException;
/**
* Handle a match data type violation.
@@ -251,6 +269,9 @@ void handleMatchPatternViolation(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if the constraint has a custom message that contains a Metapath
+ * expression that is invalid or if the expression failed to evaluate
*/
void handleMatchDatatypeViolation(
@NonNull IMatchesConstraint constraint,
@@ -259,7 +280,7 @@ void handleMatchDatatypeViolation(
@NonNull String value,
@NonNull IDataTypeAdapter> adapter,
@NonNull IllegalArgumentException cause,
- @NonNull DynamicContext dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException;
/**
* Handle an expect test violation.
@@ -276,12 +297,15 @@ void handleMatchDatatypeViolation(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
+ * if the constraint has a custom message that contains a Metapath
+ * expression that is invalid or if the expression failed to evaluate
*/
void handleExpectViolation(
@NonNull IExpectConstraint constraint,
@NonNull INodeItem node,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException;
/**
* Handle an allowed values constraint violation.
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraintValidator.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraintValidator.java
index 3405382a1..156751dac 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraintValidator.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IConstraintValidator.java
@@ -24,13 +24,14 @@ public interface IConstraintValidator {
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
* @throws MetapathException
* if an error occurred while evaluating a Metapath used in a
* constraint
*/
void validate(
@NonNull INodeItem item,
- @NonNull DynamicContext dynamicContext);
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException;
/**
* Complete any validations that require full analysis of the content model.
@@ -38,9 +39,10 @@ void validate(
* @param dynamicContext
* the Metapath dynamic execution context to use for Metapath
* evaluation
+ * @throws ConstraintValidationException
* @throws MetapathException
* if an error occurred while evaluating a Metapath used in a
* constraint
*/
- void finalizeValidation(@NonNull DynamicContext dynamicContext);
+ void finalizeValidation(@NonNull DynamicContext dynamicContext) throws ConstraintValidationException;
}
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 45914b155..56ab93236 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
@@ -10,7 +10,6 @@
import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
-import gov.nist.secauto.metaschema.core.metapath.type.InvalidTypeMetapathException;
import gov.nist.secauto.metaschema.core.model.constraint.impl.DefaultIndex;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
@@ -24,6 +23,10 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
+/**
+ * An index that can support the {@link IIndexConstraint},
+ * {@link IIndexHasKeyConstraint}, and {@link IUniqueConstraint}.
+ */
public interface IIndex {
/**
@@ -64,22 +67,6 @@ static boolean isAllNulls(@NonNull Iterable key) {
@NonNull
List getKeyFields();
- /**
- * Store the provided item in the index using the index's key field components
- * to generate the key.
- *
- * @param item
- * the item to store in the index
- * @param dynamicContext
- * the Metapath evaluation context
- * @return the previous item stored in the index, or {@code null} otherwise
- */
- @Nullable
- default INodeItem put(@NonNull INodeItem item, @NonNull DynamicContext dynamicContext) {
- List key = toKey(item, getKeyFields(), dynamicContext);
- return put(item, key);
- }
-
/**
* Store the provided item using the provided key.
*
@@ -93,22 +80,6 @@ default INodeItem put(@NonNull INodeItem item, @NonNull DynamicContext dynamicCo
@Nullable
INodeItem put(@NonNull INodeItem item, @NonNull List key);
- /**
- * Retrieve the item from the index that matches the key generated by evaluating
- * the index's default key field components against the provided item.
- *
- * @param item
- * the item to store in the index
- * @param dynamicContext
- * the Metapath evaluation context
- * @return the previous item stored in the index, or {@code null} otherwise
- */
- @Nullable
- default INodeItem get(@NonNull INodeItem item, @NonNull DynamicContext dynamicContext) {
- List key = toKey(item, getKeyFields(), dynamicContext);
- return get(key);
- }
-
/**
* Retrieve the item from the index that matches the provided key.
*
@@ -130,9 +101,17 @@ default INodeItem get(@NonNull INodeItem item, @NonNull DynamicContext dynamicCo
* @param dynamicContext
* the Metapath evaluation context
* @return a new key
+ * @throws IllegalArgumentException
+ * if a key field has a configured pattern that fails to match the key
+ * item value or if the pattern is malformed
+ * @throws MetapathException
+ * if the evaluation of a key field's metapath resulted in an
+ * unexpected error
*/
@NonNull
- static List toKey(@NonNull INodeItem item, @NonNull List extends IKeyField> keyFields,
+ static List toKey(
+ @NonNull INodeItem item,
+ @NonNull List extends IKeyField> keyFields,
@NonNull DynamicContext dynamicContext) {
return CollectionUtil.unmodifiableList(
ObjectUtils.notNull(keyFields.stream()
@@ -154,6 +133,12 @@ static List toKey(@NonNull INodeItem item, @NonNull List extends IKeyF
* @param dynamicContext
* the Metapath evaluation context
* @return the key value or {@code null} if the evaluation resulted in no value
+ * @throws IllegalArgumentException
+ * if the key field has a configured pattern that fails to match the
+ * key item value or if the pattern is malformed
+ * @throws MetapathException
+ * if the evaluation of the key metapath resulted in an unexpected
+ * error
*/
@Nullable
private static String buildKeyItem(
@@ -162,12 +147,7 @@ private static String buildKeyItem(
@NonNull DynamicContext dynamicContext) {
IMetapathExpression keyMetapath = keyField.getTarget();
- IItem keyItem;
- try {
- keyItem = keyMetapath.evaluateAs(item, IMetapathExpression.ResultType.ITEM, dynamicContext);
- } catch (InvalidTypeMetapathException ex) {
- throw new MetapathException("Key path did not result in a single item", ex);
- }
+ IItem keyItem = keyMetapath.evaluateAs(item, IMetapathExpression.ResultType.ITEM, dynamicContext);
String keyValue = null;
if (keyItem != null) {
@@ -177,12 +157,15 @@ private static String buildKeyItem(
if (pattern != null) {
keyValue = applyPattern(keyMetapath, keyValue, pattern);
}
- } // empty key
+ } // else empty key
return keyValue;
}
/**
* Apply the key value pattern, if configured, to generate the final key value.
+ *
+ * The provided pattern is expected to have a single matching group, which will
+ * contain the final key value on match
*
* @param keyItem
* the node item used to form the key field
@@ -191,21 +174,31 @@ private static String buildKeyItem(
* @param keyValue
* the current key value
* @return the final key value
+ * @throws IllegalArgumentException
+ * if the provided key value does not match the provided pattern or if
+ * the pattern is malformed
*/
- private static String applyPattern(@NonNull IMetapathExpression keyMetapath, @NonNull String keyValue,
+ @Nullable
+ private static String applyPattern(
+ @NonNull IMetapathExpression keyMetapath,
+ @NonNull String keyValue,
@NonNull Pattern pattern) {
Matcher matcher = pattern.matcher(keyValue);
if (!matcher.matches()) {
- throw new MetapathException(
+ // TODO: use a different exception type?
+ throw new IllegalArgumentException(
String.format("Key field declares the pattern '%s' which does not match the value '%s' of node '%s'",
pattern.pattern(), keyValue, keyMetapath));
}
if (matcher.groupCount() != 1) {
- throw new MetapathException(String.format(
- "The first group was not a match for value '%s' of node '%s' for key field pattern '%s'",
- keyValue, keyMetapath, pattern.pattern()));
+ throw new IllegalArgumentException(
+ String.format("The first group was not a match for value '%s' of node '%s' for key field pattern '%s'",
+ keyValue, keyMetapath, pattern.pattern()));
}
- return matcher.group(1);
+
+ String result = matcher.group(1);
+
+ return result == null || result.isEmpty() ? null : result;
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ILet.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ILet.java
index c64ae358d..79dc7f236 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ILet.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/ILet.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.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.impl.DefaultLet;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
@@ -46,21 +45,11 @@ static ILet of(
@NonNull String valueExpression,
@NonNull ISource source,
@Nullable MarkupMultiline remarks) {
- try {
- return of(
- name,
- IMetapathExpression.lazyCompile(valueExpression, source.getStaticContext()),
- source,
- remarks);
- } catch (MetapathException ex) {
- throw new MetapathException(
- String.format("Unable to compile the let expression '%s=%s'%s. %s",
- name,
- valueExpression,
- source.getSource() == null ? "" : " in " + source.getSource(),
- ex.getMessage()),
- ex);
- }
+ return of(
+ name,
+ IMetapathExpression.lazyCompile(valueExpression, source.getStaticContext()),
+ source,
+ remarks);
}
/**
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/LoggingConstraintValidationHandler.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/LoggingConstraintValidationHandler.java
index ea5a50927..a74f6b2fd 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/LoggingConstraintValidationHandler.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/LoggingConstraintValidationHandler.java
@@ -122,7 +122,7 @@ public void handleCardinalityMinimumViolation(
@NonNull ICardinalityConstraint constraint,
@NonNull INodeItem node,
@NonNull ISequence extends INodeItem> targets,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
Level level = constraint.getLevel();
if (isLogged(level)) {
logMessage(
@@ -143,7 +143,7 @@ public void handleCardinalityMaximumViolation(
@NonNull ICardinalityConstraint constraint,
@NonNull INodeItem node,
@NonNull ISequence extends INodeItem> targets,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
Level level = constraint.getLevel();
if (isLogged(level)) {
logMessage(
@@ -165,7 +165,7 @@ public void handleIndexDuplicateKeyViolation(
@NonNull INodeItem node,
@NonNull INodeItem oldItem,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
Level level = constraint.getLevel();
if (isLogged(level)) {
logMessage(
@@ -188,7 +188,7 @@ public void handleUniqueKeyViolation(
@NonNull INodeItem node,
@NonNull INodeItem oldItem,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
Level level = constraint.getLevel();
if (isLogged(level)) {
logMessage(
@@ -231,7 +231,7 @@ public void handleMatchPatternViolation(
@NonNull INodeItem target,
@NonNull String value,
@NonNull Pattern pattern,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
Level level = constraint.getLevel();
if (isLogged(level)) {
logMessage(
@@ -257,7 +257,7 @@ public void handleMatchDatatypeViolation(
@NonNull String value,
@NonNull IDataTypeAdapter> adapter,
@NonNull IllegalArgumentException cause,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
Level level = constraint.getLevel();
if (isLogged(level)) {
logMessage(
@@ -280,7 +280,7 @@ public void handleExpectViolation(
@NonNull IExpectConstraint constraint,
@NonNull INodeItem node,
@NonNull INodeItem target,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
Level level = constraint.getLevel();
if (isLogged(level)) {
logMessage(
@@ -343,7 +343,7 @@ public void handleIndexMiss(
@NonNull INodeItem node,
@NonNull INodeItem target,
@NonNull List key,
- @NonNull DynamicContext dynamicContext) {
+ @NonNull DynamicContext dynamicContext) throws ConstraintValidationException {
Level level = constraint.getLevel();
if (isLogged(level)) {
logMessage(
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 0513c96b1..b2f6d5053 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
@@ -9,11 +9,13 @@
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.InvalidMetapathGrammarException;
import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
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;
+import gov.nist.secauto.metaschema.core.model.constraint.ConstraintValidationException;
import gov.nist.secauto.metaschema.core.model.constraint.IConfigurableMessageConstraint;
import gov.nist.secauto.metaschema.core.model.constraint.IConstraint;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
@@ -85,7 +87,8 @@ public String getMessage() {
}
@Override
- public String generateMessage(@NonNull INodeItem item, @NonNull DynamicContext context) {
+ public String generateMessage(@NonNull INodeItem item, @NonNull DynamicContext context)
+ throws ConstraintValidationException {
String message = getMessage();
if (message == null) {
throw new ConstraintInitializationException(
@@ -93,10 +96,9 @@ public String generateMessage(@NonNull INodeItem item, @NonNull DynamicContext c
IConstraint.getConstraintIdentity(this),
getSource().getLocationHint()));
}
-
- return ObjectUtils.notNull(StringUtils.replaceTokens(message, METAPATH_VALUE_TEMPLATE_PATTERN, match -> {
- String metapath = ObjectUtils.notNull(match.group(2));
- try {
+ try {
+ return ObjectUtils.notNull(StringUtils.replaceTokens(message, METAPATH_VALUE_TEMPLATE_PATTERN, match -> {
+ String metapath = ObjectUtils.notNull(match.group(2));
IMetapathExpression expr = IMetapathExpression.compile(
metapath,
// need to use the static context of the source to resolve prefixes, etc., since
@@ -108,14 +110,19 @@ public String generateMessage(@NonNull INodeItem item, @NonNull DynamicContext c
// 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",
- metapath,
- IConstraint.getConstraintIdentity(this),
- ex.getLocalizedMessage()),
- ex);
- }
- }).toString());
+ }).toString());
+ } catch (InvalidMetapathGrammarException ex) {
+ throw new ConstraintValidationException(
+ String.format("Unable to compile a message replacement expression in constraint '%s'. %s",
+ IConstraint.getConstraintIdentity(this),
+ ex.getLocalizedMessage()),
+ ex);
+ } catch (MetapathException ex) {
+ throw new ConstraintValidationException(
+ String.format("Unable to evaluate a message replacement expression in constraint '%s'. %s",
+ IConstraint.getConstraintIdentity(this),
+ ex.getLocalizedMessage()),
+ ex);
+ }
}
}
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultAllowedValue.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultAllowedValue.java
index d1f219efc..f5de750fa 100644
--- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultAllowedValue.java
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/impl/DefaultAllowedValue.java
@@ -12,6 +12,9 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
+/**
+ * Organizes information for a single allowed value in a set of allowed values.
+ */
public class DefaultAllowedValue implements IAllowedValue {
@NonNull
private final String value;
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 fd1291c8f..834a52775 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
@@ -6,7 +6,6 @@
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;
import gov.nist.secauto.metaschema.core.model.IConstraintLoader;
@@ -38,7 +37,6 @@
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
-import org.apache.xmlbeans.impl.values.XmlValueNotSupportedException;
import java.io.IOException;
import java.net.URI;
@@ -181,18 +179,7 @@ protected List parseScopedConstraints(
assert scope != null;
List targetedConstraints = new LinkedList<>(); // NOPMD - intentional
- try {
- SCOPE_PARSER.parse(source, scope, Pair.of(source, targetedConstraints));
- } catch (MetapathException | XmlValueNotSupportedException ex) {
- if (ex.getCause() instanceof MetapathException) {
- throw new MetapathException(
- String.format("Unable to compile a Metapath in '%s'. %s",
- source.getSource(),
- ex.getLocalizedMessage()),
- ex);
- }
- throw ex;
- }
+ SCOPE_PARSER.parse(source, scope, Pair.of(source, targetedConstraints));
URI namespace = ObjectUtils.notNull(URI.create(scope.getMetaschemaNamespace()));
String shortName = ObjectUtils.requireNonNull(scope.getMetaschemaShortName());
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 f3c2f9fe1..a85bd4680 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
@@ -9,7 +9,6 @@
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.MetapathException;
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;
@@ -53,7 +52,6 @@
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
-import org.apache.xmlbeans.impl.values.XmlValueNotSupportedException;
import java.math.BigInteger;
import java.util.List;
@@ -253,18 +251,7 @@ private static void parse(
@NonNull T constraints,
@NonNull XmlObject xmlObject,
@NonNull ISource source) {
- try {
- parser.parse(source, xmlObject, constraints);
- } catch (MetapathException | XmlValueNotSupportedException ex) {
- if (ex.getCause() instanceof MetapathException) {
- throw new MetapathException(
- String.format("Unable to compile a Metapath in '%s'. %s",
- source.getSource(),
- ex.getLocalizedMessage()),
- ex);
- }
- throw ex;
- }
+ parser.parse(source, xmlObject, constraints);
}
@SuppressWarnings("PMD.UnusedPrivateMethod")
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 8a0207953..87fbc1bdf 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
@@ -7,6 +7,7 @@
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.IAttributable;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.AbstractConstraintBuilder;
@@ -503,10 +504,10 @@ public static ICardinalityConstraint newCardinalityConstraint(
public static ILet newLet(
@NonNull ConstraintLetType xmlObject,
@NonNull ISource source) {
-
+ StaticContext staticContext = source.getStaticContext();
return ILet.of(
- source.getStaticContext().parseVariableName(ObjectUtils.requireNonNull(xmlObject.getVar())),
- IMetapathExpression.lazyCompile(ObjectUtils.notNull(xmlObject.getExpression()), source.getStaticContext()),
+ staticContext.parseVariableName(ObjectUtils.requireNonNull(xmlObject.getVar())),
+ IMetapathExpression.lazyCompile(ObjectUtils.notNull(xmlObject.getExpression()), staticContext),
source,
xmlObject.isSetRemarks()
? remarks(ObjectUtils.notNull(xmlObject.getRemarks()))
diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/util/ExceptionUtils.java b/core/src/main/java/gov/nist/secauto/metaschema/core/util/ExceptionUtils.java
new file mode 100644
index 000000000..9463c83bb
--- /dev/null
+++ b/core/src/main/java/gov/nist/secauto/metaschema/core/util/ExceptionUtils.java
@@ -0,0 +1,89 @@
+/*
+ * SPDX-FileCopyrightText: none
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+package gov.nist.secauto.metaschema.core.util;
+
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * Provides a means for throwing important checked exceptions over non-checked
+ * methods, e.g. lambda invocations.
+ *
+ * This capability should be used with care, and generally in limited
+ * circumstances.
+ */
+public final class ExceptionUtils {
+ @NonNull
+ public static WrappedException wrap(@NonNull Throwable ex) {
+ return new WrappedException(ex);
+ }
+
+ @NonNull
+ public static WrappedException wrapAndThrow(@NonNull Throwable ex) {
+ return new WrappedException(ex);
+ }
+
+ @NonNull
+ public static Throwable unwrap(
+ @NonNull WrappedException ex) {
+ return ex.unwrap();
+ }
+
+ @NonNull
+ public static E unwrap(
+ @NonNull WrappedException ex,
+ @NonNull Class wrappedExceptionClass) {
+ return ex.unwrap(wrappedExceptionClass);
+ }
+
+ public static final class WrappedException
+ extends RuntimeException {
+
+ /**
+ * the serial version UID.
+ */
+ private static final long serialVersionUID = 2L;
+
+ public WrappedException(@NonNull Throwable cause) {
+ super(cause);
+ }
+
+ @Override
+ public synchronized Throwable initCause(Throwable cause) {
+ throw new UnsupportedOperationException("must set cause in constructor");
+ }
+
+ @NonNull
+ public Throwable unwrap() {
+ return ObjectUtils.notNull(getCause());
+ }
+
+ @NonNull
+ public E unwrap(@NonNull Class wrappedExceptionClass) {
+ Throwable cause = unwrap();
+ if (wrappedExceptionClass.isInstance(cause)) {
+ E unwrappedEx = wrappedExceptionClass.cast(cause);
+ unwrappedEx.addSuppressed(this);
+ return unwrappedEx;
+ }
+ throw new IllegalArgumentException(
+ String.format("Wrapped exception '%s' did not match excpeted type '%s'.",
+ cause.getClass().getName(),
+ wrappedExceptionClass.getName()));
+ }
+
+ public void unwrapAndThrow() throws Throwable {
+ throw unwrap();
+ }
+
+ public void unwrapAndThrow(@NonNull Class wrappedExceptionClass) throws E {
+ throw unwrap(wrappedExceptionClass);
+ }
+ }
+
+ private ExceptionUtils() {
+ // prevent construction
+ }
+}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/MetapathExpressionTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/MetapathExpressionTest.java
index 89d31e20b..1ff709792 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/MetapathExpressionTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/MetapathExpressionTest.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.core.metapath;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -13,8 +14,12 @@
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem;
-import org.junit.jupiter.api.Disabled;
+import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvFileSource;
+
+import java.io.IOException;
import io.hosuaby.inject.resources.junit.jupiter.GivenTextResource;
import io.hosuaby.inject.resources.junit.jupiter.TestWithResources;
@@ -28,12 +33,16 @@ class MetapathExpressionTest {
// @GivenTextResource(from = "/incorrect-examples.txt", charset = "UTF-8")
// String incorrectMetapathInstances;
- @Test
- @Disabled
- void testCorrect() {
- for (String line : correctMetapathInstances.split("\\r?\\n")) {
- if (line.startsWith("# ")) {
- continue;
+ @ParameterizedTest
+ @CsvFileSource(resources = "/correct-examples.txt", delimiter = ';')
+ void testCorrect(String line) {
+ if (!line.startsWith("# ")
+ && !line.contains("text()")
+ && !line.contains("number(")
+ && !line.contains("current(")
+ && !line.contains("last(")) {
+ if (line.endsWith(";")) {
+ line = line.substring(0, line.length() - 1);
}
// System.out.println(line);
IMetapathExpression.compile(line);
@@ -74,10 +83,13 @@ void test() {
}
@Test
- void testMalformedIf() {
- StaticMetapathException ex = assertThrows(StaticMetapathException.class, () -> {
+ void testMalformedIf() throws IOException {
+ InvalidMetapathGrammarException thrown = assertThrows(InvalidMetapathGrammarException.class, () -> {
IMetapathExpression.compile("if 'a' = '1.1.2' then true() else false()");
});
- assertEquals(StaticMetapathException.INVALID_PATH_GRAMMAR, ex.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(InvalidMetapathGrammarException.class)
+ .cause()
+ .isExactlyInstanceOf(ParseCancellationException.class);
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/StaticContextTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/StaticContextTest.java
index f2d5e69ac..45b230abc 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/StaticContextTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/StaticContextTest.java
@@ -5,6 +5,7 @@
package gov.nist.secauto.metaschema.core.metapath;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -141,11 +142,12 @@ void testVariableValues(
@Test
void lookupNonExistantDataType() {
- StaticMetapathException ex = assertThrows(StaticMetapathException.class, () -> {
+ StaticMetapathException thrown = assertThrows(StaticMetapathException.class, () -> {
StaticContext.instance().lookupAtomicType("xs:string");
});
-
- assertEquals(StaticMetapathException.PREFIX_NOT_EXPANDABLE, ex.getCode());
+ assertThat(thrown)
+ .extracting(ex -> ex.getErrorCode().getCode())
+ .isEqualTo(StaticMetapathException.PREFIX_NOT_EXPANDABLE);
}
@Test
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/ArrowExpressionTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/ArrowExpressionTest.java
index dbd0a97b2..aa0e0dbad 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/ArrowExpressionTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/ArrowExpressionTest.java
@@ -7,19 +7,17 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.bool;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException;
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.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
-import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@@ -72,11 +70,15 @@ void testArrowExpressionWithUndefinedVariable() {
.build();
DynamicContext dynamicContext = new DynamicContext(staticContext);
- MetapathException ex = assertThrows(
- MetapathException.class,
+ StaticMetapathException thrown = assertThrows(StaticMetapathException.class,
() -> IMetapathExpression.compile("() => $ex:undefined()", staticContext)
.evaluate(null, dynamicContext));
- assertEquals(StaticMetapathException.NOT_DEFINED,
- ObjectUtils.requireNonNull((AbstractCodedMetapathException) ex.getCause()).getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(StaticMetapathException.class)
+ .extracting(
+ ex -> ex instanceof StaticMetapathException
+ ? ex.getErrorCode().getCode()
+ : null)
+ .isEqualTo(StaticMetapathException.NOT_DEFINED);
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCstVisitorTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCstVisitorTest.java
index e17699788..54c7a0b07 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCstVisitorTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCstVisitorTest.java
@@ -10,6 +10,7 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.eqname;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.contains;
@@ -26,7 +27,6 @@
import gov.nist.secauto.metaschema.core.metapath.IExpression;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.metapath.MetapathConstants;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException;
import gov.nist.secauto.metaschema.core.metapath.antlr.FailingErrorListener;
@@ -297,16 +297,16 @@ void testNamedFunctionRefNotFound(
StaticContext staticContext = StaticContext.builder().build();
DynamicContext dynamicContext = new DynamicContext(staticContext);
- MetapathException thrown = assertThrows(MetapathException.class,
+ StaticMetapathException thrown = assertThrows(StaticMetapathException.class,
() -> IMetapathExpression.compile(metapath, staticContext).evaluateAs(null,
IMetapathExpression.ResultType.ITEM, dynamicContext));
- Throwable cause = thrown.getCause();
-
- assertEquals(
- StaticMetapathException.NO_FUNCTION_MATCH,
- cause instanceof StaticMetapathException
- ? ((StaticMetapathException) cause).getCode()
- : null);
+ assertThat(thrown)
+ .isExactlyInstanceOf(StaticMetapathException.class)
+ .extracting(
+ ex -> ex instanceof StaticMetapathException
+ ? ex.getErrorCode().getCode()
+ : null)
+ .isEqualTo(StaticMetapathException.NO_FUNCTION_MATCH);
}
static Stream testNamedFunctionRefCall() {
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashOnlyPathTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashOnlyPathTest.java
index 2d54e8ab2..7d037855d 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashOnlyPathTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashOnlyPathTest.java
@@ -10,8 +10,8 @@
import static org.mockito.Mockito.doReturn;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
+import gov.nist.secauto.metaschema.core.metapath.InvalidTreatTypeDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
@@ -54,11 +54,10 @@ void testRootSlashOnlyPathUsingNonDocument() {
RootSlashOnlyPath expr = new RootSlashOnlyPath("test data");
DynamicContext dynamicContext = newDynamicContext();
- DynamicMetapathException thrown = assertThrows(DynamicMetapathException.class, () -> {
- ISequence> result = expr.accept(dynamicContext, ISequence.of(item));
- assertEquals(ISequence.of(item), result);
+ assertThrows(InvalidTreatTypeDynamicMetapathException.class, () -> {
+ expr.accept(dynamicContext, ISequence.of(item))
+ // ensure the stream is processed
+ .safeStream();
});
-
- assertEquals(DynamicMetapathException.TREAT_DOES_NOT_MATCH_TYPE, thrown.getCode());
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/type/CastTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/type/CastTest.java
index 05c872f4b..1f52242e5 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/type/CastTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/type/CastTest.java
@@ -13,11 +13,13 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.yearMonthDuration;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
+import gov.nist.secauto.metaschema.core.metapath.InvalidMetapathGrammarException;
import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
@@ -116,25 +118,46 @@ void testCast(@NonNull IAnyAtomicItem actual, @NonNull String singleType, @NonNu
@Test
void testInvalidTypePrefix() {
- StaticMetapathException ex = assertThrows(StaticMetapathException.class, () -> {
+ InvalidMetapathGrammarException thrown = assertThrows(InvalidMetapathGrammarException.class, () -> {
IMetapathExpression.compile("'a' cast as foo:bar");
});
- assertEquals(StaticMetapathException.PREFIX_NOT_EXPANDABLE, ex.getCode());
+ assertThat(thrown)
+ .cause()
+ .isExactlyInstanceOf(StaticMetapathException.class)
+ .extracting(
+ ex -> ex instanceof StaticMetapathException
+ ? ((StaticMetapathException) ex).getErrorCode().getCode()
+ : null)
+ .isEqualTo(StaticMetapathException.PREFIX_NOT_EXPANDABLE);
}
@Test
void testInvalidType() {
- StaticMetapathException ex = assertThrows(StaticMetapathException.class, () -> {
+ InvalidMetapathGrammarException thrown = assertThrows(InvalidMetapathGrammarException.class, () -> {
IMetapathExpression.compile("'a' cast as meta:bar");
});
- assertEquals(StaticMetapathException.CAST_UNKNOWN_TYPE, ex.getCode());
+ assertThat(thrown)
+ .cause()
+ .isExactlyInstanceOf(StaticMetapathException.class)
+ .extracting(
+ ex -> ex instanceof StaticMetapathException
+ ? ((StaticMetapathException) ex).getErrorCode().getCode()
+ : null)
+ .isEqualTo(StaticMetapathException.CAST_UNKNOWN_TYPE);
}
@Test
void testAnyAtomicType() {
- StaticMetapathException ex = assertThrows(StaticMetapathException.class, () -> {
+ InvalidMetapathGrammarException thrown = assertThrows(InvalidMetapathGrammarException.class, () -> {
IMetapathExpression.compile("'a' cast as meta:any-atomic-type");
});
- assertEquals(StaticMetapathException.CAST_ANY_ATOMIC, ex.getCode());
+ assertThat(thrown)
+ .cause()
+ .isExactlyInstanceOf(StaticMetapathException.class)
+ .extracting(
+ ex -> ex instanceof StaticMetapathException
+ ? ((StaticMetapathException) ex).getErrorCode().getCode()
+ : null)
+ .isEqualTo(StaticMetapathException.CAST_ANY_ATOMIC);
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/type/CastableTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/type/CastableTest.java
index 5a774a4c4..daaf31326 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/type/CastableTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/type/CastableTest.java
@@ -5,12 +5,13 @@
package gov.nist.secauto.metaschema.core.metapath.cst.type;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
+import gov.nist.secauto.metaschema.core.metapath.InvalidMetapathGrammarException;
import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
@@ -48,25 +49,46 @@ void testCastable(@NonNull IAnyAtomicItem actual, @NonNull String singleType) {
@Test
void testInvalidTypePrefix() {
- StaticMetapathException ex = assertThrows(StaticMetapathException.class, () -> {
+ InvalidMetapathGrammarException thrown = assertThrows(InvalidMetapathGrammarException.class, () -> {
IMetapathExpression.compile("'a' castable as foo:bar");
});
- assertEquals(StaticMetapathException.PREFIX_NOT_EXPANDABLE, ex.getCode());
+ assertThat(thrown)
+ .cause()
+ .isExactlyInstanceOf(StaticMetapathException.class)
+ .extracting(
+ ex -> ex instanceof StaticMetapathException
+ ? ((StaticMetapathException) ex).getErrorCode().getCode()
+ : null)
+ .isEqualTo(StaticMetapathException.PREFIX_NOT_EXPANDABLE);
}
@Test
void testInvalidType() {
- StaticMetapathException ex = assertThrows(StaticMetapathException.class, () -> {
+ InvalidMetapathGrammarException thrown = assertThrows(InvalidMetapathGrammarException.class, () -> {
IMetapathExpression.compile("'a' castable as meta:bar");
});
- assertEquals(StaticMetapathException.CAST_UNKNOWN_TYPE, ex.getCode());
+ assertThat(thrown)
+ .cause()
+ .isExactlyInstanceOf(StaticMetapathException.class)
+ .extracting(
+ ex -> ex instanceof StaticMetapathException
+ ? ((StaticMetapathException) ex).getErrorCode().getCode()
+ : null)
+ .isEqualTo(StaticMetapathException.CAST_UNKNOWN_TYPE);
}
@Test
void testAnyAtomicType() {
- StaticMetapathException ex = assertThrows(StaticMetapathException.class, () -> {
+ InvalidMetapathGrammarException thrown = assertThrows(InvalidMetapathGrammarException.class, () -> {
IMetapathExpression.compile("'a' castable as meta:any-atomic-type");
});
- assertEquals(StaticMetapathException.CAST_ANY_ATOMIC, ex.getCode());
+ assertThat(thrown)
+ .cause()
+ .isExactlyInstanceOf(StaticMetapathException.class)
+ .extracting(
+ ex -> ex instanceof StaticMetapathException
+ ? ((StaticMetapathException) ex).getErrorCode().getCode()
+ : null)
+ .isEqualTo(StaticMetapathException.CAST_ANY_ATOMIC);
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/impl/OperationFunctionsTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/impl/OperationFunctionsTest.java
index fd8e1d943..310217cdf 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/impl/OperationFunctionsTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/impl/OperationFunctionsTest.java
@@ -14,12 +14,15 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.time;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.yearMonthDuration;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.from;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
import gov.nist.secauto.metaschema.core.metapath.function.ArithmeticFunctionException;
+import gov.nist.secauto.metaschema.core.metapath.function.CastFunctionException;
import gov.nist.secauto.metaschema.core.metapath.function.DateTimeFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDateItem;
@@ -147,7 +150,12 @@ void testOpNumericDivideByZero(
ArithmeticFunctionException thrown = assertThrows(ArithmeticFunctionException.class, () -> {
OperationFunctions.opNumericDivide(dividend, divisor);
});
- assertEquals(ArithmeticFunctionException.DIVISION_BY_ZERO, thrown.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(ArithmeticFunctionException.class)
+ .returns(
+ ArithmeticFunctionException.DIVISION_BY_ZERO,
+ from(ex -> ex.getErrorCode().getCode()))
+ .hasNoCause();
}
}
@@ -193,7 +201,12 @@ void testOpNumericIntegerDivideByZero(
ArithmeticFunctionException thrown = assertThrows(ArithmeticFunctionException.class, () -> {
OperationFunctions.opNumericIntegerDivide(dividend, divisor);
});
- assertEquals(ArithmeticFunctionException.DIVISION_BY_ZERO, thrown.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(ArithmeticFunctionException.class)
+ .returns(
+ ArithmeticFunctionException.DIVISION_BY_ZERO,
+ from(ex -> ex.getErrorCode().getCode()))
+ .hasNoCause();
}
}
@@ -465,7 +478,13 @@ void testOpAddYearMonthDurationsOverflow() {
IYearMonthDurationItem.valueOf("P" + Integer.MAX_VALUE + "Y"),
IYearMonthDurationItem.valueOf("P" + Integer.MAX_VALUE + "Y"));
});
- assertEquals(DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR, thrown.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(DateTimeFunctionException.class)
+ .returns(
+ DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR,
+ from(ex -> ex.getErrorCode().getCode()))
+ .cause()
+ .isExactlyInstanceOf(ArithmeticException.class);
}
@Test
@@ -486,7 +505,13 @@ void testOpSubtractYearMonthDurationsOverflow() {
IYearMonthDurationItem.valueOf("-P" + Integer.MAX_VALUE + "Y"),
IYearMonthDurationItem.valueOf("P" + Integer.MAX_VALUE + "Y"));
});
- assertEquals(DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR, thrown.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(DateTimeFunctionException.class)
+ .returns(
+ DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR,
+ from(ex -> ex.getErrorCode().getCode()))
+ .cause()
+ .isExactlyInstanceOf(ArithmeticException.class);
}
@Test
@@ -518,7 +543,18 @@ void testOpMultiplyYearMonthDurationsOverflow() {
IYearMonthDurationItem.valueOf("P" + Integer.MAX_VALUE + "Y"),
IDecimalItem.valueOf("2.5"));
});
- assertEquals(DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR, thrown.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(DateTimeFunctionException.class)
+ .returns(
+ DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR,
+ from(ex -> ex.getErrorCode().getCode()))
+ .cause()
+ .isExactlyInstanceOf(CastFunctionException.class)
+ .returns(
+ CastFunctionException.INPUT_VALUE_TOO_LARGE,
+ from(ex -> ex instanceof CastFunctionException
+ ? ((CastFunctionException) ex).getErrorCode().getCode()
+ : null));
}
@Test
@@ -564,7 +600,12 @@ void testOpAddDayTimeDurationsOverflow() {
IDayTimeDurationItem.valueOf("PT" + (Long.MAX_VALUE - 807) + "S"),
IDayTimeDurationItem.valueOf("PT" + (Long.MAX_VALUE - 807) + "S"));
});
- assertEquals(DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR, thrown.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(DateTimeFunctionException.class)
+ .hasCauseExactlyInstanceOf(ArithmeticException.class)
+ .returns(
+ DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR,
+ from(ex -> ex.getErrorCode().getCode()));
}
@Test
@@ -585,7 +626,12 @@ void testOpSubtractDayTimeDurationsOverflow() {
IDayTimeDurationItem.valueOf("-PT" + (Long.MAX_VALUE - 807) + "S"),
IDayTimeDurationItem.valueOf("PT" + (Long.MAX_VALUE - 807) + "S"));
});
- assertEquals(DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR, thrown.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(DateTimeFunctionException.class)
+ .hasCauseExactlyInstanceOf(ArithmeticException.class)
+ .returns(
+ DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR,
+ from(ex -> ex.getErrorCode().getCode()));
}
@Test
@@ -606,7 +652,18 @@ void testOpMultiplyDayTimeDurationsOverflow() {
IDayTimeDurationItem.valueOf("PT" + Long.MAX_VALUE / 2 + "S"),
IDecimalItem.valueOf("5"));
});
- assertEquals(DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR, thrown.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(DateTimeFunctionException.class)
+ .returns(
+ DateTimeFunctionException.DURATION_OVERFLOW_UNDERFLOW_ERROR,
+ from(ex -> ex.getErrorCode().getCode()))
+ .cause()
+ .isExactlyInstanceOf(CastFunctionException.class)
+ .returns(
+ CastFunctionException.INPUT_VALUE_TOO_LARGE,
+ from(ex -> ex instanceof CastFunctionException
+ ? ((CastFunctionException) ex).getErrorCode().getCode()
+ : null));
}
@Test
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAvgTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAvgTest.java
index d36ab830d..c6a651b8f 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAvgTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAvgTest.java
@@ -10,10 +10,8 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.yearMonthDuration;
-import static org.junit.jupiter.api.Assertions.assertAll;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertThrows;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidArgumentFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
@@ -26,6 +24,7 @@
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
+import java.util.List;
import java.util.stream.Stream;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -52,18 +51,20 @@ private static Stream provideValuesForAvg() {
@ParameterizedTest
@MethodSource("provideValuesForAvg")
void testAvg(@Nullable IAnyAtomicItem expected, @NonNull IAnyAtomicItem... values) {
- try {
+ List> arguments = CollectionUtil.singletonList(ISequence.of(values));
+ if (expected == null) {
+ assertThrows(InvalidArgumentFunctionException.class, () -> {
+ FunctionTestBase.executeFunction(
+ FnAvg.SIGNATURE,
+ newDynamicContext(),
+ null,
+ arguments);
+ });
+ } else {
assertFunctionResult(
FnAvg.SIGNATURE,
ISequence.of(expected),
- CollectionUtil.singletonList(ISequence.of(values)));
- } catch (MetapathException ex) {
- if (expected == null) {
- assertAll(
- () -> assertInstanceOf(InvalidArgumentFunctionException.class, ex.getCause()));
- } else {
- throw ex;
- }
+ arguments);
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBooleanTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBooleanTest.java
index f41de971f..9f9021b7a 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBooleanTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBooleanTest.java
@@ -10,11 +10,8 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.uri;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.yearMonthDuration;
-import static org.junit.jupiter.api.Assertions.assertAll;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
-import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidArgumentFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
@@ -29,6 +26,7 @@
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
+import java.util.List;
import java.util.stream.Stream;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -55,15 +53,20 @@ static Stream provideValues() {
@ParameterizedTest
@MethodSource("provideValues")
void test(@Nullable IBooleanItem expected, @NonNull IItem... values) {
- try {
+ List> arguments = CollectionUtil.singletonList(ISequence.of(values));
+ if (expected == null) {
+ assertThrows(InvalidArgumentFunctionException.class, () -> {
+ FunctionTestBase.executeFunction(
+ FnBoolean.SIGNATURE,
+ newDynamicContext(),
+ null,
+ arguments);
+ });
+ } else {
assertFunctionResult(
FnBoolean.SIGNATURE,
ISequence.of(expected),
- CollectionUtil.singletonList(ISequence.of(values)));
- } catch (MetapathException ex) {
- assertAll(
- () -> assertNull(expected),
- () -> assertInstanceOf(InvalidArgumentFunctionException.class, ex.getCause()));
+ arguments);
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnExactlyOneTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnExactlyOneTest.java
index 8b85cb303..4c7418819 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnExactlyOneTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnExactlyOneTest.java
@@ -7,13 +7,12 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.sequence;
-import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidArgumentFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
@@ -47,20 +46,15 @@ private static Stream provideValues() { // NOPMD - false positive
@ParameterizedTest
@MethodSource("provideValues")
void test(@Nullable ISequence> expected, @NonNull String metapath) {
- try {
+ if (expected == null) {
+ InvalidArgumentFunctionException thrown = assertThrows(InvalidArgumentFunctionException.class, () -> {
+ IMetapathExpression.compile(metapath).evaluate(null, newDynamicContext());
+ });
+ assertThat(thrown).extracting(ex -> ex.getErrorCode().getCode())
+ .isEqualTo(InvalidArgumentFunctionException.INVALID_ARGUMENT_EXACTLY_ONE);
+ } else {
assertEquals(expected, IMetapathExpression.compile(metapath)
.evaluate(null, newDynamicContext()));
- } catch (MetapathException ex) {
- // FIXME: After refactoring the exception hierarchy, target the actual exception
- Throwable cause = ex.getCause() == null ? ex.getCause() : ex.getCause().getCause();
- assertAll(
- () -> assertNull(expected),
- () -> assertEquals(InvalidArgumentFunctionException.class, cause.getClass()),
- () -> assertEquals(
- InvalidArgumentFunctionException.INVALID_ARGUMENT_EXACTLY_ONE,
- cause instanceof InvalidArgumentFunctionException
- ? ((InvalidArgumentFunctionException) cause).getCode()
- : null));
}
}
}
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 9aaf85dd4..7aeb67a0f 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
@@ -5,19 +5,16 @@
package gov.nist.secauto.metaschema.core.metapath.function.library;
-import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import gov.nist.secauto.metaschema.core.metapath.ContextAbsentDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
import gov.nist.secauto.metaschema.core.metapath.type.InvalidTypeMetapathException;
-import gov.nist.secauto.metaschema.core.metapath.type.TypeMetapathException;
import gov.nist.secauto.metaschema.core.testing.model.mocking.MockedDocumentGenerator;
import org.junit.jupiter.api.Test;
@@ -72,37 +69,19 @@ void test(boolean expected, @NonNull String metapath) {
void testContextAbsent() {
DynamicContext dynamicContext = newDynamicContext();
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(ContextAbsentDynamicMetapathException.class, () -> {
IMetapathExpression.compile("has-children()", dynamicContext.getStaticContext())
.evaluateAs(null, IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(DynamicMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(DynamicMetapathException.DYNAMIC_CONTEXT_ABSENT, cause instanceof DynamicMetapathException
- ? ((DynamicMetapathException) cause).getCode()
- : null));
}
@Test
void testNotANode() {
DynamicContext dynamicContext = newDynamicContext();
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(InvalidTypeMetapathException.class, () -> {
IMetapathExpression.compile("has-children()", dynamicContext.getStaticContext())
.evaluateAs(IStringItem.valueOf("test"), IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(InvalidTypeMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(TypeMetapathException.INVALID_TYPE_ERROR, cause instanceof TypeMetapathException
- ? ((TypeMetapathException) cause).getCode()
- : null));
}
}
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 04c697714..ae3d85b25 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
@@ -6,19 +6,16 @@
package gov.nist.secauto.metaschema.core.metapath.function.library;
-import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
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.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
import gov.nist.secauto.metaschema.core.metapath.type.InvalidTypeMetapathException;
-import gov.nist.secauto.metaschema.core.metapath.type.TypeMetapathException;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.testing.model.mocking.MockedDocumentGenerator;
@@ -77,19 +74,9 @@ void test(@NonNull String expectedValueMetapath, @NonNull String actualValuesMet
@Test
void testNotANode() {
DynamicContext dynamicContext = newDynamicContext();
-
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(InvalidTypeMetapathException.class, () -> {
IMetapathExpression.compile("innermost('test')", dynamicContext.getStaticContext())
.evaluateAs(IStringItem.valueOf("test"), IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(InvalidTypeMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(TypeMetapathException.INVALID_TYPE_ERROR, cause instanceof TypeMetapathException
- ? ((TypeMetapathException) cause).getCode()
- : null));
}
}
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 a5d75bba5..355fef05a 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
@@ -5,19 +5,16 @@
package gov.nist.secauto.metaschema.core.metapath.function.library;
-import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import gov.nist.secauto.metaschema.core.metapath.ContextAbsentDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.type.InvalidTypeMetapathException;
-import gov.nist.secauto.metaschema.core.metapath.type.TypeMetapathException;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.testing.model.mocking.MockedDocumentGenerator;
@@ -81,37 +78,19 @@ void test(@Nullable IEnhancedQName expected, @NonNull String metapath) {
void testContextAbsent() {
DynamicContext dynamicContext = newDynamicContext();
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(ContextAbsentDynamicMetapathException.class, () -> {
IMetapathExpression.compile("local-name()", dynamicContext.getStaticContext())
.evaluateAs(null, IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(DynamicMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(DynamicMetapathException.DYNAMIC_CONTEXT_ABSENT, cause instanceof DynamicMetapathException
- ? ((DynamicMetapathException) cause).getCode()
- : null));
}
@Test
void testNotANode() {
DynamicContext dynamicContext = newDynamicContext();
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(InvalidTypeMetapathException.class, () -> {
IMetapathExpression.compile("local-name()", dynamicContext.getStaticContext())
.evaluateAs(IStringItem.valueOf("test"), IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(InvalidTypeMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(TypeMetapathException.INVALID_TYPE_ERROR, cause instanceof TypeMetapathException
- ? ((TypeMetapathException) cause).getCode()
- : null));
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMatchesTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMatchesTest.java
index 18f40ab92..321fd1f80 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMatchesTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMatchesTest.java
@@ -8,13 +8,14 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.bool;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.sequence;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.from;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
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.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.regex.RegularExpressionMetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem;
@@ -28,6 +29,7 @@
import org.junit.jupiter.params.provider.MethodSource;
import java.util.List;
+import java.util.regex.PatternSyntaxException;
import java.util.stream.Stream;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -78,46 +80,41 @@ void test(@NonNull IBooleanItem expected, @NonNull String metapath) {
@Test
void testInvalidPattern() {
- RegularExpressionMetapathException throwable = assertThrows(RegularExpressionMetapathException.class,
+ RegularExpressionMetapathException thrown = assertThrows(RegularExpressionMetapathException.class,
() -> {
- try {
- FunctionTestBase.executeFunction(
- FnMatches.SIGNATURE_TWO_ARG,
- newDynamicContext(),
- ISequence.empty(),
- ObjectUtils.notNull(List.of(sequence(string("input")), sequence(string("pattern[")))));
- } catch (MetapathException ex) {
- Throwable cause = ex.getCause();
- if (cause != null) {
- throw cause;
- }
- throw ex;
- }
+ FunctionTestBase.executeFunction(
+ FnMatches.SIGNATURE_TWO_ARG,
+ newDynamicContext(),
+ ISequence.empty(),
+ ObjectUtils.notNull(List.of(sequence(string("input")), sequence(string("pattern[")))));
});
- assertEquals(RegularExpressionMetapathException.INVALID_EXPRESSION, throwable.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(RegularExpressionMetapathException.class)
+ .hasCauseExactlyInstanceOf(PatternSyntaxException.class)
+ .returns(
+ RegularExpressionMetapathException.INVALID_EXPRESSION,
+ from(ex -> ex.getErrorCode().getCode()));
+
}
@Test
void testInvalidFlag() {
- RegularExpressionMetapathException throwable = assertThrows(RegularExpressionMetapathException.class,
+ RegularExpressionMetapathException thrown = assertThrows(RegularExpressionMetapathException.class,
() -> {
- try {
- FunctionTestBase.executeFunction(
- FnMatches.SIGNATURE_THREE_ARG,
- newDynamicContext(),
- ISequence.empty(),
- ObjectUtils.notNull(List.of(
- sequence(string("input")),
- sequence(string("pattern")),
- sequence(string("dsm")))));
- } catch (MetapathException ex) {
- Throwable cause = ex.getCause();
- if (cause != null) {
- throw cause;
- }
- throw ex;
- }
+ FunctionTestBase.executeFunction(
+ FnMatches.SIGNATURE_THREE_ARG,
+ newDynamicContext(),
+ ISequence.empty(),
+ ObjectUtils.notNull(List.of(
+ sequence(string("input")),
+ sequence(string("pattern")),
+ sequence(string("dsm")))));
});
- assertEquals(RegularExpressionMetapathException.INVALID_FLAG, throwable.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(RegularExpressionMetapathException.class)
+ .hasNoCause()
+ .returns(
+ RegularExpressionMetapathException.INVALID_FLAG,
+ from(ex -> ex.getErrorCode().getCode()));
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMinMaxTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMinMaxTest.java
index 7726b9ff8..0b325e4a8 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMinMaxTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMinMaxTest.java
@@ -9,10 +9,8 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.uri;
-import static org.junit.jupiter.api.Assertions.assertAll;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertThrows;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidArgumentFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
@@ -23,6 +21,7 @@
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
+import java.util.List;
import java.util.stream.Stream;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -46,18 +45,20 @@ private static Stream provideValuesMin() {
@ParameterizedTest
@MethodSource("provideValuesMin")
void testMin(@Nullable IAnyAtomicItem expected, @NonNull IAnyAtomicItem... values) {
- try {
+ List> arguments = CollectionUtil.singletonList(ISequence.of(values));
+ if (expected == null) {
+ assertThrows(InvalidArgumentFunctionException.class, () -> {
+ FunctionTestBase.executeFunction(
+ FnMinMax.SIGNATURE_MIN,
+ newDynamicContext(),
+ null,
+ arguments);
+ });
+ } else {
assertFunctionResult(
FnMinMax.SIGNATURE_MIN,
ISequence.of(expected),
- CollectionUtil.singletonList(ISequence.of(values)));
- } catch (MetapathException ex) {
- if (expected == null) {
- assertAll(
- () -> assertInstanceOf(InvalidArgumentFunctionException.class, ex.getCause()));
- } else {
- throw ex;
- }
+ arguments);
}
}
@@ -84,18 +85,20 @@ private static Stream provideValuesMax() {
@ParameterizedTest
@MethodSource("provideValuesMax")
void testMax(@Nullable IAnyAtomicItem expected, @NonNull IAnyAtomicItem... values) {
- try {
+ List> arguments = CollectionUtil.singletonList(ISequence.of(values));
+ if (expected == null) {
+ assertThrows(InvalidArgumentFunctionException.class, () -> {
+ FunctionTestBase.executeFunction(
+ FnMinMax.SIGNATURE_MAX,
+ newDynamicContext(),
+ null,
+ arguments);
+ });
+ } else {
assertFunctionResult(
FnMinMax.SIGNATURE_MAX,
ISequence.of(expected),
CollectionUtil.singletonList(ISequence.of(values)));
- } catch (MetapathException ex) {
- if (expected == null) {
- assertAll(
- () -> assertInstanceOf(InvalidArgumentFunctionException.class, ex.getCause()));
- } else {
- throw ex;
- }
}
}
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 5ae111f4b..27a309930 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
@@ -5,19 +5,16 @@
package gov.nist.secauto.metaschema.core.metapath.function.library;
-import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import gov.nist.secauto.metaschema.core.metapath.ContextAbsentDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.type.InvalidTypeMetapathException;
-import gov.nist.secauto.metaschema.core.metapath.type.TypeMetapathException;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.testing.model.mocking.MockedDocumentGenerator;
@@ -80,37 +77,19 @@ void test(@Nullable IEnhancedQName expected, @NonNull String metapath) {
void testContextAbsent() {
DynamicContext dynamicContext = newDynamicContext();
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(ContextAbsentDynamicMetapathException.class, () -> {
IMetapathExpression.compile("name()", dynamicContext.getStaticContext())
.evaluateAs(null, IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(DynamicMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(DynamicMetapathException.DYNAMIC_CONTEXT_ABSENT, cause instanceof DynamicMetapathException
- ? ((DynamicMetapathException) cause).getCode()
- : null));
}
@Test
void testNotANode() {
DynamicContext dynamicContext = newDynamicContext();
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(InvalidTypeMetapathException.class, () -> {
IMetapathExpression.compile("name()", dynamicContext.getStaticContext())
.evaluateAs(IStringItem.valueOf("test"), IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(InvalidTypeMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(TypeMetapathException.INVALID_TYPE_ERROR, cause instanceof TypeMetapathException
- ? ((TypeMetapathException) cause).getCode()
- : null));
}
}
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 d5f96ea88..d06da856c 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
@@ -5,19 +5,16 @@
package gov.nist.secauto.metaschema.core.metapath.function.library;
-import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import gov.nist.secauto.metaschema.core.metapath.ContextAbsentDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.type.InvalidTypeMetapathException;
-import gov.nist.secauto.metaschema.core.metapath.type.TypeMetapathException;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.testing.model.mocking.MockedDocumentGenerator;
@@ -81,37 +78,19 @@ void test(@Nullable IEnhancedQName expected, @NonNull String metapath) {
void testContextAbsent() {
DynamicContext dynamicContext = newDynamicContext();
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(ContextAbsentDynamicMetapathException.class, () -> {
IMetapathExpression.compile("namespace-uri()", dynamicContext.getStaticContext())
.evaluateAs(null, IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(DynamicMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(DynamicMetapathException.DYNAMIC_CONTEXT_ABSENT, cause instanceof DynamicMetapathException
- ? ((DynamicMetapathException) cause).getCode()
- : null));
}
@Test
void testNotANode() {
DynamicContext dynamicContext = newDynamicContext();
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(InvalidTypeMetapathException.class, () -> {
IMetapathExpression.compile("namespace-uri()", dynamicContext.getStaticContext())
.evaluateAs(IStringItem.valueOf("test"), IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(InvalidTypeMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(TypeMetapathException.INVALID_TYPE_ERROR, cause instanceof TypeMetapathException
- ? ((TypeMetapathException) cause).getCode()
- : null));
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNormalizeSpaceTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNormalizeSpaceTest.java
index 25dbe5214..f4875349b 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNormalizeSpaceTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNormalizeSpaceTest.java
@@ -10,10 +10,9 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.ContextAbsentDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
@@ -46,18 +45,13 @@ void testExpression(@NonNull IStringItem expected, @NonNull String metapath) {
@Test
void testNoFocus() {
- DynamicMetapathException throwable = assertThrows(DynamicMetapathException.class,
+ assertThrows(ContextAbsentDynamicMetapathException.class,
() -> {
- try {
- FunctionTestBase.executeFunction(
- FnNormalizeSpace.SIGNATURE_NO_ARG,
- newDynamicContext(),
- null,
- CollectionUtil.singletonList(sequence()));
- } catch (MetapathException ex) {
- throw ex.getCause();
- }
+ FunctionTestBase.executeFunction(
+ FnNormalizeSpace.SIGNATURE_NO_ARG,
+ newDynamicContext(),
+ null,
+ CollectionUtil.singletonList(sequence()));
});
- assertEquals(DynamicMetapathException.DYNAMIC_CONTEXT_ABSENT, throwable.getCode());
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNotTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNotTest.java
index 848b09dfb..278282ae0 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNotTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNotTest.java
@@ -10,11 +10,8 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.uri;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.yearMonthDuration;
-import static org.junit.jupiter.api.Assertions.assertAll;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
-import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidArgumentFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
@@ -29,6 +26,7 @@
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
+import java.util.List;
import java.util.stream.Stream;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -55,15 +53,20 @@ static Stream provideValues() {
@ParameterizedTest
@MethodSource("provideValues")
void test(@Nullable IBooleanItem expected, @NonNull IItem... values) {
- try {
+ List> arguments = CollectionUtil.singletonList(ISequence.of(values));
+ if (expected == null) {
+ assertThrows(InvalidArgumentFunctionException.class, () -> {
+ FunctionTestBase.executeFunction(
+ FnNot.SIGNATURE,
+ newDynamicContext(),
+ null,
+ arguments);
+ });
+ } else {
assertFunctionResult(
FnNot.SIGNATURE,
ISequence.of(expected),
- CollectionUtil.singletonList(ISequence.of(values)));
- } catch (MetapathException ex) {
- assertAll(
- () -> assertNull(expected),
- () -> assertInstanceOf(InvalidArgumentFunctionException.class, ex.getCause()));
+ arguments);
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOneOrMoreTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOneOrMoreTest.java
index 016f0cf5a..eaf8ad00d 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOneOrMoreTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnOneOrMoreTest.java
@@ -7,13 +7,12 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.sequence;
-import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidArgumentFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
@@ -47,20 +46,15 @@ private static Stream provideValues() { // NOPMD - false positive
@ParameterizedTest
@MethodSource("provideValues")
void test(@Nullable ISequence> expected, @NonNull String metapath) {
- try {
+ if (expected == null) {
+ InvalidArgumentFunctionException thrown = assertThrows(InvalidArgumentFunctionException.class, () -> {
+ IMetapathExpression.compile(metapath).evaluate(null, newDynamicContext());
+ });
+ assertThat(thrown).extracting(ex -> ex.getErrorCode().getCode())
+ .isEqualTo(InvalidArgumentFunctionException.INVALID_ARGUMENT_ONE_OR_MORE);
+ } else {
assertEquals(expected, IMetapathExpression.compile(metapath)
.evaluate(null, newDynamicContext()));
- } catch (MetapathException ex) {
- // FIXME: After refactoring the exception hierarchy, target the actual exception
- Throwable cause = ex.getCause() == null ? ex.getCause() : ex.getCause().getCause();
- assertAll(
- () -> assertNull(expected),
- () -> assertEquals(InvalidArgumentFunctionException.class, cause == null ? null : cause.getClass()),
- () -> assertEquals(
- InvalidArgumentFunctionException.INVALID_ARGUMENT_ONE_OR_MORE,
- cause instanceof InvalidArgumentFunctionException
- ? ((InvalidArgumentFunctionException) cause).getCode()
- : null));
}
}
}
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 9b0695044..b44cd65aa 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
@@ -6,19 +6,16 @@
package gov.nist.secauto.metaschema.core.metapath.function.library;
-import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
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.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
import gov.nist.secauto.metaschema.core.metapath.type.InvalidTypeMetapathException;
-import gov.nist.secauto.metaschema.core.metapath.type.TypeMetapathException;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.testing.model.mocking.MockedDocumentGenerator;
@@ -89,18 +86,9 @@ void test(@NonNull String expectedValueMetapath, @NonNull String actualValuesMet
void testNotANode() {
DynamicContext dynamicContext = newDynamicContext();
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(InvalidTypeMetapathException.class, () -> {
IMetapathExpression.compile("outermost('test')", dynamicContext.getStaticContext())
.evaluateAs(IStringItem.valueOf("test"), IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(InvalidTypeMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(TypeMetapathException.INVALID_TYPE_ERROR, cause instanceof TypeMetapathException
- ? ((TypeMetapathException) cause).getCode()
- : null));
}
}
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 9013d6795..c8fcccb6c 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
@@ -5,19 +5,16 @@
package gov.nist.secauto.metaschema.core.metapath.function.library;
-import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import gov.nist.secauto.metaschema.core.metapath.ContextAbsentDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
import gov.nist.secauto.metaschema.core.metapath.type.InvalidTypeMetapathException;
-import gov.nist.secauto.metaschema.core.metapath.type.TypeMetapathException;
import gov.nist.secauto.metaschema.core.testing.model.mocking.MockedDocumentGenerator;
import org.junit.jupiter.api.Test;
@@ -69,37 +66,19 @@ void test(@NonNull String metapath) {
void testContextAbsent() {
DynamicContext dynamicContext = newDynamicContext();
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(ContextAbsentDynamicMetapathException.class, () -> {
IMetapathExpression.compile("root()", dynamicContext.getStaticContext())
.evaluateAs(null, IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(DynamicMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(DynamicMetapathException.DYNAMIC_CONTEXT_ABSENT, cause instanceof DynamicMetapathException
- ? ((DynamicMetapathException) cause).getCode()
- : null));
}
@Test
void testNotANode() {
DynamicContext dynamicContext = newDynamicContext();
- MetapathException ex = assertThrows(MetapathException.class, () -> {
+ assertThrows(InvalidTypeMetapathException.class, () -> {
IMetapathExpression.compile("root()", dynamicContext.getStaticContext())
.evaluateAs(IStringItem.valueOf("test"), IMetapathExpression.ResultType.ITEM, dynamicContext);
});
- Throwable cause = ex.getCause() != null ? ex.getCause().getCause() : null;
-
- assertAll(
- () -> assertEquals(InvalidTypeMetapathException.class, cause == null
- ? null
- : cause.getClass()),
- () -> assertEquals(TypeMetapathException.INVALID_TYPE_ERROR, cause instanceof TypeMetapathException
- ? ((TypeMetapathException) cause).getCode()
- : null));
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStringLengthTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStringLengthTest.java
index 70dace849..39c2f30ae 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStringLengthTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStringLengthTest.java
@@ -10,10 +10,9 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.ContextAbsentDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
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.atomic.IIntegerItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
@@ -61,18 +60,13 @@ void testFocusStringTest() {
@Test
void testNoFocus() {
- DynamicMetapathException throwable = assertThrows(DynamicMetapathException.class,
+ assertThrows(ContextAbsentDynamicMetapathException.class,
() -> {
- try {
- FunctionTestBase.executeFunction(
- FnStringLength.SIGNATURE_NO_ARG,
- newDynamicContext(),
- null,
- CollectionUtil.singletonList(sequence()));
- } catch (MetapathException ex) {
- throw ex.getCause();
- }
+ FunctionTestBase.executeFunction(
+ FnStringLength.SIGNATURE_NO_ARG,
+ newDynamicContext(),
+ null,
+ CollectionUtil.singletonList(sequence()));
});
- assertEquals(DynamicMetapathException.DYNAMIC_CONTEXT_ABSENT, throwable.getCode());
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStringTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStringTest.java
index 35fbd51c9..9c4956e78 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStringTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStringTest.java
@@ -9,13 +9,13 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.sequence;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException;
+import gov.nist.secauto.metaschema.core.metapath.ContextAbsentDynamicMetapathException;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidTypeFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
@@ -58,34 +58,25 @@ void testExpression(@NonNull IStringItem expected, @NonNull String metapath) {
@Test
void testNoFocus() {
- DynamicMetapathException throwable = assertThrows(DynamicMetapathException.class,
+ assertThrows(ContextAbsentDynamicMetapathException.class,
() -> {
- try {
- FunctionTestBase.executeFunction(
- FnString.SIGNATURE_NO_ARG,
- newDynamicContext(),
- null,
- CollectionUtil.singletonList(sequence()));
- } catch (MetapathException ex) {
- throw ex.getCause();
- }
+ FunctionTestBase.executeFunction(
+ FnString.SIGNATURE_NO_ARG,
+ newDynamicContext(),
+ null,
+ CollectionUtil.singletonList(sequence()));
});
- assertEquals(DynamicMetapathException.DYNAMIC_CONTEXT_ABSENT, throwable.getCode());
}
@Test
void testInvalidArgument() {
assertThrows(InvalidTypeMetapathException.class,
() -> {
- try {
- FunctionTestBase.executeFunction(
- FnString.SIGNATURE_ONE_ARG,
- newDynamicContext(),
- ISequence.empty(),
- ObjectUtils.notNull(List.of(sequence(integer(1), integer(2)))));
- } catch (MetapathException ex) {
- throw ex.getCause();
- }
+ FunctionTestBase.executeFunction(
+ FnString.SIGNATURE_ONE_ARG,
+ newDynamicContext(),
+ ISequence.empty(),
+ ObjectUtils.notNull(List.of(sequence(integer(1), integer(2)))));
});
}
@@ -93,20 +84,18 @@ void testInvalidArgument() {
void testInvalidArgumentType() {
InvalidTypeFunctionException throwable = assertThrows(InvalidTypeFunctionException.class,
() -> {
- try {
- FunctionTestBase.executeFunction(
- FnString.SIGNATURE_ONE_ARG,
- newDynamicContext(),
- ISequence.empty(),
- ObjectUtils.notNull(List.of(
- sequence(
- array(
- array(integer(1), integer(2)),
- array(integer(3), integer(4)))))));
- } catch (MetapathException ex) {
- throw ex.getCause();
- }
+ FunctionTestBase.executeFunction(
+ FnString.SIGNATURE_ONE_ARG,
+ newDynamicContext(),
+ ISequence.empty(),
+ ObjectUtils.notNull(List.of(
+ sequence(
+ array(
+ array(integer(1), integer(2)),
+ array(integer(3), integer(4)))))));
});
- assertEquals(InvalidTypeFunctionException.ARGUMENT_TO_STRING_IS_FUNCTION, throwable.getCode());
+ assertThat(throwable)
+ .extracting(ex -> ex.getErrorCode().getCode())
+ .isEqualTo(InvalidTypeFunctionException.ARGUMENT_TO_STRING_IS_FUNCTION);
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnSumTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnSumTest.java
index 2e7c317c3..fd353a3a7 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnSumTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnSumTest.java
@@ -9,10 +9,8 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.yearMonthDuration;
-import static org.junit.jupiter.api.Assertions.assertAll;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertThrows;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidArgumentFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
@@ -53,19 +51,21 @@ private static Stream provideValuesOneArg() {
@ParameterizedTest
@MethodSource("provideValuesOneArg")
- void testAvg(@Nullable IAnyAtomicItem expected, @NonNull IAnyAtomicItem... values) {
- try {
+ void testSum(@Nullable IAnyAtomicItem expected, @NonNull IAnyAtomicItem... values) {
+ List> arguments = CollectionUtil.singletonList(ISequence.of(values));
+ if (expected == null) {
+ assertThrows(InvalidArgumentFunctionException.class, () -> {
+ FunctionTestBase.executeFunction(
+ FnSum.SIGNATURE_ONE_ARG,
+ newDynamicContext(),
+ null,
+ arguments);
+ });
+ } else {
assertFunctionResult(
FnSum.SIGNATURE_ONE_ARG,
ISequence.of(expected),
- CollectionUtil.singletonList(ISequence.of(values)));
- } catch (MetapathException ex) {
- if (expected == null) {
- assertAll(
- () -> assertInstanceOf(InvalidArgumentFunctionException.class, ex.getCause()));
- } else {
- throw ex;
- }
+ arguments);
}
}
@@ -84,25 +84,27 @@ private static Stream provideValuesTwoArg() {
@ParameterizedTest
@MethodSource("provideValuesTwoArg")
- void testAvgWithZero(@Nullable IAnyAtomicItem expected, @Nullable IAnyAtomicItem zero,
+ void testSumWithZero(@Nullable IAnyAtomicItem expected, @Nullable IAnyAtomicItem zero,
@NonNull IAnyAtomicItem... values) {
- try {
+ List> arguments = ObjectUtils.notNull(List.of(ISequence.of(values), ISequence.of(zero)));
+ if (expected == null) {
+ assertThrows(InvalidArgumentFunctionException.class, () -> {
+ FunctionTestBase.executeFunction(
+ FnSum.SIGNATURE_TWO_ARG,
+ newDynamicContext(),
+ null,
+ arguments);
+ });
+ } else {
assertFunctionResult(
FnSum.SIGNATURE_TWO_ARG,
ISequence.of(expected),
- ObjectUtils.notNull(List.of(ISequence.of(values), ISequence.of(zero))));
- } catch (MetapathException ex) {
- if (expected == null) {
- assertAll(
- () -> assertInstanceOf(InvalidArgumentFunctionException.class, ex.getCause()));
- } else {
- throw ex;
- }
+ arguments);
}
}
@Test
- void testAvgNoOpTwoArg() {
+ void testSumNoOpTwoArg() {
assertFunctionResult(
FnSum.SIGNATURE_TWO_ARG,
ISequence.empty(),
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnTokenizeTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnTokenizeTest.java
index a44f7c390..911ba7f7d 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnTokenizeTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnTokenizeTest.java
@@ -7,12 +7,12 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.sequence;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.regex.RegularExpressionMetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
@@ -23,6 +23,7 @@
import org.junit.jupiter.params.provider.MethodSource;
import java.util.List;
+import java.util.regex.PatternSyntaxException;
import java.util.stream.Stream;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -58,69 +59,58 @@ void test(@NonNull ISequence> expected, @NonNull String metapath) {
assertEquals(expected, IMetapathExpression.compile(metapath).evaluate(null, newDynamicContext()));
}
+ // TODO: make sure this (and others) exception chain is flattened
@Test
void testMatchZeroLengthString() {
- RegularExpressionMetapathException throwable = assertThrows(RegularExpressionMetapathException.class,
+ RegularExpressionMetapathException thrown = assertThrows(RegularExpressionMetapathException.class,
() -> {
- try {
- FunctionTestBase.executeFunction(
- FnTokenize.SIGNATURE_TWO_ARG,
- newDynamicContext(),
- ISequence.empty(),
- ObjectUtils.notNull(List.of(sequence(string("abba")), sequence(string(".?")))));
- } catch (MetapathException ex) {
- Throwable cause = ex.getCause();
- if (cause != null) {
- throw cause;
- }
- throw ex;
- }
+ FunctionTestBase.executeFunction(
+ FnTokenize.SIGNATURE_TWO_ARG,
+ newDynamicContext(),
+ ISequence.empty(),
+ ObjectUtils.notNull(List.of(sequence(string("abba")), sequence(string(".?")))));
});
- assertEquals(RegularExpressionMetapathException.MATCHES_ZERO_LENGTH_STRING, throwable.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(RegularExpressionMetapathException.class)
+ .hasNoCause()
+ .extracting(ex -> ex.getErrorCode().getCode())
+ .isEqualTo(RegularExpressionMetapathException.MATCHES_ZERO_LENGTH_STRING);
}
@Test
void testInvalidPattern() {
- RegularExpressionMetapathException throwable = assertThrows(RegularExpressionMetapathException.class,
+ RegularExpressionMetapathException thrown = assertThrows(RegularExpressionMetapathException.class,
() -> {
- try {
- FunctionTestBase.executeFunction(
- FnTokenize.SIGNATURE_TWO_ARG,
- newDynamicContext(),
- ISequence.empty(),
- ObjectUtils.notNull(List.of(sequence(string("input")), sequence(string("pattern[")))));
- } catch (MetapathException ex) {
- Throwable cause = ex.getCause();
- if (cause != null) {
- throw cause;
- }
- throw ex;
- }
+ FunctionTestBase.executeFunction(
+ FnTokenize.SIGNATURE_TWO_ARG,
+ newDynamicContext(),
+ ISequence.empty(),
+ ObjectUtils.notNull(List.of(sequence(string("input")), sequence(string("pattern[")))));
});
- assertEquals(RegularExpressionMetapathException.INVALID_EXPRESSION, throwable.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(RegularExpressionMetapathException.class)
+ .hasCauseExactlyInstanceOf(PatternSyntaxException.class)
+ .extracting(ex -> ex.getErrorCode().getCode())
+ .isEqualTo(RegularExpressionMetapathException.INVALID_EXPRESSION);
}
@Test
void testInvalidFlag() {
- RegularExpressionMetapathException throwable = assertThrows(RegularExpressionMetapathException.class,
+ RegularExpressionMetapathException thrown = assertThrows(RegularExpressionMetapathException.class,
() -> {
- try {
- FunctionTestBase.executeFunction(
- FnTokenize.SIGNATURE_THREE_ARG,
- newDynamicContext(),
- ISequence.empty(),
- ObjectUtils.notNull(List.of(
- sequence(string("input")),
- sequence(string("pattern")),
- sequence(string("dsm")))));
- } catch (MetapathException ex) {
- Throwable cause = ex.getCause();
- if (cause != null) {
- throw cause;
- }
- throw ex;
- }
+ FunctionTestBase.executeFunction(
+ FnTokenize.SIGNATURE_THREE_ARG,
+ newDynamicContext(),
+ ISequence.empty(),
+ ObjectUtils.notNull(List.of(
+ sequence(string("input")),
+ sequence(string("pattern")),
+ sequence(string("dsm")))));
});
- assertEquals(RegularExpressionMetapathException.INVALID_FLAG, throwable.getCode());
+ assertThat(thrown)
+ .isExactlyInstanceOf(RegularExpressionMetapathException.class)
+ .hasNoCause()
+ .extracting(ex -> ex.getErrorCode().getCode())
+ .isEqualTo(RegularExpressionMetapathException.INVALID_FLAG);
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnZeroOrOneTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnZeroOrOneTest.java
index 048b64420..37ed5bf93 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnZeroOrOneTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnZeroOrOneTest.java
@@ -7,13 +7,12 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.sequence;
-import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidArgumentFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
@@ -47,20 +46,15 @@ private static Stream provideValues() { // NOPMD - false positive
@ParameterizedTest
@MethodSource("provideValues")
void test(@Nullable ISequence> expected, @NonNull String metapath) {
- try {
+ if (expected == null) {
+ InvalidArgumentFunctionException thrown = assertThrows(InvalidArgumentFunctionException.class, () -> {
+ IMetapathExpression.compile(metapath).evaluate(null, newDynamicContext());
+ });
+ assertThat(thrown).extracting(ex -> ex.getErrorCode().getCode())
+ .isEqualTo(InvalidArgumentFunctionException.INVALID_ARGUMENT_ZERO_OR_ONE);
+ } else {
assertEquals(expected, IMetapathExpression.compile(metapath)
.evaluate(null, newDynamicContext()));
- } catch (MetapathException ex) {
- // FIXME: After refactoring the exception hierarchy, target the actual exception
- Throwable cause = ex.getCause() == null ? ex.getCause() : ex.getCause().getCause();
- assertAll(
- () -> assertNull(expected),
- () -> assertEquals(InvalidArgumentFunctionException.class, cause == null ? null : cause.getClass()),
- () -> assertEquals(
- InvalidArgumentFunctionException.INVALID_ARGUMENT_ZERO_OR_ONE,
- cause instanceof InvalidArgumentFunctionException
- ? ((InvalidArgumentFunctionException) cause).getCode()
- : null));
}
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/function/LookupTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/function/LookupTest.java
index 8fd319fcb..fef6d728b 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/function/LookupTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/function/LookupTest.java
@@ -11,6 +11,7 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.map;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.sequence;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -154,11 +155,7 @@ void testUnaryLookupMissingMember() {
assertNotNull(result);
result.safeStream();
});
- Throwable cause = thrown.getCause();
- assertEquals(
- ArrayException.INDEX_OUT_OF_BOUNDS,
- cause instanceof ArrayException
- ? ((ArrayException) cause).getCode()
- : null);
+ assertThat(thrown)
+ .isExactlyInstanceOf(IndexOutOfBoundsArrayMetapathException.class);
}
}
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidatorTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidatorTest.java
index 775f16974..ded14d332 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidatorTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidatorTest.java
@@ -51,7 +51,7 @@ private static IEnhancedQName qname(@NonNull String name) {
@SuppressWarnings("null")
@Test
- void testAllowedValuesAllowOther() {
+ void testAllowedValuesAllowOther() throws ConstraintValidationException {
MockNodeItemFactory itemFactory = new MockNodeItemFactory();
IFlagNodeItem flag = itemFactory.flag(qname("value"), IStringItem.valueOf("value"));
@@ -92,7 +92,7 @@ void testAllowedValuesAllowOther() {
@SuppressWarnings("null")
@Test
- void testAllowedValuesMultipleAllowOther() {
+ void testAllowedValuesMultipleAllowOther() throws ConstraintValidationException {
MockNodeItemFactory itemFactory = new MockNodeItemFactory();
IFlagNodeItem flag = itemFactory.flag(qname("value"), IStringItem.valueOf("value"));
@@ -143,7 +143,7 @@ void testAllowedValuesMultipleAllowOther() {
@SuppressWarnings("null")
@Test
- void testMultipleAllowedValuesConflictingAllowOther() {
+ void testMultipleAllowedValuesConflictingAllowOther() throws ConstraintValidationException {
MockNodeItemFactory itemFactory = new MockNodeItemFactory();
IFlagNodeItem flag1 = itemFactory.flag(qname("value"), IStringItem.valueOf("value"));
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
index 5bd3bf03a..654b2b364 100644
--- 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
@@ -15,6 +15,7 @@
import gov.nist.secauto.metaschema.core.metapath.StaticContext;
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.ConstraintValidationException;
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;
@@ -29,7 +30,7 @@ class AbstractConfigurableMessageConstraintTest
extends ExpressionTestBase {
@Test
- void testDifferentNS() {
+ void testDifferentNS() throws ConstraintValidationException {
StaticContext constraintContext = StaticContext.builder()
.defaultModelNamespace(NS)
.baseUri(ObjectUtils.notNull(URI.create("https://example.com/other")))
@@ -56,7 +57,7 @@ void testDifferentNS() {
}
@Test
- void testWildCard() {
+ void testWildCard() throws ConstraintValidationException {
StaticContext constraintContext = StaticContext.builder()
.defaultModelNamespace(NS)
.baseUri(ObjectUtils.notNull(URI.create("https://example.com/other")))
@@ -83,7 +84,7 @@ void testWildCard() {
}
@Test
- void testPrefix() {
+ void testPrefix() throws ConstraintValidationException {
StaticContext constraintContext = StaticContext.builder()
.defaultModelNamespace(NS)
.baseUri(ObjectUtils.notNull(URI.create("https://example.com/other")))
@@ -111,7 +112,7 @@ void testPrefix() {
}
@Test
- void testQualifiedName() {
+ void testQualifiedName() throws ConstraintValidationException {
StaticContext constraintContext = StaticContext.builder()
.defaultModelNamespace(NS)
.baseUri(ObjectUtils.notNull(URI.create("https://example.com/other")))
diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/model/xml/MetaConstraintLoaderTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/model/xml/MetaConstraintLoaderTest.java
index 1841dbf7a..037e68426 100644
--- a/core/src/test/java/gov/nist/secauto/metaschema/core/model/xml/MetaConstraintLoaderTest.java
+++ b/core/src/test/java/gov/nist/secauto/metaschema/core/model/xml/MetaConstraintLoaderTest.java
@@ -9,8 +9,6 @@
import gov.nist.secauto.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
-import gov.nist.secauto.metaschema.core.metapath.function.library.FnPath;
-import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.IModuleNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory;
@@ -44,14 +42,15 @@ void test() throws MetaschemaException, IOException {
IMetapathExpression expression = IMetapathExpression.compile("//@id", module.getModuleStaticContext());
IModuleNodeItem moduleItem = INodeItemFactory.instance().newModuleNodeItem(module);
- for (IItem item : expression.evaluate(moduleItem)) {
- IDefinitionNodeItem, ?> nodeItem = (IDefinitionNodeItem, ?>) item;
- System.out.print(FnPath.fnPath(nodeItem));
- System.out.print(": ");
- System.out.println(Long.toString(nodeItem.getDefinition().getMatchesConstraints().stream()
- .filter(matches -> MetaschemaDataTypeProvider.UUID.equals(matches.getDataType()))
- .count()));
- }
+ // for (IItem item : expression.evaluate(moduleItem)) {
+ // IDefinitionNodeItem, ?> nodeItem = (IDefinitionNodeItem, ?>) item;
+ // System.out.print(FnPath.fnPath(nodeItem));
+ // System.out.print(": ");
+ // System.out.println(Long.toString(nodeItem.getDefinition().getMatchesConstraints().stream()
+ // .filter(matches ->
+ // MetaschemaDataTypeProvider.UUID.equals(matches.getDataType()))
+ // .count()));
+ // }
expression.evaluate(moduleItem).stream()
.map(item -> (IDefinitionNodeItem, ?>) item)
diff --git a/core/src/test/resources/correct-examples.txt b/core/src/test/resources/correct-examples.txt
index 52548c8f0..401bf5cd7 100644
--- a/core/src/test/resources/correct-examples.txt
+++ b/core/src/test/resources/correct-examples.txt
@@ -322,7 +322,7 @@ text;
//button[text()="Submit"];
//c/@x;
//center;
-//center//processing-instruction('b-pi');
+#//center//processing-instruction('b-pi');
//center/@center-attr-1;
//center/@center-attr-3;
//center/text()[1];
@@ -525,7 +525,7 @@ text;
@val;
@value;
@width;
-@xml:att1;
+#@xml:att1;
@xx;
@x|@z;
@z;
@@ -668,9 +668,9 @@ count(a[string-length(@ex) > 0]);
count(a[string-length(@ex)=0]);
count(alpha/*[last()][name()='z']);
count(div);
-count(id('c'));
-count(id('d b c k'));
-count(id('k'));
+#count(id('c'));
+#count(id('d b c k'));
+#count(id('k'));
count(section[1]//@*);
count(section[1]//@title);
count(section[2]//@*);
@@ -747,20 +747,20 @@ foo[(bar[2][(baz[2])='goodbye'])];
grandchild;
growth;
human;
-id('c a d');
-id('c')/@id;
-id('d b c');
-id('id0')/a/b;
-id('id0')/c/c/a;
-id('id10')/a;
-id('id13');
-id('id2')/a | id('id5') | id('id15')/a;
-id('id4');
-id('id8')/b/b;
-id('id9');
-id('nomatch')/@id;
-id(main/@list);
-id(main/b);
+#id('c a d');
+#id('c')/@id;
+#id('d b c');
+#id('id0')/a/b;
+#id('id0')/c/c/a;
+#id('id10')/a;
+#id('id13');
+#id('id2')/a | id('id5') | id('id15')/a;
+#id('id4');
+#id('id8')/b/b;
+#id('id9');
+#id('nomatch')/@id;
+#id(main/@list);
+#id(main/b);
inner;
item;
item[1][last()];
@@ -869,7 +869,7 @@ Personal_Information/Age;
pos-bad;
primary/name/first;
primary/name/last;
-processing-instruction();
+#processing-instruction();
r;
revenue;
root/x;
@@ -991,7 +991,7 @@ text()[1];
text()[3];
time;
title;
-town[generate-id() = generate-id(key('places',@state)[1])];
+#town[generate-id() = generate-id(key('places',@state)[1])];
translate("BAR","abc","ABC");
translate("BAR","Rab","TxX");
translate("bar","RAB","xyz");
@@ -1019,6 +1019,6 @@ z[1];
zoneone;
xs:date("2000-01-01");
xs:dayTimeDuration("P21D");
-17 cast as apple;
-apple(17);
+#17 cast as apple;
+#apple(17);
//product[id = 47];
diff --git a/databind-metaschema/src/main/java/gov/nist/secauto/metaschema/modules/sarif/SarifValidationHandler.java b/databind-metaschema/src/main/java/gov/nist/secauto/metaschema/modules/sarif/SarifValidationHandler.java
index f9e842c98..e5c7e35f5 100644
--- a/databind-metaschema/src/main/java/gov/nist/secauto/metaschema/modules/sarif/SarifValidationHandler.java
+++ b/databind-metaschema/src/main/java/gov/nist/secauto/metaschema/modules/sarif/SarifValidationHandler.java
@@ -9,6 +9,7 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
import gov.nist.secauto.metaschema.core.model.IAttributable;
import gov.nist.secauto.metaschema.core.model.IResourceLocation;
+import gov.nist.secauto.metaschema.core.model.MetaschemaException;
import gov.nist.secauto.metaschema.core.model.constraint.ConstraintValidationFinding;
import gov.nist.secauto.metaschema.core.model.constraint.IConstraint;
import gov.nist.secauto.metaschema.core.model.constraint.IConstraint.Level;
@@ -292,7 +293,7 @@ private Sarif generateSarif(@NonNull URI outputUri) throws IOException {
*/
@NonNull
public String writeToString(@NonNull IBindingContext bindingContext) throws IOException {
- bindingContext.registerModule(SarifModule.class);
+ registerSarifMetaschemaModule(bindingContext);
try (StringWriter writer = new StringWriter()) {
bindingContext.newSerializer(Format.JSON, Sarif.class)
.disableFeature(SerializationFeature.SERIALIZE_ROOT)
@@ -319,7 +320,7 @@ public void write(
URI output = ObjectUtils.notNull(outputFile.toUri());
Sarif sarif = generateSarif(output);
- bindingContext.registerModule(SarifModule.class);
+ registerSarifMetaschemaModule(bindingContext);
bindingContext.newSerializer(Format.JSON, Sarif.class)
.disableFeature(SerializationFeature.SERIALIZE_ROOT)
.serialize(
@@ -330,6 +331,14 @@ public void write(
StandardOpenOption.TRUNCATE_EXISTING);
}
+ private static void registerSarifMetaschemaModule(@NonNull IBindingContext bindingContext) {
+ try {
+ bindingContext.registerModule(SarifModule.class);
+ } catch (MetaschemaException ex) {
+ throw new IllegalStateException("Unable to register the builtin SARIF module.", ex);
+ }
+ }
+
private interface IResult {
@NonNull
IValidationFinding getFinding();
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/AbstractModuleLoaderStrategy.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/AbstractModuleLoaderStrategy.java
index f64c771d1..e0dc9b9af 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/AbstractModuleLoaderStrategy.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/AbstractModuleLoaderStrategy.java
@@ -7,8 +7,11 @@
import gov.nist.secauto.metaschema.core.model.IBoundObject;
import gov.nist.secauto.metaschema.core.model.IModule;
+import gov.nist.secauto.metaschema.core.model.MetaschemaException;
import gov.nist.secauto.metaschema.core.model.constraint.DefaultConstraintValidator;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
+import gov.nist.secauto.metaschema.core.util.ExceptionUtils;
+import gov.nist.secauto.metaschema.core.util.ExceptionUtils.WrappedException;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import gov.nist.secauto.metaschema.databind.IBindingContext.IBindingMatcher;
import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly;
@@ -72,9 +75,10 @@ public IBoundModule loadModule(
}
@Override
+ @SuppressWarnings("PMD.ExceptionAsFlowControl")
public IBoundModule registerModule(
IModule module,
- IBindingContext bindingContext) {
+ IBindingContext bindingContext) throws MetaschemaException {
modulesLock.lock();
try {
return ObjectUtils.notNull(moduleToBoundModuleMap.computeIfAbsent(module, key -> {
@@ -84,8 +88,12 @@ public IBoundModule registerModule(
if (key instanceof IBoundModule) {
boundModule = (IBoundModule) key;
} else {
- Class extends IBoundModule> moduleClass = handleUnboundModule(key);
- boundModule = lookupInstance(moduleClass, bindingContext);
+ try {
+ Class extends IBoundModule> moduleClass = handleUnboundModule(key);
+ boundModule = lookupInstance(moduleClass, bindingContext);
+ } catch (MetaschemaException ex) {
+ throw ExceptionUtils.wrap(ex);
+ }
}
boundModule.getExportedAssemblyDefinitions().forEach(assembly -> {
@@ -98,13 +106,15 @@ public IBoundModule registerModule(
return boundModule;
}));
+ } catch (WrappedException ex) {
+ throw ExceptionUtils.unwrap(ex, MetaschemaException.class);
} finally {
modulesLock.unlock();
}
}
@NonNull
- protected abstract Class extends IBoundModule> handleUnboundModule(@NonNull IModule key);
+ protected abstract Class extends IBoundModule> handleUnboundModule(@NonNull IModule key) throws MetaschemaException;
/**
* Get the Module instance for a given class annotated by the
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/DefaultBindingContext.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/DefaultBindingContext.java
index c6dfad591..070a6fa03 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/DefaultBindingContext.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/DefaultBindingContext.java
@@ -98,7 +98,11 @@ public DefaultBindingContext() {
public DefaultBindingContext(@NonNull IBindingContext.IModuleLoaderStrategy strategy) {
// only allow extended classes
moduleLoaderStrategy = strategy;
- registerModule(MetaschemaModelModule.class);
+ try {
+ registerModule(MetaschemaModelModule.class);
+ } catch (MetaschemaException ex) {
+ throw new IllegalStateException("Unable to register the builtin Metaschema module.", ex);
+ }
}
@Override
@@ -114,20 +118,20 @@ public IBindingModuleLoader newModuleLoader() {
@Override
@NonNull
- public final IBoundModule registerModule(@NonNull Class extends IBoundModule> clazz) {
+ public final IBoundModule registerModule(@NonNull Class extends IBoundModule> clazz) throws MetaschemaException {
IModuleLoaderStrategy strategy = getModuleLoaderStrategy();
IBoundModule module = strategy.loadModule(clazz, this);
registerImportedModules(module);
return strategy.registerModule(module, this);
}
- private void registerImportedModules(@NonNull IBoundModule module) {
+ private void registerImportedModules(@NonNull IBoundModule module) throws MetaschemaException {
IModuleLoaderStrategy strategy = getModuleLoaderStrategy();
- module.getImportedModules().stream()
- .forEachOrdered(parentModule -> {
- registerImportedModules(ObjectUtils.notNull(parentModule));
- strategy.registerModule(ObjectUtils.notNull(parentModule), this);
- });
+ for (IBoundModule parentModule : module.getImportedModules()) {
+ assert parentModule != null;
+ registerImportedModules(parentModule);
+ strategy.registerModule(parentModule, this);
+ }
}
/**
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java
index aa3985eaf..66849402b 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java
@@ -17,6 +17,7 @@
import gov.nist.secauto.metaschema.core.model.IModule;
import gov.nist.secauto.metaschema.core.model.IModuleLoader;
import gov.nist.secauto.metaschema.core.model.MetaschemaException;
+import gov.nist.secauto.metaschema.core.model.constraint.ConstraintValidationException;
import gov.nist.secauto.metaschema.core.model.constraint.DefaultConstraintValidator;
import gov.nist.secauto.metaschema.core.model.constraint.ExternalConstraintsModulePostProcessor;
import gov.nist.secauto.metaschema.core.model.constraint.FindingCollectingConstraintValidationHandler;
@@ -244,9 +245,11 @@ default IConstraintLoader newConstraintLoader() {
* @param clazz
* the class implementing a bound Metaschema module
* @return the loaded module
+ * @throws MetaschemaException
+ * if an error occurred while registering the module
*/
@NonNull
- IBoundModule registerModule(@NonNull Class extends IBoundModule> clazz);
+ IBoundModule registerModule(@NonNull Class extends IBoundModule> clazz) throws MetaschemaException;
/**
* Registers the provided Metaschema module with this binding context.
@@ -259,6 +262,8 @@ default IConstraintLoader newConstraintLoader() {
* the Module module to generate classes for
* @return the registered module, which may be a different instance than what
* was provided if dynamic compilation was performed
+ * @throws MetaschemaException
+ * if an error occurred while registering the module
* @throws UnsupportedOperationException
* if this binding context is not configured to support dynamic bound
* module loading and the module instance is not a subclass of
@@ -266,7 +271,7 @@ default IConstraintLoader newConstraintLoader() {
* @since 2.0.0
*/
@NonNull
- default IBoundModule registerModule(@NonNull IModule module) {
+ default IBoundModule registerModule(@NonNull IModule module) throws MetaschemaException {
return getModuleLoaderStrategy().registerModule(module, this);
}
@@ -463,13 +468,13 @@ default IConstraintValidator newValidator(
* @param config
* the validation configuration
* @return the validation result
+ * @throws ConstraintValidationException
* @throws IllegalArgumentException
- * if the provided class is not bound to a Module assembly or field
*/
default IValidationResult validate(
@NonNull IDocumentNodeItem nodeItem,
@NonNull IBoundLoader loader,
- @Nullable IConfiguration> config) {
+ @Nullable IConfiguration> config) throws ConstraintValidationException {
IRootAssemblyNodeItem root = nodeItem.getRootAssemblyNodeItem();
return validate(root, loader, config);
}
@@ -485,13 +490,13 @@ default IValidationResult validate(
* @param config
* the validation configuration
* @return the validation result
+ * @throws ConstraintValidationException
* @throws IllegalArgumentException
- * if the provided class is not bound to a Module assembly or field
*/
default IValidationResult validate(
@NonNull IDefinitionNodeItem, ?> nodeItem,
@NonNull IBoundLoader loader,
- @Nullable IConfiguration> config) {
+ @Nullable IConfiguration> config) throws ConstraintValidationException {
FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler();
IConstraintValidator validator = newValidator(handler, config);
@@ -519,12 +524,13 @@ default IValidationResult validate(
* @return the validation result
* @throws IOException
* if an error occurred while reading the target
+ * @throws ConstraintValidationException
*/
default IValidationResult validate(
@NonNull URI target,
@NonNull Format asFormat,
@NonNull ISchemaValidationProvider schemaProvider,
- @Nullable IConfiguration> config) throws IOException {
+ @Nullable IConfiguration> config) throws IOException, ConstraintValidationException {
IValidationResult retval = schemaProvider.validateWithSchema(target, asFormat, this);
@@ -546,11 +552,12 @@ default IValidationResult validate(
* @return the validation results
* @throws IOException
* if an error occurred while parsing the target
+ * @throws ConstraintValidationException
*/
default IValidationResult validateWithConstraints(
@NonNull URI target,
@Nullable IConfiguration> config)
- throws IOException {
+ throws IOException, ConstraintValidationException {
IBoundLoader loader = newBoundLoader();
loader.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS);
IDocumentNodeItem nodeItem = loader.loadAsNodeItem(target);
@@ -628,6 +635,8 @@ default void postProcessModule(
* the Metaschema binding context used to load bound resources
* @return the registered module, which may be a different instance than what
* was provided if dynamic compilation was performed
+ * @throws MetaschemaException
+ * if an error occurred while dynamically binding the provided module
* @throws UnsupportedOperationException
* if this binding context is not configured to support dynamic bound
* module loading and the module instance is not a subclass of
@@ -637,7 +646,7 @@ default void postProcessModule(
@NonNull
IBoundModule registerModule(
@NonNull IModule module,
- @NonNull IBindingContext bindingContext);
+ @NonNull IBindingContext bindingContext) throws MetaschemaException;
//
// /**
// * Register a matcher used to identify a bound class by the definition's root
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/PostProcessingModuleLoaderStrategy.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/PostProcessingModuleLoaderStrategy.java
index c32bd8cb3..b419b6afd 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/PostProcessingModuleLoaderStrategy.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/PostProcessingModuleLoaderStrategy.java
@@ -8,6 +8,7 @@
import gov.nist.secauto.metaschema.core.model.IBoundObject;
import gov.nist.secauto.metaschema.core.model.IModule;
import gov.nist.secauto.metaschema.core.model.IModuleLoader;
+import gov.nist.secauto.metaschema.core.model.MetaschemaException;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
import gov.nist.secauto.metaschema.databind.IBindingContext.IBindingMatcher;
import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelComplex;
@@ -62,7 +63,7 @@ public void postProcessModule(IModule module, IBindingContext bindingContext) {
}
@Override
- public IBoundModule registerModule(IModule module, IBindingContext bindingContext) {
+ public IBoundModule registerModule(IModule module, IBindingContext bindingContext) throws MetaschemaException {
IBoundModule boundModule;
postProcessedModulesLock.lock();
try {
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/SimpleModuleLoaderStrategy.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/SimpleModuleLoaderStrategy.java
index b568fbef1..f127a0174 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/SimpleModuleLoaderStrategy.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/SimpleModuleLoaderStrategy.java
@@ -6,6 +6,7 @@
package gov.nist.secauto.metaschema.databind;
import gov.nist.secauto.metaschema.core.model.IModule;
+import gov.nist.secauto.metaschema.core.model.MetaschemaException;
import gov.nist.secauto.metaschema.databind.codegen.IModuleBindingGenerator;
import gov.nist.secauto.metaschema.databind.model.IBoundModule;
@@ -33,7 +34,7 @@ public SimpleModuleLoaderStrategy(@NonNull IModuleBindingGenerator generator) {
}
@Override
- protected Class extends IBoundModule> handleUnboundModule(IModule module) {
+ protected Class extends IBoundModule> handleUnboundModule(IModule module) throws MetaschemaException {
return generator.generate(module);
}
}
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/DefaultModuleBindingGenerator.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/DefaultModuleBindingGenerator.java
index fd78c17c9..1aa802413 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/DefaultModuleBindingGenerator.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/DefaultModuleBindingGenerator.java
@@ -5,8 +5,8 @@
package gov.nist.secauto.metaschema.databind.codegen;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.model.IModule;
+import gov.nist.secauto.metaschema.core.model.MetaschemaException;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import gov.nist.secauto.metaschema.databind.model.IBoundModule;
@@ -24,7 +24,7 @@ public DefaultModuleBindingGenerator(@NonNull Path compilePath) {
}
@Override
- public Class extends IBoundModule> generate(IModule module) {
+ public Class extends IBoundModule> generate(IModule module) throws MetaschemaException {
ClassLoader classLoader = ModuleCompilerHelper.newClassLoader(
compilePath,
ObjectUtils.notNull(Thread.currentThread().getContextClassLoader()));
@@ -33,7 +33,7 @@ public Class extends IBoundModule> generate(IModule module) {
try {
production = ModuleCompilerHelper.compileMetaschema(module, compilePath);
} catch (IOException ex) {
- throw new MetapathException(
+ throw new MetaschemaException(
String.format("Unable to generate and compile classes for module '%s'.", module.getLocation()),
ex);
}
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/IModuleBindingGenerator.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/IModuleBindingGenerator.java
index d64bbb0fc..00b84b2b8 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/IModuleBindingGenerator.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/IModuleBindingGenerator.java
@@ -6,11 +6,12 @@
package gov.nist.secauto.metaschema.databind.codegen;
import gov.nist.secauto.metaschema.core.model.IModule;
+import gov.nist.secauto.metaschema.core.model.MetaschemaException;
import gov.nist.secauto.metaschema.databind.model.IBoundModule;
import edu.umd.cs.findbugs.annotations.NonNull;
public interface IModuleBindingGenerator {
@NonNull
- Class extends IBoundModule> generate(@NonNull IModule module);
+ Class extends IBoundModule> generate(@NonNull IModule module) throws MetaschemaException;
}
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/AbstractDeserializer.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/AbstractDeserializer.java
index b14aee1b5..6587cd92d 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/AbstractDeserializer.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/AbstractDeserializer.java
@@ -12,6 +12,7 @@
import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
import gov.nist.secauto.metaschema.core.model.IBoundObject;
+import gov.nist.secauto.metaschema.core.model.constraint.ConstraintValidationException;
import gov.nist.secauto.metaschema.core.model.constraint.DefaultConstraintValidator;
import gov.nist.secauto.metaschema.core.model.constraint.IConstraintValidationHandler;
import gov.nist.secauto.metaschema.core.model.constraint.LoggingConstraintValidationHandler;
@@ -91,7 +92,11 @@ public INodeItem deserializeToNodeItem(Reader reader, URI documentUri) throws IO
}
if (isValidating()) {
- validate(nodeItem);
+ try {
+ validate(nodeItem);
+ } catch (ConstraintValidationException ex) {
+ throw new IOException(ex);
+ }
}
return nodeItem;
}
@@ -117,7 +122,11 @@ public final CLASS deserializeToValue(Reader reader, URI documentUri) throws IOE
if (isValidating()) {
INodeItem nodeItem = deserializeToNodeItemInternal(reader, documentUri);
- validate(nodeItem);
+ try {
+ validate(nodeItem);
+ } catch (ConstraintValidationException ex) {
+ throw new IOException(ex);
+ }
retval = ObjectUtils.asType(ObjectUtils.requireNonNull(nodeItem.getValue()));
} else {
retval = deserializeToValueInternal(reader, documentUri);
@@ -125,7 +134,7 @@ public final CLASS deserializeToValue(Reader reader, URI documentUri) throws IOE
return retval;
}
- private void validate(@NonNull INodeItem nodeItem) {
+ private void validate(@NonNull INodeItem nodeItem) throws ConstraintValidationException {
IDefinitionNodeItem, ?> definitionNodeItem;
if (nodeItem instanceof IDocumentNodeItem) {
definitionNodeItem = ((IDocumentNodeItem) nodeItem).getRootAssemblyNodeItem();
diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/ConstraintSupport.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/ConstraintSupport.java
index 5533d91dd..836bdba99 100644
--- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/ConstraintSupport.java
+++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/ConstraintSupport.java
@@ -5,7 +5,6 @@
package gov.nist.secauto.metaschema.databind.model.impl;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.model.ISource;
import gov.nist.secauto.metaschema.core.model.constraint.IModelConstrained;
import gov.nist.secauto.metaschema.core.model.constraint.IValueConstrained;
@@ -39,27 +38,21 @@ public static void parse( // NOPMD - intentional
@NonNull ISource source,
@NonNull IValueConstrained set) {
if (valueAnnotation != null) {
- try {
- Arrays.stream(valueAnnotation.lets())
- .map(annotation -> ConstraintFactory.newLetExpression(annotation, source))
- .forEachOrdered(set::addLetExpression);
- Arrays.stream(valueAnnotation.allowedValues())
- .map(annotation -> ConstraintFactory.newAllowedValuesConstraint(annotation, source))
- .forEachOrdered(set::addConstraint);
- Arrays.stream(valueAnnotation.matches())
- .map(annotation -> ConstraintFactory.newMatchesConstraint(annotation, source))
- .forEachOrdered(set::addConstraint);
- Arrays.stream(valueAnnotation.indexHasKey())
- .map(annotation -> ConstraintFactory.newIndexHasKeyConstraint(annotation, source))
- .forEachOrdered(set::addConstraint);
- Arrays.stream(valueAnnotation.expect())
- .map(annotation -> ConstraintFactory.newExpectConstraint(annotation, source))
- .forEachOrdered(set::addConstraint);
- } catch (MetapathException ex) {
- throw new MetapathException(
- String.format("Unable to compile a Metapath in '%s'. %s", source.getSource(), ex.getLocalizedMessage()),
- ex);
- }
+ Arrays.stream(valueAnnotation.lets())
+ .map(annotation -> ConstraintFactory.newLetExpression(annotation, source))
+ .forEachOrdered(set::addLetExpression);
+ Arrays.stream(valueAnnotation.allowedValues())
+ .map(annotation -> ConstraintFactory.newAllowedValuesConstraint(annotation, source))
+ .forEachOrdered(set::addConstraint);
+ Arrays.stream(valueAnnotation.matches())
+ .map(annotation -> ConstraintFactory.newMatchesConstraint(annotation, source))
+ .forEachOrdered(set::addConstraint);
+ Arrays.stream(valueAnnotation.indexHasKey())
+ .map(annotation -> ConstraintFactory.newIndexHasKeyConstraint(annotation, source))
+ .forEachOrdered(set::addConstraint);
+ Arrays.stream(valueAnnotation.expect())
+ .map(annotation -> ConstraintFactory.newExpectConstraint(annotation, source))
+ .forEachOrdered(set::addConstraint);
}
}
@@ -80,23 +73,17 @@ public static void parse( // NOPMD - intentional
@NonNull ISource source,
@NonNull IModelConstrained set) {
if (assemblyAnnotation != null) {
- try {
- Arrays.stream(assemblyAnnotation.index())
- .map(annotation -> ConstraintFactory.newIndexConstraint(annotation, source))
- .forEachOrdered(set::addConstraint);
+ Arrays.stream(assemblyAnnotation.index())
+ .map(annotation -> ConstraintFactory.newIndexConstraint(annotation, source))
+ .forEachOrdered(set::addConstraint);
- Arrays.stream(assemblyAnnotation.unique())
- .map(annotation -> ConstraintFactory.newUniqueConstraint(annotation, source))
- .forEachOrdered(set::addConstraint);
+ Arrays.stream(assemblyAnnotation.unique())
+ .map(annotation -> ConstraintFactory.newUniqueConstraint(annotation, source))
+ .forEachOrdered(set::addConstraint);
- Arrays.stream(assemblyAnnotation.cardinality())
- .map(annotation -> ConstraintFactory.newCardinalityConstraint(annotation, source))
- .forEachOrdered(set::addConstraint);
- } catch (MetapathException ex) {
- throw new MetapathException(
- String.format("Unable to compile a Metapath in '%s'. %s", source.getSource(), ex.getLocalizedMessage()),
- ex);
- }
+ Arrays.stream(assemblyAnnotation.cardinality())
+ .map(annotation -> ConstraintFactory.newCardinalityConstraint(annotation, source))
+ .forEachOrdered(set::addConstraint);
}
}
}
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 b44cfdb5d..9e0e7ef52 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
@@ -6,7 +6,6 @@
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;
import gov.nist.secauto.metaschema.core.model.IConstraintLoader;
@@ -36,8 +35,6 @@
import gov.nist.secauto.metaschema.databind.model.metaschema.binding.MetaschemaModuleConstraints;
import gov.nist.secauto.metaschema.databind.model.metaschema.impl.ConstraintBindingSupport;
-import org.apache.xmlbeans.impl.values.XmlValueNotSupportedException;
-
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
@@ -181,31 +178,20 @@ protected List parseScopedConstraints(
assert scope != null;
List targetedConstraints = new LinkedList<>();
- try {
- for (IValueConstraintsBase constraintsObj : CollectionUtil.listOrEmpty(scope.getConstraints())) {
- if (constraintsObj instanceof MetaschemaModuleConstraints.Scope.Assembly) {
- targetedConstraints.add(handleScopedAssembly(
- (MetaschemaModuleConstraints.Scope.Assembly) constraintsObj,
- source));
- } else if (constraintsObj instanceof MetaschemaModuleConstraints.Scope.Field) {
- targetedConstraints.add(handleScopedField(
- (MetaschemaModuleConstraints.Scope.Field) constraintsObj,
- source));
- } else if (constraintsObj instanceof MetaschemaModuleConstraints.Scope.Flag) {
- targetedConstraints.add(handleScopedFlag(
- (MetaschemaModuleConstraints.Scope.Flag) constraintsObj,
- source));
- }
- }
- } catch (MetapathException | XmlValueNotSupportedException ex) {
- if (ex.getCause() instanceof MetapathException) {
- throw new MetapathException(
- String.format("Unable to compile a Metapath in '%s'. %s",
- source.getSource(),
- ex.getLocalizedMessage()),
- ex);
+ for (IValueConstraintsBase constraintsObj : CollectionUtil.listOrEmpty(scope.getConstraints())) {
+ if (constraintsObj instanceof MetaschemaModuleConstraints.Scope.Assembly) {
+ targetedConstraints.add(handleScopedAssembly(
+ (MetaschemaModuleConstraints.Scope.Assembly) constraintsObj,
+ source));
+ } else if (constraintsObj instanceof MetaschemaModuleConstraints.Scope.Field) {
+ targetedConstraints.add(handleScopedField(
+ (MetaschemaModuleConstraints.Scope.Field) constraintsObj,
+ source));
+ } else if (constraintsObj instanceof MetaschemaModuleConstraints.Scope.Flag) {
+ targetedConstraints.add(handleScopedFlag(
+ (MetaschemaModuleConstraints.Scope.Flag) constraintsObj,
+ source));
}
- throw ex;
}
URI namespace = ObjectUtils.requireNonNull(scope.getMetaschemaNamespace());
diff --git a/databind/src/test/java/gov/nist/secauto/metaschema/databind/io/Issue206MetaschemaReaderTest.java b/databind/src/test/java/gov/nist/secauto/metaschema/databind/io/Issue206MetaschemaReaderTest.java
index 8cedf50d5..deb55e096 100644
--- a/databind/src/test/java/gov/nist/secauto/metaschema/databind/io/Issue206MetaschemaReaderTest.java
+++ b/databind/src/test/java/gov/nist/secauto/metaschema/databind/io/Issue206MetaschemaReaderTest.java
@@ -14,6 +14,7 @@
import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
import gov.nist.secauto.metaschema.core.model.IBoundObject;
import gov.nist.secauto.metaschema.core.model.IMetaschemaData;
+import gov.nist.secauto.metaschema.core.model.MetaschemaException;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import gov.nist.secauto.metaschema.databind.IBindingContext;
import gov.nist.secauto.metaschema.databind.io.json.JsonFactoryFactory;
@@ -49,7 +50,7 @@ class Issue206MetaschemaReaderTest {
JUnit5Mockery context = new JUnit5Mockery();
@Test
- void testIssue205Json() throws IOException {
+ void testIssue205Json() throws IOException, MetaschemaException {
String json = "{" +
" \"flag\": \"flag-value\"" +
"}";
@@ -76,7 +77,7 @@ void testIssue205Json() throws IOException {
}
@Test
- void testIssue205XmlNoValue() throws IOException, XMLStreamException {
+ void testIssue205XmlNoValue() throws IOException, XMLStreamException, MetaschemaException {
String xml = "";
URI source = ObjectUtils.notNull(URI.create("https://example.com/not-a-resource"));
@@ -100,7 +101,7 @@ void testIssue205XmlNoValue() throws IOException, XMLStreamException {
}
@Test
- void testIssue205XmlEmptyValue() throws IOException, XMLStreamException {
+ void testIssue205XmlEmptyValue() throws IOException, XMLStreamException, MetaschemaException {
String xml = "";
URI source = ObjectUtils.notNull(URI.create("https://example.com/not-a-resource"));
diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractConvertSubcommand.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractConvertSubcommand.java
index e4cafba16..e7552733d 100644
--- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractConvertSubcommand.java
+++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractConvertSubcommand.java
@@ -11,6 +11,7 @@
import gov.nist.secauto.metaschema.cli.processor.command.AbstractTerminalCommand;
import gov.nist.secauto.metaschema.cli.processor.command.CommandExecutionException;
import gov.nist.secauto.metaschema.cli.processor.command.ExtraArgument;
+import gov.nist.secauto.metaschema.core.model.MetaschemaException;
import gov.nist.secauto.metaschema.core.util.AutoCloser;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import gov.nist.secauto.metaschema.databind.IBindingContext;
@@ -94,9 +95,12 @@ protected AbstractConversionCommandExecutor(
* @return the context
* @throws CommandExecutionException
* if an error occurred getting the binding context
+ * @throws MetaschemaException
+ * if an error occurred while setting up the binding context, such as
+ * pre-loading any needed modules
*/
@NonNull
- protected abstract IBindingContext getBindingContext() throws CommandExecutionException;
+ protected abstract IBindingContext getBindingContext() throws CommandExecutionException, MetaschemaException;
@SuppressWarnings({
"PMD.OnlyOneReturn", // readability
@@ -120,9 +124,8 @@ public void execute() throws CommandExecutionException {
Format toFormat = MetaschemaCommands.getFormat(cmdLine, MetaschemaCommands.TO_OPTION);
- IBindingContext bindingContext = getBindingContext();
-
try {
+ IBindingContext bindingContext = getBindingContext();
IBoundLoader loader = bindingContext.newBoundLoader();
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Converting '{}'.", source);
@@ -145,7 +148,7 @@ public void execute() throws CommandExecutionException {
handleConversion(source, toFormat, writer, loader);
}
}
- } catch (IllegalArgumentException ex) {
+ } catch (IllegalArgumentException | MetaschemaException ex) {
throw new CommandExecutionException(ExitCode.PROCESSING_ERROR, ex);
} catch (IOException ex) {
throw new CommandExecutionException(ExitCode.IO_ERROR, ex);
diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java
index 89d270a73..5a6d1d045 100644
--- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java
+++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java
@@ -17,6 +17,8 @@
import gov.nist.secauto.metaschema.core.configuration.IMutableConfiguration;
import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.model.IModule;
+import gov.nist.secauto.metaschema.core.model.MetaschemaException;
+import gov.nist.secauto.metaschema.core.model.constraint.ConstraintValidationException;
import gov.nist.secauto.metaschema.core.model.constraint.IConstraintSet;
import gov.nist.secauto.metaschema.core.model.constraint.ValidationFeature;
import gov.nist.secauto.metaschema.core.model.validation.AggregateValidationResult;
@@ -162,6 +164,7 @@ protected abstract IBindingContext getBindingContext(@NonNull Set constraintSets)
}
@Override
- protected IModule getModule(CommandLine commandLine, IBindingContext bindingContext) {
- return bindingContext.registerModule(MetaschemaModelModule.class);
+ protected IModule getModule(CommandLine commandLine, IBindingContext bindingContext)
+ throws CommandExecutionException {
+ try {
+ return bindingContext.registerModule(MetaschemaModelModule.class);
+ } catch (MetaschemaException ex) {
+ throw new CommandExecutionException(ExitCode.PROCESSING_ERROR, ex);
+ }
}
@Override
diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/EvaluateMetapathCommand.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/EvaluateMetapathCommand.java
index 2e679a1cc..89329b90a 100644
--- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/EvaluateMetapathCommand.java
+++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/metapath/EvaluateMetapathCommand.java
@@ -21,6 +21,7 @@
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory;
import gov.nist.secauto.metaschema.core.model.IModule;
+import gov.nist.secauto.metaschema.core.model.MetaschemaException;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import gov.nist.secauto.metaschema.databind.IBindingContext;
@@ -127,11 +128,15 @@ private void executeCommand(
if (cmdLine.hasOption(MetaschemaCommands.METASCHEMA_OPTIONAL_OPTION)) {
IBindingContext bindingContext = MetaschemaCommands.newBindingContextWithDynamicCompilation();
- module = bindingContext.registerModule(MetaschemaCommands.loadModule(
- cmdLine,
- MetaschemaCommands.METASCHEMA_OPTIONAL_OPTION,
- ObjectUtils.notNull(getCurrentWorkingDirectory().toUri()),
- bindingContext));
+ try {
+ module = bindingContext.registerModule(MetaschemaCommands.loadModule(
+ cmdLine,
+ MetaschemaCommands.METASCHEMA_OPTIONAL_OPTION,
+ ObjectUtils.notNull(getCurrentWorkingDirectory().toUri()),
+ bindingContext));
+ } catch (MetaschemaException ex) {
+ throw new CommandExecutionException(ExitCode.PROCESSING_ERROR, ex);
+ }
// determine if the query is evaluated against the module or the instance
if (cmdLine.hasOption(CONTENT_OPTION)) {
diff --git a/metaschema-maven-plugin/src/main/java/gov/nist/secauto/metaschema/maven/plugin/AbstractMetaschemaMojo.java b/metaschema-maven-plugin/src/main/java/gov/nist/secauto/metaschema/maven/plugin/AbstractMetaschemaMojo.java
index c27cf17cc..65aa80526 100644
--- a/metaschema-maven-plugin/src/main/java/gov/nist/secauto/metaschema/maven/plugin/AbstractMetaschemaMojo.java
+++ b/metaschema-maven-plugin/src/main/java/gov/nist/secauto/metaschema/maven/plugin/AbstractMetaschemaMojo.java
@@ -5,12 +5,12 @@
package gov.nist.secauto.metaschema.maven.plugin;
-import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.model.IConstraintLoader;
import gov.nist.secauto.metaschema.core.model.IModule;
import gov.nist.secauto.metaschema.core.model.IModuleLoader;
import gov.nist.secauto.metaschema.core.model.IResourceLocation;
import gov.nist.secauto.metaschema.core.model.MetaschemaException;
+import gov.nist.secauto.metaschema.core.model.constraint.ConstraintValidationException;
import gov.nist.secauto.metaschema.core.model.constraint.ConstraintValidationFinding;
import gov.nist.secauto.metaschema.core.model.constraint.ExternalConstraintsModulePostProcessor;
import gov.nist.secauto.metaschema.core.model.constraint.IConstraintSet;
@@ -425,7 +425,7 @@ protected Set getClassPath() throws DependencyResolutionRequiredExceptio
protected Set getModulesToGenerateFor(
@NonNull IBindingContext bindingContext,
@NonNull IModuleLoader.IModulePostProcessor modulePostProcessor)
- throws MetaschemaException, IOException {
+ throws MetaschemaException, IOException, ConstraintValidationException {
// Don't use the normal loader, since it attempts to register and compile the
// module.
@@ -718,12 +718,12 @@ public ModuleBindingGenerator(
}
@NonNull
- public IProduction generateClasses(@NonNull IModule module) {
+ public IProduction generateClasses(@NonNull IModule module) throws MetaschemaException {
IProduction production;
try {
production = JavaGenerator.generate(module, compilePath, bindingConfiguration);
} catch (IOException ex) {
- throw new MetapathException(
+ throw new MetaschemaException(
String.format("Unable to generate and compile classes for module '%s'.", module.getLocation()),
ex);
}
@@ -779,7 +779,7 @@ public void info(String msg) {
}
@Override
- public Class extends IBoundModule> generate(IModule module) {
+ public Class extends IBoundModule> generate(IModule module) throws MetaschemaException {
IProduction production = generateClasses(module);
try {
compileClasses(production, compilePath);
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 75872f719..21309911c 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
@@ -94,6 +94,7 @@ protected static AllowedValueCollection getContextIndependentEnumeratedValues(
closed = true;
}
+ // FIXME: Should this compare the actual compiled expression?
if (!IMetapathExpression.contextNode().getPath().equals(constraint.getTarget().getPath())) {
values = CollectionUtil.emptyList();
break;
diff --git a/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/AbstractSchemaGenerator.java b/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/AbstractSchemaGenerator.java
index 31a2c3d95..42b55feb1 100644
--- a/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/AbstractSchemaGenerator.java
+++ b/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/AbstractSchemaGenerator.java
@@ -109,9 +109,7 @@ protected List analyzeDefinitions(
@NonNull S generationState,
@Nullable BiConsumer handler) {
// TODO: use of handler here is confusing and introduces side effects. Consider
- // refactoring this in
- // the caller
-
+ // refactoring this in the caller
List rootAssemblyDefinitions = new LinkedList<>();
for (ModuleIndex.DefinitionEntry entry : generationState.getMetaschemaIndex().getDefinitions()) {
diff --git a/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/json/impl/JsonSchemaHelper.java b/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/json/impl/JsonSchemaHelper.java
index fd0d12fc2..fb59894a5 100644
--- a/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/json/impl/JsonSchemaHelper.java
+++ b/schemagen/src/main/java/gov/nist/secauto/metaschema/schemagen/json/impl/JsonSchemaHelper.java
@@ -20,7 +20,6 @@
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.StaticMetapathException;
import gov.nist.secauto.metaschema.core.model.IChoiceInstance;
import gov.nist.secauto.metaschema.core.model.IContainerModelAbsolute;
import gov.nist.secauto.metaschema.core.model.IFlagInstance;
@@ -199,12 +198,7 @@ public static List buildFlagProperties(
// determine the flag instances to generate
if (jsonKeyFlagName != null) {
- IFlagInstance jsonKeyFlag;
- try {
- jsonKeyFlag = definition.getFlagInstanceByName(jsonKeyFlagName.getIndexPosition());
- } catch (StaticMetapathException ex) {
- throw new IllegalArgumentException(ex);
- }
+ IFlagInstance jsonKeyFlag = definition.getFlagInstanceByName(jsonKeyFlagName.getIndexPosition());
if (jsonKeyFlag == null) {
throw new IllegalArgumentException(
String.format("The referenced json-key flag-name '%s' does not exist on definition '%s'.",