This is an automated email from the ASF dual-hosted git repository.
afs 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 641765ebe0 GH-4129: Fix: rdf:reifies triple dropped when a
substitution variable is used inside an RDF 1.2 annotation
641765ebe0 is described below
commit 641765ebe08caa67fe2742223e6d1e565f46e1cf
Author: Aditya Nikam <[email protected]>
AuthorDate: Sun Aug 9 13:28:35 2026 +0530
GH-4129: Fix: rdf:reifies triple dropped when a substitution variable is
used inside an RDF 1.2 annotation
---
.../syntax/syntaxtransform/QueryTransformOps.java | 30 +++++++++++-----
.../syntaxtransform/TestQuerySyntaxTransform.java | 40 ++++++++++++++++++++++
2 files changed, 62 insertions(+), 8 deletions(-)
diff --git
a/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/QueryTransformOps.java
b/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/QueryTransformOps.java
index 5ef86ea56f..e5eb167438 100644
---
a/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/QueryTransformOps.java
+++
b/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/QueryTransformOps.java
@@ -24,6 +24,7 @@ package org.apache.jena.sparql.syntax.syntaxtransform;
import java.util.*;
import org.apache.jena.graph.Node;
+import org.apache.jena.graph.NodeFactory;
import org.apache.jena.graph.Triple;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryVisitor;
@@ -336,14 +337,27 @@ public class QueryTransformOps {
// Transform a variable node.
// Returns the argument java object for "no transform"
private static Node transformOrSame(Node node, ExprTransform
exprTransform) {
- if ( ! Var.isVar(node) )
- return node;
- Expr e2 = exprTransform.transform(node);
- if ( e2 == null )
- return node;
- if ( ! e2.isConstant() )
- return node;
- return e2.getConstant().getNode();
+ if ( Var.isVar(node) ) {
+ Expr e2 = exprTransform.transform(node);
+ if ( e2 == null )
+ return node;
+ if ( ! e2.isConstant() )
+ return node;
+ return e2.getConstant().getNode();
+ }
+ // RDF 1.2 triple term (e.g. the object of an rdf:reifies triple from
a {| ... |}
+ // annotation) may itself contain variables. Recurse into the triple
term
+ // and replace any variables used inside a reified triple's annotation.
+ if ( node.isTripleTerm() && ! node.isConcrete() ) {
+ Triple triple = node.getTriple();
+ Node s = transformOrSame(triple.getSubject(), exprTransform);
+ Node p = transformOrSame(triple.getPredicate(), exprTransform);
+ Node o = transformOrSame(triple.getObject(), exprTransform);
+ if ( s == triple.getSubject() && p == triple.getPredicate() && o
== triple.getObject() )
+ return node;
+ return NodeFactory.createTripleTerm(s, p, o);
+ }
+ return node;
}
static class QueryShallowCopy implements QueryVisitor {
diff --git
a/jena-arq/src/test/java/org/apache/jena/sparql/syntax/syntaxtransform/TestQuerySyntaxTransform.java
b/jena-arq/src/test/java/org/apache/jena/sparql/syntax/syntaxtransform/TestQuerySyntaxTransform.java
index 74f11dd142..3140eeb1f0 100644
---
a/jena-arq/src/test/java/org/apache/jena/sparql/syntax/syntaxtransform/TestQuerySyntaxTransform.java
+++
b/jena-arq/src/test/java/org/apache/jena/sparql/syntax/syntaxtransform/TestQuerySyntaxTransform.java
@@ -22,21 +22,27 @@
package org.apache.jena.sparql.syntax.syntaxtransform;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.apache.jena.graph.Node;
+import org.apache.jena.graph.Triple;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryFactory;
+import org.apache.jena.query.Syntax;
import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.sparql.core.Quad;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.sse.SSE;
import org.apache.jena.sparql.util.ModelUtils;
import org.apache.jena.update.UpdateFactory;
import org.apache.jena.update.UpdateRequest;
+import org.apache.jena.vocabulary.RDF;
/** Test of variable replaced by value */
public class TestQuerySyntaxTransform
@@ -158,6 +164,40 @@ public class TestQuerySyntaxTransform
"s", "<urn:ex:z>", "g", "<urn:ex:g>");
}
+ @Test public void transformTransformReplace_reifies_01() {
+ String queryString = """
+ PREFIX ex: <http://example.com/>
+ CONSTRUCT {
+ ?this ex:seeAlso ex:Nothing {| ex:tempTriple true |} .
+ } WHERE {}
+ """ ;
+ Query query = QueryFactory.create(queryString, Syntax.syntaxARQ);
+
+ Node thing = SSE.parseNode("<http://www.w3.org/2002/07/owl#Thing>");
+ Node seeAlso = SSE.parseNode("<http://example.com/seeAlso>");
+ Node nothing = SSE.parseNode("<http://example.com/Nothing>");
+
+ Query transformed = QueryTransformOps.replaceVars(query,
Map.of(Var.alloc("this"), thing));
+ List<Quad> quads = transformed.getConstructTemplate().getQuads();
+
+ boolean hasBaseTriple = quads.stream().anyMatch(q ->
+ q.getSubject().equals(thing) &&
q.getPredicate().equals(seeAlso) && q.getObject().equals(nothing));
+ assertTrue(hasBaseTriple, "Base triple should have ?this substituted");
+
+ boolean hasCorrectReifiesTriple = quads.stream().anyMatch(q -> {
+ if ( ! RDF.Nodes.reifies.equals(q.getPredicate()) )
+ return false;
+ Node obj = q.getObject();
+ if ( ! obj.isTripleTerm() )
+ return false;
+ Triple reified = obj.getTriple();
+ return reified.getSubject().equals(thing)
+ && reified.getPredicate().equals(seeAlso)
+ && reified.getObject().equals(nothing);
+ });
+ assertTrue(hasCorrectReifiesTriple, "rdf:reifies triple's quoted
triple should also have ?this substituted");
+ }
+
@Test public void transformSubstituteupdate_01() {
testUpdate("DELETE { ?s <urn:ex:p> ?x } WHERE {}",
"DELETE { ?s <urn:ex:p> <urn:ex:z> } WHERE {}",