On 10/9/14 3:39 AM, "Andy Seaborne" <a...@apache.org> wrote:
>Nicolas, > >Which version of Jena are you referring to? (the line number for >RDFDataMgr does not seem to line up). This is from the 2.11.2 version of jena-arq In the git master branch, the corresponding code is at line 1331: private static void write$(OutputStream out, DatasetGraph dataset, RDFFormat serialization) { WriterDatasetRIOT w = createDatasetWriter$(serialization) ; w.write(out, dataset, RiotLib.prefixMap(dataset), null, null) ; // line 1331 } >And what's the data being serialized? There is some BananaDRF >processing applied to the data read in teh example. Could you provide >(N-Triples is quite forgiving) the data or a short, standalone program >that can produce it? The test was originally written like this: "write simple graph as TURTLE string" in { val turtleString = writer.asString(referenceGraph, "http://www.w3.org/2001/sw/RDFCore/").get turtleString should not be ('empty) val graph = Await.result(reader.read(turtleString, rdfCore), Duration(1, SECONDS)) assert(referenceGraph isIsomorphicWith graph) } At this point, "referenceGraph" is well-formed: every URI is absolute {http://www.w3.org/2001/sw/RDFCore/ntriples/ @http://purl.org/dc/elements/1.1/publisher http://www.w3.org/; http://www.w3.org/2001/sw/RDFCore/ntriples/ @http://purl.org/dc/elements/1.1/creator "Art Barstow"; http://www.w3.org/2001/sw/RDFCore/ntriples/ @http://purl.org/dc/elements/1.1/creator "Dave Beckett"} When writer.asString() executes, it calls this: def asString(graph: Jena#Graph, base: String): Try[String] = Try { val result = new StringWriter() import org.w3.banana.jena.Jena.ops._ val relativeGraph : Jena#Graph = graph.relativize(URI(base)) RDFDataMgr.write(result, relativeGraph, lang) result.toString() } graph.relativize() is a banana-rdf API -- it constructs a new Jena Graph: {ntriples/ @http://purl.org/dc/elements/1.1/creator "Dave Beckett"; ntriples/ @http://purl.org/dc/elements/1.1/creator "Art Barstow"; ntriples/ @http://purl.org/dc/elements/1.1/publisher http://www.w3.org/} As I mentioned above, the Jena API RDFDataMgr.write() does not provide a way to pass a base URI for the graph. So given a relative Jena Graph as input, we get the serialization of that graph which is also relative (as the value of the "result" string writer: <ntriples/> <http://purl.org/dc/elements/1.1/creator> "Dave Beckett" , "Art Barstow" ; <http://purl.org/dc/elements/1.1/publisher> <http://www.w3.org/> . > >There is some confusion about relative URIs here. Possibly > >The RDF data model is defined in terms of absolute URIs. A relative URI >should never occur in an RDF graph. They can occur in RDF syntax. However, the Jena API -- specifically RDFDataMgr.write() -- seems to exepect that all URIs in the input graph are absolute since it does not provide support for specifying a base URI for relative URIs in the graph. > >A base URI on writing is used to convert an absolute URI to a relative >one in the output syntax. As the base URI is also written out, the >whole RDF Graph still has absolute URIs when read back in again. I think the problem is the following: - it is possible to construct a Jena Graph where some URIs are relative. - some of Jena's "write" APIs do not provide a way to specify the base URI for converting relative URIs in the graph into absolute URIs in the output syntax (whether it is using a "@base" or not) > >The report you reference was caused by "" as a subject URI. That's not >legal RDF. <> is not "". Sorry -- I don't understand what you're referring to. > >Supplying the baseURI on writing only affects the abbreviation of URIs >in the data. They must be absolute in the data in the first place. I agree with you except that, as I explained above, it *is* possible to construct Jena Graphs where some URIs are relative. Perhaps writing such graphs (regardless of the output format) should throw an exception unless one is supplying a base URI. > >BananaRDF has some way to use Jena so that it creates the output it >wants. I thought BananaRDF achieved this by adding some sort of >identifiable maker to URIs as the initial part of the URI. No. Here's my understanding of the design & goal of the banana-rdf API (I'm a recent user) banana-rdf is effectively a parameterized API for RDF. The API parameter "binds" the generic banana-rdf API types & operations to the types & operations of a particular API library (e.g. Jena, Sesame, etcŠ) So normally, it shouldn't matter which library one uses -- Jena, Sesame, etc.. -- the results should be consistent. For example, reading a graph with one API and reading the same graph with another API should result in 2 API-specific graphs that should be isomorphic to each other as far as the W3 RDF spec is concerned. Banana-rdf provides a generic API for constructing RDF graphs -- I.e., the same code can be compiled by binding the parameter to, e.g. The Jena API or the Sesame API. Similarly, constructing a graph with the banana-rdf API and serializing with different libraries -- e.g., Jena, Sesame -- should result in 2 API-specific serializations of graphs that should be isomorphic to each other as far as the W3 RDF spec is concerned. - Nicolas. > > Andy > >On 09/10/14 00:26, Rouquette, Nicolas F (313D) wrote: >> I understand that several folks have had this exception in conjunction >> with Fuseki/TDB: >> >>http://jena.markmail.org/search/?q=BadURIException#query:BadURIException+ >>pa >> ge:1+mid:fur2joez3ny5ibvw+state:results >> >> I've tracked down this exception in a Scala example from the >>w3/banana-rdf >> project -- specifically: >> >>https://github.com/w3c/banana-rdf/blob/master/examples/src/main/scala/org >>/w >> 3/banana/examples/IOExample.scala >> >> This exception happens during the RDF/XML serialization: >> >> Unparser.wObjStar() line: 358 >> Unparser.wRDF() line: 345 >> Unparser.write() line: 247 >> Abbreviated.writeBody(Model, PrintWriter, String, Boolean) line: 142 >> BaseXMLWriter.writeXMLBody(Model, PrintWriter, String) line: 492 >> BaseXMLWriter.write(Model, Writer, String) line: 464 >> Abbreviated.write(Model, Writer, String) line: 127 >> BaseXMLWriter.write(Model, OutputStream, String) line: 450 >> AdapterRDFWriter.write(OutputStream, Graph, PrefixMap, String, Context) >> line: 52 >> RDFDataMgr.write$(OutputStream, Graph, RDFFormat) line: 1262 >> RDFDataMgr.write(OutputStream, Graph, RDFFormat) line: 1028 >> RDFDataMgr.write(OutputStream, Graph, Lang) line: 1018 >> JenaRDFWriter$$anon$1$$anonfun$write$1.apply$mcV$sp() line: 20 >> JenaRDFWriter$$anon$1$$anonfun$write$1.apply() line: 17 >> JenaRDFWriter$$anon$1$$anonfun$write$1.apply() line: 17 >> Try$.apply(Function0) line: 191 >> JenaRDFWriter$$anon$1.write(Graph, OutputStream, String) line: 17 >> JenaRDFWriter$$anon$1.write(Object, OutputStream, String) line: 15 >> IOExample$class.main(IOExample, Array[String]) line: 44 >> IOExampleWithJena$.main(Array[String]) line: 64 >> IOExampleWithJena.main(Array[String]) line: not available >> >> >> I believe the problem originates, in part, here: >> >> RDFDataMgr.write$(OutputStream, Graph, RDFFormat) line: 1262 >> >> >> private static void write$(OutputStream out, Graph graph, RDFFormat >> serialization) >> { >> WriterGraphRIOT w = createGraphWriter$(serialization) ; >> w.write(out, graph, RiotLib.prefixMap(graph), null, null) ; // >> line 1262 >> } >> >> The last 2 null arguments are the values for the "baseURI" and "context" >> parameters. >> Are all writers able to cope with a null base URI? > > > > >> >> It seems that the Turtle writer can but not the RDF/XML writer. >> The BadURIException happens during Unparser.wObjStar() when one of the >> Resources has a null URI: >> >> BaseXMLWriter.checkURI(String) line: 820 >> BaseXMLWriter.relativize(String) line: 797 >> Unparser.wURIreference(String) line: 918 >> Unparser.wURIreference(Resource) line: 922 >> Unparser.wAboutAttr(Resource) line: 913 >> Unparser.wIdAboutAttrOpt(Resource) line: 869 >> Unparser.wTypedNodeOrDescriptionLong(Unparser$WType, Resource, Resource, >> List) line: 830 >> Unparser.wTypedNodeOrDescription(Unparser$WType, Resource, Resource) >>line: >> 764 >> Unparser.wTypedNode(Resource) line: 737 >> Unparser.wObj(Resource, Boolean) line: 677 >> Unparser.wObjStar() line: 364 >> >> Because the writer has a null baseURI, then >>BaseXMLWriter.relativize(null) >> returns null. >> This then fails the URI check; hence the BadURIException. >> >> To avoid this problem, I refactored the call to RDFDataMgr.write(), >> originally: >> >> def write(graph: Jena#Graph, os: OutputStream, base: String): Try[Unit] >>= >> Try { >> import org.w3.banana.jena.Jena.ops._ >> val relativeGraph : Jena#Graph = graph.relativize(URI(base)) >> RDFDataMgr.write(os, relativeGraph, lang) >> } >> >> To the following: >> >> def write(graph: Jena#Graph, os: OutputStream, base: String): Try[Unit] >>= >> Try { >> import org.w3.banana.jena.Jena.ops._ >> val relativeGraph : Jena#Graph = graph.relativize(URI(base)) >> val serialization: RDFFormat = >> RDFWriterRegistry.defaultSerialization(lang) >> val wf: WriterGraphRIOTFactory = >> RDFWriterRegistry.getWriterGraphFactory(serialization) >> if ( wf == null ) >> throw new RiotException("No graph writer for >>"+serialization) >> ; >> val w: WriterGraphRIOT = wf.create(serialization) >> w.write(os, relativeGraph, >>system.RiotLib.prefixMap(relativeGraph), >> base, null) >> } >> >> This is basically a copy/paste adaptation of what the Jena API does >>anyway >> with the difference that I pass the graph's base URI to the writer. >> >> Well, the refactored version of the test works, the original doesn't. >> >> - Nicolas. >> >