[ 
https://issues.apache.org/jira/browse/JENA-2320?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17526380#comment-17526380
 ] 

Andy Seaborne edited comment on JENA-2320 at 4/22/22 12:27 PM:
---------------------------------------------------------------

A common violation happened would be nice, but the shape in question will have 
shape-specific data. That could be accessed by a visitor but that really only 
moves code around, and doesn't look like it is a real simplification.
 
Maybe these calls of {{vCxt.getValidationListener().onViolated...(...)}} during 
validation could be {{vCxt.violationOccured(shape, focus node, 
this).onViolated...(...)}} where {{violationOccured}} calls a new interface 
method in the lifecycle part "onViolation" in the listener and also returns the 
ValidationListener. That's both 1 and 2.

 
{code:java}
//ValidationContext::violationOccured
  public ValidationListener violationOccured(shape, focusNode, constraint) {
     getValidationListener().onViolated...(...)
    return getValidationListener();
}
 {code}
The way I see it is that there are really two listeners which are intertwined.

There is the general lifecycle:
{noformat}
onBeginValidateShape
onValueNodesDeterminedForPropertyShape
onViolation   <-- new
onEndValidateShape
onBeginValidateConstraint
onEndValidateConstraint
{noformat}
and the per constraint calls.

They aren't separate because the order/timing of calls is part of the overall 
contract . In a similar situation recently (ShEx printing) splitting into 
multiple interfaces can be artificial and likely implemented as one object with 
2 interfaces if it is going to share any state (like print depth for indenting 
trace information, or statistics counting things).


was (Author: andy.seaborne):
A common violation happened would be nice, but the shape in question will have 
shape-specific data. That could be accessed by a visitor but that really only 
moves code around, and doesn't look like it is a real simplification.
 
Maybe these calls of {{vCxt.getValidationListener().onViolated...(...)}} during 
validation could be {{vCxt.violationOccured(shape, focus 
node).onViolated...(...)}} where {{violationOccured}} calls a new interface 
method in the lifecycle part "onViolation" in the listener and also returns the 
ValidationListener. That's both 1 and 2.

 
{code:java}
//ValidationContext::violationOccured
  public ValidationListener violationOccured(shape, focusNode) {
     getValidationListener().onViolated...(...)
    return getValidationListener();
}
 {code}

The way I see it is that there are really two listeners which are intertwined.

There is the general lifecycle:
{noformat}
onBeginValidateShape
onValueNodesDeterminedForPropertyShape
onViolation   <-- new
onEndValidateShape
onBeginValidateConstraint
onEndValidateConstraint
{noformat}
and the per constraint calls.

They aren't separate because the order/timing of calls is part of the overall 
contract . In a similar situation recently (ShEx printing) splitting into 
multiple interfaces can be artificial and likely implemented as one object with 
2 interfaces if it is going to share any state (like print depth for indenting 
trace information, or statistics counting things).

> Callback or more detailed report from SHACL validation
> ------------------------------------------------------
>
>                 Key: JENA-2320
>                 URL: https://issues.apache.org/jira/browse/JENA-2320
>             Project: Apache Jena
>          Issue Type: New Feature
>          Components: SHACL
>            Reporter: Florian Kleedorfer
>            Priority: Minor
>
> Summary:
> Could we make the ValidationContext constructors protected and use instance 
> methods instead of the current static factory methods (at least for 
> {{create(ValidationContext)}} so that a subclassed ValidationContext can be 
> provided for validation that can also be propagated into the sub-evaluations?
> Explanation:
> I'm working on code that quite intimately builds on jena's SHACL validation. 
> Here's what I'm trying to do: There is a set of nodes V in the data graph G 
> that I am trying to find substitutions for by other RDF nodes. A substitution 
> is valid if no shape has a violation. Now for figuring out which 
> substitutions might be valid, it is not enough to know that shape S is 
> violated on focus node F - I need to know why exactly - i.e. which of my 
> substitutions made the validation fail. I already have a system in place that 
> notices which nodes in V (or their respective substitutes) are looked at 
> during evaluation of S. Also, If the violation is of a simple property shape, 
> I can follow the {{sh:ResultPath}} of the report from F to get to the node; 
> however, if the shape uses an aggregate like {{sh:xOne}}, or a {{sh:node}} 
> the report does not help me find the culprit, I just know it's one of the 
> nodes that were looked at.
> I have two ideas how this could be fixed for me:
> *More detailed report*
> An optional, non-standard report could be generated that always allows me to 
> figure out which of my substitutions for nodes in V (or lack thereof) caused 
> the violation. Maybe it would be enough to pass the validationreport of 
> sub-evaluations through to the main one.
> or 
> *ValidationCallback*
> A callback that I can provide for an evaluation, either as a method param to 
> {{VLib.validateShape()}}, as an optional member in the ValidationContext, or 
> in a ThreadLocal. The latter may be a problem if evaluation is done in 
> multiple threads, so maybe that's not such a great idea. 
> The callback would need to be called whenever a reportEntry is added to the 
> context - also in sub-evaluations that use a new context.
> One way with minimal impact on the codebase to achieve at least the second of 
> these solutions would be to allow me to extend the {{ValidationContext}} 
> (currently not possible because of the private constructors) and to allow me 
> to return my subclassed {{ValidationContext}} in 
> {{ValidationContext.create(ValidationContext)}} - and maybe also in the 
> other, currently static, factory methods. If that was possible, I could 
> easily intercept {{reportEntry}} methods, which (I hope) is enough.
> If that is an option, I'll provide a PR, so that I can make sure the 
> suggested changes really do solve my problem.



--
This message was sent by Atlassian Jira
(v8.20.7#820007)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to