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 e68c9dd07d GH-2555: Allow ^^rdf:langString in result sets
e68c9dd07d is described below
commit e68c9dd07d64a2b98edd0e5bd8e1b20326611905
Author: Andy Seaborne <[email protected]>
AuthorDate: Fri Jul 5 18:50:27 2024 +0100
GH-2555: Allow ^^rdf:langString in result sets
---
jena-arq/pom.xml | 5 +
.../org/apache/jena/riot/rowset/RowSetReader.java | 7 +-
.../jena/riot/rowset/RowSetReaderRegistry.java | 9 ++
.../jena/riot/resultset/TS_ResultSetRIOT.java | 10 +-
.../org/apache/jena/riot/rowset/TS_RowSetRIOT.java | 12 ++-
.../jena/riot/rowset/rw/TestRowSetReader.java | 120 +++++++++++++++++++++
.../java/org/apache/jena/graph/NodeFactory.java | 30 ++++--
.../apache/jena/graph/test/TestNodeEdgeCases.java | 47 ++++++++
.../apache/jena/graph/test/TestPackage_graph.java | 1 +
9 files changed, 224 insertions(+), 17 deletions(-)
diff --git a/jena-arq/pom.xml b/jena-arq/pom.xml
index 0efa9cd1c8..952b52a4ae 100644
--- a/jena-arq/pom.xml
+++ b/jena-arq/pom.xml
@@ -127,6 +127,11 @@
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-suite-engine</artifactId>
+ </dependency>
+
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
diff --git
a/jena-arq/src/main/java/org/apache/jena/riot/rowset/RowSetReader.java
b/jena-arq/src/main/java/org/apache/jena/riot/rowset/RowSetReader.java
index 264f9cf9f6..c45b525488 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/rowset/RowSetReader.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/rowset/RowSetReader.java
@@ -21,12 +21,12 @@ package org.apache.jena.riot.rowset;
import java.io.InputStream;
import java.io.Reader;
+import org.apache.jena.riot.Lang;
import org.apache.jena.sparql.exec.QueryExecResult;
import org.apache.jena.sparql.exec.RowSet;
import org.apache.jena.sparql.util.Context;
public interface RowSetReader {
-
/**
* Read from an {@code InputStream} and produce a {@link RowSet}.
* Note that return row set may stream and so the input stream may be read
@@ -67,4 +67,9 @@ public interface RowSetReader {
public default RowSet read(Reader in, Context context) {
throw new UnsupportedOperationException("RowSetReader.read - input
from a Java Reader not supported. Use an InputStream.");
}
+
+ /** Convenience operation - create a {@link RowSetReader} for {@link Lang}
or return null. */
+ public static RowSetReader createReader(Lang lang) {
+ return RowSetReaderRegistry.createReader(lang);
+ }
}
diff --git
a/jena-arq/src/main/java/org/apache/jena/riot/rowset/RowSetReaderRegistry.java
b/jena-arq/src/main/java/org/apache/jena/riot/rowset/RowSetReaderRegistry.java
index 582fe3ba31..20da936741 100644
---
a/jena-arq/src/main/java/org/apache/jena/riot/rowset/RowSetReaderRegistry.java
+++
b/jena-arq/src/main/java/org/apache/jena/riot/rowset/RowSetReaderRegistry.java
@@ -35,6 +35,15 @@ public class RowSetReaderRegistry {
return registry.get(lang);
}
+ /** Create a {@link RowSetReader} for {@link Lang} or return null. */
+ public static RowSetReader createReader(Lang lang) {
+ Objects.requireNonNull(lang);
+ RowSetReaderFactory factory = getFactory(lang);
+ if ( factory == null )
+ return null;
+ return factory.create(lang);
+ }
+
/** Register a {@link RowSetReaderFactory} for a {@link Lang} */
public static void register(Lang lang, RowSetReaderFactory factory) {
Objects.requireNonNull(lang);
diff --git
a/jena-arq/src/test/java/org/apache/jena/riot/resultset/TS_ResultSetRIOT.java
b/jena-arq/src/test/java/org/apache/jena/riot/resultset/TS_ResultSetRIOT.java
index f29ee4b0d8..8b214fedf5 100644
---
a/jena-arq/src/test/java/org/apache/jena/riot/resultset/TS_ResultSetRIOT.java
+++
b/jena-arq/src/test/java/org/apache/jena/riot/resultset/TS_ResultSetRIOT.java
@@ -20,15 +20,15 @@ package org.apache.jena.riot.resultset;
import org.apache.jena.riot.resultset.rw.TestResultSetWriterCSV;
import org.apache.jena.riot.resultset.rw.TestResultSetWriterTSV;
-import org.junit.runner.RunWith ;
-import org.junit.runners.Suite ;
+import org.junit.platform.suite.api.*;
-@RunWith(Suite.class)
[email protected]( {
+@Suite
+@SelectClasses({
TestResultSetIO.class
+ , TestResultSetLang.class
, TestResultSetWriterCSV.class
, TestResultSetWriterTSV.class
, TestResultSetLang.class
-})
+ })
public class TS_ResultSetRIOT { }
diff --git
a/jena-arq/src/test/java/org/apache/jena/riot/rowset/TS_RowSetRIOT.java
b/jena-arq/src/test/java/org/apache/jena/riot/rowset/TS_RowSetRIOT.java
index 2cd1f05b4b..d2d91e562d 100644
--- a/jena-arq/src/test/java/org/apache/jena/riot/rowset/TS_RowSetRIOT.java
+++ b/jena-arq/src/test/java/org/apache/jena/riot/rowset/TS_RowSetRIOT.java
@@ -18,15 +18,17 @@
package org.apache.jena.riot.rowset;
+import org.apache.jena.riot.rowset.rw.TestRowSetReader;
import org.apache.jena.riot.rowset.rw.TestRowSetWriterCSV;
import org.apache.jena.riot.rowset.rw.TestRowSetWriterTSV;
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
+import org.junit.platform.suite.api.SelectClasses;
+import org.junit.platform.suite.api.Suite;;
-@RunWith(Suite.class)
[email protected]( {
+@Suite
+@SelectClasses({
TestRowSetWriterCSV.class,
- TestRowSetWriterTSV.class
+ TestRowSetWriterTSV.class,
+ TestRowSetReader.class
})
public class TS_RowSetRIOT { }
diff --git
a/jena-arq/src/test/java/org/apache/jena/riot/rowset/rw/TestRowSetReader.java
b/jena-arq/src/test/java/org/apache/jena/riot/rowset/rw/TestRowSetReader.java
new file mode 100644
index 0000000000..c340a19023
--- /dev/null
+++
b/jena-arq/src/test/java/org/apache/jena/riot/rowset/rw/TestRowSetReader.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.riot.rowset.rw;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.jena.atlas.io.IOX;
+import org.apache.jena.atlas.lib.Bytes;
+import org.apache.jena.query.ARQ;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.resultset.ResultSetLang;
+import org.apache.jena.riot.rowset.RowSetReader;
+import org.apache.jena.sparql.exec.RowSet;
+import org.apache.jena.sparql.exec.RowSetOps;
+import org.apache.jena.sys.JenaSystem;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Addition tests for result readers.
+ * The SPARQl test suite cover most usage. This class adds tests
+ */
+public class TestRowSetReader {
+ static { JenaSystem.init(); }
+
+ // Check "abc"^^rdf:langString and "abc"^^rdf:dirLangString and "
+ @Test public void resultSet_json_1() {
+ String r = """
+ {
+ "head": { "vars": [ "s" , "p" , "o" ] } ,
+ "results": {
+ "bindings": [
+ {
+ "s": { "type": "uri" , "value": "http://example/s" } ,
+ "p": { "type": "uri" , "value": "http://example/p" } ,
+ "o": { "type": "literal" , "datatype":
"http://www.w3.org/1999/02/22-rdf-syntax-ns#langString" , "value": "abc" }
+ } ,
+ {
+ "s": { "type": "uri" , "value": "http://example/s" } ,
+ "p": { "type": "uri" , "value": "http://example/p" } ,
+ "o": { "type": "literal" , "datatype":
"http://www.w3.org/1999/02/22-rdf-syntax-ns#dirLangString" , "value": "abc" }
+ }
+ ]
+ }}
+ """;
+ RowSet rowset = read(r, ResultSetLang.RS_JSON);
+ assertNotNull(rowset);
+ assertEquals(2, RowSetOps.count(rowset));
+ }
+
+ @Test public void resultSet_xml_1() {
+ String r = """
+<?xml version="1.0"?>
+<sparql xmlns="http://www.w3.org/2005/sparql-results#">
+ <head>
+ <variable name="s"/>
+ <variable name="p"/>
+ <variable name="o"/>
+ </head>
+ <results>
+ <result>
+ <binding name="s">
+ <uri>http://example/s</uri>
+ </binding>
+ <binding name="p">
+ <uri>http://example/p</uri>
+ </binding>
+ <binding name="o">
+ <literal
datatype="http://www.w3.org/1999/02/22-rdf-syntax-ns#langString">abc</literal>
+ </binding>
+ </result>
+ <result>
+ <binding name="s">
+ <uri>http://example/s</uri>
+ </binding>
+ <binding name="p">
+ <uri>http://example/p</uri>
+ </binding>
+ <binding name="o">
+ <literal
datatype="http://www.w3.org/1999/02/22-rdf-syntax-ns#dirLangString">abc</literal>
+ </binding>
+ </result>
+
+ </results>
+</sparql>
+ """;
+ RowSet rowset = read(r, ResultSetLang.RS_XML);
+ assertNotNull(rowset);
+ assertEquals(2, RowSetOps.count(rowset));
+ }
+
+ private static RowSet read(String x, Lang rsLang) {
+ try ( InputStream input = new
ByteArrayInputStream(Bytes.string2bytes(x)) ) {
+ RowSet rowSet = RowSetReader.createReader(rsLang)
+ .read(input, ARQ.getContext().copy())
+ .materialize();
+ return rowSet;
+ } catch (IOException ex) { throw IOX.exception(ex); }
+ }
+}
diff --git a/jena-core/src/main/java/org/apache/jena/graph/NodeFactory.java
b/jena-core/src/main/java/org/apache/jena/graph/NodeFactory.java
index 264046092f..4979cb06c8 100644
--- a/jena-core/src/main/java/org/apache/jena/graph/NodeFactory.java
+++ b/jena-core/src/main/java/org/apache/jena/graph/NodeFactory.java
@@ -224,22 +224,40 @@ public class NodeFactory {
if ( ! dtype.equals(RDFLangString.rdfLangString) )
throw new JenaException("Datatype is not
rdf:langString but a language was given");
} else {
- if ( ! dtype.equals(RDFDirLangString.rdfDirLangString) )
+ if ( ! dtype.equals(RDFDirLangString.rdfDirLangString) )
throw new JenaException("Datatype is not
rdf:dirLangString but a language and initial text direction was given");
}
}
return createLiteralDirLang(lex, langFmt, textDir);
}
+
if ( dtype == null )
// No datatype, no lang (it is null or "") => xsd:string.
return createLiteralString(lex);
- // No lang, with a datatype
- if ( dtype.equals(RDFLangString.rdfLangString) )
- throw new JenaException("Datatype is rdf:langString but no
language given");
- if ( dtype.equals(RDFDirLangString.rdfDirLangString) &&
noTextDir(textDir) )
- throw new JenaException("Datatype is rdf:dirLangString but no
initial text direction given");
+ // No language. Has a datatype.
+ boolean hasTextDirLang = ( textDir != null );
+ if ( hasTextDirLang ) {
+ if ( dtype.equals(RDFDirLangString.rdfDirLangString) ) {
+ // No language. Datatype is rdf:dirLangString, Does have an
initial text direction
+ throw new JenaException("Datatype is rdf:dirLangString and has
an initial text direction but no language given");
+ } else if ( dtype.equals(RDFLangString.rdfLangString) ) {
+ // No language. Datatype is rdf:langString, Does have an
initial text direction.
+ throw new JenaException("Datatype is rdf:langString and has an
initial text direction but no language given");
+ }
+ }
+
+ // Datatype. No language, no initial text direction.
+ // Allow "abc"^^rdf:langString
+ // Allow "abc"^^rdf:dirLangString
+
+ // To disallow.
+// if ( dtype.equals(RDFLangString.rdfLangString) )
+// throw new JenaException("Datatype is rdf:langString but no
language given");
+// if ( dtype.equals(RDFDirLangString.rdfDirLangString) &&
noTextDir(textDir) )
+// throw new JenaException("Datatype is rdf:dirLangString but no
initial text direction given");
+
Node n = createLiteralDT(lex, dtype);
return n;
}
diff --git
a/jena-core/src/test/java/org/apache/jena/graph/test/TestNodeEdgeCases.java
b/jena-core/src/test/java/org/apache/jena/graph/test/TestNodeEdgeCases.java
new file mode 100644
index 0000000000..43cd6f2813
--- /dev/null
+++ b/jena-core/src/test/java/org/apache/jena/graph/test/TestNodeEdgeCases.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.graph.test;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.jena.datatypes.xsd.impl.RDFDirLangString;
+import org.apache.jena.datatypes.xsd.impl.RDFLangString;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.NodeFactory;
+import org.junit.Test;
+
+public class TestNodeEdgeCases {
+
+ // Corner cases of NodeFactory
+ @Test public void term_create_01() {
+ // "abc"^^rdf:langString (no language)
+ Node node1 = NodeFactory.createLiteral("abc", null, (String)null,
RDFLangString.rdfLangString);
+ assertNotNull(node1);
+ Node node2 = NodeFactory.createLiteralDT("abc",
RDFLangString.rdfLangString);
+ assertNotNull(node2);
+ }
+
+ @Test public void term_create_02() {
+ // "abc"^rdf:dirLangString (no language, no initial text direction)
+ Node node1 = NodeFactory.createLiteral("abc", null, (String)null,
RDFDirLangString.rdfDirLangString);
+ assertNotNull(node1);
+ Node node2 = NodeFactory.createLiteralDT("abc",
RDFDirLangString.rdfDirLangString);
+ assertNotNull(node2);
+ }
+}
diff --git
a/jena-core/src/test/java/org/apache/jena/graph/test/TestPackage_graph.java
b/jena-core/src/test/java/org/apache/jena/graph/test/TestPackage_graph.java
index 5236ca13b5..ee2606b951 100644
--- a/jena-core/src/test/java/org/apache/jena/graph/test/TestPackage_graph.java
+++ b/jena-core/src/test/java/org/apache/jena/graph/test/TestPackage_graph.java
@@ -55,6 +55,7 @@ public class TestPackage_graph extends TestSuite {
addTestSuite( TestGraphBaseToString.class );
addTest( new JUnit4TestAdapter(TestNodeExtras.class) );
addTest( new JUnit4TestAdapter(TestRDFStringLiterals.class) );
+ addTest( new JUnit4TestAdapter(TestNodeEdgeCases.class) );
// Has to be in a different package.
addTest( new JUnit4TestAdapter(TestGraphUtil.class) );