Open jetztgradnet opened 2 years ago
In the ShaclSail I ended up writing my own rdf list implementation because of this issue. My fix was to not generate the type statements.
This should be a simple fix in the TurtleWriter
without further side effects, so I would rather go for a real solution here instead of working around it (although we do currently have a workaround in our application until this is fixed, because the resulting RDF text looks rather weird). This seems just like an oversight when checking list whether they are well-formed.
I guess it doesn't hurt to have simplified solutions for special cases as you created for the ShaclSail
, but in general I'd rather reuse a single, well-tested and compliant implementation.
Would you be interested in making a PR with the fix and some tests?
If we do a minor change in consumeCollection Method in RDFCollections Class, we will be able to produce the desired output. consumeCollection is called in asRDF method by RDFCollections.asRDF(..).
public static void consumeCollection(Iterable<?> values, Resource head, Consumer<Statement> consumer,
ValueFactory vf,
Resource... contexts) {
Objects.requireNonNull(values, "input collection may not be null");
Objects.requireNonNull(consumer, "consumer may not be null");
Objects.requireNonNull(vf, "injected value factory may not be null");
Resource current = head != null ? head : vf.createBNode();
//Statements.consume(vf, current, RDF.TYPE, RDF.LIST, consumer, contexts);
//--just comment out this above line in order to get the desired output which is list items are properly inlined.
Iterator<?> iter = values.iterator();
while (iter.hasNext()) {
Object o = iter.next();
Value v = o instanceof Value ? (Value) o : Literals.createLiteralOrFail(vf, o);
Statements.consume(vf, current, RDF.FIRST, v, consumer, contexts);
if (iter.hasNext()) {
Resource next = vf.createBNode();
Statements.consume(vf, current, RDF.REST, next, consumer, contexts);
current = next;
} else {
Statements.consume(vf, current, RDF.REST, RDF.NIL, consumer, contexts);
}
}
}
public static void consumeCollection(Iterable<?> values, Resource head, Consumer<Statement> consumer,
Resource... contexts) {
consumeCollection(values, head, consumer, SimpleValueFactory.getInstance(), contexts);
}
public static <C extends Collection<Statement>> C asRDF(Iterable<?> values, Resource head, C sink,
Resource... contexts) {
Objects.requireNonNull(sink);
consumeCollection(values, head, sink::add, contexts);
return sink;
}
Output: @prefix ex: http://example.com/ns# . @prefix rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns# .
ex:Cities ex:list (ex:NewYork ex:Rio ex:Tokyo) .
It would be a great help if someone could help me solve this problem from inside turtlewriter which will be the ideal fix for this issue. Ready to collaborate. @jetztgradnet
Thanks for picking this up @The-Nightwing ! I've left a few comments on your first PR, including a suggestion for a better fix in the TurtleWriter itself. Happy to talk further if anything is unclear.
Current Behavior
When serializing an RDF list created using
RDFCollections.asRDF()
withTurtleWriter
the first segment of the list is not properly inlined as it is not recognized as a well-formed list.The result looks as this:
Please notice the first part with explicit
rdf:first
andrdf:rest
statements instead of the inlining of the list, which is done for the last two segments of the list.This is caused by
org.eclipse.rdf4j.rio.turtle.TurtleWriter.isWellFormedCollection()
not recognizing therdf:type rdf:List
type statement for the first part of the list segment which is generated inRDFCollections.asRDF()
(or more specifically inorg.eclipse.rdf4j.model.util.RDFCollections.consumeCollection(Iterable<?>, Resource, Consumer<Statement>, ValueFactory, Resource...)
). A simple solution would be to adjustorg.eclipse.rdf4j.rio.turtle.TurtleWriter.isWellFormedCollection()
to recognize and accept that statement when checking for additional statements within the list.Expected Behavior
The proper visualization of the list would instead look like this:
Steps To Reproduce
This test case reproduces the behavior:
Adding this line before serializing the model as string makes the test work, but the fix should not remove that statement but rather recognize and accept it.
Version
3.7.4 (and likely earlier versions as well)
Are you interested in contributing a solution yourself?
Perhaps?
Anything else?
No response