You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2025/08/21 13:57:23 UTC

(jena) branch main updated: GH-3386: Include sh:sourceConstraint in SHACL SPARQL violations

This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new 928598dded GH-3386: Include sh:sourceConstraint in SHACL SPARQL violations
928598dded is described below

commit 928598dded85714e8cf63add9d90cdec613ce599
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Wed Aug 20 09:40:00 2025 +0100

    GH-3386: Include sh:sourceConstraint in SHACL SPARQL violations
---
 .../org/apache/jena/shacl/ValidationReport.java    |  9 ++++--
 .../jena/shacl/engine/ValidationContext.java       |  7 ++++-
 .../shacl/engine/constraint/SparqlValidation.java  |  2 +-
 .../apache/jena/shacl/validation/ReportEntry.java  | 35 +++++++++++-----------
 .../files/local/other/sparql-vars-001-results.ttl  |  1 +
 .../jena/shacl/tests/std/TestShaclSparqlWG.java    |  2 +-
 6 files changed, 34 insertions(+), 22 deletions(-)

diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/ValidationReport.java b/jena-shacl/src/main/java/org/apache/jena/shacl/ValidationReport.java
index dc4e03905e..1df900373b 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/ValidationReport.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/ValidationReport.java
@@ -176,10 +176,14 @@ public class ValidationReport {
         }
 
         public void addReportEntry(String message, Shape shape, Node focusNode, Path path, Node valueNode, Constraint constraint) {
-            addReportEntryW(message, shape, null, focusNode, path, valueNode, constraint);
+            addReportEntry(message, shape, focusNode, path, valueNode, constraint, null);
         }
 
-        private void addReportEntryW(String message, Shape shape, Triple triple, Node focusNode, Path path, Node valueNode, Constraint constraint) {
+        public void addReportEntry(String message, Shape shape, Node focusNode, Path path, Node valueNode, Constraint constraint, Node sourceConstraint) {
+            addReportEntryW(message, shape, null, focusNode, path, valueNode, constraint, sourceConstraint);
+        }
+
+        private void addReportEntryW(String message, Shape shape, Triple triple, Node focusNode, Path path, Node valueNode, Constraint constraint, Node sourceConstraint) {
             Collection<Node> messages;
 
             if ( shape.getMessages() != null && ! shape.getMessages().isEmpty() )
@@ -193,6 +197,7 @@ public class ValidationReport {
                 .severity(shape.getSeverity())
                 .source(shape.getShapeNode())
                 .constraint(constraint)
+                .sourceConstraint(sourceConstraint)
                 //.detail(null)
                 .value(valueNode)
                 .triple(triple)
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java
index 359d234ac6..eaaba7cbee 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java
@@ -99,10 +99,15 @@ public class ValidationContext {
     }
 
     public void reportEntry(String message, Shape shape, Node focusNode, Path path, Node valueNode, Constraint constraint) {
+        reportEntry(message, shape, focusNode, path, valueNode, constraint, null);
+    }
+
+    public void reportEntry(String message, Shape shape, Node focusNode, Path path, Node valueNode, Constraint constraint, Node sourceConstraint) {
+        // SHACL 1.0 - sourceConstraint is SPARQL specific.
         if ( verbose )
             System.out.println("Validation report entry");
         seenValidationReportEntry = true;
-        validationReportBuilder.addReportEntry(message, shape, focusNode, path, valueNode, constraint);
+        validationReportBuilder.addReportEntry(message, shape, focusNode, path, valueNode, constraint, sourceConstraint);
     }
 
     public ValidationReport generateReport() {
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/SparqlValidation.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/SparqlValidation.java
index 6f4a725010..1ceffdbcf2 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/SparqlValidation.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/SparqlValidation.java
@@ -184,7 +184,7 @@ import org.apache.jena.sparql.util.ModelUtils;
             final Node finalValue = value;
             vCxt.notifyValidationListener(() ->
                 new ConstraintEvaluatedOnSinglePathNodeEvent(vCxt, shape, focusNode, reportConstraint, finalRPath, finalValue, false));
-            vCxt.reportEntry(msg, shape, focusNode, rPath, value, reportConstraint);
+            vCxt.reportEntry(msg, shape, focusNode, rPath, value, reportConstraint, /*sh:sourceConstaint*/shape.getShapeNode());
         }
         return false;
     }
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ReportEntry.java b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ReportEntry.java
index 6358225faf..73e7e05b73 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ReportEntry.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ReportEntry.java
@@ -80,24 +80,25 @@ public class ReportEntry {
         return new ReportEntry();
     }
 
-//        sh:result    [ a                             sh:ValidationResult ;
-//            sh:focusNode                  ex:x ;
-//            sh:resultMessage              "Value does not have class http://example/ns#T" ;
-//            sh:resultSeverity             sh:Violation ;
-//            sh:sourceConstraintComponent  sh:ClassConstraintComponent ;
-//            sh:sourceShape                shx:class_T ;
-//            sh:value                      ex:x
-//          ]
 //    sh:result [
-//               a sh:ValidationResult ;
-//               sh:resultSeverity sh:Violation ;
-//               sh:focusNode ex:Bob ;
-//               sh:resultPath ex:age ;
-//               sh:value "twenty two" ;
-//               sh:resultMessage "ex:age expects a literal of datatype xsd:integer." ;
-//               sh:sourceConstraintComponent sh:DatatypeConstraintComponent ;
-//               sh:sourceShape ex:PersonShape-age ;
-//           ]
+//        a                             sh:ValidationResult ;
+//        sh:focusNode                  ex:x ;
+//        sh:resultMessage              "Value does not have class http://example/ns#T" ;
+//        sh:resultSeverity             sh:Violation ;
+//        sh:sourceConstraintComponent  sh:ClassConstraintComponent ;
+//        sh:sourceShape                shx:class_T ;
+//        sh:value                      ex:x
+//    ]
+//    sh:result [
+//        a                             sh:ValidationResult ;
+//        sh:resultSeverity             sh:Violation ;
+//        sh:focusNode                  ex:Bob ;
+//        sh:resultPath                 ex:age ;
+//        sh:value                      "twenty two" ;
+//        sh:resultMessage              "ex:age expects a literal of datatype xsd:integer." ;
+//        sh:sourceConstraintComponent  sh:DatatypeConstraintComponent ;
+//        sh:sourceShape ex:PersonShape-age ;
+//    ]
 
     public Node focusNode() { return focusNode; }
 
diff --git a/jena-shacl/src/test/files/local/other/sparql-vars-001-results.ttl b/jena-shacl/src/test/files/local/other/sparql-vars-001-results.ttl
index 88cd6fc18f..21a949fa1d 100644
--- a/jena-shacl/src/test/files/local/other/sparql-vars-001-results.ttl
+++ b/jena-shacl/src/test/files/local/other/sparql-vars-001-results.ttl
@@ -12,6 +12,7 @@ PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>
                  sh:resultMessage              "Property-value pair (<http://example/p1> 1) found";
                  sh:resultPath                 :p1;
                  sh:resultSeverity             sh:Violation;
+                 sh:sourceConstraint           <http://jena.apache.org/test/shape#PropertyValueShape>;        
                  sh:sourceConstraintComponent  sh:SPARQLConstraintComponent;
                  sh:sourceShape                <shape#PropertyValueShape>;
                  sh:value                      1
diff --git a/jena-shacl/src/test/java/org/apache/jena/shacl/tests/std/TestShaclSparqlWG.java b/jena-shacl/src/test/java/org/apache/jena/shacl/tests/std/TestShaclSparqlWG.java
index b0fe3300ea..9a2e0b9f5e 100644
--- a/jena-shacl/src/test/java/org/apache/jena/shacl/tests/std/TestShaclSparqlWG.java
+++ b/jena-shacl/src/test/java/org/apache/jena/shacl/tests/std/TestShaclSparqlWG.java
@@ -37,7 +37,7 @@ public class TestShaclSparqlWG {
     public static Collection<Object[]> data() throws Exception {
         String manifest = "src/test/files/std/sparql/manifest.ttl";
 
-        // The W3C WG tests for  SPARQL-based Constraints is made up of:
+        // The W3C WG tests for SPARQL-based Constraints is made up of:
         //String manifest = "src/test/files/std/sparql/property/manifest.ttl";
         //String manifest = "src/test/files/std/sparql/pre-binding/manifest.ttl";
         //String manifest = "src/test/files/std/sparql/node/manifest.ttl";