rdf 1.1.17.1 → 1.99.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,12 +5,12 @@ module RDF
5
5
  # An {RDF::Graph} contains a unique set of {RDF::Statement}. It is
6
6
  # based on an underlying data object, which may be specified when the
7
7
  # graph is initialized, and will default to a {RDF::Repository} without
8
- # support for contexts otherwise.
8
+ # support for named graphs otherwise.
9
9
  #
10
10
  # Note that in RDF 1.1, graphs are not named, but are associated with
11
- # a name in the context of a Dataset, as a pair of <name, graph>.
11
+ # a graph name in a Dataset, as a pair of <name, graph>.
12
12
  # This class allows a name to be associated with a graph when it is
13
- # a projection of an underlying {RDF::Repository} supporting contexts.
13
+ # a projection of an underlying {RDF::Repository} supporting graph_names.
14
14
  #
15
15
  # @example Creating an empty unnamed graph
16
16
  # graph = RDF::Graph.new
@@ -45,13 +45,23 @@ module RDF
45
45
 
46
46
  ##
47
47
  # Name of this graph, if it is part of an {RDF::Repository}
48
- # @!attribute [rw] context
48
+ # @!attribute [rw] graph_name
49
49
  # @return [RDF::Resource]
50
- # @since 1.1.0
51
- attr_accessor :context
50
+ # @since 1.1.18
51
+ attr_accessor :graph_name
52
+
53
+ alias_method :name, :graph_name
52
54
 
53
- alias_method :name, :context
54
- alias_method :name=, :context=
55
+ ##
56
+ # Name of this graph, if it is part of an {RDF::Repository}
57
+ # @!attribute [rw] graph_name
58
+ # @return [RDF::Resource]
59
+ # @since 1.1.0
60
+ # @deprecated Use {#graph_name} instead.
61
+ def context
62
+ warn "[DEPRECATION] Graph#context is being replaced with Graph@graph_name in RDF.rb 2.0. Called from #{Gem.location_of_caller.join(':')}"
63
+ graph_name
64
+ end
55
65
 
56
66
  ##
57
67
  # {RDF::Queryable} backing this graph.
@@ -61,7 +71,7 @@ module RDF
61
71
 
62
72
  ##
63
73
  # Creates a new `Graph` instance populated by the RDF data returned by
64
- # dereferencing the given context URL.
74
+ # dereferencing the given graph_name Resource.
65
75
  #
66
76
  # @param [String, #to_s] url
67
77
  # @param [Hash{Symbol => Object}] options
@@ -84,19 +94,19 @@ module RDF
84
94
  end
85
95
 
86
96
  ##
87
- # @overload initialize(context, options)
88
- # @param [RDF::Resource] context
89
- # The context from the associated {RDF::Queryable} associated
97
+ # @overload initialize(graph_name, options)
98
+ # @param [RDF::Resource] graph_name
99
+ # The graph_name from the associated {RDF::Queryable} associated
90
100
  # with this graph as provided with the `:data` option
91
101
  # (only for {RDF::Queryable} instances supporting
92
- # named contexts).
102
+ # named graphs).
93
103
  # @param [Hash{Symbol => Object}] options
94
104
  # @option options [RDF::Queryable] :data (RDF::Repository.new)
95
105
  # Storage behind this graph.
96
- # @raise [ArgumentError] if a `data` does not support contexts.
106
+ # @raise [ArgumentError] if a `data` does not support named graphs.
97
107
  # @note
98
108
  # Contexts are only useful when used as a projection
99
- # on a `:data` which supports contexts. Otherwise, there is no
109
+ # on a `:data` which supports named graphs. Otherwise, there is no
100
110
  # such thing as a named graph in RDF 1.1, a repository may have
101
111
  # graphs which are named, but the name is not a property of the graph.
102
112
  # @overload initialize(options)
@@ -106,19 +116,19 @@ module RDF
106
116
  # @yield [graph]
107
117
  # @yieldparam [Graph]
108
118
  def initialize(*args, &block)
109
- context = args.shift unless args.first.is_a?(Hash)
119
+ graph_name = args.shift unless args.first.is_a?(Hash)
110
120
  options = args.first || {}
111
- @context = case context
121
+ @graph_name = case graph_name
112
122
  when nil then nil
113
- when RDF::Resource then context
114
- else RDF::URI.new(context)
123
+ when RDF::Resource then graph_name
124
+ else RDF::URI.new(graph_name)
115
125
  end
116
126
 
117
127
  @options = options.dup
118
- @data = @options.delete(:data) || RDF::Repository.new(:with_context => false)
128
+ @data = @options.delete(:data) || RDF::Repository.new(with_graph_name: false)
119
129
 
120
- raise ArgumentError, "Can't apply context unless initialized with `data` supporting contexts" if
121
- @context && !@data.supports?(:context)
130
+ raise ArgumentError, "Can't apply graph_name unless initialized with `data` supporting graph_names" if
131
+ @graph_name && !@data.supports?(:graph_name)
122
132
 
123
133
  if block_given?
124
134
  case block.arity
@@ -129,14 +139,14 @@ module RDF
129
139
  end
130
140
 
131
141
  ##
132
- # (re)loads the graph from the specified location, or from the location associated with the graph context, if any
142
+ # (re)loads the graph from the specified location, or from the location associated with the graph name, if any
133
143
  # @return [void]
134
144
  # @see RDF::Mutable#load
135
145
  def load!(*args)
136
146
  case
137
147
  when args.empty?
138
- raise ArgumentError, "Can't reload graph with no context" unless context.is_a?(RDF::URI)
139
- load(context.to_s, {:base_uri => context}.merge(@options))
148
+ raise ArgumentError, "Can't reload graph without a graph_name" unless graph_name.is_a?(RDF::URI)
149
+ load(graph_name.to_s, {base_uri: graph_name}.merge(@options))
140
150
  else super
141
151
  end
142
152
  end
@@ -164,7 +174,7 @@ module RDF
164
174
  # @return [Boolean]
165
175
  # @note The next release, graphs will not be named, this will return true
166
176
  def unnamed?
167
- context.nil?
177
+ graph_name.nil?
168
178
  end
169
179
 
170
180
  ##
@@ -180,16 +190,26 @@ module RDF
180
190
  # Returns all unique RDF contexts for this graph.
181
191
  #
182
192
  # @return [Enumerator<RDF::Resource>]
193
+ # @deprecated Use {#graph_names} instead.
183
194
  def contexts(options = {})
195
+ warn "[DEPRECATION] Graph#contexts is being replaced with Graph#graph_names in RDF.rb 2.0. Called from #{Gem.location_of_caller.join(':')}"
184
196
  (named? ? [context] : []).to_enum.extend(RDF::Countable)
185
197
  end
186
198
 
199
+ ##
200
+ # Returns all unique RDF names for this graph.
201
+ #
202
+ # @return [Enumerator<RDF::Resource>]
203
+ def graph_names(options = {})
204
+ (named? ? [graph_name] : []).extend(RDF::Countable)
205
+ end
206
+
187
207
  ##
188
208
  # Returns the {RDF::Resource} representation of this graph.
189
209
  #
190
210
  # @return [RDF::Resource]
191
211
  def to_uri
192
- context
212
+ graph_name
193
213
  end
194
214
 
195
215
  ##
@@ -197,16 +217,16 @@ module RDF
197
217
  #
198
218
  # @return [String]
199
219
  def to_s
200
- named? ? context.to_s : "default"
220
+ named? ? graph_name.to_s : "default"
201
221
  end
202
222
 
203
223
  ##
204
- # Returns `true` if this graph has an anonymous context, `false` otherwise.
224
+ # Returns `true` if this graph has an anonymous graph, `false` otherwise.
205
225
  #
206
226
  # @return [Boolean]
207
227
  # @note The next release, graphs will not be named, this will return true
208
228
  def anonymous?
209
- context.nil? ? false : context.anonymous?
229
+ graph_name.nil? ? false : graph_name.anonymous?
210
230
  end
211
231
 
212
232
  ##
@@ -215,7 +235,7 @@ module RDF
215
235
  # @return [Integer]
216
236
  # @see RDF::Enumerable#count
217
237
  def count
218
- @data.query(:context => context || false).count
238
+ @data.query(graph_name: graph_name || false).count
219
239
  end
220
240
 
221
241
  ##
@@ -226,7 +246,7 @@ module RDF
226
246
  # @see RDF::Enumerable#has_statement?
227
247
  def has_statement?(statement)
228
248
  statement = statement.dup
229
- statement.context = context
249
+ statement.graph_name = graph_name
230
250
  @data.has_statement?(statement)
231
251
  end
232
252
 
@@ -239,7 +259,7 @@ module RDF
239
259
  # @see RDF::Enumerable#each_statement
240
260
  def each(&block)
241
261
  if @data.respond_to?(:query)
242
- @data.query(:context => context || false, &block)
262
+ @data.query(graph_name: graph_name || false, &block)
243
263
  elsif @data.respond_to?(:each)
244
264
  @data.each(&block)
245
265
  else
@@ -257,16 +277,16 @@ module RDF
257
277
  # @see http://rubygems.org/gems/rdf-isomorphic
258
278
  def ==(other)
259
279
  other.is_a?(RDF::Graph) &&
260
- context == other.context &&
280
+ graph_name == other.graph_name &&
261
281
  statements.to_a == other.statements.to_a
262
282
  end
263
283
 
264
284
  ##
265
285
  # @private
266
- # @see RDF::Queryable#query
267
- def query_pattern(pattern, &block)
286
+ # @see RDF::Queryable#query_pattern
287
+ def query_pattern(pattern, options = {}, &block)
268
288
  pattern = pattern.dup
269
- pattern.context = context || false
289
+ pattern.graph_name = graph_name || false
270
290
  @data.query(pattern, &block)
271
291
  end
272
292
 
@@ -275,7 +295,7 @@ module RDF
275
295
  # @see RDF::Mutable#insert
276
296
  def insert_statement(statement)
277
297
  statement = statement.dup
278
- statement.context = context
298
+ statement.graph_name = graph_name
279
299
  @data.insert(statement)
280
300
  end
281
301
 
@@ -284,7 +304,7 @@ module RDF
284
304
  # @see RDF::Mutable#delete
285
305
  def delete_statement(statement)
286
306
  statement = statement.dup
287
- statement.context = context
307
+ statement.graph_name = graph_name
288
308
  @data.delete(statement)
289
309
  end
290
310
 
@@ -292,7 +312,7 @@ module RDF
292
312
  # @private
293
313
  # @see RDF::Mutable#clear
294
314
  def clear_statements
295
- @data.delete(:context => context || false)
315
+ @data.delete(graph_name: graph_name || false)
296
316
  end
297
317
 
298
318
  protected :query_pattern
@@ -66,7 +66,7 @@ module RDF
66
66
  def initialize(subject = nil, graph = nil, values = nil, &block)
67
67
  @subject = subject || RDF.nil
68
68
  @graph = graph || RDF::Graph.new
69
- is_empty = @graph.query(:subject => subject, :predicate => RDF.first).empty?
69
+ is_empty = @graph.query(subject: subject, predicate: RDF.first).empty?
70
70
 
71
71
  if subject && is_empty
72
72
  # An empty list with explicit subject and value initializers
@@ -113,7 +113,7 @@ module RDF
113
113
  list_nodes << li
114
114
  rest = nil
115
115
  firsts = rests = 0
116
- @graph.query(:subject => li) do |st|
116
+ @graph.query(subject: li) do |st|
117
117
  return false unless st.subject.node?
118
118
  case st.predicate
119
119
  when RDF.first
@@ -454,7 +454,7 @@ module RDF
454
454
  # @return [Boolean]
455
455
  # @see http://ruby-doc.org/core-1.9/classes/Array.html#M000434
456
456
  def empty?
457
- graph.query(:subject => subject, :predicate => RDF.first).empty?
457
+ graph.query(subject: subject, predicate: RDF.first).empty?
458
458
  end
459
459
 
460
460
  ##
@@ -574,7 +574,7 @@ module RDF
574
574
  #
575
575
  # @return [RDF::Term]
576
576
  def first
577
- graph.first_object(:subject => first_subject, :predicate => RDF.first)
577
+ graph.first_object(subject: first_subject, predicate: RDF.first)
578
578
  end
579
579
 
580
580
  ##
@@ -685,7 +685,7 @@ module RDF
685
685
  # @return [RDF::Term]
686
686
  # @see http://ruby-doc.org/core-1.9/classes/Array.html#M000422
687
687
  def last
688
- graph.first_object(:subject => last_subject, :predicate => RDF.first)
688
+ graph.first_object(subject: last_subject, predicate: RDF.first)
689
689
  end
690
690
 
691
691
  ##
@@ -729,7 +729,7 @@ module RDF
729
729
  #
730
730
  # @return [RDF::Resource]
731
731
  def rest_subject
732
- graph.first_object(:subject => subject, :predicate => RDF.rest)
732
+ graph.first_object(subject: subject, predicate: RDF.rest)
733
733
  end
734
734
 
735
735
  ##
@@ -760,7 +760,7 @@ module RDF
760
760
  yield subject
761
761
 
762
762
  loop do
763
- rest = graph.first_object(:subject => subject, :predicate => RDF.rest)
763
+ rest = graph.first_object(subject: subject, predicate: RDF.rest)
764
764
  break if rest.nil? || rest.eql?(RDF.nil)
765
765
  yield subject = rest
766
766
  end
@@ -780,7 +780,7 @@ module RDF
780
780
  return to_enum unless block_given?
781
781
 
782
782
  each_subject do |subject|
783
- if value = graph.first_object(:subject => subject, :predicate => RDF.first)
783
+ if value = graph.first_object(subject: subject, predicate: RDF.first)
784
784
  yield value # FIXME
785
785
  end
786
786
  end
@@ -800,7 +800,7 @@ module RDF
800
800
  return enum_statement unless block_given?
801
801
 
802
802
  each_subject do |subject|
803
- graph.query(:subject => subject, &block)
803
+ graph.query(subject: subject, &block)
804
804
  end
805
805
  end
806
806
  alias_method :to_rdf, :each_statement
@@ -5,7 +5,7 @@ module RDF; class Literal
5
5
  # @see http://www.w3.org/TR/xmlschema11-2/#boolean
6
6
  # @since 0.2.1
7
7
  class Boolean < Literal
8
- DATATYPE = XSD.boolean
8
+ DATATYPE = RDF::XSD.boolean
9
9
  GRAMMAR = /^(true|false|1|0)$/i.freeze
10
10
  TRUES = %w(true 1).freeze
11
11
  FALSES = %w(false 0).freeze
@@ -5,7 +5,7 @@ module RDF; class Literal
5
5
  # @see http://www.w3.org/TR/xmlschema11-2/#date
6
6
  # @since 0.2.1
7
7
  class Date < Literal
8
- DATATYPE = XSD.date
8
+ DATATYPE = RDF::XSD.date
9
9
  GRAMMAR = %r(\A(-?\d{4}-\d{2}-\d{2})((?:[\+\-]\d{2}:\d{2})|UTC|GMT|Z)?\Z).freeze
10
10
  FORMAT = '%Y-%m-%d'.freeze
11
11
 
@@ -5,9 +5,9 @@ module RDF; class Literal
5
5
  # @see http://www.w3.org/TR/xmlschema11-2/#dateTime#boolean
6
6
  # @since 0.2.1
7
7
  class DateTime < Literal
8
- DATATYPE = XSD.dateTime
8
+ DATATYPE = RDF::XSD.dateTime
9
9
  GRAMMAR = %r(\A(-?\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?)((?:[\+\-]\d{2}:\d{2})|UTC|GMT|Z)?\Z).freeze
10
- FORMAT = '%Y-%m-%dT%H:%M:%SZ'.freeze
10
+ FORMAT = '%Y-%m-%dT%H:%M:%S%:z'.freeze
11
11
 
12
12
  ##
13
13
  # @param [DateTime] value
@@ -32,9 +32,9 @@ module RDF; class Literal
32
32
  def canonicalize!
33
33
  if self.valid?
34
34
  @string = if has_timezone?
35
- @object.new_offset.strftime(FORMAT)
35
+ @object.new_offset.new_offset.strftime(FORMAT[0..-4] + 'Z')
36
36
  else
37
- @object.strftime(FORMAT[0..-2])
37
+ @object.strftime(FORMAT[0..-4])
38
38
  end
39
39
  end
40
40
  self
@@ -58,7 +58,7 @@ module RDF; class Literal
58
58
  # @return [RDF::Literal]
59
59
  def timezone
60
60
  if tz == 'Z'
61
- RDF::Literal("PT0S", :datatype => RDF::XSD.dayTimeDuration)
61
+ RDF::Literal("PT0S", datatype: RDF::XSD.dayTimeDuration)
62
62
  elsif md = tz.to_s.match(/^([+-])?(\d+):(\d+)?$/)
63
63
  plus_minus, hour, min = md[1,3]
64
64
  plus_minus = nil unless plus_minus == "-"
@@ -11,7 +11,7 @@ module RDF; class Literal
11
11
  # @see http://www.w3.org/TR/xmlschema11-2/#decimal
12
12
  # @since 0.2.1
13
13
  class Decimal < Numeric
14
- DATATYPE = XSD.decimal
14
+ DATATYPE = RDF::XSD.decimal
15
15
  GRAMMAR = /^[\+\-]?\d+(\.\d*)?$/.freeze
16
16
 
17
17
  ##
@@ -11,18 +11,20 @@ module RDF; class Literal
11
11
  # @see http://www.w3.org/TR/xmlschema11-2/#double
12
12
  # @since 0.2.1
13
13
  class Double < Numeric
14
- DATATYPE = XSD.double
14
+ DATATYPE = RDF::XSD.double
15
15
  GRAMMAR = /^NaN|(?:[\+\-]?(?:INF|(?:\d+(\.\d*)?([eE][\+\-]?\d+)?)))$/.freeze
16
16
 
17
17
  ##
18
18
  # @param [Float, #to_f] value
19
19
  # @option options [String] :lexical (nil)
20
20
  def initialize(value, options = {})
21
+ #require 'byebug'; byebug
21
22
  @datatype = RDF::URI(options[:datatype] || self.class.const_get(:DATATYPE))
22
23
  @string = options[:lexical] if options.has_key?(:lexical)
23
24
  @string ||= value if value.is_a?(String)
24
25
  @object = case
25
26
  when value.is_a?(::String) then case value
27
+ when '+INF' then 1/0.0
26
28
  when 'INF' then 1/0.0
27
29
  when '-INF' then -1/0.0
28
30
  when 'NaN' then 0/0.0
@@ -12,7 +12,7 @@ module RDF; class Literal
12
12
  # @see http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#integer
13
13
  # @since 0.2.1
14
14
  class Integer < Decimal
15
- DATATYPE = XSD.integer
15
+ DATATYPE = RDF::XSD.integer
16
16
  GRAMMAR = /^[\+\-]?\d+$/.freeze
17
17
 
18
18
  ##
@@ -10,9 +10,9 @@ module RDF; class Literal
10
10
  # @see http://www.w3.org/TR/xmlschema11-2/#time
11
11
  # @since 0.2.1
12
12
  class Time < Literal
13
- DATATYPE = XSD.time
13
+ DATATYPE = RDF::XSD.time
14
14
  GRAMMAR = %r(\A(\d{2}:\d{2}:\d{2}(?:\.\d+)?)((?:[\+\-]\d{2}:\d{2})|UTC|GMT|Z)?\Z).freeze
15
- FORMAT = '%H:%M:%SZ'.freeze
15
+ FORMAT = '%H:%M:%S%:z'.freeze
16
16
 
17
17
  ##
18
18
  # @param [Time] value
@@ -44,9 +44,9 @@ module RDF; class Literal
44
44
  def canonicalize!
45
45
  if self.valid?
46
46
  @string = if has_timezone?
47
- @object.new_offset.strftime(FORMAT)
47
+ @object.new_offset.new_offset.strftime(FORMAT[0..-4] + 'Z')
48
48
  else
49
- @object.strftime(FORMAT[0..-2])
49
+ @object.strftime(FORMAT[0..-4])
50
50
  end
51
51
  end
52
52
  self
@@ -92,7 +92,7 @@ module RDF; class Literal
92
92
  #
93
93
  # @return [String]
94
94
  def to_s
95
- @string || @object.strftime('%H:%M:%S%:z').sub("+00:00", 'Z')
95
+ @string || @object.strftime(FORMAT).sub("+00:00", 'Z')
96
96
  end
97
97
 
98
98
  ##
@@ -5,7 +5,7 @@ module RDF; class Literal
5
5
  # @see http://www.w3.org/TR/xmlschema11-2/#token
6
6
  # @since 0.2.3
7
7
  class Token < Literal
8
- DATATYPE = XSD.token
8
+ DATATYPE = RDF::XSD.token
9
9
  GRAMMAR = /\A[^\x0D\x0A\x09]+\z/i.freeze # FIXME
10
10
 
11
11
  ##
@@ -24,17 +24,17 @@ module RDF
24
24
  # value.plain? #=> true`
25
25
  #
26
26
  # @example Creating a language-tagged literal (1)
27
- # value = RDF::Literal.new("Hello!", :language => :en)
27
+ # value = RDF::Literal.new("Hello!", language: :en)
28
28
  # value.has_language? #=> true
29
29
  # value.language #=> :en
30
30
  #
31
31
  # @example Creating a language-tagged literal (2)
32
- # RDF::Literal.new("Wazup?", :language => :"en-US")
33
- # RDF::Literal.new("Hej!", :language => :sv)
34
- # RDF::Literal.new("¡Hola!", :language => :es)
32
+ # RDF::Literal.new("Wazup?", language: :"en-US")
33
+ # RDF::Literal.new("Hej!", language: :sv)
34
+ # RDF::Literal.new("¡Hola!", language: :es)
35
35
  #
36
36
  # @example Creating an explicitly datatyped literal
37
- # value = RDF::Literal.new("2009-12-31", :datatype => RDF::XSD.date)
37
+ # value = RDF::Literal.new("2009-12-31", datatype: RDF::XSD.date)
38
38
  # value.has_datatype? #=> true
39
39
  # value.datatype #=> RDF::XSD.date
40
40
  #
@@ -203,12 +203,46 @@ module RDF
203
203
  false
204
204
  end
205
205
 
206
+ ##
207
+ # Term compatibility according to SPARQL
208
+ #
209
+ # Compatibility of two arguments is defined as:
210
+ # * The arguments are simple literals or literals typed as xsd:string
211
+ # * The arguments are plain literals with identical language tags
212
+ # * The first argument is a plain literal with language tag and the second argument is a simple literal or literal typed as xsd:string
213
+ #
214
+ # @example
215
+ # compatible?("abc" "b") #=> true
216
+ # compatible?("abc" "b"^^xsd:string) #=> true
217
+ # compatible?("abc"^^xsd:string "b") #=> true
218
+ # compatible?("abc"^^xsd:string "b"^^xsd:string) #=> true
219
+ # compatible?("abc"@en "b") #=> true
220
+ # compatible?("abc"@en "b"^^xsd:string) #=> true
221
+ # compatible?("abc"@en "b"@en) #=> true
222
+ # compatible?("abc"@fr "b"@ja) #=> false
223
+ # compatible?("abc" "b"@ja) #=> false
224
+ # compatible?("abc" "b"@en) #=> false
225
+ # compatible?("abc"^^xsd:string "b"@en) #=> false
226
+ #
227
+ # @see http://www.w3.org/TR/sparql11-query/#func-arg-compatibility
228
+ # @since 2.0
229
+ def compatible?(other)
230
+ return false unless other.literal? && plain? && other.plain?
231
+
232
+ # * The arguments are simple literals or literals typed as xsd:string
233
+ # * The arguments are plain literals with identical language tags
234
+ # * The first argument is a plain literal with language tag and the second argument is a simple literal or literal typed as xsd:string
235
+ has_language? ?
236
+ (language == other.language || other.datatype == RDF::XSD.string) :
237
+ other.datatype == RDF::XSD.string
238
+ end
239
+
206
240
  ##
207
241
  # Returns a hash code for this literal.
208
242
  #
209
243
  # @return [Fixnum]
210
244
  def hash
211
- @hash ||= to_s.hash
245
+ @hash ||= [to_s, datatype, language].hash
212
246
  end
213
247
 
214
248
 
@@ -16,7 +16,7 @@ module RDF
16
16
  # Defines the maximum number of interned Node references that can be held
17
17
  # cached in memory at any one time.
18
18
  #
19
- # Note that 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 context 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.
19
+ # @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
20
  CACHE_SIZE = -1 # unlimited by default
21
21
 
22
22
  ##