rdf 3.0.13 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AUTHORS +1 -1
- data/README.md +46 -11
- data/VERSION +1 -1
- data/etc/doap.nt +74 -80
- data/lib/rdf.rb +32 -23
- data/lib/rdf/changeset.rb +87 -19
- data/lib/rdf/cli.rb +6 -6
- data/lib/rdf/format.rb +17 -10
- data/lib/rdf/mixin/enumerable.rb +3 -2
- data/lib/rdf/mixin/mutable.rb +5 -15
- data/lib/rdf/mixin/queryable.rb +12 -4
- data/lib/rdf/mixin/writable.rb +9 -14
- data/lib/rdf/model/dataset.rb +1 -1
- data/lib/rdf/model/graph.rb +5 -2
- data/lib/rdf/model/list.rb +5 -5
- data/lib/rdf/model/statement.rb +30 -7
- data/lib/rdf/model/uri.rb +42 -23
- data/lib/rdf/nquads.rb +6 -6
- data/lib/rdf/ntriples.rb +6 -4
- data/lib/rdf/ntriples/reader.rb +32 -7
- data/lib/rdf/ntriples/writer.rb +10 -1
- data/lib/rdf/query.rb +27 -35
- data/lib/rdf/query/hash_pattern_normalizer.rb +14 -12
- data/lib/rdf/query/pattern.rb +51 -18
- data/lib/rdf/query/solution.rb +20 -1
- data/lib/rdf/query/solutions.rb +15 -5
- data/lib/rdf/query/variable.rb +17 -5
- data/lib/rdf/reader.rb +76 -25
- data/lib/rdf/repository.rb +32 -18
- data/lib/rdf/transaction.rb +1 -1
- data/lib/rdf/util.rb +6 -5
- data/lib/rdf/util/cache.rb +2 -2
- data/lib/rdf/util/coercions.rb +60 -0
- data/lib/rdf/util/file.rb +2 -2
- data/lib/rdf/util/logger.rb +7 -7
- data/lib/rdf/vocab/owl.rb +401 -86
- data/lib/rdf/vocab/rdfs.rb +81 -18
- data/lib/rdf/vocab/rdfv.rb +147 -1
- data/lib/rdf/vocab/writer.rb +43 -4
- data/lib/rdf/vocab/xsd.rb +203 -2
- data/lib/rdf/vocabulary.rb +108 -14
- data/lib/rdf/writer.rb +32 -10
- metadata +28 -27
data/lib/rdf/cli.rb
CHANGED
@@ -175,7 +175,7 @@ module RDF
|
|
175
175
|
unless repository.count > 0
|
176
176
|
start = Time.new
|
177
177
|
count = 0
|
178
|
-
self.parse(argv, opts) do |reader|
|
178
|
+
self.parse(argv, **opts) do |reader|
|
179
179
|
reader.each_statement do |statement|
|
180
180
|
count += 1
|
181
181
|
end
|
@@ -240,7 +240,7 @@ module RDF
|
|
240
240
|
out = opts[:output]
|
241
241
|
opts = opts.merge(prefixes: {})
|
242
242
|
writer_opts = opts.merge(standard_prefixes: true)
|
243
|
-
writer_class.new(out, writer_opts) do |writer|
|
243
|
+
writer_class.new(out, **writer_opts) do |writer|
|
244
244
|
writer << repository
|
245
245
|
end
|
246
246
|
end
|
@@ -501,7 +501,7 @@ module RDF
|
|
501
501
|
if cmds.any? {|c| COMMANDS[c.to_sym][:parse]}
|
502
502
|
start = Time.new
|
503
503
|
count = 0
|
504
|
-
self.parse(args, options) do |reader|
|
504
|
+
self.parse(args, **options) do |reader|
|
505
505
|
@repository << reader
|
506
506
|
end
|
507
507
|
secs = Time.new - start
|
@@ -575,7 +575,7 @@ module RDF
|
|
575
575
|
RDF::Format.each do |format|
|
576
576
|
format.cli_commands.each do |command, options|
|
577
577
|
options = {lambda: options} unless options.is_a?(Hash)
|
578
|
-
add_command(command, options)
|
578
|
+
add_command(command, **options)
|
579
579
|
end
|
580
580
|
end
|
581
581
|
@commands_loaded = true
|
@@ -637,13 +637,13 @@ module RDF
|
|
637
637
|
r = RDF::Reader.for(format|| {sample: sample})
|
638
638
|
raise ArgumentError, "Unknown format for evaluated input" unless r
|
639
639
|
(@readers ||= []) << r
|
640
|
-
r.new(input, options) do |reader|
|
640
|
+
r.new(input, **options) do |reader|
|
641
641
|
yield(reader)
|
642
642
|
end
|
643
643
|
else
|
644
644
|
options[:format] = format if format
|
645
645
|
files.each do |file|
|
646
|
-
RDF::Reader.open(file, options) do |reader|
|
646
|
+
RDF::Reader.open(file, **options) do |reader|
|
647
647
|
(@readers ||= []) << reader.class.to_s
|
648
648
|
yield(reader)
|
649
649
|
end
|
data/lib/rdf/format.rb
CHANGED
@@ -122,7 +122,7 @@ module RDF
|
|
122
122
|
sample = case sample
|
123
123
|
when Proc then sample.call.to_s
|
124
124
|
else sample.dup.to_s
|
125
|
-
end.force_encoding(Encoding::ASCII_8BIT)
|
125
|
+
end.dup.force_encoding(Encoding::ASCII_8BIT)
|
126
126
|
# Given a sample, perform format detection across the appropriate formats, choosing the last that matches
|
127
127
|
# Return last format that has a positive detection
|
128
128
|
formats = formats.select {|f| f.detect(sample)}
|
@@ -145,10 +145,10 @@ module RDF
|
|
145
145
|
# @param [String, RDF::URI] filename
|
146
146
|
# @return [Class]
|
147
147
|
#
|
148
|
-
# @overload for(
|
148
|
+
# @overload for(options)
|
149
149
|
# Finds an RDF serialization format class based on various options.
|
150
150
|
#
|
151
|
-
# @param [Hash{Symbol => Object}] options
|
151
|
+
# @param [Hash{Symbol => Object}] options ({})
|
152
152
|
# @option options [String, #to_s] :file_name (nil)
|
153
153
|
# @option options [Symbol, #to_sym] :file_extension (nil)
|
154
154
|
# @option options [String, #to_s] :content_type (nil)
|
@@ -164,19 +164,26 @@ module RDF
|
|
164
164
|
# @yieldreturn [String] another way to provide a sample, allows lazy for retrieving the sample.
|
165
165
|
#
|
166
166
|
# @return [Class]
|
167
|
-
def self.for(*
|
167
|
+
def self.for(*arg, &block)
|
168
|
+
case arg.length
|
169
|
+
when 0 then arg = nil
|
170
|
+
when 1 then arg = arg.first
|
171
|
+
else
|
172
|
+
raise ArgumentError, "Format.for accepts zero or one argument, got #{arg.length}."
|
173
|
+
end
|
174
|
+
|
175
|
+
options = arg.is_a?(Hash) ? arg : {}
|
168
176
|
options = {sample: block}.merge(options) if block_given?
|
169
|
-
formats = case
|
177
|
+
formats = case arg
|
170
178
|
when String, RDF::URI
|
171
179
|
# Find a format based on the file name
|
172
|
-
self.each(file_name:
|
180
|
+
self.each(file_name: arg, **options).to_a
|
173
181
|
when Symbol
|
174
182
|
# Try to find a match based on the full class name
|
175
183
|
# We want this to work even if autoloading fails
|
176
|
-
|
177
|
-
classes = self.each(options).select {|f| f.symbols.include?(fmt)}
|
184
|
+
classes = self.each(**options).select {|f| f.symbols.include?(arg)}
|
178
185
|
if classes.empty?
|
179
|
-
classes = case
|
186
|
+
classes = case arg
|
180
187
|
when :ntriples then [RDF::NTriples::Format]
|
181
188
|
when :nquads then [RDF::NQuads::Format]
|
182
189
|
else []
|
@@ -184,7 +191,7 @@ module RDF
|
|
184
191
|
end
|
185
192
|
classes
|
186
193
|
else
|
187
|
-
self.each(options.merge(all_if_none: false)).to_a
|
194
|
+
self.each(**options.merge(all_if_none: false)).to_a
|
188
195
|
end
|
189
196
|
|
190
197
|
# Return the last detected format
|
data/lib/rdf/mixin/enumerable.rb
CHANGED
@@ -71,6 +71,7 @@ module RDF
|
|
71
71
|
# * `:literal_equality' preserves [term-equality](https://www.w3.org/TR/rdf11-concepts/#dfn-literal-term-equality) for literals. Literals are equal only if their lexical values and datatypes are equal, character by character. Literals may be "inlined" to value-space for efficiency only if `:literal_equality` is `false`.
|
72
72
|
# * `:validity` allows a concrete Enumerable implementation to indicate that it does or does not support valididty checking. By default implementations are assumed to support validity checking.
|
73
73
|
# * `:skolemize` supports [Skolemization](https://www.w3.org/wiki/BnodeSkolemization) of an `Enumerable`. Implementations supporting this feature must implement a `#skolemize` method, taking a base URI used for minting URIs for BNodes as stable identifiers and a `#deskolemize` method, also taking a base URI used for turning URIs having that prefix back into the same BNodes which were originally skolemized.
|
74
|
+
# * `:rdfstar` supports RDF* where statements may be subjects or objects of other statements.
|
74
75
|
#
|
75
76
|
# @param [Symbol, #to_sym] feature
|
76
77
|
# @return [Boolean]
|
@@ -220,7 +221,7 @@ module RDF
|
|
220
221
|
def each_triple
|
221
222
|
if block_given?
|
222
223
|
each_statement do |statement|
|
223
|
-
yield
|
224
|
+
yield(*statement.to_triple)
|
224
225
|
end
|
225
226
|
end
|
226
227
|
enum_triple
|
@@ -282,7 +283,7 @@ module RDF
|
|
282
283
|
def each_quad
|
283
284
|
if block_given?
|
284
285
|
each_statement do |statement|
|
285
|
-
yield
|
286
|
+
yield(*statement.to_quad)
|
286
287
|
end
|
287
288
|
end
|
288
289
|
enum_quad
|
data/lib/rdf/mixin/mutable.rb
CHANGED
@@ -9,6 +9,7 @@ module RDF
|
|
9
9
|
extend RDF::Util::Aliasing::LateBound
|
10
10
|
include RDF::Readable
|
11
11
|
include RDF::Writable
|
12
|
+
include RDF::Util::Coercions
|
12
13
|
|
13
14
|
##
|
14
15
|
# Returns `true` if `self` is mutable.
|
@@ -37,10 +38,10 @@ module RDF
|
|
37
38
|
# @option options [RDF::Resource] :graph_name
|
38
39
|
# Set set graph name of each loaded statement
|
39
40
|
# @return [void]
|
40
|
-
|
41
|
+
def load(url, graph_name: nil, **options)
|
41
42
|
raise TypeError.new("#{self} is immutable") if immutable?
|
42
43
|
|
43
|
-
Reader.open(url,
|
44
|
+
Reader.open(url, base_uri: url, **options) do |reader|
|
44
45
|
if graph_name
|
45
46
|
statements = []
|
46
47
|
reader.each_statement do |statement|
|
@@ -154,20 +155,9 @@ module RDF
|
|
154
155
|
def delete(*statements)
|
155
156
|
raise TypeError.new("#{self} is immutable") if immutable?
|
156
157
|
|
157
|
-
statements
|
158
|
-
|
159
|
-
when value.respond_to?(:each_statement)
|
160
|
-
delete_statements(value)
|
161
|
-
nil
|
162
|
-
when (statement = Statement.from(value)).constant?
|
163
|
-
statement
|
164
|
-
else
|
165
|
-
delete_statements(query(value))
|
166
|
-
nil
|
167
|
-
end
|
158
|
+
coerce_statements(statements, query: true, constant: true) do |value|
|
159
|
+
delete_statements(value)
|
168
160
|
end
|
169
|
-
statements.compact!
|
170
|
-
delete_statements(statements) unless statements.empty?
|
171
161
|
|
172
162
|
return self
|
173
163
|
end
|
data/lib/rdf/mixin/queryable.rb
CHANGED
@@ -19,7 +19,7 @@ module RDF
|
|
19
19
|
#
|
20
20
|
# @example Querying for statements having a given predicate
|
21
21
|
# queryable.query([nil, RDF::Vocab::DOAP.developer, nil])
|
22
|
-
# queryable.query(predicate: RDF::Vocab::DOAP.developer) do |statement|
|
22
|
+
# queryable.query({predicate: RDF::Vocab::DOAP.developer}) do |statement|
|
23
23
|
# puts statement.inspect
|
24
24
|
# end
|
25
25
|
#
|
@@ -50,7 +50,7 @@ module RDF
|
|
50
50
|
solutions = RDF::Query::Solutions.new
|
51
51
|
block = lambda {|solution| solutions << solution} unless block_given?
|
52
52
|
before_query(pattern) if respond_to?(:before_query)
|
53
|
-
query_execute(pattern, options, &block)
|
53
|
+
query_execute(pattern, **options, &block)
|
54
54
|
after_query(pattern) if respond_to?(:after_query)
|
55
55
|
# Returns the solutions, not an enumerator
|
56
56
|
solutions
|
@@ -85,7 +85,7 @@ module RDF
|
|
85
85
|
|
86
86
|
# Otherwise, we delegate to `#query_pattern`:
|
87
87
|
else # pattern.variable?
|
88
|
-
query_pattern(pattern, options, &block)
|
88
|
+
query_pattern(pattern, **options, &block)
|
89
89
|
end
|
90
90
|
after_query(pattern) if respond_to?(:after_query)
|
91
91
|
enum
|
@@ -116,7 +116,7 @@ module RDF
|
|
116
116
|
# query execution by breaking down the query into its constituent
|
117
117
|
# triple patterns and invoking `RDF::Query::Pattern#execute` on each
|
118
118
|
# pattern.
|
119
|
-
query.execute(self, options, &block)
|
119
|
+
query.execute(self, **options, &block)
|
120
120
|
end
|
121
121
|
protected :query_execute
|
122
122
|
|
@@ -128,6 +128,14 @@ module RDF
|
|
128
128
|
# method in order to provide for storage-specific optimized triple
|
129
129
|
# pattern matching.
|
130
130
|
#
|
131
|
+
# ## RDFStar (RDF*)
|
132
|
+
#
|
133
|
+
# Statements may have embedded statements as either a subject or object, recursively.
|
134
|
+
#
|
135
|
+
# Patterns may also have embedded patterns as either a subject or object, recursively.
|
136
|
+
#
|
137
|
+
# When matching, match an embedded pattern against embedded statements, recursively. (see {RDF::Query::Pattern#eql?})
|
138
|
+
#
|
131
139
|
# @param [RDF::Query::Pattern] pattern
|
132
140
|
# the query pattern to match
|
133
141
|
# @param [Hash{Symbol => Object}] options ({})
|
data/lib/rdf/mixin/writable.rb
CHANGED
@@ -7,6 +7,7 @@ module RDF
|
|
7
7
|
# @see RDF::Repository
|
8
8
|
module Writable
|
9
9
|
extend RDF::Util::Aliasing::LateBound
|
10
|
+
include RDF::Util::Coercions
|
10
11
|
|
11
12
|
##
|
12
13
|
# Returns `true` if `self` is writable.
|
@@ -53,31 +54,20 @@ module RDF
|
|
53
54
|
# @overload insert(*statements)
|
54
55
|
# @param [Array<RDF::Statement>] statements
|
55
56
|
# @return [self]
|
57
|
+
# @raise [ArgumentError] on an attempt to insert an embedded statement when it is not supported
|
56
58
|
#
|
57
59
|
# @overload insert(statements)
|
58
60
|
# @param [Enumerable<RDF::Statement>] statements
|
59
61
|
# @return [self]
|
62
|
+
# @raise [ArgumentError] on an attempt to insert an embedded statement when it is not supported
|
60
63
|
def insert(*statements)
|
61
|
-
statements
|
62
|
-
case
|
63
|
-
when value.respond_to?(:each_statement)
|
64
|
-
insert_statements(value)
|
65
|
-
nil
|
66
|
-
when (statement = Statement.from(value))
|
67
|
-
statement
|
68
|
-
else
|
69
|
-
raise ArgumentError.new("not a valid statement: #{value.inspect}")
|
70
|
-
end
|
71
|
-
end
|
72
|
-
statements.compact!
|
73
|
-
insert_statements(statements) unless statements.empty?
|
64
|
+
coerce_statements(statements) { |value| insert_statements value }
|
74
65
|
|
75
66
|
return self
|
76
67
|
end
|
77
68
|
alias_method :insert!, :insert
|
78
69
|
|
79
70
|
protected
|
80
|
-
|
81
71
|
##
|
82
72
|
# Inserts statements from the given RDF reader into the underlying
|
83
73
|
# storage or output stream.
|
@@ -132,10 +122,14 @@ module RDF
|
|
132
122
|
#
|
133
123
|
# @param [RDF::Enumerable] statements
|
134
124
|
# @return [void]
|
125
|
+
# @raise [ArgumentError] on an attempt to insert an embedded statement when it is not supported
|
135
126
|
# @since 0.1.6
|
136
127
|
def insert_statements(statements)
|
137
128
|
each = statements.respond_to?(:each_statement) ? :each_statement : :each
|
138
129
|
statements.__send__(each) do |statement|
|
130
|
+
if statement.embedded? && respond_to?(:supports?) && !supports?(:rdfstar)
|
131
|
+
raise ArgumentError, "Wriable does not support embedded statements"
|
132
|
+
end
|
139
133
|
insert_statement(statement)
|
140
134
|
end
|
141
135
|
end
|
@@ -150,6 +144,7 @@ module RDF
|
|
150
144
|
#
|
151
145
|
# @param [RDF::Statement] statement
|
152
146
|
# @return [void]
|
147
|
+
# @raise [ArgumentError] on an attempt to insert an embedded statement when it is not supported
|
153
148
|
# @abstract
|
154
149
|
def insert_statement(statement)
|
155
150
|
raise NotImplementedError.new("#{self.class}#insert_statement")
|
data/lib/rdf/model/dataset.rb
CHANGED
data/lib/rdf/model/graph.rb
CHANGED
@@ -211,7 +211,7 @@ module RDF
|
|
211
211
|
# @return [Integer]
|
212
212
|
# @see RDF::Enumerable#count
|
213
213
|
def count
|
214
|
-
@data.query(graph_name: graph_name || false).count
|
214
|
+
@data.query({graph_name: graph_name || false}).count
|
215
215
|
end
|
216
216
|
|
217
217
|
##
|
@@ -237,7 +237,7 @@ module RDF
|
|
237
237
|
# @see RDF::Enumerable#each_statement
|
238
238
|
def each(&block)
|
239
239
|
if @data.respond_to?(:query)
|
240
|
-
@data.query(graph_name: graph_name || false, &block)
|
240
|
+
@data.query({graph_name: graph_name || false}, &block)
|
241
241
|
elsif @data.respond_to?(:each)
|
242
242
|
@data.each(&block)
|
243
243
|
else
|
@@ -283,6 +283,9 @@ module RDF
|
|
283
283
|
# @private
|
284
284
|
# @see RDF::Mutable#insert
|
285
285
|
def insert_statement(statement)
|
286
|
+
if statement.embedded? && !@data.supports?(:rdfstar)
|
287
|
+
raise ArgumentError, "Graph does not support embedded statements"
|
288
|
+
end
|
286
289
|
statement = statement.dup
|
287
290
|
statement.graph_name = graph_name
|
288
291
|
@data.insert(statement)
|
data/lib/rdf/model/list.rb
CHANGED
@@ -59,7 +59,7 @@ module RDF
|
|
59
59
|
def initialize(subject: nil, graph: nil, values: nil, &block)
|
60
60
|
@subject = subject || RDF.nil
|
61
61
|
@graph = graph || RDF::Graph.new
|
62
|
-
is_empty = @graph.query(subject: subject, predicate: RDF.first).empty?
|
62
|
+
is_empty = @graph.query({subject: subject, predicate: RDF.first}).empty?
|
63
63
|
|
64
64
|
if subject && is_empty
|
65
65
|
# An empty list with explicit subject and value initializers
|
@@ -115,7 +115,7 @@ module RDF
|
|
115
115
|
list_nodes << li
|
116
116
|
rest = nil
|
117
117
|
firsts = rests = 0
|
118
|
-
@graph.query(subject: li) do |st|
|
118
|
+
@graph.query({subject: li}) do |st|
|
119
119
|
return false unless st.subject.node?
|
120
120
|
case st.predicate
|
121
121
|
when RDF.first
|
@@ -136,7 +136,7 @@ module RDF
|
|
136
136
|
|
137
137
|
# All elements other than the head must be referenced exactly once
|
138
138
|
return list_nodes.all? do |li|
|
139
|
-
refs = @graph.query(object: li).count
|
139
|
+
refs = @graph.query({object: li}).count
|
140
140
|
case refs
|
141
141
|
when 0 then li == subject
|
142
142
|
when 1 then true
|
@@ -479,7 +479,7 @@ module RDF
|
|
479
479
|
# @return [Boolean]
|
480
480
|
# @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-empty-3F
|
481
481
|
def empty?
|
482
|
-
graph.query(subject: subject, predicate: RDF.first).empty?
|
482
|
+
graph.query({subject: subject, predicate: RDF.first}).empty?
|
483
483
|
end
|
484
484
|
|
485
485
|
##
|
@@ -822,7 +822,7 @@ module RDF
|
|
822
822
|
return enum_statement unless block_given?
|
823
823
|
|
824
824
|
each_subject do |subject|
|
825
|
-
graph.query(subject: subject, &block)
|
825
|
+
graph.query({subject: subject}, &block)
|
826
826
|
end
|
827
827
|
end
|
828
828
|
alias_method :to_rdf, :each_statement
|
data/lib/rdf/model/statement.rb
CHANGED
@@ -26,7 +26,7 @@ module RDF
|
|
26
26
|
# RDF::Statement(s, p, "o")
|
27
27
|
#
|
28
28
|
class Statement
|
29
|
-
include RDF::
|
29
|
+
include RDF::Resource
|
30
30
|
|
31
31
|
##
|
32
32
|
# @private
|
@@ -112,7 +112,7 @@ module RDF
|
|
112
112
|
elsif @subject.nil?
|
113
113
|
nil
|
114
114
|
else
|
115
|
-
raise ArgumentError, "expected subject to be nil or a
|
115
|
+
raise ArgumentError, "expected subject to be nil or a resource, was #{@subject.inspect}"
|
116
116
|
end
|
117
117
|
@predicate = Node.intern(@predicate) if @predicate.is_a?(Symbol)
|
118
118
|
@object = if @object.is_a?(Value)
|
@@ -124,6 +124,15 @@ module RDF
|
|
124
124
|
else
|
125
125
|
Literal.new(@object)
|
126
126
|
end
|
127
|
+
@graph_name = if @graph_name.is_a?(Value)
|
128
|
+
@graph_name.to_term
|
129
|
+
elsif @graph_name.is_a?(Symbol)
|
130
|
+
Node.intern(@graph_name)
|
131
|
+
elsif !@graph_name
|
132
|
+
@graph_name
|
133
|
+
else
|
134
|
+
raise ArgumentError, "expected graph_name to be nil or a resource, was #{@graph_name.inspect}"
|
135
|
+
end
|
127
136
|
end
|
128
137
|
|
129
138
|
##
|
@@ -140,10 +149,18 @@ module RDF
|
|
140
149
|
#
|
141
150
|
# @return [Boolean]
|
142
151
|
def variable?
|
143
|
-
!(has_subject? && subject.
|
144
|
-
has_predicate? && predicate.
|
145
|
-
has_object? &&
|
146
|
-
(has_graph? ? graph_name.
|
152
|
+
!(has_subject? && subject.constant? &&
|
153
|
+
has_predicate? && predicate.constant? &&
|
154
|
+
has_object? && object.constant? &&
|
155
|
+
(has_graph? ? graph_name.constant? : true))
|
156
|
+
end
|
157
|
+
|
158
|
+
##
|
159
|
+
# Returns `true` if any element of the statement is, itself, a statement.
|
160
|
+
#
|
161
|
+
# @return [Boolean]
|
162
|
+
def embedded?
|
163
|
+
subject && subject.statement? || object && object.statement?
|
147
164
|
end
|
148
165
|
|
149
166
|
##
|
@@ -386,7 +403,13 @@ module RDF
|
|
386
403
|
# @return [String]
|
387
404
|
def to_s
|
388
405
|
(graph_name ? to_quad : to_triple).map do |term|
|
389
|
-
term.
|
406
|
+
if term.is_a?(Statement)
|
407
|
+
"<<#{term.to_s[0..-3]}>>"
|
408
|
+
elsif term.respond_to?(:to_base)
|
409
|
+
term.to_base
|
410
|
+
else
|
411
|
+
term.inspect
|
412
|
+
end
|
390
413
|
end.join(" ") + " ."
|
391
414
|
end
|
392
415
|
|