rdf 3.1.1 → 3.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
 
@@ -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)
@@ -45,7 +45,7 @@ module RDF
45
45
  # identified by `subject`, but will be invalid.
46
46
  #
47
47
  # @example add constructed list to existing graph
48
- # l = RDF::List(nil, nil (1, 2, 3))
48
+ # l = RDF::List(values: (1, 2, 3))
49
49
  # g = RDF::Graph.new << l
50
50
  # g.count # => l.count
51
51
  #
@@ -68,8 +68,8 @@ module RDF
68
68
  if first || values.length > 0
69
69
  # Intantiate the list from values, and insert the first value using subject.
70
70
  values.reverse_each {|value| self.unshift(value)}
71
- graph.insert RDF::Statement(subject, RDF.first, first || RDF.nil)
72
- graph.insert RDF::Statement(subject, RDF.rest, @subject)
71
+ @graph.insert RDF::Statement(subject, RDF.first, first || RDF.nil)
72
+ @graph.insert RDF::Statement(subject, RDF.rest, @subject)
73
73
  end
74
74
  @subject = subject
75
75
  else
@@ -175,7 +175,7 @@ module RDF
175
175
  # @return [RDF::List]
176
176
  # @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-26
177
177
  def &(other)
178
- RDF::List[*(to_a & other.to_a)]
178
+ self.class.new(values: (to_a & other.to_a))
179
179
  end
180
180
 
181
181
  ##
@@ -193,7 +193,7 @@ module RDF
193
193
  # @return [RDF::List]
194
194
  # @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-7C
195
195
  def |(other)
196
- RDF::List[*(to_a | other.to_a)]
196
+ self.class.new(values: (to_a | other.to_a))
197
197
  end
198
198
 
199
199
  ##
@@ -206,7 +206,7 @@ module RDF
206
206
  # @return [RDF::List]
207
207
  # @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-2B
208
208
  def +(other)
209
- RDF::List[*(to_a + other.to_a)]
209
+ self.class.new(values: (to_a + other.to_a))
210
210
  end
211
211
 
212
212
  ##
@@ -220,7 +220,7 @@ module RDF
220
220
  # @return [RDF::List]
221
221
  # @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-2D
222
222
  def -(other)
223
- RDF::List[*(to_a - other.to_a)]
223
+ self.class.new(values: (to_a - other.to_a))
224
224
  end
225
225
 
226
226
  ##
@@ -250,7 +250,7 @@ module RDF
250
250
  # @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-2A
251
251
  def *(int_or_str)
252
252
  case int_or_str
253
- when Integer then RDF::List[*(to_a * int_or_str)]
253
+ when Integer then self.class.new(values: (to_a * int_or_str))
254
254
  else join(int_or_str.to_s)
255
255
  end
256
256
  end
@@ -538,13 +538,13 @@ module RDF
538
538
  ##
539
539
  # @private
540
540
  def slice_with_start_and_length(start, length)
541
- RDF::List[*to_a.slice(start, length)]
541
+ self.class.new(values: to_a.slice(start, length))
542
542
  end
543
543
 
544
544
  ##
545
545
  # @private
546
546
  def slice_with_range(range)
547
- RDF::List[*to_a.slice(range)]
547
+ self.class.new(values: to_a.slice(range))
548
548
  end
549
549
 
550
550
  protected :slice_with_start_and_length
@@ -851,7 +851,7 @@ module RDF
851
851
  # @return [RDF::List]
852
852
  # @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-reverse
853
853
  def reverse
854
- RDF::List[*to_a.reverse]
854
+ self.class.new(values: to_a.reverse)
855
855
  end
856
856
 
857
857
  ##
@@ -863,7 +863,7 @@ module RDF
863
863
  # @return [RDF::List]
864
864
  # @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-sort
865
865
  def sort(&block)
866
- RDF::List[*super]
866
+ self.class.new(values: super)
867
867
  end
868
868
 
869
869
  ##
@@ -875,7 +875,7 @@ module RDF
875
875
  # @return [RDF::List]
876
876
  # @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-sort_by
877
877
  def sort_by(&block)
878
- RDF::List[*super]
878
+ self.class.new(values: super)
879
879
  end
880
880
 
881
881
  ##
@@ -887,7 +887,7 @@ module RDF
887
887
  # @return [RDF::List]
888
888
  # @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-uniq
889
889
  def uniq
890
- RDF::List[*to_a.uniq]
890
+ self.class.new(values: to_a.uniq)
891
891
  end
892
892
 
893
893
  ##
@@ -964,7 +964,7 @@ module RDF
964
964
  case value
965
965
  when nil then RDF.nil
966
966
  when RDF::Value then value
967
- when Array then RDF::List.new(subject: nil, graph: graph, values: value)
967
+ when Array then self.class.new(subject: nil, graph: graph, values: value)
968
968
  else value
969
969
  end
970
970
  end
@@ -118,6 +118,7 @@ module RDF
118
118
  when ::Integer then RDF::Literal::Integer
119
119
  when ::Float then RDF::Literal::Double
120
120
  when ::BigDecimal then RDF::Literal::Decimal
121
+ when ::Rational then RDF::Literal::Double
121
122
  when ::DateTime then RDF::Literal::DateTime
122
123
  when ::Time then RDF::Literal::DateTime
123
124
  when ::Date then RDF::Literal::Date
@@ -63,9 +63,9 @@ 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::Integer]
67
67
  def round
68
- self.class.new(to_d.round)
68
+ RDF::Literal::Integer.new(to_d.round)
69
69
  end
70
70
 
71
71
  ##
@@ -74,9 +74,9 @@ module RDF; class Literal
74
74
  # @example
75
75
  # RDF::Literal(1).ceil #=> RDF::Literal(1)
76
76
  #
77
- # @return [RDF::Literal]
77
+ # @return [RDF::Literal::Integer]
78
78
  def ceil
79
- self.class.new(to_d.ceil)
79
+ RDF::Literal::Integer.new(to_d.ceil)
80
80
  end
81
81
 
82
82
  ##
@@ -85,9 +85,9 @@ module RDF; class Literal
85
85
  # @example
86
86
  # RDF::Literal(1).floor #=> RDF::Literal(1)
87
87
  #
88
- # @return [RDF::Literal]
88
+ # @return [RDF::Literal::Integer]
89
89
  def floor
90
- self.class.new(to_d.floor)
90
+ RDF::Literal::Integer.new(to_d.floor)
91
91
  end
92
92
 
93
93
  ##
@@ -142,7 +142,7 @@ module RDF; class Literal
142
142
  end
143
143
 
144
144
  ##
145
- # Returns the smallest number greater than or equal to `self`.
145
+ # Returns the smallest integer greater than or equal to `self`.
146
146
  #
147
147
  # @example
148
148
  # RDF::Literal(1.2).ceil #=> RDF::Literal(2)
@@ -150,14 +150,14 @@ module RDF; class Literal
150
150
  # RDF::Literal(2.0).ceil #=> RDF::Literal(2)
151
151
  # RDF::Literal(-2.0).ceil #=> RDF::Literal(-2)
152
152
  #
153
- # @return [RDF::Literal]
153
+ # @return [RDF::Literal::Integer]
154
154
  # @since 0.2.3
155
155
  def ceil
156
- self.class.new(to_f.ceil)
156
+ RDF::Literal::Integer.new(to_f.ceil)
157
157
  end
158
158
 
159
159
  ##
160
- # Returns the largest number less than or equal to `self`.
160
+ # Returns the largest integer less than or equal to `self`.
161
161
  #
162
162
  # @example
163
163
  # RDF::Literal(1.2).floor #=> RDF::Literal(1)
@@ -165,10 +165,10 @@ module RDF; class Literal
165
165
  # RDF::Literal(2.0).floor #=> RDF::Literal(2)
166
166
  # RDF::Literal(-2.0).floor #=> RDF::Literal(-2)
167
167
  #
168
- # @return [RDF::Literal]
168
+ # @return [RDF::Literal::Integer]
169
169
  # @since 0.2.3
170
170
  def floor
171
- self.class.new(to_f.floor)
171
+ RDF::Literal::Integer.new(to_f.floor)
172
172
  end
173
173
 
174
174
  ##
@@ -181,11 +181,11 @@ module RDF; class Literal
181
181
  end
182
182
 
183
183
  ##
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.
184
+ # Returns the integer 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::Integer]
187
187
  def round
188
- self.class.new(to_f.round)
188
+ RDF::Literal::Integer.new(to_f.round)
189
189
  end
190
190
 
191
191
  ##
@@ -123,6 +123,40 @@ module RDF; class Literal
123
123
  end
124
124
  end
125
125
 
126
+ ##
127
+ # Exponent − Performs exponential (power) calculation on operators.
128
+ #
129
+ # Promotes values, as necessary, with the result type depending on the input values.
130
+ #
131
+ # @param [Literal::Numeric, #to_i, #to_f, #to_d] other
132
+ # @return [RDF::Literal::Numeric]
133
+ # @since 0.2.3
134
+ # @see https://www.w3.org/TR/xpath-functions/#func-math-pow
135
+ def **(other)
136
+ RDF::Literal(object ** (other.is_a?(RDF::Literal::Numeric) ? other.object : other))
137
+ rescue ZeroDivisionError
138
+ RDF::Literal::Double.new('INF')
139
+ end
140
+
141
+ ##
142
+ # Exponent − Performs remainder of `self` divided by `other`.
143
+ #
144
+ # @param [Literal::Numeric, #to_i, #to_f, #to_d] other
145
+ # @return [RDF::Literal]
146
+ # @since 0.2.3
147
+ # @see https://www.w3.org/TR/xpath-functions/#func-numeric-mod
148
+ def %(other)
149
+ if self.class == Double || [Double, ::Float].include?(other.class)
150
+ self.class.new(to_f % other.to_f)
151
+ elsif ((self.class == RDF::Literal::Float || other.class == RDF::Literal::Float) rescue false)
152
+ self.class.new(to_f % other.to_f)
153
+ elsif self.class == Decimal || other.class == Decimal
154
+ self.class.new(to_d % (other.respond_to?(:to_d) ? other.to_d : BigDecimal(other.to_s)))
155
+ else
156
+ self.class.new(to_i % other.to_i)
157
+ end
158
+ end
159
+
126
160
  ##
127
161
  # Returns the quotient of `self` divided by `other`.
128
162
  #
@@ -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
 
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- require 'uri'
2
+ require 'cgi'
3
3
 
4
4
  module RDF
5
5
  ##
@@ -400,7 +400,7 @@ module RDF
400
400
  # @example Joining two URIs
401
401
  # RDF::URI.new('http://example.org/foo/bar').join('/foo')
402
402
  # #=> RDF::URI('http://example.org/foo')
403
- # @see <http://github.com/ruby-rdf/rdf-spec/blob/master/lib/rdf/spec/uri.rb>
403
+ # @see <https://github.com/ruby-rdf/rdf-spec/blob/master/lib/rdf/spec/uri.rb>
404
404
  # @see <http://tools.ietf.org/html/rfc3986#section-5.2>
405
405
  # @see RDF::URI#/
406
406
  # @see RDF::URI#+
@@ -471,7 +471,7 @@ module RDF
471
471
  # @see RDF::URI#+
472
472
  # @see RDF::URI#join
473
473
  # @see <http://tools.ietf.org/html/rfc3986#section-5.2>
474
- # @see <http://github.com/ruby-rdf/rdf-spec/blob/master/lib/rdf/spec/uri.rb>
474
+ # @see <https://github.com/ruby-rdf/rdf-spec/blob/master/lib/rdf/spec/uri.rb>
475
475
  # @example Building a HTTP URL
476
476
  # RDF::URI.new('http://example.org') / 'jhacker' / 'foaf.ttl'
477
477
  # #=> RDF::URI('http://example.org/jhacker/foaf.ttl')
@@ -846,7 +846,7 @@ module RDF
846
846
  parts[:user] = (user.dup.force_encoding(Encoding::UTF_8) if user)
847
847
  parts[:password] = (password.dup.force_encoding(Encoding::UTF_8) if password)
848
848
  parts[:host] = (host.dup.force_encoding(Encoding::UTF_8) if host)
849
- parts[:port] = (URI.decode(port).to_i if port)
849
+ parts[:port] = (CGI.unescape(port).to_i if port)
850
850
  parts[:path] = (path.to_s.dup.force_encoding(Encoding::UTF_8) unless path.empty?)
851
851
  parts[:query] = (query[1..-1].dup.force_encoding(Encoding::UTF_8) if query)
852
852
  parts[:fragment] = (fragment[1..-1].dup.force_encoding(Encoding::UTF_8) if fragment)
@@ -902,7 +902,7 @@ module RDF
902
902
  # Normalized version of user
903
903
  # @return [String]
904
904
  def normalized_user
905
- URI.encode(URI.decode(user), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/) if user
905
+ URI.encode(CGI.unescape(user), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/).force_encoding(Encoding::UTF_8) if user
906
906
  end
907
907
 
908
908
  ##
@@ -928,7 +928,7 @@ module RDF
928
928
  # Normalized version of password
929
929
  # @return [String]
930
930
  def normalized_password
931
- URI.encode(URI.decode(password), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/) if password
931
+ URI.encode(CGI.unescape(password), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/).force_encoding(Encoding::UTF_8) if password
932
932
  end
933
933
 
934
934
  HOST_FROM_AUTHORITY_RE = /(?:[^@]+@)?([^:]+)(?::.*)?$/.freeze
@@ -1180,8 +1180,8 @@ module RDF
1180
1180
  inject(return_type == Hash ? {} : []) do |memo,kv|
1181
1181
  k,v = kv.to_s.split('=', 2)
1182
1182
  next if k.to_s.empty?
1183
- k = URI.decode(k)
1184
- v = URI.decode(v) if v
1183
+ k = CGI.unescape(k)
1184
+ v = CGI.unescape(v) if v
1185
1185
  if return_type == Hash
1186
1186
  case memo[k]
1187
1187
  when nil then memo[k] = v
@@ -1293,9 +1293,9 @@ module RDF
1293
1293
  def normalize_segment(value, expr, downcase = false)
1294
1294
  if value
1295
1295
  value = value.dup.force_encoding(Encoding::UTF_8)
1296
- decoded = URI.decode(value)
1296
+ decoded = CGI.unescape(value)
1297
1297
  decoded.downcase! if downcase
1298
- URI.encode(decoded, /[^(?:#{expr})]/)
1298
+ URI.encode(decoded, /[^(?:#{expr})]/).force_encoding(Encoding::UTF_8)
1299
1299
  end
1300
1300
  end
1301
1301
 
@@ -69,9 +69,9 @@ module RDF
69
69
 
70
70
  begin
71
71
  unless blank? || read_comment
72
- subject = read_uriref || read_node || fail_subject
72
+ subject = read_uriref || read_node || read_rdfstar || fail_subject
73
73
  predicate = read_uriref(intern: true) || fail_predicate
74
- object = read_uriref || read_node || read_literal || fail_object
74
+ object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
75
75
  graph_name = read_uriref || read_node
76
76
  if validate? && !read_eos
77
77
  log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
@@ -15,15 +15,17 @@ module RDF
15
15
  #
16
16
  # <https://rubygems.org/gems/rdf> <http://purl.org/dc/terms/title> "rdf" .
17
17
  #
18
- # Installation
19
- # ------------
18
+ # ## RDFStar (RDF*)
19
+ #
20
+ # Supports statements as resources using `<<s p o>>`.
21
+ #
22
+ # ## Installation
20
23
  #
21
24
  # This is the only RDF serialization format that is directly supported by
22
25
  # RDF.rb. Support for other formats is available in the form of add-on
23
26
  # gems, e.g. 'rdf-xml' or 'rdf-json'.
24
27
  #
25
- # Documentation
26
- # -------------
28
+ # ## Documentation
27
29
  #
28
30
  # * {RDF::NTriples::Format}
29
31
  # * {RDF::NTriples::Reader}