From 79a04c0d5c875594a8d1cf96487cb7733ca5457b Mon Sep 17 00:00:00 2001 From: Andy Seaborne Date: Sun, 10 Jun 2018 17:29:23 +0100 Subject: [PATCH 1/2] JENA-1563: Accept lang and dt=rdf:langString --- .../riot/resultset/rw/ResultSetReaderJSON.java | 13 +++++++++++-- .../org/apache/jena/datatypes/TypeMapper.java | 18 +++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java index e13cc23b7b8..045bd641533 100644 --- a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java +++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java @@ -51,6 +51,7 @@ import org.apache.jena.sparql.resultset.ResultSetException; import org.apache.jena.sparql.resultset.SPARQLResult; import org.apache.jena.sparql.util.Context; +import org.apache.jena.vocabulary.RDF; /** Read JSON format SPARQL Results. *

@@ -209,8 +210,16 @@ private static Node parseOneTerm(JsonObject term, LabelToNode labelMap) { if ( kLiteral.equals(type) || kTypedLiteral.equals(type) ) { String lang = stringOrNull(term, kXmlLang); String dtStr = stringOrNull(term, kDatatype); - if ( lang != null && dtStr != null ) - throw new ResultSetException("Both language and datatype defined: " + term); + if ( lang != null ) { + // Strictly, xml:lang=... and datatype=rdf:langString is wrong (the datatype should be absent) + // The RDF specs recommend omitting the datatype. They did however come after the SPARQL 1.1 docs + // it's more of a "SHOULD" than a "MUST". + // datatype=xsd:string is also unnecessary. + if ( dtStr != null && ! dtStr.equals(RDF.dtLangString.getURI() ) ) { + // Must agree. + throw new ResultSetException("Both language and datatype defined, datatype is not rdf:langString:\n" + term); + } + } RDFDatatype dt = TypeMapper.getInstance().getSafeTypeByName(dtStr); return NodeFactory.createLiteral(v, lang, dt); } diff --git a/jena-core/src/main/java/org/apache/jena/datatypes/TypeMapper.java b/jena-core/src/main/java/org/apache/jena/datatypes/TypeMapper.java index c5058896c8a..30d41ab8430 100644 --- a/jena-core/src/main/java/org/apache/jena/datatypes/TypeMapper.java +++ b/jena-core/src/main/java/org/apache/jena/datatypes/TypeMapper.java @@ -106,14 +106,18 @@ public TypeMapper() { /** - * Version of getTypeByName which will treat unknown URIs as typed - * literals but with just the default implementation + * Version of getTypeByName which will treat unknown URIs as typed literals but with + * just the default implementation + *

+ * RDF 1.1: null for {@code uri} returns null and it wil mean {@code xsd:string} + * because plain literals (no lang tag) and xsd:strings are now the same. * - * @param uri the URI of the desired datatype - * @return Datatype the datatype definition - * registered at uri, if there is no such registered type it - * returns a new instance of the default datatype implementation, if the - * uri is null it returns null (indicating a plain RDF literal). + * @param uri + * the URI of the desired datatype + * @return Datatype the datatype definition registered at uri, if there is no such + * registered type it returns a new instance of the default datatype + * implementation, if the uri is null it returns null (indicating a plain RDF + * literal). */ public RDFDatatype getSafeTypeByName(final String uri) { RDFDatatype dtype = uriToDT.get(uri); From aab46d434912d751c7e86cbf28c708812cb1001e Mon Sep 17 00:00:00 2001 From: Andy Seaborne Date: Thu, 14 Jun 2018 11:30:02 +0100 Subject: [PATCH 2/2] JENA-1563: Tests --- .../jena/sparql/resultset/TestResultSet.java | 21 +++++++++++++++++++ jena-arq/testing/ResultSet/output2.srj | 0 jena-arq/testing/ResultSet/output2.srx | 12 ----------- .../testing/ResultSet/rs-datatype-string.srj | 16 ++++++++++++++ .../ResultSet/rs-xmllang-datatype-1.srj | 16 ++++++++++++++ .../ResultSet/rs-xmllang-datatype-2.srj | 16 ++++++++++++++ .../org/apache/jena/datatypes/TypeMapper.java | 2 +- 7 files changed, 70 insertions(+), 13 deletions(-) delete mode 100644 jena-arq/testing/ResultSet/output2.srj delete mode 100644 jena-arq/testing/ResultSet/output2.srx create mode 100644 jena-arq/testing/ResultSet/rs-datatype-string.srj create mode 100644 jena-arq/testing/ResultSet/rs-xmllang-datatype-1.srj create mode 100644 jena-arq/testing/ResultSet/rs-xmllang-datatype-2.srj diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSet.java b/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSet.java index bff88a90b83..85db33bf4f6 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSet.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSet.java @@ -194,6 +194,27 @@ public static void teardown() { assertFalse(rs.hasNext()); } + // Test reading "variations". Things that are accepted but not in the form Jena writes. + + // JENA-1563: xml:lang= and datatype=rdf:langString + @Test + public void rs_xmllang_datatype_1() { + ResultSetFactory.load(DIR + "rs-xmllang-datatype-1.srj"); + } + + // JENA-1563: xml:lang= and incompatible datatype + @Test(expected=ResultSetException.class) + public void rs_xmllang_datatype_2() { + // Bad: datatype is not rdf:langString (it is xsd:string in the test data) + ResultSetFactory.load(DIR + "rs-xmllang-datatype-2.srj"); + } + + // Explicit (unnecessary) datatype=xsd:string + @Test + public void rs_datatype_string() { + ResultSet rs = ResultSetFactory.load(DIR + "rs-datatype-string.srj"); + } + @Test public void test_RS_union_1() { ResultSet rs1 = make("x", org.apache.jena.graph.NodeFactory.createURI("tag:local")) ; diff --git a/jena-arq/testing/ResultSet/output2.srj b/jena-arq/testing/ResultSet/output2.srj deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/jena-arq/testing/ResultSet/output2.srx b/jena-arq/testing/ResultSet/output2.srx deleted file mode 100644 index 98e9aa79c3c..00000000000 --- a/jena-arq/testing/ResultSet/output2.srx +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - true - - diff --git a/jena-arq/testing/ResultSet/rs-datatype-string.srj b/jena-arq/testing/ResultSet/rs-datatype-string.srj new file mode 100644 index 00000000000..9d49058e098 --- /dev/null +++ b/jena-arq/testing/ResultSet/rs-datatype-string.srj @@ -0,0 +1,16 @@ +{ + "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/2001/XMLSchema#string", + "value": "foo" } + } + ] + } +} diff --git a/jena-arq/testing/ResultSet/rs-xmllang-datatype-1.srj b/jena-arq/testing/ResultSet/rs-xmllang-datatype-1.srj new file mode 100644 index 00000000000..700aa7a7ccb --- /dev/null +++ b/jena-arq/testing/ResultSet/rs-xmllang-datatype-1.srj @@ -0,0 +1,16 @@ +{ + "head": { + "vars": [ "s" , "p" , "o" ] + } , + "results": { + "bindings": [ + { + "s": { "type": "uri" , "value": "http://example/s" } , + "p": { "type": "uri" , "value": "http://example/p" } , + "o": { "type": "literal" , + "xml:lang": "en" , + "datatype" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", + "value": "foo" } + } ] + } +} diff --git a/jena-arq/testing/ResultSet/rs-xmllang-datatype-2.srj b/jena-arq/testing/ResultSet/rs-xmllang-datatype-2.srj new file mode 100644 index 00000000000..a3a878fb294 --- /dev/null +++ b/jena-arq/testing/ResultSet/rs-xmllang-datatype-2.srj @@ -0,0 +1,16 @@ +{ + "head": { + "vars": [ "s" , "p" , "o" ] + } , + "results": { + "bindings": [ + { + "s": { "type": "uri" , "value": "http://example/s" } , + "p": { "type": "uri" , "value": "http://example/p" } , + "o": { "type": "literal" , + "xml:lang": "en" , + "datatype" : "http://www.w3.org/2001/XMLSchema#string", + "value": "foo" } + } ] + } +} diff --git a/jena-core/src/main/java/org/apache/jena/datatypes/TypeMapper.java b/jena-core/src/main/java/org/apache/jena/datatypes/TypeMapper.java index 30d41ab8430..1da6913042c 100644 --- a/jena-core/src/main/java/org/apache/jena/datatypes/TypeMapper.java +++ b/jena-core/src/main/java/org/apache/jena/datatypes/TypeMapper.java @@ -109,7 +109,7 @@ public TypeMapper() { * Version of getTypeByName which will treat unknown URIs as typed literals but with * just the default implementation *

- * RDF 1.1: null for {@code uri} returns null and it wil mean {@code xsd:string} + * RDF 1.1: null for {@code uri} returns null and it will mean {@code xsd:string} * because plain literals (no lang tag) and xsd:strings are now the same. * * @param uri