Skip to content

Commit 9fc2776

Browse files
committed
Writer#write_statement now ensure that nodes are unique, and updates the node to have a new unique identifier if that identifier has already been written for a different node, taking into consider possible node duplication. Fixes #262.
1 parent eb6b8bc commit 9fc2776

File tree

1 file changed

+35
-8
lines changed

1 file changed

+35
-8
lines changed

lib/rdf/writer.rb

+35-8
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ def to_sym
258258
# @yieldreturn [void]
259259
def initialize(output = $stdout, options = {}, &block)
260260
@output, @options = output, options.dup
261-
@nodes, @node_id = {}, 0
261+
@nodes, @node_id, @node_id_map = {}, 0, {}
262262

263263
if block_given?
264264
write_prologue
@@ -409,16 +409,43 @@ def write_comment(text)
409409
end
410410

411411
##
412+
# Add a statement to the writer. This will check to ensure that the statement is complete (no nil terms) and is valid, if the `:validation` option is set.
413+
#
414+
# Additionally, it will de-duplicate BNode terms sharing a common identifier.
415+
#
412416
# @param [RDF::Statement] statement
413417
# @return [self]
414418
# @note logs error if attempting to write an invalid {RDF::Statement} or if canonicalizing a statement which cannot be canonicalized.
415419
def write_statement(statement)
416420
statement = statement.canonicalize! if canonicalize?
417421

422+
# Make sure BNodes in statement use unique identifiers
423+
if statement.node?
424+
terms = statement.to_quad.map do |term|
425+
if term.is_a?(RDF::Node)
426+
term = term.original while term.original
427+
@nodes[term] ||= begin
428+
# Account for duplicated nodes
429+
@node_id_map[term.to_s] ||= term
430+
if !@node_id_map[term.to_s].equal?(term)
431+
# Rename node
432+
term.make_unique!
433+
@node_id_map[term.to_s] = term
434+
end
435+
end
436+
else
437+
term
438+
end
439+
end
440+
statement = RDF::Statement.from(statement.to_quad)
441+
end
442+
418443
if statement.incomplete?
419444
log_error "Statement #{statement.inspect} is incomplete"
420445
elsif validate? && statement.invalid?
421446
log_error "Statement #{statement.inspect} is invalid"
447+
elsif respond_to?(:write_quad)
448+
write_quad(*statement.to_quad)
422449
else
423450
write_triple(*statement.to_triple)
424451
end
@@ -515,16 +542,16 @@ def puts(*args)
515542
end
516543

517544
##
518-
# @param [RDF::Resource] uriref
545+
# @param [RDF::Resource] term
519546
# @return [String]
520-
def uri_for(uriref)
547+
def uri_for(term)
521548
case
522-
when uriref.is_a?(RDF::Node)
523-
@nodes[uriref]
524-
when uriref.respond_to?(:to_uri)
525-
uriref.to_uri.to_s
549+
when term.is_a?(RDF::Node)
550+
@nodes[term] ||= term.to_base
551+
when term.respond_to?(:to_uri)
552+
term.to_uri.to_s
526553
else
527-
uriref.to_s
554+
term.to_s
528555
end
529556
end
530557

0 commit comments

Comments
 (0)