rdf 3.1.6 → 3.1.11
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/README.md +58 -23
- data/VERSION +1 -1
- data/lib/rdf.rb +24 -0
- data/lib/rdf/cli.rb +38 -10
- data/lib/rdf/mixin/enumerable.rb +46 -28
- data/lib/rdf/mixin/mutable.rb +1 -1
- data/lib/rdf/model/dataset.rb +1 -1
- data/lib/rdf/model/graph.rb +14 -7
- data/lib/rdf/model/list.rb +29 -4
- data/lib/rdf/model/literal.rb +14 -14
- data/lib/rdf/model/literal/date.rb +5 -3
- data/lib/rdf/model/literal/datetime.rb +11 -7
- data/lib/rdf/model/literal/decimal.rb +8 -2
- data/lib/rdf/model/literal/double.rb +3 -3
- data/lib/rdf/model/literal/time.rb +7 -5
- data/lib/rdf/model/node.rb +2 -6
- data/lib/rdf/model/statement.rb +36 -23
- data/lib/rdf/model/term.rb +8 -0
- data/lib/rdf/model/uri.rb +27 -19
- data/lib/rdf/nquads.rb +2 -2
- data/lib/rdf/ntriples/reader.rb +6 -6
- data/lib/rdf/ntriples/writer.rb +3 -3
- data/lib/rdf/query.rb +1 -1
- data/lib/rdf/query/pattern.rb +7 -7
- data/lib/rdf/query/solution.rb +8 -6
- data/lib/rdf/query/solutions.rb +5 -3
- data/lib/rdf/reader.rb +6 -19
- data/lib/rdf/repository.rb +29 -20
- data/lib/rdf/transaction.rb +9 -3
- data/lib/rdf/util/cache.rb +10 -6
- data/lib/rdf/util/logger.rb +1 -1
- data/lib/rdf/vocab/owl.rb +366 -388
- data/lib/rdf/vocab/rdfs.rb +72 -74
- data/lib/rdf/vocab/rdfv.rb +74 -74
- data/lib/rdf/vocab/writer.rb +41 -25
- data/lib/rdf/vocab/xsd.rb +198 -463
- data/lib/rdf/vocabulary.rb +137 -89
- data/lib/rdf/writer.rb +2 -2
- metadata +12 -12
data/lib/rdf/mixin/mutable.rb
CHANGED
@@ -122,7 +122,7 @@ module RDF
|
|
122
122
|
|
123
123
|
statements.each do |statement|
|
124
124
|
if (statement = Statement.from(statement))
|
125
|
-
if statement.
|
125
|
+
if statement.object?
|
126
126
|
delete_insert([[statement.subject, statement.predicate, nil]], [statement])
|
127
127
|
else
|
128
128
|
delete([statement.subject, statement.predicate, nil])
|
data/lib/rdf/model/dataset.rb
CHANGED
data/lib/rdf/model/graph.rb
CHANGED
@@ -215,18 +215,25 @@ module RDF
|
|
215
215
|
end
|
216
216
|
|
217
217
|
##
|
218
|
-
#
|
218
|
+
# @overload statement?
|
219
|
+
# Returns `false` indicating this is not an RDF::Statemenet.
|
220
|
+
# @see RDF::Value#statement?
|
221
|
+
# @return [Boolean]
|
222
|
+
# @overload statement?(statement)
|
223
|
+
# Returns `true` if this graph contains the given RDF statement.
|
219
224
|
#
|
220
|
-
#
|
225
|
+
# A statement is in a graph if the statement if it has the same triples without regard to graph_name.
|
221
226
|
#
|
222
|
-
#
|
223
|
-
#
|
224
|
-
#
|
225
|
-
def
|
227
|
+
# @param [Statement] statement
|
228
|
+
# @return [Boolean]
|
229
|
+
# @see RDF::Enumerable#statement?
|
230
|
+
def statement?(statement = nil)
|
231
|
+
return false if statement.nil?
|
226
232
|
statement = statement.dup
|
227
233
|
statement.graph_name = graph_name
|
228
|
-
@data.
|
234
|
+
@data.statement?(statement)
|
229
235
|
end
|
236
|
+
alias_method :has_statement?, :statement?
|
230
237
|
|
231
238
|
##
|
232
239
|
# Enumerates each RDF statement in this graph.
|
data/lib/rdf/model/list.rb
CHANGED
@@ -49,14 +49,23 @@ module RDF
|
|
49
49
|
# g = RDF::Graph.new << l
|
50
50
|
# g.count # => l.count
|
51
51
|
#
|
52
|
+
# @example use a transaction for block initialization
|
53
|
+
# l = RDF::List(graph: graph, wrap_transaction: true) do |list|
|
54
|
+
# list << RDF::Literal(1)
|
55
|
+
# # list.graph.rollback will rollback all list changes within this block.
|
56
|
+
# end
|
57
|
+
# list.count #=> 1
|
58
|
+
#
|
52
59
|
# @param [RDF::Resource] subject (RDF.nil)
|
53
60
|
# Subject should be an {RDF::Node}, not a {RDF::URI}. A list with an IRI head will not validate, but is commonly used to detect if a list is valid.
|
54
61
|
# @param [RDF::Graph] graph (RDF::Graph.new)
|
55
62
|
# @param [Array<RDF::Term>] values
|
56
63
|
# Any values which are not terms are coerced to `RDF::Literal`.
|
64
|
+
# @param [Boolean] wrap_transaction (false)
|
65
|
+
# Wraps the callback in a transaction, and replaces the graph with that transaction for the duraction of the callback. This has the effect of allowing any list changes to be made atomically, or rolled back.
|
57
66
|
# @yield [list]
|
58
67
|
# @yieldparam [RDF::List] list
|
59
|
-
def initialize(subject: nil, graph: nil, values: nil, &block)
|
68
|
+
def initialize(subject: nil, graph: nil, values: nil, wrap_transaction: false, &block)
|
60
69
|
@subject = subject || RDF.nil
|
61
70
|
@graph = graph || RDF::Graph.new
|
62
71
|
is_empty = @graph.query({subject: subject, predicate: RDF.first}).empty?
|
@@ -78,9 +87,25 @@ module RDF
|
|
78
87
|
end
|
79
88
|
|
80
89
|
if block_given?
|
81
|
-
|
82
|
-
|
83
|
-
|
90
|
+
if wrap_transaction
|
91
|
+
old_graph = @graph
|
92
|
+
begin
|
93
|
+
Transaction.begin(@graph, graph_name: @graph.graph_name, mutable: @graph.mutable?) do |trans|
|
94
|
+
@graph = trans
|
95
|
+
case block.arity
|
96
|
+
when 1 then block.call(self)
|
97
|
+
else instance_eval(&block)
|
98
|
+
end
|
99
|
+
trans.execute if trans.mutated?
|
100
|
+
end
|
101
|
+
ensure
|
102
|
+
@graph = old_graph
|
103
|
+
end
|
104
|
+
else
|
105
|
+
case block.arity
|
106
|
+
when 1 then block.call(self)
|
107
|
+
else instance_eval(&block)
|
108
|
+
end
|
84
109
|
end
|
85
110
|
end
|
86
111
|
end
|
data/lib/rdf/model/literal.rb
CHANGED
@@ -25,7 +25,7 @@ module RDF
|
|
25
25
|
#
|
26
26
|
# @example Creating a language-tagged literal (1)
|
27
27
|
# value = RDF::Literal.new("Hello!", language: :en)
|
28
|
-
# value.
|
28
|
+
# value.language? #=> true
|
29
29
|
# value.language #=> :en
|
30
30
|
#
|
31
31
|
# @example Creating a language-tagged literal (2)
|
@@ -35,12 +35,12 @@ module RDF
|
|
35
35
|
#
|
36
36
|
# @example Creating an explicitly datatyped literal
|
37
37
|
# value = RDF::Literal.new("2009-12-31", datatype: RDF::XSD.date)
|
38
|
-
# value.
|
38
|
+
# value.datatype? #=> true
|
39
39
|
# value.datatype #=> RDF::XSD.date
|
40
40
|
#
|
41
41
|
# @example Creating an implicitly datatyped literal
|
42
42
|
# value = RDF::Literal.new(Date.today)
|
43
|
-
# value.
|
43
|
+
# value.datatype? #=> true
|
44
44
|
# value.datatype #=> RDF::XSD.date
|
45
45
|
#
|
46
46
|
# @example Creating implicitly datatyped literals
|
@@ -225,7 +225,7 @@ module RDF
|
|
225
225
|
# * The arguments are simple literals or literals typed as xsd:string
|
226
226
|
# * The arguments are plain literals with identical language tags
|
227
227
|
# * The first argument is a plain literal with language tag and the second argument is a simple literal or literal typed as xsd:string
|
228
|
-
|
228
|
+
language? ?
|
229
229
|
(language == other.language || other.datatype == RDF::URI("http://www.w3.org/2001/XMLSchema#string")) :
|
230
230
|
other.datatype == RDF::URI("http://www.w3.org/2001/XMLSchema#string")
|
231
231
|
end
|
@@ -289,7 +289,7 @@ module RDF
|
|
289
289
|
case
|
290
290
|
when self.eql?(other)
|
291
291
|
true
|
292
|
-
when self.
|
292
|
+
when self.language? && self.language.to_s == other.language.to_s
|
293
293
|
# Literals with languages can compare if languages are identical
|
294
294
|
self.value_hash == other.value_hash && self.value == other.value
|
295
295
|
when self.simple? && other.simple?
|
@@ -335,10 +335,10 @@ module RDF
|
|
335
335
|
#
|
336
336
|
# @return [Boolean] `true` or `false`
|
337
337
|
# @see http://www.w3.org/TR/rdf-concepts/#dfn-plain-literal
|
338
|
-
def
|
338
|
+
def language?
|
339
339
|
datatype == RDF.langString
|
340
340
|
end
|
341
|
-
alias_method :
|
341
|
+
alias_method :has_language?, :language?
|
342
342
|
|
343
343
|
##
|
344
344
|
# Returns `true` if this is a datatyped literal.
|
@@ -347,12 +347,12 @@ module RDF
|
|
347
347
|
#
|
348
348
|
# @return [Boolean] `true` or `false`
|
349
349
|
# @see http://www.w3.org/TR/rdf-concepts/#dfn-typed-literal
|
350
|
-
def
|
350
|
+
def datatype?
|
351
351
|
!plain? && !language?
|
352
352
|
end
|
353
|
-
alias_method :
|
354
|
-
alias_method :typed?,
|
355
|
-
alias_method :datatyped?,
|
353
|
+
alias_method :has_datatype?, :datatype?
|
354
|
+
alias_method :typed?, :datatype?
|
355
|
+
alias_method :datatyped?, :datatype?
|
356
356
|
|
357
357
|
##
|
358
358
|
# Returns `true` if the value adheres to the defined grammar of the
|
@@ -386,16 +386,16 @@ module RDF
|
|
386
386
|
# This behavior is intuited from SPARQL data-r2/expr-equal/eq-2-2
|
387
387
|
# @return [Boolean]
|
388
388
|
def comperable_datatype?(other)
|
389
|
-
return false unless self.plain? || self.
|
389
|
+
return false unless self.plain? || self.language?
|
390
390
|
|
391
391
|
case other
|
392
392
|
when RDF::Literal::Numeric, RDF::Literal::Boolean,
|
393
393
|
RDF::Literal::Date, RDF::Literal::Time, RDF::Literal::DateTime
|
394
394
|
# Invald types can be compared without raising a TypeError if literal has a language (open-eq-08)
|
395
|
-
!other.valid? && self.
|
395
|
+
!other.valid? && self.language?
|
396
396
|
else
|
397
397
|
# An unknown datatype may not be used for comparison, unless it has a language? (open-eq-8)
|
398
|
-
self.
|
398
|
+
self.language?
|
399
399
|
end
|
400
400
|
end
|
401
401
|
|
@@ -51,11 +51,13 @@ module RDF; class Literal
|
|
51
51
|
#
|
52
52
|
# @return [Boolean]
|
53
53
|
# @since 1.1.6
|
54
|
-
def
|
54
|
+
def timezone?
|
55
55
|
md = self.to_s.match(GRAMMAR)
|
56
56
|
md && !!md[2]
|
57
57
|
end
|
58
|
-
alias_method :
|
58
|
+
alias_method :tz?, :timezone?
|
59
|
+
alias_method :has_tz?, :timezone?
|
60
|
+
alias_method :has_timezone?, :timezone?
|
59
61
|
|
60
62
|
##
|
61
63
|
# Returns the value as a string.
|
@@ -72,7 +74,7 @@ module RDF; class Literal
|
|
72
74
|
# @since 1.1.6
|
73
75
|
def humanize(lang = :en)
|
74
76
|
d = object.strftime("%A, %d %B %Y")
|
75
|
-
if
|
77
|
+
if timezone?
|
76
78
|
d += if self.tz == 'Z'
|
77
79
|
" UTC"
|
78
80
|
else
|
@@ -30,7 +30,7 @@ module RDF; class Literal
|
|
30
30
|
# @see http://www.w3.org/TR/xmlschema11-2/#dateTime
|
31
31
|
def canonicalize!
|
32
32
|
if self.valid?
|
33
|
-
@string = if
|
33
|
+
@string = if timezone?
|
34
34
|
@object.new_offset.new_offset.strftime(FORMAT[0..-4] + 'Z').sub('.000', '')
|
35
35
|
else
|
36
36
|
@object.strftime(FORMAT[0..-4]).sub('.000', '')
|
@@ -45,7 +45,7 @@ module RDF; class Literal
|
|
45
45
|
# @return [RDF::Literal]
|
46
46
|
# @see http://www.w3.org/TR/sparql11-query/#func-tz
|
47
47
|
def tz
|
48
|
-
zone =
|
48
|
+
zone = timezone? ? object.zone : ""
|
49
49
|
zone = "Z" if zone == "+00:00"
|
50
50
|
RDF::Literal(zone)
|
51
51
|
end
|
@@ -85,21 +85,25 @@ module RDF; class Literal
|
|
85
85
|
#
|
86
86
|
# @return [Boolean]
|
87
87
|
# @since 1.1.6
|
88
|
-
def
|
88
|
+
def milliseconds?
|
89
89
|
self.format("%L").to_i > 0
|
90
90
|
end
|
91
|
-
alias_method :
|
91
|
+
alias_method :has_milliseconds?, :milliseconds?
|
92
|
+
alias_method :has_ms?, :milliseconds?
|
93
|
+
alias_method :ms?, :milliseconds?
|
92
94
|
|
93
95
|
##
|
94
96
|
# Does the literal representation include a timezone? Note that this is only possible if initialized using a string, or `:lexical` option.
|
95
97
|
#
|
96
98
|
# @return [Boolean]
|
97
99
|
# @since 1.1.6
|
98
|
-
def
|
100
|
+
def timezone?
|
99
101
|
md = self.to_s.match(GRAMMAR)
|
100
102
|
md && !!md[2]
|
101
103
|
end
|
102
|
-
alias_method :
|
104
|
+
alias_method :tz?, :timezone?
|
105
|
+
alias_method :has_tz?, :timezone?
|
106
|
+
alias_method :has_timezone?, :timezone?
|
103
107
|
|
104
108
|
##
|
105
109
|
# Returns the `timezone` of the literal. If the
|
@@ -118,7 +122,7 @@ module RDF; class Literal
|
|
118
122
|
# @since 1.1.6
|
119
123
|
def humanize(lang = :en)
|
120
124
|
d = object.strftime("%r on %A, %d %B %Y")
|
121
|
-
if
|
125
|
+
if timezone?
|
122
126
|
zone = if self.tz == 'Z'
|
123
127
|
"UTC"
|
124
128
|
else
|
@@ -63,9 +63,15 @@ module RDF; class Literal
|
|
63
63
|
##
|
64
64
|
# Returns the number with no fractional part that is closest to the argument. If there are two such numbers, then the one that is closest to positive infinity is returned. An error is raised if arg is not a numeric value.
|
65
65
|
#
|
66
|
-
# @return [RDF::Literal::
|
66
|
+
# @return [RDF::Literal::Decimal]
|
67
67
|
def round
|
68
|
-
|
68
|
+
rounded = to_d.round(half: (to_d < 0 ? :down : :up))
|
69
|
+
if rounded == -0.0
|
70
|
+
# to avoid -0.0
|
71
|
+
self.class.new(0.0)
|
72
|
+
else
|
73
|
+
self.class.new(rounded)
|
74
|
+
end
|
69
75
|
end
|
70
76
|
|
71
77
|
##
|
@@ -181,11 +181,11 @@ module RDF; class Literal
|
|
181
181
|
end
|
182
182
|
|
183
183
|
##
|
184
|
-
# Returns the
|
184
|
+
# Returns the number with no fractional part that is closest to the argument. If there are two such numbers, then the one that is closest to positive infinity is returned. An error is raised if arg is not a numeric value.
|
185
185
|
#
|
186
|
-
# @return [RDF::Literal::
|
186
|
+
# @return [RDF::Literal::Double]
|
187
187
|
def round
|
188
|
-
|
188
|
+
self.class.new(to_d.round(half: (to_d < 0 ? :down : :up)))
|
189
189
|
end
|
190
190
|
|
191
191
|
##
|
@@ -42,7 +42,7 @@ module RDF; class Literal
|
|
42
42
|
# @see http://www.w3.org/TR/xmlschema11-2/#time
|
43
43
|
def canonicalize!
|
44
44
|
if self.valid?
|
45
|
-
@string = if
|
45
|
+
@string = if timezone?
|
46
46
|
@object.new_offset.new_offset.strftime(FORMAT[0..-4] + 'Z').sub('.000', '')
|
47
47
|
else
|
48
48
|
@object.strftime(FORMAT[0..-4]).sub('.000', '')
|
@@ -57,7 +57,7 @@ module RDF; class Literal
|
|
57
57
|
# @return [RDF::Literal]
|
58
58
|
# @see http://www.w3.org/TR/sparql11-query/#func-tz
|
59
59
|
def tz
|
60
|
-
zone =
|
60
|
+
zone = timezone? ? object.zone : ""
|
61
61
|
zone = "Z" if zone == "+00:00"
|
62
62
|
RDF::Literal(zone)
|
63
63
|
end
|
@@ -79,11 +79,13 @@ module RDF; class Literal
|
|
79
79
|
#
|
80
80
|
# @return [Boolean]
|
81
81
|
# @since 1.1.6
|
82
|
-
def
|
82
|
+
def timezone?
|
83
83
|
md = self.to_s.match(GRAMMAR)
|
84
84
|
md && !!md[2]
|
85
85
|
end
|
86
|
-
alias_method :
|
86
|
+
alias_method :tz?, :timezone?
|
87
|
+
alias_method :has_tz?, :timezone?
|
88
|
+
alias_method :has_timezone?, :timezone?
|
87
89
|
|
88
90
|
##
|
89
91
|
# Returns the value as a string.
|
@@ -101,7 +103,7 @@ module RDF; class Literal
|
|
101
103
|
# @since 1.1.6
|
102
104
|
def humanize(lang = :en)
|
103
105
|
t = object.strftime("%r")
|
104
|
-
if
|
106
|
+
if timezone?
|
105
107
|
t += if self.tz == 'Z'
|
106
108
|
" UTC"
|
107
109
|
else
|
data/lib/rdf/model/node.rb
CHANGED
@@ -13,18 +13,14 @@ module RDF
|
|
13
13
|
include RDF::Resource
|
14
14
|
|
15
15
|
##
|
16
|
-
#
|
17
|
-
# cached in memory at any one time.
|
16
|
+
# Cache size may be set through {RDF.config} using `node_cache_size`.
|
18
17
|
#
|
19
18
|
# @note caching interned nodes means that two different invocations using the same symbol will result in the same node, which may not be appropriate depending on the graph from which it is used. RDF requires that bnodes with the same label are, in fact, different bnodes, unless they are used within the same document.
|
20
|
-
CACHE_SIZE = -1 # unlimited by default
|
21
|
-
|
22
|
-
##
|
23
19
|
# @return [RDF::Util::Cache]
|
24
20
|
# @private
|
25
21
|
def self.cache
|
26
22
|
require 'rdf/util/cache' unless defined?(::RDF::Util::Cache)
|
27
|
-
@cache ||= RDF::Util::Cache.new(
|
23
|
+
@cache ||= RDF::Util::Cache.new(RDF.config.node_cache_size)
|
28
24
|
end
|
29
25
|
|
30
26
|
##
|
data/lib/rdf/model/statement.rb
CHANGED
@@ -96,7 +96,7 @@ module RDF
|
|
96
96
|
@predicate = predicate
|
97
97
|
@object = object
|
98
98
|
end
|
99
|
-
@id = @options.delete(:id) if @options.
|
99
|
+
@id = @options.delete(:id) if @options.key?(:id)
|
100
100
|
@graph_name = @options.delete(:graph_name)
|
101
101
|
initialize!
|
102
102
|
end
|
@@ -149,10 +149,10 @@ module RDF
|
|
149
149
|
#
|
150
150
|
# @return [Boolean]
|
151
151
|
def variable?
|
152
|
-
!(
|
153
|
-
|
154
|
-
|
155
|
-
(
|
152
|
+
!(subject? && subject.constant? &&
|
153
|
+
predicate? && predicate.constant? &&
|
154
|
+
object? && object.constant? &&
|
155
|
+
(graph? ? graph_name.constant? : true))
|
156
156
|
end
|
157
157
|
|
158
158
|
##
|
@@ -172,10 +172,10 @@ module RDF
|
|
172
172
|
##
|
173
173
|
# @return [Boolean]
|
174
174
|
def valid?
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
(
|
175
|
+
subject? && subject.resource? && subject.valid? &&
|
176
|
+
predicate? && predicate.uri? && predicate.valid? &&
|
177
|
+
object? && object.term? && object.valid? &&
|
178
|
+
(graph? ? (graph_name.resource? && graph_name.valid?) : true)
|
179
179
|
end
|
180
180
|
|
181
181
|
##
|
@@ -216,31 +216,37 @@ module RDF
|
|
216
216
|
|
217
217
|
##
|
218
218
|
# @return [Boolean]
|
219
|
-
def
|
219
|
+
def graph?
|
220
220
|
!!graph_name
|
221
221
|
end
|
222
|
-
alias_method :
|
222
|
+
alias_method :name?, :graph?
|
223
|
+
alias_method :has_graph?, :graph?
|
224
|
+
alias_method :has_name?, :graph?
|
223
225
|
|
224
226
|
##
|
225
227
|
# @return [Boolean]
|
226
|
-
def
|
228
|
+
def subject?
|
227
229
|
!!subject
|
228
230
|
end
|
231
|
+
alias_method :has_subject?, :subject?
|
229
232
|
|
230
233
|
##
|
231
234
|
# @return [Boolean]
|
232
|
-
def
|
235
|
+
def predicate?
|
233
236
|
!!predicate
|
234
237
|
end
|
238
|
+
alias_method :has_predicate?, :predicate?
|
235
239
|
|
236
240
|
##
|
237
241
|
# @return [Boolean]
|
238
|
-
def
|
242
|
+
def object?
|
239
243
|
!!object
|
240
244
|
end
|
245
|
+
alias_method :has_object?, :object?
|
241
246
|
|
242
247
|
##
|
243
|
-
# Returns `true` if any resource of this statement is a blank node
|
248
|
+
# Returns `true` if any resource of this statement is a blank node
|
249
|
+
# or has an embedded statement including a blank node.
|
244
250
|
#
|
245
251
|
# @return [Boolean]
|
246
252
|
# @since 2.0
|
@@ -312,10 +318,10 @@ module RDF
|
|
312
318
|
# @see RDF::Literal#eql?
|
313
319
|
# @see RDF::Query::Variable#eql?
|
314
320
|
def ===(other)
|
315
|
-
return false if
|
316
|
-
return false if
|
317
|
-
return false if
|
318
|
-
return false if
|
321
|
+
return false if object? && !object.eql?(other.object)
|
322
|
+
return false if predicate? && !predicate.eql?(other.predicate)
|
323
|
+
return false if subject? && !subject.eql?(other.subject)
|
324
|
+
return false if graph? && !graph_name.eql?(other.graph_name)
|
319
325
|
return true
|
320
326
|
end
|
321
327
|
|
@@ -359,6 +365,13 @@ module RDF
|
|
359
365
|
end
|
360
366
|
alias_method :to_a, :to_triple
|
361
367
|
|
368
|
+
##
|
369
|
+
# Returns an array of all the non-nil non-statement terms.
|
370
|
+
# @return [Array(RDF::Term)]
|
371
|
+
def terms
|
372
|
+
to_quad.map {|t| t.respond_to?(:terms) ? t.terms : t}.flatten.compact
|
373
|
+
end
|
374
|
+
|
362
375
|
##
|
363
376
|
# Canonicalizes each unfrozen term in the statement
|
364
377
|
#
|
@@ -366,10 +379,10 @@ module RDF
|
|
366
379
|
# @since 1.0.8
|
367
380
|
# @raise [ArgumentError] if any element cannot be canonicalized.
|
368
381
|
def canonicalize!
|
369
|
-
self.subject.canonicalize! if
|
370
|
-
self.predicate.canonicalize! if
|
371
|
-
self.object.canonicalize! if
|
372
|
-
self.graph_name.canonicalize! if
|
382
|
+
self.subject.canonicalize! if subject? && !self.subject.frozen?
|
383
|
+
self.predicate.canonicalize! if predicate? && !self.predicate.frozen?
|
384
|
+
self.object.canonicalize! if object? && !self.object.frozen?
|
385
|
+
self.graph_name.canonicalize! if graph? && !self.graph_name.frozen?
|
373
386
|
self.validate!
|
374
387
|
@hash = nil
|
375
388
|
self
|