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.
@@ -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
@@ -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(**options)
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(*args, **options, &block)
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 args.first
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: args.first, **options).to_a
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
- fmt = args.first
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 fmt
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
@@ -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 *statement.to_triple
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 *statement.to_quad
286
+ yield(*statement.to_quad)
286
287
  end
287
288
  end
288
289
  enum_quad
@@ -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
- def load(url, graph_name: nil, **options)
41
+ def load(url, graph_name: nil, **options)
41
42
  raise TypeError.new("#{self} is immutable") if immutable?
42
43
 
43
- Reader.open(url, {base_uri: url}.merge(options)) do |reader|
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.map! do |value|
158
- case
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
@@ -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 ({})
@@ -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.map! do |value|
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")
@@ -104,7 +104,7 @@ module RDF
104
104
  # @private
105
105
  # @see RDF::Enumerable#supports?
106
106
  def supports?(feature)
107
- return true if feature == :graph_name
107
+ return true if [:graph_name, :rdfstar].include?(feature)
108
108
  super
109
109
  end
110
110
 
@@ -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)
@@ -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
@@ -26,7 +26,7 @@ module RDF
26
26
  # RDF::Statement(s, p, "o")
27
27
  #
28
28
  class Statement
29
- include RDF::Value
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 term, was #{@subject.inspect}"
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.resource? &&
144
- has_predicate? && predicate.resource? &&
145
- has_object? && (object.resource? || object.literal?) &&
146
- (has_graph? ? graph_name.resource? : true))
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.respond_to?(:to_base) ? term.to_base : term.inspect
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