Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 329a6c4

Browse files
committedJun 18, 2025
Make Node and ExprTransform affect OpPropFunc arguments
1 parent e828a50 commit 329a6c4

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed
 

‎jena-arq/src/main/java/org/apache/jena/sparql/algebra/walker/ApplyTransformVisitor.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import org.apache.jena.atlas.lib.InternalErrorException ;
2424
import org.apache.jena.atlas.logging.Log ;
25+
import org.apache.jena.graph.Node ;
2526
import org.apache.jena.query.SortCondition ;
2627
import org.apache.jena.sparql.algebra.Op ;
2728
import org.apache.jena.sparql.algebra.OpVisitor ;
@@ -30,7 +31,9 @@
3031
import org.apache.jena.sparql.core.Var ;
3132
import org.apache.jena.sparql.core.VarExprList ;
3233
import org.apache.jena.sparql.expr.* ;
34+
import org.apache.jena.sparql.expr.NodeValue ;
3335
import org.apache.jena.sparql.expr.aggregate.Aggregator ;
36+
import org.apache.jena.sparql.pfunction.PropFuncArg ;
3437

3538
/** Apply the {@link Transform}, {@link ExprTransform}
3639
* Works in conjunction with {@link WalkerVisitor}.
@@ -335,6 +338,55 @@ public void visit(OpFilter opFilter) {
335338
push(opStack, f.apply(opTransform, subOp)) ;
336339
}
337340

341+
protected PropFuncArg visitPropFuncArg(PropFuncArg arg) {
342+
ExprList in = arg.asExprList() ;
343+
ExprList out = collect(in);
344+
345+
PropFuncArg result;
346+
if (out.equals(in)) {
347+
result = arg;
348+
} else {
349+
if (arg.isNode()) {
350+
Node n = ExprLib.exprToNode(out.get(0));
351+
result = new PropFuncArg(n);
352+
} else {
353+
List<Node> nodes = out.getList().stream().map(ExprLib::exprToNode).toList();
354+
result = new PropFuncArg(nodes);
355+
}
356+
}
357+
return result;
358+
}
359+
360+
@Override
361+
public void visit(OpPropFunc opPropFunc) {
362+
Op outSubOp = null;
363+
Op inSubOp = opPropFunc.getSubOp();
364+
if (inSubOp != null) {
365+
outSubOp = pop(opStack);
366+
}
367+
368+
// This logic would also rename the function name
369+
// (update OpVistorByTypeAndExpr to put the name onto the stack).
370+
// List<Expr> opProperty = collect(1);
371+
// Node inP = opPropFunc.getProperty();
372+
// Node outP = ExprLib.exprToNode(opProperty.get(0));
373+
374+
Node outP = opPropFunc.getProperty();
375+
376+
PropFuncArg inS = opPropFunc.getSubjectArgs();
377+
PropFuncArg outS = visitPropFuncArg(inS);
378+
379+
PropFuncArg inO = opPropFunc.getObjectArgs();
380+
PropFuncArg outO = visitPropFuncArg(inO);
381+
382+
OpPropFunc f = opPropFunc;
383+
if (inS != outS || inO != outO || inSubOp != outSubOp /* || inP != outP */) {
384+
f = new OpPropFunc(outP, outS, outO, outSubOp);
385+
}
386+
387+
push(opStack, f.apply(opTransform, outSubOp)) ;
388+
}
389+
338390
@Override
339391
public void visit(OpLeftJoin op) {
340392
Op left = null ;

‎jena-arq/src/main/java/org/apache/jena/sparql/algebra/walker/OpVisitorByTypeAndExpr.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ public default void visit(OpProcedure opProcedure) {
9494

9595
@Override
9696
public default void visit(OpPropFunc opPropFunc) {
97+
visitExpr(opPropFunc.getObjectArgs().asExprList());
98+
visitExpr(opPropFunc.getSubjectArgs().asExprList());
99+
// visitExpr(new ExprList(ExprLib.nodeToExpr(opPropFunc.getProperty())));
97100
visit1(opPropFunc);
98101
}
99102

‎jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprLib.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,20 @@ public static Expr nodeToExpr(Node n) {
224224
return NodeValue.makeNode(n);
225225
}
226226

227+
/**
228+
* Go from an expression to a node.
229+
* If the argument cannot be converted to a node then an {@link IllegalArgumentException} is raised.
230+
*/
231+
public static Node exprToNode(Expr e) {
232+
if (e.isConstant()) {
233+
return e.getConstant().asNode();
234+
} else if (e.isVariable()) {
235+
return e.getExprVar().asVar();
236+
} else {
237+
throw new IllegalArgumentException("Cannot convert Expression to Node: " + e);
238+
}
239+
}
240+
227241
public static Expr rewriteTriple(Triple t) {
228242
Expr e1 = nodeToExpr(t.getSubject());
229243
Expr e2 = nodeToExpr(t.getPredicate());

‎jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestNodeTransform.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import static org.junit.Assert.assertEquals;
2222

23+
import org.apache.jena.graph.NodeFactory;
2324
import org.apache.jena.query.Query;
2425
import org.apache.jena.query.QueryFactory;
2526
import org.apache.jena.sparql.core.Var;
@@ -109,4 +110,28 @@ private static void testOp(Op opExpected, Op opInput, NodeTransform nt) {
109110
? Var.alloc(n.getName() + "ZZZ")
110111
: n;
111112
};
113+
114+
@Test
115+
public void transformPropFunc() {
116+
Op inOp = SSE.parseOp("""
117+
(propfunc <urn:p>
118+
<urn:x> ("y" ?z)
119+
(table unit))
120+
""");
121+
122+
// Property function name is not affected by node transform.
123+
Op expectedOp = SSE.parseOp("""
124+
(propfunc <urn:p>
125+
<URN:X> ("Y" ?Z)
126+
(table unit))
127+
""");
128+
129+
Op actualOp = NodeTransformLib.transform(x ->
130+
x.isURI() ? NodeFactory.createURI(x.getURI().toUpperCase()) :
131+
x.isVariable() ? Var.alloc(x.getName().toUpperCase()) :
132+
x.isLiteral() ? NodeFactory.createLiteralString(x.getLiteralLexicalForm().toUpperCase()) :
133+
x, inOp);
134+
135+
assertEquals(expectedOp, actualOp);
136+
}
112137
}

0 commit comments

Comments
 (0)
Please sign in to comment.