From 37f4980b3918831eed2ff68f3327cecd99fd9ba1 Mon Sep 17 00:00:00 2001 From: David Waltermire Date: Wed, 11 Dec 2024 20:32:39 -0500 Subject: [PATCH] Improved the error handling for constraint message replacements using Metapath expressions. Resolves #289. --- .../function/impl/AbstractFunction.java | 2 + .../DefaultConstraintValidator.java | 40 ++++++++++--------- ...AbstractConfigurableMessageConstraint.java | 13 +++++- 3 files changed, 35 insertions(+), 20 deletions(-) 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 069f7a8ab..0a7a77181 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 @@ -259,6 +259,8 @@ public ISequence execute( result = executeInternal(convertedArguments, dynamicContext, contextItem); if (callingContext != null) { + // ensure the result sequence is list backed + result.getValue(); // add result to cache dynamicContext.cacheResult(callingContext, result); } 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 63a22be4e..0fadac1dc 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 @@ -676,28 +676,32 @@ private void validateExpect( @NonNull INodeItem node, @NonNull ISequence targets, @NonNull DynamicContext dynamicContext) { - IMetapathExpression metapath = IMetapathExpression.compile( - constraint.getTest(), - dynamicContext.getStaticContext()); + try { + IMetapathExpression metapath = IMetapathExpression.compile( + constraint.getTest(), + dynamicContext.getStaticContext()); - IConstraintValidationHandler handler = getConstraintValidationHandler(); - targets.stream() - .forEachOrdered(item -> { - assert item != null; + 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); + 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, item, ex, dynamicContext); } - } - }); + }); + } catch (MetapathException ex) { + handleError(constraint, node, ex, dynamicContext); + } } /** 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 fe7a34a90..7738a9144 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,6 +9,7 @@ import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; import gov.nist.secauto.metaschema.core.metapath.DynamicContext; import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression; +import gov.nist.secauto.metaschema.core.metapath.MetapathException; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.model.IAttributable; import gov.nist.secauto.metaschema.core.model.ISource; @@ -95,8 +96,16 @@ public String generateMessage(@NonNull INodeItem item, @NonNull DynamicContext c return ObjectUtils.notNull(ReplacementScanner.replaceTokens(message, METAPATH_VALUE_TEMPLATE_PATTERN, match -> { String metapath = ObjectUtils.notNull(match.group(2)); - IMetapathExpression expr = IMetapathExpression.compile(metapath, context.getStaticContext()); - return expr.evaluateAs(item, IMetapathExpression.ResultType.STRING, context); + try { + IMetapathExpression expr = IMetapathExpression.compile(metapath, context.getStaticContext()); + return expr.evaluateAs(item, IMetapathExpression.ResultType.STRING, context); + } catch (MetapathException ex) { + throw new MetapathException( + String.format("Unable to evaluate the message replacement expression '%s'. %s", + metapath, + ex.getLocalizedMessage()), + ex); + } }).toString()); } }