Skip to content

Commit 6edc6f2

Browse files
committed
Serialized asserted and embedded as subject triples using annotation syntax. {| ... |}.
1 parent de3349e commit 6edc6f2

2 files changed

Lines changed: 57 additions & 5 deletions

File tree

lib/rdf/turtle/writer.rb

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -380,10 +380,10 @@ def order_subjects
380380
# List elements which are bnodes should not be targets for top-level serialization
381381
list_elements = @lists.values.map(&:to_a).flatten.select(&:node?).compact
382382

383-
# Sort subjects by resources over bnodes, ref_counts and the subject URI itself
383+
# Sort subjects by resources and statements over bnodes, ref_counts and the subject URI itself
384384
recursable = (@subjects.keys - list_elements).
385385
select {|s| !seen.include?(s)}.
386-
map {|r| [r.node? ? 1 : 0, ref_count(r), r]}.
386+
map {|r| [r.node? ? 2 : (r.statement? ? 1 : 0), ref_count(r), r]}.
387387
sort
388388

389389
subjects + recursable.map{|r| r.last}
@@ -586,7 +586,7 @@ def predicate(resource)
586586
end
587587

588588
# Render an objectList having a common subject and predicate
589-
def objectList(objects)
589+
def objectList(subject, predicate, objects)
590590
log_debug("objectList") {objects.inspect}
591591
return if objects.empty?
592592

@@ -597,6 +597,15 @@ def objectList(objects)
597597
@output.write ",\n#{indent(4)}"
598598
end
599599
path(obj, :object)
600+
601+
# If subject, predicate, and object are embedded, write those bits out too.
602+
emb = RDF::Statement(subject, predicate, obj)
603+
if !@graph.query({subject: emb}).empty?
604+
@output.write ' {| '
605+
predicateObjectList(emb, true)
606+
@output.write ' |}'
607+
subject_done(emb)
608+
end
600609
end
601610
end
602611

@@ -616,10 +625,11 @@ def predicateObjectList(subject, from_bpl = false)
616625
@output.write("\n#{indent(2)}") if properties.keys.length > 1 && from_bpl
617626
prop_list.each_with_index do |prop, i|
618627
begin
628+
pred = RDF::URI.intern(prop)
619629
@output.write(";\n#{indent(2)}") if i > 0
620-
predicate(RDF::URI.intern(prop))
630+
predicate(pred)
621631
@output.write(" ")
622-
objectList(properties[prop])
632+
objectList(subject, pred, properties[prop])
623633
end
624634
end
625635
properties.keys.length

spec/writer_spec.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,48 @@
707707
serialize(graph, params.fetch(:regexp, []), prefixes: {ex: 'http://example/'}, **params)
708708
end
709709
end
710+
711+
context "annotations" do
712+
{
713+
'turtle-star-annotation-1' => {
714+
input: %(
715+
PREFIX : <http://example/>
716+
:s :p :o {| :r :z |} .
717+
),
718+
regexp: [
719+
%r(ex:s ex:p ex:o {\| ex:r ex:z \|} \.)
720+
]
721+
},
722+
'turtle-star-annotation-2' => {
723+
input: %(
724+
PREFIX : <http://example/>
725+
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
726+
727+
:s :p :o {| :source [ :graph <http://host1/> ;
728+
:date "2020-01-20"^^xsd:date
729+
] ;
730+
:source [ :graph <http://host2/> ;
731+
:date "2020-12-31"^^xsd:date
732+
]
733+
|} .
734+
),
735+
regexp: [
736+
%r(ex:s ex:p ex:o {\| ex:source \[),
737+
%r(\s+ex:date "2020-01-20"\^\^<http://www.w3.org/2001/XMLSchema#date>;),
738+
%r(\s+ex:graph <http://host1/>),
739+
%r(\s+\], \[),
740+
%r(\s+ex:date "2020-12-31"\^\^<http://www.w3.org/2001/XMLSchema#date>;),
741+
%r(\s+ex:graph <http://host2/>),
742+
%r(\s+\] \|} \.)
743+
]
744+
}
745+
}.each do |name, params|
746+
it name do
747+
graph = RDF::Graph.new {|g| g << parse(params[:input], rdfstar: true)}
748+
serialize(graph, params.fetch(:regexp, []), prefixes: {ex: 'http://example/'}, **params)
749+
end
750+
end
751+
end
710752
end
711753

712754
# W3C Turtle Test suite from https://www.w3.org/TR/turtle/tests/

0 commit comments

Comments
 (0)