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 524a00073c GH-4058: Test RDF validity inside triple terms
524a00073c is described below
commit 524a00073ce3659824cf7813bf53312428fe2ca3
Author: Andy Seaborne <[email protected]>
AuthorDate: Sat Jul 11 17:15:59 2026 +0100
GH-4058: Test RDF validity inside triple terms
---
.../org/apache/jena/sparql/util/NodeUtils.java | 43 ++++++++++++++++++++--
.../java/org/apache/jena/sparql/api/TestAPI.java | 34 ++++++++++++++++-
2 files changed, 73 insertions(+), 4 deletions(-)
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeUtils.java
b/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeUtils.java
index 9719f89597..74f5b9c40c 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeUtils.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeUtils.java
@@ -211,6 +211,21 @@ public class NodeUtils
*/
public static boolean isDirLangString(Node n) { return
Util.isDirLangString(n); }
+ /**
+ * Determines whether a triple is valid as a RDF statement.
+ * <p>
+ * This function reflects the fact that the {@link Triple} API is flexible
in
+ * allowing any Node type in any position (including non-RDF node types
like
+ * Variable) and as such not all Triples can be safely converted into
Statements
+ * </p>
+ * @param triple Triple
+ * @return true if a valid as a statement
+ */
+ public static boolean isValidAsRDF(Triple triple) {
+ if ( triple == null )
+ return false;
+ return isValidAsRDF(triple.getSubject(), triple.getPredicate(),
triple.getObject());
+ }
/**
* Determines whether a triple (as s/p/o) is valid as a RDF statement.
@@ -222,7 +237,7 @@ public class NodeUtils
* @param s Subject
* @param p Predicate
* @param o Object
- * @return True if a valid as a statement
+ * @return true if a valid as a statement
*/
public static boolean isValidAsRDF(Node s, Node p, Node o) {
if ( s == null || ( ! s.isBlank() && ! s.isURI() ) )
@@ -231,20 +246,42 @@ public class NodeUtils
return false;
if ( o == null || ( ! o.isBlank() && ! o.isURI() && ! o.isLiteral() &&
!o.isTripleTerm() ) )
return false;
+
+ if ( o.isTripleTerm() ) {
+ Triple tt = o.getTriple();
+ return isValidAsRDF(tt.getSubject(), tt.getPredicate(),
tt.getObject());
+ }
return true;
}
+ /**
+ * Determines whether a quad is valid as a RDF statement.
+ * <p>
+ * This function reflects the fact that the {@link Triple} API is flexible
in
+ * allowing any Node type in any position (including non-RDF node types
like
+ * Variable) and as such not all quads can be safely converted into
Statements
+ * </p>
+ * @param quad Quad
+ * @return true if a valid as a graph name and statement
+ */
+ public static boolean isValidAsRDF(Quad quad) {
+ if ( quad == null )
+ return false;
+ return isValidAsRDF(quad.getGraph(), quad.getSubject(),
quad.getPredicate(), quad.getObject());
+ }
+
/**
* Determines whether a quad (as g/s/p/o) is valid as a RDF statement.
* <p>
* This function reflects the fact that the {@link Triple} API is flexible
in
* allowing any Node type in any position (including non-RDF node types
like
- * Variable) and as such not all Triples can be safely converted into
Statements
+ * Variable) and as such not all quads can be safely converted into
Statements
* </p>
+ * @param g Graph
* @param s Subject
* @param p Predicate
* @param o Object
- * @return True if a valid as a statement
+ * @return true if a valid as a graph name and statement
*/
public static boolean isValidAsRDF(Node g, Node s, Node p, Node o) {
if ( g == null || ( ! g.isURI() && ! g.isBlank() ) )
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/api/TestAPI.java
b/jena-arq/src/test/java/org/apache/jena/sparql/api/TestAPI.java
index 33bfdfa5c9..35c6947eed 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/api/TestAPI.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/api/TestAPI.java
@@ -71,7 +71,7 @@ public class TestAPI
}
@Test
- public void test_API1() {
+ public void testSelect1() {
String qs = "SELECT * {?s ?p ?o}";
try (QueryExecution qExec = QueryExecution.model(m).query(qs).build())
{
ResultSet rs = qExec.execSelect();
@@ -84,6 +84,38 @@ public class TestAPI
}
}
+ @Test
+ public void testConstruct1() {
+
+ String qs = "CONSTRUCT {?s ?p ?o} WHERE { ?s ?p ?o }";
+ try (QueryExecution qExec = QueryExecution.model(m).query(qs).build())
{
+ Model m2 = qExec.execConstruct();
+ assertTrue(!m2.isEmpty(), () -> "No results");
+ assertTrue(m.isIsomorphicWith(m2), ()-> "Not isonorphic");
+ }
+ }
+
+ @Test
+ public void testConstructBad1() {
+ String qs = """
+ PREFIX : <http://example/>
+ PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+ CONSTRUCT {
+ << 456 :p :o >> .
+ ?x :p :o .
+ :s ?x :o .
+ :tt1 :p <<( ?x :c2 :c3 )>> .
+ :tt2 :p <<( :c1 ?x :c3 )>> .
+ :tt3 :p <<( :c1 :c2 <<( ?x :d2 :d3 )>> )>> .
+ } WHERE { BIND(123 AS ?x) }
+ """;
+ // Bad triples in result. They should be filtered out.
+ try (QueryExecution qExec = QueryExecution.model(m).query(qs).build())
{
+ Model m2 = qExec.execConstruct();
+ assertTrue(m2.isEmpty(), () -> "Expected empty graph");
+ }
+ }
+
@Test
public void testSubstitutionConstruct1() {
QuerySolutionMap init = new QuerySolutionMap();