rdf 3.1.11 → 3.2.1

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.
@@ -78,16 +78,25 @@ module RDF; class Query
78
78
  end
79
79
 
80
80
  ##
81
- # Returns `true` if this solution sequence contains bindings for any of
81
+ # @overload variable?
82
+ # Returns `false`.
83
+ #
84
+ # @return [Boolean]
85
+ # @overload variable?(variables)
86
+ # Returns `true` if this solution sequence contains bindings for any of
82
87
  # the given `variables`.
83
88
  #
84
- # @param [Array<Symbol, #to_sym>] variables
85
- # an array of variables to check
86
- # @return [Boolean] `true` or `false`
89
+ # @param [Array<Symbol, #to_sym>] variables
90
+ # @return [Boolean]
87
91
  # @see RDF::Query::Solution#variable?
88
92
  # @see RDF::Query#execute
89
- def variable?(variables)
90
- self.any? { |solution| solution.variables?(variables) }
93
+ def variable?(*args)
94
+ case args.length
95
+ when 0 then false
96
+ when 1
97
+ self.any? { |solution| solution.variables?(args.first) }
98
+ else raise ArgumentError("wrong number of arguments (given #{args.length}, expected 0 or 1)")
99
+ end
91
100
  end
92
101
  alias_method :variables?, :variable?
93
102
  alias_method :have_variables?, :variable?
@@ -87,13 +87,27 @@ class RDF::Query
87
87
  end
88
88
 
89
89
  ##
90
- # Returns `true`.
90
+ # @overload variable?
91
+ # Returns `true` if `self` is a {RDF::Query::Variable}, or does it contain a variable?
91
92
  #
92
- # @return [Boolean]
93
- # @see RDF::Term#variable?
93
+ # @return [Boolean]
94
+ # @overload variable?(variable)
95
+ # Returns `true` if `self` contains the given variable.
96
+ #
97
+ # @param [RDF::Resource] value
98
+ # @return [Boolean]
94
99
  # @since 0.1.7
95
- def variable?
96
- true
100
+ def variable?(*args)
101
+ case args.length
102
+ when 0 then true
103
+ when 1
104
+ case variable = args.first
105
+ when RDF::Query::Variable then self == variable
106
+ when Symbol then to_sym == variable
107
+ else false
108
+ end
109
+ else raise ArgumentError("wrong number of arguments (given #{args.length}, expected 0 or 1)")
110
+ end
97
111
  end
98
112
 
99
113
  ##
data/lib/rdf/query.rb CHANGED
@@ -443,11 +443,22 @@ module RDF
443
443
  end
444
444
 
445
445
  ##
446
- # Returns `true` if any pattern contains a variable.
446
+ # @overload variable?
447
+ # Returns `true` if any pattern contains a variable.
447
448
  #
448
- # @return [Boolean]
449
- def variable?
450
- !variables.empty?
449
+ # @return [Boolean]
450
+ # @overload variable?(variables)
451
+ # Returns `true` if any pattern contains any of the variables.
452
+ #
453
+ # @param [Array<Symbol, #to_sym>] variables
454
+ # @return [Boolean]
455
+ def variable?(*args)
456
+ case args.length
457
+ when 0 then !variables.empty?
458
+ when 1
459
+ patterns.any? {|p| p.variable?(*args)}
460
+ else raise ArgumentError("wrong number of arguments (given #{args.length}, expected 0 or 1)")
461
+ end
451
462
  end
452
463
  alias_method :variables?, :variable?
453
464
  alias_method :has_variables?, :variable?
data/lib/rdf/reader.rb CHANGED
@@ -647,7 +647,7 @@ module RDF
647
647
  ##
648
648
  # @return [String]
649
649
  def readline
650
- @line = @line_rest || @input.readline
650
+ @line = instance_variable_defined?(:@line_rest) && @line_rest || @input.readline
651
651
  @line, @line_rest = @line.split("\r", 2)
652
652
  @line = String.new if @line.nil? # not frozen
653
653
  @line.chomp!
@@ -243,17 +243,16 @@ module RDF
243
243
  #
244
244
  # @see RDF::Repository
245
245
  module Implementation
246
- require 'hamster'
247
246
  DEFAULT_GRAPH = false
248
247
 
249
248
  ##
250
249
  # @private
251
250
  def self.extend_object(obj)
252
251
  obj.instance_variable_set(:@data, obj.options.delete(:data) ||
253
- Hamster::Hash.new)
252
+ Hash.new)
254
253
  obj.instance_variable_set(:@tx_class,
255
254
  obj.options.delete(:transaction_class) ||
256
- SerializedTransaction)
255
+ RDF::Transaction::SerializedTransaction)
257
256
  super
258
257
  end
259
258
 
@@ -263,7 +262,6 @@ module RDF
263
262
  def supports?(feature)
264
263
  case feature.to_sym
265
264
  when :graph_name then @options[:with_graph_name]
266
- when :inference then false # forward-chaining inference
267
265
  when :validity then @options.fetch(:with_validity, true)
268
266
  when :literal_equality then true
269
267
  when :atomic_write then true
@@ -287,10 +285,22 @@ module RDF
287
285
  end
288
286
 
289
287
  ##
290
- # @private
291
- # @see RDF::Enumerable#graph?
292
- def graph?(graph)
293
- @data.key?(graph)
288
+ # @overload graph?
289
+ # Returns `false` to indicate that this is not a graph.
290
+ #
291
+ # @return [Boolean]
292
+ # @overload graph?(name)
293
+ # Returns `true` if `self` contains the given RDF graph_name.
294
+ #
295
+ # @param [RDF::Resource, false] graph_name
296
+ # Use value `false` to query for the default graph_name
297
+ # @return [Boolean]
298
+ def graph?(*args)
299
+ case args.length
300
+ when 0 then false
301
+ when 1 then @data.key?(args.first)
302
+ else raise ArgumentError("wrong number of arguments (given #{args.length}, expected 0 or 1)")
303
+ end
294
304
  end
295
305
  alias_method :has_graph?, :graph?
296
306
 
@@ -322,8 +332,12 @@ module RDF
322
332
  # @overload statement?(statement)
323
333
  # @private
324
334
  # @see RDF::Enumerable#statement?
325
- def statement?(statement = nil)
326
- statement && statement_in?(@data, statement)
335
+ def statement?(*args)
336
+ case args.length
337
+ when 0 then false
338
+ when 1 then args.first && statement_in?(@data, args.first)
339
+ else raise ArgumentError("wrong number of arguments (given #{args.length}, expected 0 or 1)")
340
+ end
327
341
  end
328
342
  alias_method :has_statement?, :statement?
329
343
 
@@ -365,7 +379,7 @@ module RDF
365
379
  ##
366
380
  # @see RDF::Dataset#isolation_level
367
381
  def isolation_level
368
- :serializable
382
+ :snapshot
369
383
  end
370
384
 
371
385
  ##
@@ -455,7 +469,7 @@ module RDF
455
469
  # @private
456
470
  # @see RDF::Mutable#clear
457
471
  def clear_statements
458
- @data = @data.clear
472
+ @data = @data.class.new
459
473
  end
460
474
 
461
475
  ##
@@ -497,14 +511,11 @@ module RDF
497
511
  unless statement_in?(data, statement)
498
512
  s, p, o, c = statement.to_quad
499
513
  c ||= DEFAULT_GRAPH
500
-
501
- return data.put(c) do |subs|
502
- (subs || Hamster::Hash.new).put(s) do |preds|
503
- (preds || Hamster::Hash.new).put(p) do |objs|
504
- (objs || Hamster::Hash.new).put(o, statement.options)
505
- end
506
- end
507
- end
514
+
515
+ data = data.has_key?(c) ? data.dup : data.merge(c => {})
516
+ data[c] = data[c].has_key?(s) ? data[c].dup : data[c].merge(s => {})
517
+ data[c][s] = data[c][s].has_key?(p) ? data[c][s].dup : data[c][s].merge(p => {})
518
+ data[c][s][p] = data[c][s][p].merge(o => statement.options)
508
519
  end
509
520
  data
510
521
  end
@@ -513,93 +524,18 @@ module RDF
513
524
  # @private
514
525
  # @return [Hamster::Hash] a new, updated hamster hash
515
526
  def delete_from(data, statement)
516
- if statement_in?(data, statement)
527
+ if has_statement_in?(data, statement)
517
528
  s, p, o, g = statement.to_quad
518
529
  g = DEFAULT_GRAPH unless supports?(:graph_name)
519
530
  g ||= DEFAULT_GRAPH
520
531
 
521
- os = data[g][s][p].delete(o)
522
- ps = os.empty? ? data[g][s].delete(p) : data[g][s].put(p, os)
523
- ss = ps.empty? ? data[g].delete(s) : data[g].put(s, ps)
524
- return ss.empty? ? data.delete(g) : data.put(g, ss)
532
+ os = data[g][s][p].dup.delete_if {|k,v| k == o}
533
+ ps = os.empty? ? data[g][s].dup.delete_if {|k,v| k == p} : data[g][s].merge(p => os)
534
+ ss = ps.empty? ? data[g].dup.delete_if {|k,v| k == s} : data[g].merge(s => ps)
535
+ return ss.empty? ? data.dup.delete_if {|k,v| k == g} : data.merge(g => ss)
525
536
  end
526
537
  data
527
538
  end
528
-
529
- ##
530
- # A transaction for the Hamster-based `RDF::Repository::Implementation`
531
- # with full serializability.
532
- #
533
- # @todo refactor me!
534
- # @see RDF::Transaction
535
- class SerializedTransaction < Transaction
536
- ##
537
- # @see Transaction#initialize
538
- def initialize(*args, **options, &block)
539
- super(*args, **options, &block)
540
- @base_snapshot = @snapshot
541
- end
542
-
543
- ##
544
- # Inserts the statement to the transaction's working snapshot.
545
- #
546
- # @see Transaction#insert_statement
547
- def insert_statement(statement)
548
- @snapshot = @snapshot.class
549
- .new(data: @snapshot.send(:insert_to,
550
- @snapshot.send(:data),
551
- process_statement(statement)))
552
- end
553
-
554
- ##
555
- # Deletes the statement from the transaction's working snapshot.
556
- #
557
- # @see Transaction#insert_statement
558
- def delete_statement(statement)
559
- @snapshot = @snapshot.class
560
- .new(data: @snapshot.send(:delete_from,
561
- @snapshot.send(:data),
562
- process_statement(statement)))
563
- end
564
-
565
- ##
566
- # @see RDF::Dataset#isolation_level
567
- def isolation_level
568
- :serializable
569
- end
570
-
571
- ##
572
- # @note this is a simple object equality check.
573
- #
574
- # @see RDF::Transaction#mutated?
575
- def mutated?
576
- !@snapshot.send(:data).equal?(repository.send(:data))
577
- end
578
-
579
- ##
580
- # Replaces repository data with the transaction's snapshot in a safely
581
- # serializable fashion.
582
- #
583
- # @note this transaction uses a pessimistic merge strategy which
584
- # fails the transaction if any data has changed in the repository
585
- # since transaction start time. However, the specific guarantee is
586
- # softer: multiple concurrent conflicting transactions will not
587
- # succeed. We may choose to implement a less pessimistic merge
588
- # strategy as a non-breaking change.
589
- #
590
- # @raise [TransactionError] when the transaction can't be merged.
591
- # @see Transaction#execute
592
- def execute
593
- raise TransactionError, 'Cannot execute a rolled back transaction. ' \
594
- 'Open a new one instead.' if @rolledback
595
-
596
- raise TransactionError, 'Error merging transaction. Repository' \
597
- 'has changed during transaction time.' unless
598
- repository.send(:data).equal? @base_snapshot.send(:data)
599
-
600
- repository.send(:data=, @snapshot.send(:data))
601
- end
602
- end
603
539
  end # Implementation
604
540
  end # Repository
605
541
  end # RDF
@@ -213,8 +213,12 @@ module RDF
213
213
  # @see RDF::Value#statement?
214
214
  # @overload statement?(statement)
215
215
  # @see RDF::Enumerable#statement?
216
- def statement?(statement = nil)
217
- statement && read_target.has_statement?(statement)
216
+ def statement?(*args)
217
+ case args.length
218
+ when 0 then false
219
+ when 1 then read_target.statement?(*args)
220
+ else raise ArgumentError("wrong number of arguments (given #{args.length}, expected 0 or 1)")
221
+ end
218
222
  end
219
223
  alias_method :has_statement?, :statement?
220
224
 
@@ -243,7 +247,7 @@ module RDF
243
247
  # @raise [TransactionError] if the transaction can't be applied
244
248
  def execute
245
249
  raise TransactionError, 'Cannot execute a rolled back transaction. ' \
246
- 'Open a new one instead.' if @rolledback
250
+ 'Open a new one instead.' if instance_variable_defined?(:@rolledback) && @rolledback
247
251
  @changes.apply(@repository)
248
252
  end
249
253
 
@@ -318,7 +322,81 @@ module RDF
318
322
  end
319
323
 
320
324
  public
321
-
325
+
326
+ ##
327
+ # A transaction with full serializability.
328
+ #
329
+ # @todo refactor me!
330
+ # @see RDF::Transaction
331
+ class SerializedTransaction < Transaction
332
+ ##
333
+ # @see Transaction#initialize
334
+ def initialize(*args, **options, &block)
335
+ super(*args, **options, &block)
336
+ @base_snapshot = @snapshot
337
+ end
338
+
339
+ ##
340
+ # Inserts the statement to the transaction's working snapshot.
341
+ #
342
+ # @see Transaction#insert_statement
343
+ def insert_statement(statement)
344
+ @snapshot = @snapshot.class
345
+ .new(data: @snapshot.send(:insert_to,
346
+ @snapshot.send(:data),
347
+ process_statement(statement)))
348
+ end
349
+
350
+ ##
351
+ # Deletes the statement from the transaction's working snapshot.
352
+ #
353
+ # @see Transaction#insert_statement
354
+ def delete_statement(statement)
355
+ @snapshot = @snapshot.class
356
+ .new(data: @snapshot.send(:delete_from,
357
+ @snapshot.send(:data),
358
+ process_statement(statement)))
359
+ end
360
+
361
+ ##
362
+ # @see RDF::Dataset#isolation_level
363
+ def isolation_level
364
+ :serializable
365
+ end
366
+
367
+ ##
368
+ # @note this is a simple object equality check.
369
+ #
370
+ # @see RDF::Transaction#mutated?
371
+ def mutated?
372
+ !@snapshot.send(:data).equal?(repository.send(:data))
373
+ end
374
+
375
+ ##
376
+ # Replaces repository data with the transaction's snapshot in a safely
377
+ # serializable fashion.
378
+ #
379
+ # @note this transaction uses a pessimistic merge strategy which
380
+ # fails the transaction if any data has changed in the repository
381
+ # since transaction start time. However, the specific guarantee is
382
+ # softer: multiple concurrent conflicting transactions will not
383
+ # succeed. We may choose to implement a less pessimistic merge
384
+ # strategy as a non-breaking change.
385
+ #
386
+ # @raise [TransactionError] when the transaction can't be merged.
387
+ # @see Transaction#execute
388
+ def execute
389
+ raise TransactionError, 'Cannot execute a rolled back transaction. ' \
390
+ 'Open a new one instead.' if instance_variable_defined?(:@rolledback) && @rolledback
391
+
392
+ raise TransactionError, 'Error merging transaction. Repository' \
393
+ 'has changed during transaction time.' unless
394
+ repository.send(:data).equal? @base_snapshot.send(:data)
395
+
396
+ repository.send(:data=, @snapshot.send(:data))
397
+ end
398
+ end # SerializedTransaction
399
+
322
400
  ##
323
401
  # An error class for transaction failures.
324
402
  #
data/lib/rdf/util/file.rb CHANGED
@@ -98,7 +98,7 @@ module RDF; module Util
98
98
  headers: response.headers
99
99
  }
100
100
 
101
- remote_document = RemoteDocument.new(response.body, document_options)
101
+ RemoteDocument.new(response.body, document_options)
102
102
  when 300..399
103
103
  # Document base is redirected location
104
104
  # Location may be relative
@@ -215,7 +215,7 @@ module RDF; module Util
215
215
  headers: response.headers
216
216
  }
217
217
 
218
- remote_document = RemoteDocument.new(response.body, document_options)
218
+ RemoteDocument.new(response.body, document_options)
219
219
  else
220
220
  raise IOError, "<#{base_uri}>: #{response.status}"
221
221
  end
@@ -17,17 +17,20 @@ module RDF; module Util
17
17
  # @param [Hash{Symbol => Object}] options
18
18
  # @option options [Logger, #<<] :logger
19
19
  # @return [Logger, #write, #<<]
20
- def logger(**options)
21
- logger = options.fetch(:logger, @logger)
22
- logger = @options[:logger] if logger.nil? && @options
20
+ def logger(logger: nil, **options)
21
+ # Guard against undefined instance variables, which may be a warning if used.
22
+ @options = {} unless instance_variable_defined?(:@options) || frozen?
23
+ logger ||= @logger if instance_variable_defined?(:@logger)
24
+ logger = @options[:logger] if logger.nil? && instance_variable_defined?(:@options) && @options
23
25
  if logger.nil?
24
26
  # Unless otherwise specified, use $stderr
25
- logger = (@options || options)[:logger] = IOWrapper.new($stderr)
27
+ logger = IOWrapper.new($stderr)
26
28
 
27
29
  # Reset log_statistics so that it's not inherited across different instances
28
30
  logger.log_statistics.clear if logger.respond_to?(:log_statistics)
29
31
  end
30
- logger = (@options || options)[:logger] = ::Logger.new(::File.open(::File::NULL, "w")) unless logger # Incase false was used, which is frozen
32
+ logger = ::Logger.new(::File.open(::File::NULL, "w")) unless logger # Incase false was used, which is frozen
33
+ @options[:logger] ||= logger if instance_variable_defined?(:@options)
31
34
  logger.extend(LoggerBehavior) unless logger.is_a?(LoggerBehavior)
32
35
  logger
33
36
  end
@@ -70,7 +70,7 @@ module RDF
70
70
  # @return [Enumerator]
71
71
  def each(&block)
72
72
  if self.equal?(Vocabulary)
73
- if @vocabs
73
+ if instance_variable_defined?(:@vocabs) && @vocabs
74
74
  @vocabs.select(&:name).each(&block)
75
75
  else
76
76
  # This is needed since all vocabulary classes are defined using
@@ -356,7 +356,7 @@ module RDF
356
356
  def ontology(*args)
357
357
  case args.length
358
358
  when 0
359
- @ontology
359
+ @ontology if instance_variable_defined?(:@ontology)
360
360
  else
361
361
  uri, options = args
362
362
  URI.cache.delete(uri.to_s.to_sym) # Clear any previous entry
@@ -507,7 +507,7 @@ module RDF
507
507
  end
508
508
 
509
509
  # Also include the ontology, if it's not also a property
510
- @ontology.each_statement(&block) if @ontology && @ontology != self
510
+ @ontology.each_statement(&block) if self.ontology && self.ontology != self
511
511
  end
512
512
 
513
513
  ##
@@ -574,6 +574,7 @@ module RDF
574
574
  term_defs
575
575
  end
576
576
 
577
+ #require 'byebug'; byebug
577
578
  # Pass over embedded_defs with anonymous references, once
578
579
  embedded_defs.each do |term, attributes|
579
580
  attributes.each do |ak, avs|
@@ -1234,16 +1235,16 @@ module RDF
1234
1235
  values = values.map do |value|
1235
1236
  if value.is_a?(Literal) && %w(: comment definition notation note editorialNote).include?(k.to_s)
1236
1237
  "%(#{value.to_s.gsub('(', '\(').gsub(')', '\)')}).freeze"
1237
- # elsif value.is_a?(RDF::Vocabulary::Term)
1238
- # value.to_ruby(indent: indent + " ")
1238
+ elsif value.node? && value.is_a?(RDF::Vocabulary::Term)
1239
+ "#{value.to_ruby(indent: indent + " ")}.freeze"
1239
1240
  elsif value.is_a?(RDF::Term)
1240
1241
  "#{value.to_s.inspect}.freeze"
1241
1242
  elsif value.is_a?(RDF::List)
1242
1243
  list_elements = value.map do |u|
1243
1244
  if u.uri?
1244
1245
  "#{u.to_s.inspect}.freeze"
1245
- # elsif u.respond_to?(:to_ruby)
1246
- # u.to_ruby(indent: indent + " ")
1246
+ elsif u.node? && u.respond_to?(:to_ruby)
1247
+ u.to_ruby(indent: indent + " ")
1247
1248
  else
1248
1249
  "#{u.to_s.inspect}.freeze"
1249
1250
  end
data/lib/rdf/writer.rb CHANGED
@@ -516,7 +516,7 @@ module RDF
516
516
  when RDF::Literal then format_literal(term, **options)
517
517
  when RDF::URI then format_uri(term, **options)
518
518
  when RDF::Node then format_node(term, **options)
519
- when RDF::Statement then format_embTriple(term, **options)
519
+ when RDF::Statement then format_quotedTriple(term, **options)
520
520
  else nil
521
521
  end
522
522
  end
@@ -574,7 +574,7 @@ module RDF
574
574
  # @return [String]
575
575
  # @raise [NotImplementedError] unless implemented in subclass
576
576
  # @abstract
577
- def format_embTriple(value, **options)
577
+ def format_quotedTriple(value, **options)
578
578
  raise NotImplementedError.new("#{self.class}#format_statement") # override in subclasses
579
579
  end
580
580