rdf 1.1.0.p1 → 1.1.0.p2

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,5 +1,4 @@
1
1
  # RDF.rb: Linked Data for Ruby
2
- [![Build Status](https://secure.travis-ci.org/ruby-rdf/rdf.png?branch=master)](http://travis-ci.org/ruby-rdf/rdf)
3
2
 
4
3
  This is a pure-Ruby library for working with [Resource Description Framework
5
4
  (RDF)][RDF] data.
@@ -10,6 +9,9 @@ This is a pure-Ruby library for working with [Resource Description Framework
10
9
  * <http://blog.datagraph.org/2010/04/parsing-rdf-with-ruby>
11
10
  * <http://blog.datagraph.org/2010/04/rdf-repository-howto>
12
11
 
12
+ [![Gem Version](https://badge.fury.io/rb/rdf.png)](http://badge.fury.io/rb/rdf)
13
+ [![Build Status](https://travis-ci.org/ruby-rdf/rdf.png?branch=master)](http://travis-ci.org/ruby-rdf/rdf)
14
+
13
15
  ## Features
14
16
 
15
17
  * 100% pure Ruby with minimal dependencies and no bloat.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0.p1
1
+ 1.1.0.p2
data/lib/rdf/format.rb CHANGED
@@ -13,18 +13,18 @@ module RDF
13
13
  # RDF::Format.for("etc/doap.nt")
14
14
  # RDF::Format.for(:file_name => "etc/doap.nt")
15
15
  # RDF::Format.for(:file_extension => "nt")
16
- # RDF::Format.for(:content_type => "text/plain")
16
+ # RDF::Format.for(:content_type => "application/n-triples")
17
17
  #
18
18
  # @example Obtaining serialization format MIME types
19
- # RDF::Format.content_types #=> {"text/plain" => [RDF::NTriples::Format]}
19
+ # RDF::Format.content_types #=> {"application/n-triples" => [RDF::NTriples::Format]}
20
20
  #
21
21
  # @example Obtaining serialization format file extension mappings
22
22
  # RDF::Format.file_extensions #=> {:nt => [RDF::NTriples::Format]}
23
23
  #
24
24
  # @example Defining a new RDF serialization format class
25
25
  # class RDF::NTriples::Format < RDF::Format
26
- # content_type 'text/plain', :extension => :nt
27
- # content_encoding 'ascii'
26
+ # content_type 'application/n-triples', :extension => :nt
27
+ # content_encoding 'utf-8'
28
28
  #
29
29
  # reader RDF::NTriples::Reader
30
30
  # writer RDF::NTriples::Writer
@@ -249,7 +249,7 @@ module RDF
249
249
  #
250
250
  # @example
251
251
  #
252
- # RDF::NTriples::Format.name => "NTriples"
252
+ # RDF::NTriples::Format.name => "N-Triples"
253
253
  #
254
254
  # @return [Symbol]
255
255
  def self.name
@@ -355,7 +355,7 @@ module RDF
355
355
  # match cannot be unambigiously found otherwise.
356
356
  #
357
357
  # @example
358
- # RDF::NTriples::Format.detect("<a> <b> <c> .") => true
358
+ # RDF::NTriples::Format.detect("<a> <b> <c> .") #=> true
359
359
  #
360
360
  # @param [String] sample Beginning several bytes (~ 1K) of input.
361
361
  # @return [Boolean]
@@ -401,14 +401,21 @@ module RDF
401
401
  |ct, cl| (cl.include?(self) && ct != @@content_type[self]) ? ct : nil }].flatten.compact
402
402
  else
403
403
  @@content_type[self] = type
404
- (@@content_types[type] ||= []) << self
404
+ @@content_types[type] ||= []
405
+ @@content_types[type] << self unless @@content_types[type].include?(self)
405
406
 
406
407
  if extensions = (options[:extension] || options[:extensions])
407
408
  extensions = [extensions].flatten.map(&:to_sym)
408
- extensions.each { |ext| (@@file_extensions[ext] ||= []) << self }
409
+ extensions.each do |ext|
410
+ @@file_extensions[ext] ||= []
411
+ @@file_extensions[ext] << self unless @@file_extensions[ext].include?(self)
412
+ end
409
413
  end
410
414
  if aliases = (options[:alias] || options[:aliases])
411
- aliases = [aliases].flatten.each { |a| (@@content_types[a] ||= []) << self }
415
+ aliases = [aliases].flatten.each do |a|
416
+ @@content_types[a] ||= []
417
+ @@content_types[a] << self unless @@content_types[a].include?(self)
418
+ end
412
419
  end
413
420
  end
414
421
  end
@@ -9,9 +9,8 @@ module RDF
9
9
  #
10
10
  # @return [Boolean]
11
11
  def empty?
12
- empty = true
13
- each { empty = false; break }
14
- empty
12
+ each {return false}
13
+ true
15
14
  end
16
15
 
17
16
  ##
@@ -17,10 +17,10 @@ module RDF
17
17
  # enumerable.has_quad?([subject, predicate, object, context])
18
18
  #
19
19
  # @example Checking whether a specific value exists
20
- # enumerable.has_subject?(RDF::URI("http://rdf.rubyforge.org/"))
20
+ # enumerable.has_subject?(RDF::URI("http://rubygems.org/gems/rdf"))
21
21
  # enumerable.has_predicate?(RDF::DC.creator)
22
- # enumerable.has_object?(RDF::Literal("Hello!", :language => :en))
23
- # enumerable.has_context?(RDF::URI("http://rubyforge.org/"))
22
+ # enumerable.has_object?(RDF::Literal("A Ruby library for working with Resource Description Framework (RDF) data.", :language => :en))
23
+ # enumerable.has_context?(RDF::URI("http://ar.to/#self"))
24
24
  #
25
25
  # @example Enumerating all statements
26
26
  # enumerable.each_statement do |statement|
@@ -17,7 +17,7 @@ module RDF
17
17
  # This method delegates to the protected {RDF::Queryable#query_pattern} method for the
18
18
  # actual lower-level query pattern matching implementation.
19
19
  #
20
- # @example
20
+ # @example Querying for statements having a given predicate
21
21
  # queryable.query([nil, RDF::DOAP.developer, nil])
22
22
  # queryable.query(:predicate => RDF::DOAP.developer)
23
23
  #
@@ -12,10 +12,19 @@ module RDF
12
12
  # This class allows a name to be associated with a graph when it is
13
13
  # a projection of an underlying {RDF::Repository} supporting contexts.
14
14
  #
15
- # @example Creating an empty graph
15
+ # @example Creating an empty unnamed graph
16
16
  # graph = Graph.new
17
17
  #
18
18
  # @example Loading graph data from a URL
19
+ # graph = Graph.new("http://rubygems.org/")
20
+ #
21
+ # @example Loading graph data from a URL (1)
22
+ # require 'rdf/rdfxml' # for RDF/XML support
23
+ #
24
+ # graph = RDF::Graph.new("http://www.bbc.co.uk/programmes/b0081dq5.rdf")
25
+ # graph.load!
26
+ #
27
+ # @example Loading graph data from a URL (2)
19
28
  # require 'rdf/rdfxml' # for RDF/XML support
20
29
  #
21
30
  # graph = RDF::Graph.load("http://www.bbc.co.uk/programmes/b0081dq5.rdf")
@@ -196,15 +205,6 @@ module RDF
196
205
  named? ? context.to_s : "default"
197
206
  end
198
207
 
199
- ##
200
- # Returns `true` if this graph contains no RDF statements.
201
- #
202
- # @return [Boolean]
203
- # @see RDF::Enumerable#empty?
204
- def empty?
205
- !@data.has_context?(context || false)
206
- end
207
-
208
208
  ##
209
209
  # Returns `true` if this graph has an anonymous context, `false` otherwise.
210
210
  #
@@ -193,7 +193,7 @@ module RDF
193
193
  # Returns the element at `index`.
194
194
  #
195
195
  # @example
196
- # RDF::List[1, 2, 3][0] #=> 1
196
+ # RDF::List[1, 2, 3][0] #=> RDF::Literal(1)
197
197
  #
198
198
  # @param [Integer] index
199
199
  # @return [RDF::Term]
@@ -295,10 +295,12 @@ module RDF
295
295
  end
296
296
 
297
297
  ##
298
- # Returns the element at `index`.
298
+ # Returns a slice of a list.
299
299
  #
300
300
  # @example
301
- # RDF::List[1, 2, 3].at(0) #=> 1
301
+ # RDF::List[1, 2, 3].slice(0) #=> RDF::Literal(1),
302
+ # RDF::List[1, 2, 3].slice(0, 2) #=> RDF::List[1, 2],
303
+ # RDF::List[1, 2, 3].slice(0..2) #=> RDF::List[1, 2, 3]
302
304
  #
303
305
  # @return [RDF::Term]
304
306
  # @see http://ruby-doc.org/core-1.9/classes/Array.html#M000462
@@ -327,10 +329,10 @@ module RDF
327
329
  protected :slice_with_range
328
330
 
329
331
  ##
330
- # Returns the element at `index`.
332
+ # Returns element at `index` with default.
331
333
  #
332
334
  # @example
333
- # RDF::List[1, 2, 3].fetch(0) #=> 1
335
+ # RDF::List[1, 2, 3].fetch(0) #=> RDF::Literal(1)
334
336
  # RDF::List[1, 2, 3].fetch(4) #=> IndexError
335
337
  # RDF::List[1, 2, 3].fetch(4, nil) #=> nil
336
338
  # RDF::List[1, 2, 3].fetch(4) { |n| n*n } #=> 16
@@ -354,6 +356,7 @@ module RDF
354
356
  #
355
357
  # @example
356
358
  # RDF::List[1, 2, 3].at(0) #=> 1
359
+ # RDF::List[1, 2, 3].at(4) #=> nil
357
360
  #
358
361
  # @return [RDF::Term]
359
362
  # @see http://ruby-doc.org/core-1.9/classes/Array.html#M000419
@@ -370,7 +373,7 @@ module RDF
370
373
  # Returns the first element in this list.
371
374
  #
372
375
  # @example
373
- # RDF::List[*(1..10)].first #=> 1
376
+ # RDF::List[*(1..10)].first #=> RDF::Literal(1)
374
377
  #
375
378
  # @return [RDF::Term]
376
379
  def first
@@ -381,7 +384,7 @@ module RDF
381
384
  # Returns the second element in this list.
382
385
  #
383
386
  # @example
384
- # RDF::List[*(1..10)].second #=> 2
387
+ # RDF::List[*(1..10)].second #=> RDF::Literal(2)
385
388
  #
386
389
  # @return [RDF::Term]
387
390
  def second
@@ -392,7 +395,7 @@ module RDF
392
395
  # Returns the third element in this list.
393
396
  #
394
397
  # @example
395
- # RDF::List[*(1..10)].third #=> 3
398
+ # RDF::List[*(1..10)].third #=> RDF::Literal(4)
396
399
  #
397
400
  # @return [RDF::Term]
398
401
  def third
@@ -403,7 +406,7 @@ module RDF
403
406
  # Returns the fourth element in this list.
404
407
  #
405
408
  # @example
406
- # RDF::List[*(1..10)].fourth #=> 4
409
+ # RDF::List[*(1..10)].fourth #=> RDF::Literal(4)
407
410
  #
408
411
  # @return [RDF::Term]
409
412
  def fourth
@@ -414,7 +417,7 @@ module RDF
414
417
  # Returns the fifth element in this list.
415
418
  #
416
419
  # @example
417
- # RDF::List[*(1..10)].fifth #=> 5
420
+ # RDF::List[*(1..10)].fifth #=> RDF::Literal(5)
418
421
  #
419
422
  # @return [RDF::Term]
420
423
  def fifth
@@ -425,7 +428,7 @@ module RDF
425
428
  # Returns the sixth element in this list.
426
429
  #
427
430
  # @example
428
- # RDF::List[*(1..10)].sixth #=> 6
431
+ # RDF::List[*(1..10)].sixth #=> RDF::Literal(6)
429
432
  #
430
433
  # @return [RDF::Term]
431
434
  def sixth
@@ -436,7 +439,7 @@ module RDF
436
439
  # Returns the seventh element in this list.
437
440
  #
438
441
  # @example
439
- # RDF::List[*(1..10)].seventh #=> 7
442
+ # RDF::List[*(1..10)].seventh #=> RDF::Literal(7)
440
443
  #
441
444
  # @return [RDF::Term]
442
445
  def seventh
@@ -447,7 +450,7 @@ module RDF
447
450
  # Returns the eighth element in this list.
448
451
  #
449
452
  # @example
450
- # RDF::List[*(1..10)].eighth #=> 8
453
+ # RDF::List[*(1..10)].eighth #=> RDF::Literal(8)
451
454
  #
452
455
  # @return [RDF::Term]
453
456
  def eighth
@@ -458,7 +461,7 @@ module RDF
458
461
  # Returns the ninth element in this list.
459
462
  #
460
463
  # @example
461
- # RDF::List[*(1..10)].ninth #=> 9
464
+ # RDF::List[*(1..10)].ninth #=> RDF::Literal(9)
462
465
  #
463
466
  # @return [RDF::Term]
464
467
  def ninth
@@ -469,7 +472,7 @@ module RDF
469
472
  # Returns the tenth element in this list.
470
473
  #
471
474
  # @example
472
- # RDF::List[*(1..10)].tenth #=> 10
475
+ # RDF::List[*(1..10)].tenth #=> RDF::Literal(10)
473
476
  #
474
477
  # @return [RDF::Term]
475
478
  def tenth
@@ -480,7 +483,7 @@ module RDF
480
483
  # Returns the last element in this list.
481
484
  #
482
485
  # @example
483
- # RDF::List[1, 2, 3].last #=> 3
486
+ # RDF::List[*(1..10)].last #=> RDF::Literal(10)
484
487
  #
485
488
  # @return [RDF::Term]
486
489
  # @see http://ruby-doc.org/core-1.9/classes/Array.html#M000422
@@ -672,7 +675,7 @@ module RDF
672
675
  #
673
676
  # @example
674
677
  # RDF::List[].to_a #=> []
675
- # RDF::List[1, 2, 3].to_a #=> [1, 2, 3]
678
+ # RDF::List[1, 2, 3].to_a #=> [RDF::Literal(1), RDF::Literal(2), RDF::Literal(3)]
676
679
  #
677
680
  # @return [Array]
678
681
  def to_a
@@ -683,7 +686,7 @@ module RDF
683
686
  # Returns the elements in this list as a set.
684
687
  #
685
688
  # @example
686
- # RDF::List[1, 2, 3].to_set #=> Set[1, 2, 3]
689
+ # RDF::List[1, 2, 3].to_set #=> Set[RDF::Literal(1), RDF::Literal(2), RDF::Literal(3)]
687
690
  #
688
691
  # @return [Set]
689
692
  def to_set
@@ -48,7 +48,7 @@ module RDF
48
48
  # RDF::Literal.new(123).datatype #=> XSD.integer
49
49
  # RDF::Literal.new(9223372036854775807).datatype #=> XSD.integer
50
50
  # RDF::Literal.new(3.1415).datatype #=> XSD.double
51
- # RDF::Literal.new(Time.now).datatype #=> XSD.dateTime
51
+ # RDF::Literal.new(Time.now).datatype #=> XSD.time
52
52
  # RDF::Literal.new(Date.new(2010)).datatype #=> XSD.date
53
53
  # RDF::Literal.new(DateTime.new(2010)).datatype #=> XSD.dateTime
54
54
  #
@@ -91,6 +91,8 @@ module RDF
91
91
  ##
92
92
  # @private
93
93
  def self.new(value, options = {})
94
+ raise ArgumentError, "datatype with language must be rdf:langString" if options[:language] && (options[:datatype] || RDF.langString).to_s != RDF.langString.to_s
95
+
94
96
  klass = case
95
97
  when !self.equal?(RDF::Literal)
96
98
  self # subclasses can be directly constructed without type dispatch
@@ -116,9 +118,9 @@ module RDF
116
118
  literal
117
119
  end
118
120
 
119
- TRUE = RDF::Literal.new(true).freeze
120
- FALSE = RDF::Literal.new(false).freeze
121
- ZERO = RDF::Literal.new(0).freeze
121
+ TRUE = RDF::Literal.new(true)
122
+ FALSE = RDF::Literal.new(false)
123
+ ZERO = RDF::Literal.new(0)
122
124
 
123
125
  # @return [Symbol] The language tag (optional).
124
126
  attr_accessor :language
@@ -141,6 +143,7 @@ module RDF
141
143
  # @option options [Boolean] :canonicalize (false)
142
144
  # @raise [ArgumentError]
143
145
  # if there is a language and datatype is no rdf:langString
146
+ # or datatype is rdf:langString and there is no language
144
147
  # @see http://www.w3.org/TR/rdf11-concepts/#section-Graph-Literal
145
148
  # @see http://www.w3.org/TR/rdf11-concepts/#section-Datatypes
146
149
  def initialize(value, options = {})
@@ -151,7 +154,6 @@ module RDF
151
154
  @datatype = RDF::URI(options[:datatype]) if options[:datatype]
152
155
  @datatype ||= self.class.const_get(:DATATYPE) if self.class.const_defined?(:DATATYPE)
153
156
  @datatype ||= @language ? RDF.langString : RDF::XSD.string
154
- raise ArgumentError, "datatype with language must be rdf:langString" if @language && @datatype != RDF::langString
155
157
  raise ArgumentError, "datatype of rdf:langString requires a language" if !@language && @datatype == RDF::langString
156
158
  end
157
159
 
@@ -190,7 +192,24 @@ module RDF
190
192
  #
191
193
  # @return [Fixnum]
192
194
  def hash
193
- to_s.hash
195
+ @hash ||= to_s.hash
196
+ end
197
+
198
+
199
+ ##
200
+ # Returns a hash code for the value.
201
+ #
202
+ # @return [Fixnum]
203
+ def value_hash
204
+ @value_hash ||= value.hash
205
+ end
206
+
207
+ ##
208
+ # @private
209
+ def freeze
210
+ hash.freeze
211
+ value_hash.freeze
212
+ super
194
213
  end
195
214
 
196
215
  ##
@@ -204,6 +223,7 @@ module RDF
204
223
  def eql?(other)
205
224
  self.equal?(other) ||
206
225
  (self.class.eql?(other.class) &&
226
+ self.value_hash == other.value_hash &&
207
227
  self.value.eql?(other.value) &&
208
228
  self.language.to_s.downcase.eql?(other.language.to_s.downcase) &&
209
229
  self.datatype.eql?(other.datatype))
@@ -228,32 +248,44 @@ module RDF
228
248
  true
229
249
  when self.has_language? && self.language.to_s.downcase == other.language.to_s.downcase
230
250
  # Literals with languages can compare if languages are identical
231
- self.value == other.value
251
+ self.value_hash == other.value_hash && self.value == other.value
232
252
  when self.simple? && other.simple?
233
- self.value == other.value
253
+ self.value_hash == other.value_hash && self.value == other.value
234
254
  when other.comperable_datatype?(self) || self.comperable_datatype?(other)
235
- # Comparing plain with undefined datatypes does not generate an error, but returns false
255
+ # Comoparing plain with undefined datatypes does not generate an error, but returns false
236
256
  # From data-r2/expr-equal/eq-2-2.
237
257
  false
238
258
  else
239
259
  type_error("unable to determine whether #{self.inspect} and #{other.inspect} are equivalent")
240
260
  end
241
261
  when String
242
- self.plain? && self.value.eql?(other)
262
+ self.simple? && self.value.eql?(other)
243
263
  else false
244
264
  end
245
265
  end
246
266
  alias_method :===, :==
247
267
 
248
268
  ##
249
- # Returns `true` if this is a plain literal.
269
+ # Returns `true` if this is a plain literal. A plain literal
270
+ # may have a language, but may not have a datatype. For
271
+ # all practical purposes, this includes xsd:string literals
272
+ # too.
250
273
  #
251
274
  # @return [Boolean] `true` or `false`
252
275
  # @see http://www.w3.org/TR/rdf-concepts/#dfn-plain-literal
253
276
  def plain?
277
+ [RDF.langString, RDF::XSD.string].include?(datatype)
278
+ end
279
+
280
+ ##
281
+ # Returns `true` if this is a simple literal.
282
+ # A simple literal has no datatype or language.
283
+ #
284
+ # @return [Boolean] `true` or `false`
285
+ # @see http://www.w3.org/TR/sparql11-query/#simple_literal
286
+ def simple?
254
287
  datatype == RDF::XSD.string
255
288
  end
256
- alias_method :simple?, :plain?
257
289
 
258
290
  ##
259
291
  # Returns `true` if this is a language-tagged literal.
@@ -15,6 +15,9 @@ module RDF; class Literal
15
15
  @datatype = RDF::URI(options[:datatype] || self.class.const_get(:DATATYPE))
16
16
  @string = options[:lexical] if options.has_key?(:lexical)
17
17
  @string ||= value if value.is_a?(String)
18
+ @has_timezone = @string.nil? || if md = @string.match(GRAMMAR)
19
+ !!md[2] # If lexical value contains timezone
20
+ end
18
21
  @object = case
19
22
  when value.is_a?(::DateTime) then value
20
23
  when value.respond_to?(:to_datetime) then value.to_datetime
@@ -33,6 +36,35 @@ module RDF; class Literal
33
36
  self
34
37
  end
35
38
 
39
+ ##
40
+ # Returns the timezone part of arg as a simple literal. Returns the empty string if there is no timezone.
41
+ #
42
+ # @return [RDF::Literal]
43
+ # @see http://www.w3.org/TR/sparql11-query/#func-tz
44
+ def tz
45
+ zone = @has_timezone ? object.zone : ""
46
+ zone = "Z" if zone == "+00:00"
47
+ RDF::Literal(zone)
48
+ end
49
+
50
+ ##
51
+ # Returns the timezone part of arg as an xsd:dayTimeDuration, or `nil`
52
+ # if lexical form of literal does not include a timezone.
53
+ #
54
+ # @return [RDF::Literal]
55
+ def timezone
56
+ if tz == 'Z'
57
+ RDF::Literal("PT0S", :datatype => RDF::XSD.dayTimeDuration)
58
+ elsif md = tz.to_s.match(/^([+-])?(\d+):(\d+)?$/)
59
+ plus_minus, hour, min = md[1,3]
60
+ plus_minus = nil unless plus_minus == "-"
61
+ hour = hour.to_i
62
+ min = min.to_i
63
+ res = "#{plus_minus}PT#{hour}H#{"#{min}M" if min > 0}"
64
+ RDF::Literal(res, :datatype => RDF::XSD.dayTimeDuration)
65
+ end
66
+ end
67
+
36
68
  ##
37
69
  # Returns `true` if the value adheres to the defined grammar of the
38
70
  # datatype.
@@ -45,6 +77,8 @@ module RDF; class Literal
45
77
  super && object && value !~ %r(\A0000)
46
78
  end
47
79
 
80
+ ##
81
+ # Returns the `timezone` of the literal. If the
48
82
  ##
49
83
  # Returns the value as a string.
50
84
  #
@@ -56,6 +56,36 @@ module RDF; class Literal
56
56
  (d = to_d) && d > 0 ? self : RDF::Literal(d.abs)
57
57
  end
58
58
 
59
+ ##
60
+ # 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.
61
+ #
62
+ # @return [RDF::Literal]
63
+ def round
64
+ self.class.new(to_d.round)
65
+ end
66
+
67
+ ##
68
+ # Returns the smallest integer greater than or equal to `self`.
69
+ #
70
+ # @example
71
+ # RDF::Literal(1).ceil #=> RDF::Literal(1)
72
+ #
73
+ # @return [RDF::Literal]
74
+ def ceil
75
+ self.class.new(to_d.ceil)
76
+ end
77
+
78
+ ##
79
+ # Returns the largest integer less than or equal to `self`.
80
+ #
81
+ # @example
82
+ # RDF::Literal(1).floor #=> RDF::Literal(1)
83
+ #
84
+ # @return [RDF::Literal]
85
+ def floor
86
+ self.class.new(to_d.floor)
87
+ end
88
+
59
89
  ##
60
90
  # Returns `true` if the value is zero.
61
91
  #
@@ -118,7 +118,7 @@ module RDF; class Literal
118
118
  end
119
119
 
120
120
  ##
121
- # Returns the smallest integer greater than or equal to `self`.
121
+ # Returns the smallest number greater than or equal to `self`.
122
122
  #
123
123
  # @example
124
124
  # RDF::Literal(1.2).ceil #=> RDF::Literal(2)
@@ -129,11 +129,11 @@ module RDF; class Literal
129
129
  # @return [RDF::Literal]
130
130
  # @since 0.2.3
131
131
  def ceil
132
- RDF::Literal(to_f.ceil)
132
+ self.class.new(to_f.ceil)
133
133
  end
134
134
 
135
135
  ##
136
- # Returns the largest integer less than or equal to `self`.
136
+ # Returns the largest number less than or equal to `self`.
137
137
  #
138
138
  # @example
139
139
  # RDF::Literal(1.2).floor #=> RDF::Literal(1)
@@ -144,7 +144,7 @@ module RDF; class Literal
144
144
  # @return [RDF::Literal]
145
145
  # @since 0.2.3
146
146
  def floor
147
- RDF::Literal(to_f.floor)
147
+ self.class.new(to_f.floor)
148
148
  end
149
149
 
150
150
  ##
@@ -153,7 +153,15 @@ module RDF; class Literal
153
153
  # @return [RDF::Literal]
154
154
  # @since 0.2.3
155
155
  def abs
156
- (f = to_f) && f > 0 ? self : RDF::Literal(f.abs)
156
+ (f = to_f) && f > 0 ? self : self.class.new(f.abs)
157
+ end
158
+
159
+ ##
160
+ # 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.
161
+ #
162
+ # @return [RDF::Literal]
163
+ def round
164
+ self.class.new(to_f.round)
157
165
  end
158
166
 
159
167
  ##
@@ -83,7 +83,15 @@ module RDF; class Literal
83
83
  # @return [RDF::Literal]
84
84
  # @since 0.2.3
85
85
  def abs
86
- (n = to_i) && n > 0 ? self : RDF::Literal(n.abs)
86
+ (n = to_i) && n > 0 ? self : self.class.new(n.abs)
87
+ end
88
+
89
+ ##
90
+ # Returns `self`.
91
+ #
92
+ # @return [RDF::Literal]
93
+ def round
94
+ self
87
95
  end
88
96
 
89
97
  ##
@@ -144,6 +144,46 @@ module RDF; class Literal
144
144
  end
145
145
  end
146
146
 
147
+ ##
148
+ # Returns the absolute value of `self`.
149
+ #
150
+ # @return [RDF::Literal]
151
+ # @raise [NotImplementedError] unless implemented in subclass
152
+ def abs
153
+ raise NotImplementedError
154
+ end
155
+
156
+ ##
157
+ # 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.
158
+ #
159
+ # @return [RDF::Literal]
160
+ # @raise [NotImplementedError] unless implemented in subclass
161
+ def round
162
+ raise NotImplementedError
163
+ end
164
+
165
+ ##
166
+ # Returns the smallest integer greater than or equal to `self`.
167
+ #
168
+ # @example
169
+ # RDF::Literal(1).ceil #=> RDF::Literal(1)
170
+ #
171
+ # @return [RDF::Literal]
172
+ def ceil
173
+ self
174
+ end
175
+
176
+ ##
177
+ # Returns the largest integer less than or equal to `self`.
178
+ #
179
+ # @example
180
+ # RDF::Literal(1).floor #=> RDF::Literal(1)
181
+ #
182
+ # @return [RDF::Literal]
183
+ def floor
184
+ self
185
+ end
186
+
147
187
  ##
148
188
  # Returns the value as an integer.
149
189
  #
@@ -132,7 +132,9 @@ module RDF
132
132
  # If other is a Literal, reverse test to consolodate complex type checking logic
133
133
  other == self
134
134
  else
135
- other.respond_to?(:node?) && other.node? && other.respond_to?(:id) && @id == other.id
135
+ other.respond_to?(:node?) && other.node? &&
136
+ self.hash == other.hash &&
137
+ other.respond_to?(:id) && @id == other.id
136
138
  end
137
139
  end
138
140
  alias_method :===, :==
@@ -9,6 +9,7 @@ module RDF
9
9
  # RDF::Statement.new(s, p, o)
10
10
  #
11
11
  # @example Creating an RDF statement with a context
12
+ # uri = RDF::URI("http://example/")
12
13
  # RDF::Statement.new(s, p, o, :context => uri)
13
14
  #
14
15
  # @example Creating an RDF statement from a `Hash`
data/lib/rdf/model/uri.rb CHANGED
@@ -48,9 +48,9 @@ module RDF
48
48
  GEN_DELIMS = Regexp.compile("[:/\\?\\#\\[\\]@]").freeze
49
49
  SUB_DELIMS = Regexp.compile("[!\\$&'\\(\\)\\*\\+,;=]").freeze
50
50
  RESERVED = Regexp.compile("(?:#{GEN_DELIMS}|#{SUB_DELIMS})").freeze
51
- UNRESERVED = Regexp.compile("[A-Za-z0-9]|-|\\.|_|~").freeze
51
+ UNRESERVED = Regexp.compile("[A-Za-z0-9\._~-]").freeze
52
52
 
53
- IUNRESERVED = Regexp.compile("[A-Za-z0-9]|-|\\.|_|~|#{UCSCHAR}").freeze
53
+ IUNRESERVED = Regexp.compile("[A-Za-z0-9\._~-]|#{UCSCHAR}").freeze
54
54
 
55
55
  IPCHAR = Regexp.compile("(?:#{IUNRESERVED}|#{PCT_ENCODED}|#{SUB_DELIMS}|:|@)").freeze
56
56
 
@@ -671,7 +671,7 @@ module RDF
671
671
  # @param [RDF::URI] other
672
672
  # @return [Boolean] `true` or `false`
673
673
  def eql?(other)
674
- other.is_a?(URI) && self == other
674
+ other.is_a?(URI) && self.hash == other.hash && self == other
675
675
  end
676
676
 
677
677
  ##
@@ -693,7 +693,7 @@ module RDF
693
693
  # If other is a Literal, reverse test to consolodate complex type checking logic
694
694
  other == self
695
695
  when String then to_s == other
696
- when URI then to_s == other.to_s
696
+ when URI then hash == other.hash && to_s == other.to_s
697
697
  else other.respond_to?(:to_uri) && to_s == other.to_uri.to_s
698
698
  end
699
699
  end
@@ -1134,7 +1134,7 @@ module RDF
1134
1134
  value = value.force_encoding(Encoding::UTF_8)
1135
1135
  decoded = ::URI.decode(value)
1136
1136
  decoded.downcase! if downcase
1137
- ::URI.encode(decoded, /[^#{expr}]/)
1137
+ ::URI.encode(decoded, /[^(?:#{expr})]/)
1138
1138
  end
1139
1139
  end
1140
1140
 
data/lib/rdf/query.rb CHANGED
@@ -89,7 +89,7 @@ module RDF
89
89
  # @return [RDF::Query::Solutions]
90
90
  # the resulting solution sequence
91
91
  # @see RDF::Query#execute
92
- def self.execute(queryable, patterns = nil, options = {}, &block)
92
+ def self.execute(queryable, patterns = {}, options = {}, &block)
93
93
  self.new(patterns, options, &block).execute(queryable, options)
94
94
  end
95
95
 
@@ -243,6 +243,9 @@ module RDF
243
243
  # or named contexts.
244
244
  # The name of `false` will only match against the default context.
245
245
  #
246
+ # If the query nas no patterns, it returns a single empty solution as
247
+ # per SPARQL 1.1 _Empty Group Pattern_.
248
+ #
246
249
  # @param [RDF::Queryable] queryable
247
250
  # the graph or repository to query
248
251
  # @param [Hash{Symbol => Object}] options
@@ -259,6 +262,7 @@ module RDF
259
262
  # @return [RDF::Query::Solutions]
260
263
  # the resulting solution sequence
261
264
  # @see http://www.holygoat.co.uk/blog/entry/2005-10-25-1
265
+ # @see http://www.w3.org/TR/sparql11-query/#emptyGroupPattern
262
266
  def execute(queryable, options = {})
263
267
  validate!
264
268
  options = options.dup
@@ -271,6 +275,9 @@ module RDF
271
275
  # the first pattern
272
276
  @solutions = options[:solutions] || (Solutions.new << RDF::Query::Solution.new({}))
273
277
 
278
+ # If there are no patterns, just return the empty solution
279
+ return @solutions if empty?
280
+
274
281
  patterns = @patterns
275
282
  context = options.fetch(:context, options.fetch(:name, self.context))
276
283
 
@@ -104,7 +104,7 @@ module RDF; class Query
104
104
  # To match triples only in the default context, set context to `false`.
105
105
  #
106
106
  # @example
107
- # Pattern.new(:s, :p, :o).execute(RDF::Repository.load('data.nt'))
107
+ # Pattern.new(:s, :p, :o).execute(RDF::Repository.load('etc/doap.nt'))
108
108
  #
109
109
  # @param [RDF::Queryable] queryable
110
110
  # the graph or repository to query
@@ -156,7 +156,12 @@ module RDF; class Query
156
156
  # pattern with the corresponding terms in the given `statement`.
157
157
  #
158
158
  # @example
159
- # pattern.solution(statement)
159
+ # pattern = Pattern.new(:s, :p, :o)
160
+ # solution = pattern.solution(statement)
161
+ #
162
+ # pattern[:s] #=> statement.subject
163
+ # pattern[:p] #=> statement.predicate
164
+ # pattern[:o] #=> statement.object
160
165
  #
161
166
  # @param [RDF::Statement] statement
162
167
  # an RDF statement to bind terms from
@@ -25,7 +25,7 @@ class RDF::Query
25
25
  undef_method(*instance_methods.
26
26
  map(&:to_s).
27
27
  select {|m| m =~ /^\w+$/}.
28
- reject {|m| %w(object_id dup instance_eval inspect to_s class).include?(m) || m[0,2] == '__'}.
28
+ reject {|m| %w(object_id dup instance_eval inspect to_s class should should_not pretty_print).include?(m) || m[0,2] == '__'}.
29
29
  map(&:to_sym))
30
30
 
31
31
  include Enumerable
@@ -145,7 +145,7 @@ class RDF::Query
145
145
  # @return [RDF::Term]
146
146
  # @since 0.3.0
147
147
  def []=(name, value)
148
- @bindings[name.to_sym] = value
148
+ @bindings[name.to_sym] = value.is_a?(RDF::Term) ? value : RDF::Literal(value)
149
149
  end
150
150
 
151
151
  ##
@@ -4,13 +4,13 @@ module RDF; class Query
4
4
  #
5
5
  # @example Filtering solutions using a hash
6
6
  # solutions.filter(:author => RDF::URI("http://ar.to/#self"))
7
- # solutions.filter(:author => "Arto Bendiken")
8
- # solutions.filter(:author => [RDF::URI("http://ar.to/#self"), "Arto Bendiken"])
7
+ # solutions.filter(:author => "Gregg Kellogg")
8
+ # solutions.filter(:author => [RDF::URI("http://ar.to/#self"), "Gregg Kellogg"])
9
9
  # solutions.filter(:updated => RDF::Literal(Date.today))
10
10
  #
11
11
  # @example Filtering solutions using a block
12
12
  # solutions.filter { |solution| solution.author.literal? }
13
- # solutions.filter { |solution| solution.title =~ /^SPARQL/ }
13
+ # solutions.filter { |solution| solution.title.to_s =~ /^SPARQL/ }
14
14
  # solutions.filter { |solution| solution.price < 30.5 }
15
15
  # solutions.filter { |solution| solution.bound?(:date) }
16
16
  # solutions.filter { |solution| solution.age.datatype == RDF::XSD.integer }
@@ -93,7 +93,11 @@ module RDF; class Query
93
93
  self.reject! do |solution|
94
94
  solution = solution.is_a?(Solution) ? solution : Solution.new(solution)
95
95
  results = criteria.map do |name, value|
96
- solution[name] == value
96
+ case value
97
+ when Array then value.any? {|v| solution[name] == v}
98
+ when Regexp then solution[name].to_s.match(value)
99
+ else solution[name] == value
100
+ end
97
101
  end
98
102
  !results.all?
99
103
  end
@@ -12,7 +12,7 @@ class RDF::Query
12
12
  # var.name #=> :g2166151240
13
13
  #
14
14
  # @example Unbound variables match any value
15
- # var === 42 #=> true
15
+ # var === RDF::Literal(42) #=> true
16
16
  #
17
17
  # @example Creating a bound variable
18
18
  # var = RDF::Query::Variable.new(:y, 123)
@@ -20,10 +20,12 @@ class RDF::Query
20
20
  # var.value #=> 123
21
21
  #
22
22
  # @example Bound variables match only their actual value
23
+ # var = RDF::Query::Variable.new(:y, 123)
23
24
  # var === 42 #=> false
24
25
  # var === 123 #=> true
25
26
  #
26
27
  # @example Getting the variable name
28
+ # var = RDF::Query::Variable.new(:y, 123)
27
29
  # var.named? #=> true
28
30
  # var.name #=> :y
29
31
  # var.to_sym #=> :y
@@ -243,13 +243,6 @@ module RDF
243
243
  false
244
244
  end
245
245
 
246
- ##
247
- # @private
248
- # @see RDF::Countable#empty?
249
- def empty?
250
- @data.empty?
251
- end
252
-
253
246
  ##
254
247
  # @private
255
248
  # @see RDF::Countable#count
metadata CHANGED
@@ -1,61 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0.p1
4
+ version: 1.1.0.p2
5
+ prerelease: 6
5
6
  platform: ruby
6
7
  authors:
7
8
  - Arto Bendiken
8
9
  - Ben Lavender
9
10
  - Gregg Kellogg
10
- autorequire:
11
+ autorequire:
11
12
  bindir: bin
12
13
  cert_chain: []
13
- date: 2013-04-13 00:00:00.000000000 Z
14
+ date: 2013-05-01 00:00:00.000000000 Z
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
16
17
  name: rdf-spec
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: 1.1.0
23
+ none: false
17
24
  requirement: !ruby/object:Gem::Requirement
18
25
  requirements:
19
- - - ~>
26
+ - - "~>"
20
27
  - !ruby/object:Gem::Version
21
28
  version: 1.1.0
22
- type: :development
29
+ none: false
23
30
  prerelease: false
31
+ type: :development
32
+ - !ruby/object:Gem::Dependency
33
+ name: rdf-rdfxml
24
34
  version_requirements: !ruby/object:Gem::Requirement
25
35
  requirements:
26
- - - ~>
36
+ - - ">="
27
37
  - !ruby/object:Gem::Version
28
- version: 1.1.0
29
- - !ruby/object:Gem::Dependency
30
- name: rspec
38
+ version: !binary |-
39
+ MA==
40
+ none: false
31
41
  requirement: !ruby/object:Gem::Requirement
32
42
  requirements:
33
- - - ! '>='
43
+ - - ">="
34
44
  - !ruby/object:Gem::Version
35
- version: '2.12'
36
- type: :development
45
+ version: !binary |-
46
+ MA==
47
+ none: false
37
48
  prerelease: false
49
+ type: :development
50
+ - !ruby/object:Gem::Dependency
51
+ name: rspec
38
52
  version_requirements: !ruby/object:Gem::Requirement
39
53
  requirements:
40
- - - ! '>='
54
+ - - ">="
41
55
  - !ruby/object:Gem::Version
42
56
  version: '2.12'
43
- - !ruby/object:Gem::Dependency
44
- name: yard
57
+ none: false
45
58
  requirement: !ruby/object:Gem::Requirement
46
59
  requirements:
47
- - - ! '>='
60
+ - - ">="
48
61
  - !ruby/object:Gem::Version
49
- version: '0.8'
50
- type: :development
62
+ version: '2.12'
63
+ none: false
51
64
  prerelease: false
65
+ type: :development
66
+ - !ruby/object:Gem::Dependency
67
+ name: yard
52
68
  version_requirements: !ruby/object:Gem::Requirement
53
69
  requirements:
54
- - - ! '>='
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0.8'
73
+ none: false
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
55
77
  - !ruby/object:Gem::Version
56
78
  version: '0.8'
57
- description: RDF.rb is a pure-Ruby library for working with Resource Description Framework
58
- (RDF) data.
79
+ none: false
80
+ prerelease: false
81
+ type: :development
82
+ description: RDF.rb is a pure-Ruby library for working with Resource Description Framework (RDF) data.
59
83
  email: public-rdf-ruby@w3.org
60
84
  executables:
61
85
  - rdf
@@ -70,8 +94,19 @@ files:
70
94
  - bin/rdf
71
95
  - etc/doap.nt
72
96
  - lib/df.rb
97
+ - lib/rdf.rb
73
98
  - lib/rdf/cli.rb
74
99
  - lib/rdf/format.rb
100
+ - lib/rdf/nquads.rb
101
+ - lib/rdf/ntriples.rb
102
+ - lib/rdf/query.rb
103
+ - lib/rdf/reader.rb
104
+ - lib/rdf/repository.rb
105
+ - lib/rdf/transaction.rb
106
+ - lib/rdf/util.rb
107
+ - lib/rdf/version.rb
108
+ - lib/rdf/vocab.rb
109
+ - lib/rdf/writer.rb
75
110
  - lib/rdf/mixin/countable.rb
76
111
  - lib/rdf/mixin/durable.rb
77
112
  - lib/rdf/mixin/enumerable.rb
@@ -84,6 +119,13 @@ files:
84
119
  - lib/rdf/mixin/writable.rb
85
120
  - lib/rdf/model/graph.rb
86
121
  - lib/rdf/model/list.rb
122
+ - lib/rdf/model/literal.rb
123
+ - lib/rdf/model/node.rb
124
+ - lib/rdf/model/resource.rb
125
+ - lib/rdf/model/statement.rb
126
+ - lib/rdf/model/term.rb
127
+ - lib/rdf/model/uri.rb
128
+ - lib/rdf/model/value.rb
87
129
  - lib/rdf/model/literal/boolean.rb
88
130
  - lib/rdf/model/literal/date.rb
89
131
  - lib/rdf/model/literal/datetime.rb
@@ -93,33 +135,18 @@ files:
93
135
  - lib/rdf/model/literal/numeric.rb
94
136
  - lib/rdf/model/literal/time.rb
95
137
  - lib/rdf/model/literal/token.rb
96
- - lib/rdf/model/literal.rb
97
- - lib/rdf/model/node.rb
98
- - lib/rdf/model/resource.rb
99
- - lib/rdf/model/statement.rb
100
- - lib/rdf/model/term.rb
101
- - lib/rdf/model/uri.rb
102
- - lib/rdf/model/value.rb
103
- - lib/rdf/nquads.rb
104
138
  - lib/rdf/ntriples/format.rb
105
139
  - lib/rdf/ntriples/reader.rb
106
140
  - lib/rdf/ntriples/writer.rb
107
- - lib/rdf/ntriples.rb
108
141
  - lib/rdf/query/hash_pattern_normalizer.rb
109
142
  - lib/rdf/query/pattern.rb
110
143
  - lib/rdf/query/solution.rb
111
144
  - lib/rdf/query/solutions.rb
112
145
  - lib/rdf/query/variable.rb
113
- - lib/rdf/query.rb
114
- - lib/rdf/reader.rb
115
- - lib/rdf/repository.rb
116
- - lib/rdf/transaction.rb
117
146
  - lib/rdf/util/aliasing.rb
118
147
  - lib/rdf/util/cache.rb
119
148
  - lib/rdf/util/file.rb
120
149
  - lib/rdf/util/uuid.rb
121
- - lib/rdf/util.rb
122
- - lib/rdf/version.rb
123
150
  - lib/rdf/vocab/cc.rb
124
151
  - lib/rdf/vocab/cert.rb
125
152
  - lib/rdf/vocab/dc.rb
@@ -139,32 +166,31 @@ files:
139
166
  - lib/rdf/vocab/wot.rb
140
167
  - lib/rdf/vocab/xhtml.rb
141
168
  - lib/rdf/vocab/xsd.rb
142
- - lib/rdf/vocab.rb
143
- - lib/rdf/writer.rb
144
- - lib/rdf.rb
145
169
  homepage: http://ruby-rdf.github.com/
146
170
  licenses:
147
171
  - Public Domain
148
- metadata: {}
149
- post_install_message:
172
+ post_install_message:
150
173
  rdoc_options: []
151
174
  require_paths:
152
175
  - lib
153
176
  required_ruby_version: !ruby/object:Gem::Requirement
154
177
  requirements:
155
- - - ! '>='
178
+ - - ">="
156
179
  - !ruby/object:Gem::Version
157
180
  version: 1.9.2
181
+ none: false
158
182
  required_rubygems_version: !ruby/object:Gem::Requirement
159
183
  requirements:
160
- - - ! '>'
184
+ - - !binary |-
185
+ Pg==
161
186
  - !ruby/object:Gem::Version
162
187
  version: 1.3.1
188
+ none: false
163
189
  requirements: []
164
190
  rubyforge_project: rdf
165
- rubygems_version: 2.0.3
166
- signing_key:
167
- specification_version: 4
191
+ rubygems_version: 1.8.24
192
+ signing_key:
193
+ specification_version: 3
168
194
  summary: A Ruby library for working with Resource Description Framework (RDF) data.
169
195
  test_files: []
170
196
  has_rdoc: false
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MmJiOTYzMzMzOTA3MWUwZGU0OWM2YjI2OTNiNTkwMGI0NmFhOTdmMw==
5
- data.tar.gz: !binary |-
6
- NmMzMGE3OGQ0ZWY0MjNhMzc3NDk3MTdhOWRiNWY4ZTBkM2YwMzliZA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- MGM3NzBiNDdkN2MxNGRjMTIyMzRhMmYyZWVkZDdmMGM0OTcxNjEwYTk4NmFh
10
- YTQzODMzYjZhYzNkOTY0ZGU1ZWRjMjUwNGQ0YmZjMTcwYjY2ZjU2NmM1OGY5
11
- NzM2ZmFiZWNhNTRmNzVmYjQzOTJhNmRmMWJhMzQzNzNmMjAwNzE=
12
- data.tar.gz: !binary |-
13
- YzRkYmU0YzYzYzVlZTBhOTAxNDYzMmNhYzg5ZTU1ZGZjNjEwN2E5YzdmZTc4
14
- OTRhZTQyOGI3ZDhhOGZhNWJhM2ZmOGVmZDBkNGVkNmRiMjdjNmJjMmU5Njky
15
- ZTcxMGJlZWU2NDJhNjhkYWE5ZTJjZmYxNzc1NjZjNjE1ZjMxNDU=