rdf 1.0.5 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README +3 -1
- data/VERSION +1 -1
- data/lib/rdf/format.rb +16 -9
- data/lib/rdf/mixin/countable.rb +2 -3
- data/lib/rdf/mixin/enumerable.rb +3 -3
- data/lib/rdf/mixin/queryable.rb +1 -1
- data/lib/rdf/model/graph.rb +2 -11
- data/lib/rdf/model/list.rb +21 -18
- data/lib/rdf/model/literal/datetime.rb +34 -0
- data/lib/rdf/model/literal/decimal.rb +30 -0
- data/lib/rdf/model/literal/double.rb +13 -5
- data/lib/rdf/model/literal/integer.rb +9 -1
- data/lib/rdf/model/literal/numeric.rb +40 -0
- data/lib/rdf/model/literal.rb +53 -11
- data/lib/rdf/model/node.rb +3 -1
- data/lib/rdf/model/statement.rb +1 -0
- data/lib/rdf/model/uri.rb +2 -1
- data/lib/rdf/query/pattern.rb +7 -2
- data/lib/rdf/query/solution.rb +2 -2
- data/lib/rdf/query/solutions.rb +8 -4
- data/lib/rdf/query/variable.rb +3 -1
- data/lib/rdf/query.rb +8 -1
- data/lib/rdf/repository.rb +0 -7
- metadata +20 -2
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.0.
|
1
|
+
1.0.6
|
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 => "
|
16
|
+
# RDF::Format.for(:content_type => "application/n-triples")
|
17
17
|
#
|
18
18
|
# @example Obtaining serialization format MIME types
|
19
|
-
# RDF::Format.content_types #=> {"
|
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 '
|
27
|
-
# content_encoding '
|
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 => "
|
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> .")
|
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
|
-
|
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
|
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
|
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
|
data/lib/rdf/mixin/countable.rb
CHANGED
data/lib/rdf/mixin/enumerable.rb
CHANGED
@@ -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://
|
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("
|
23
|
-
# enumerable.has_context?(RDF::URI("http://
|
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|
|
data/lib/rdf/mixin/queryable.rb
CHANGED
@@ -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
|
#
|
data/lib/rdf/model/graph.rb
CHANGED
@@ -9,13 +9,13 @@ module RDF
|
|
9
9
|
# graph = Graph.new("http://rubygems.org/")
|
10
10
|
#
|
11
11
|
# @example Loading graph data from a URL (1)
|
12
|
-
# require 'rdf/
|
12
|
+
# require 'rdf/rdfxml' # for RDF/XML support
|
13
13
|
#
|
14
14
|
# graph = RDF::Graph.new("http://www.bbc.co.uk/programmes/b0081dq5.rdf")
|
15
15
|
# graph.load!
|
16
16
|
#
|
17
17
|
# @example Loading graph data from a URL (2)
|
18
|
-
# require 'rdf/
|
18
|
+
# require 'rdf/rdfxml' # for RDF/XML support
|
19
19
|
#
|
20
20
|
# graph = RDF::Graph.load("http://www.bbc.co.uk/programmes/b0081dq5.rdf")
|
21
21
|
#
|
@@ -181,15 +181,6 @@ module RDF
|
|
181
181
|
named? ? context.to_s : "default"
|
182
182
|
end
|
183
183
|
|
184
|
-
##
|
185
|
-
# Returns `true` if this graph contains no RDF statements.
|
186
|
-
#
|
187
|
-
# @return [Boolean]
|
188
|
-
# @see RDF::Enumerable#empty?
|
189
|
-
def empty?
|
190
|
-
!@data.has_context?(context || false)
|
191
|
-
end
|
192
|
-
|
193
184
|
##
|
194
185
|
# Returns `true` if this graph has an anonymous context, `false` otherwise.
|
195
186
|
#
|
data/lib/rdf/model/list.rb
CHANGED
@@ -196,7 +196,7 @@ module RDF
|
|
196
196
|
# Returns the element at `index`.
|
197
197
|
#
|
198
198
|
# @example
|
199
|
-
# RDF::List[1, 2, 3][0] #=> 1
|
199
|
+
# RDF::List[1, 2, 3][0] #=> RDF::Literal(1)
|
200
200
|
#
|
201
201
|
# @param [Integer] index
|
202
202
|
# @return [RDF::Term]
|
@@ -299,10 +299,12 @@ module RDF
|
|
299
299
|
end
|
300
300
|
|
301
301
|
##
|
302
|
-
# Returns
|
302
|
+
# Returns a slice of a list.
|
303
303
|
#
|
304
304
|
# @example
|
305
|
-
#
|
305
|
+
# RDF::List[1, 2, 3].slice(0) #=> RDF::Literal(1),
|
306
|
+
# RDF::List[1, 2, 3].slice(0, 2) #=> RDF::List[1, 2],
|
307
|
+
# RDF::List[1, 2, 3].slice(0..2) #=> RDF::List[1, 2, 3]
|
306
308
|
#
|
307
309
|
# @return [RDF::Term]
|
308
310
|
# @see http://ruby-doc.org/core-1.9/classes/Array.html#M000462
|
@@ -331,10 +333,10 @@ module RDF
|
|
331
333
|
protected :slice_with_range
|
332
334
|
|
333
335
|
##
|
334
|
-
# Returns
|
336
|
+
# Returns element at `index` with default.
|
335
337
|
#
|
336
338
|
# @example
|
337
|
-
# RDF::List[1, 2, 3].fetch(0) #=> 1
|
339
|
+
# RDF::List[1, 2, 3].fetch(0) #=> RDF::Literal(1)
|
338
340
|
# RDF::List[1, 2, 3].fetch(4) #=> IndexError
|
339
341
|
# RDF::List[1, 2, 3].fetch(4, nil) #=> nil
|
340
342
|
# RDF::List[1, 2, 3].fetch(4) { |n| n*n } #=> 16
|
@@ -358,6 +360,7 @@ module RDF
|
|
358
360
|
#
|
359
361
|
# @example
|
360
362
|
# RDF::List[1, 2, 3].at(0) #=> 1
|
363
|
+
# RDF::List[1, 2, 3].at(4) #=> nil
|
361
364
|
#
|
362
365
|
# @return [RDF::Term]
|
363
366
|
# @see http://ruby-doc.org/core-1.9/classes/Array.html#M000419
|
@@ -374,7 +377,7 @@ module RDF
|
|
374
377
|
# Returns the first element in this list.
|
375
378
|
#
|
376
379
|
# @example
|
377
|
-
# RDF::List[*(1..10)].first #=> 1
|
380
|
+
# RDF::List[*(1..10)].first #=> RDF::Literal(1)
|
378
381
|
#
|
379
382
|
# @return [RDF::Term]
|
380
383
|
def first
|
@@ -385,7 +388,7 @@ module RDF
|
|
385
388
|
# Returns the second element in this list.
|
386
389
|
#
|
387
390
|
# @example
|
388
|
-
# RDF::List[*(1..10)].second #=> 2
|
391
|
+
# RDF::List[*(1..10)].second #=> RDF::Literal(2)
|
389
392
|
#
|
390
393
|
# @return [RDF::Term]
|
391
394
|
def second
|
@@ -396,7 +399,7 @@ module RDF
|
|
396
399
|
# Returns the third element in this list.
|
397
400
|
#
|
398
401
|
# @example
|
399
|
-
# RDF::List[*(1..10)].third #=>
|
402
|
+
# RDF::List[*(1..10)].third #=> RDF::Literal(4)
|
400
403
|
#
|
401
404
|
# @return [RDF::Term]
|
402
405
|
def third
|
@@ -407,7 +410,7 @@ module RDF
|
|
407
410
|
# Returns the fourth element in this list.
|
408
411
|
#
|
409
412
|
# @example
|
410
|
-
# RDF::List[*(1..10)].fourth #=> 4
|
413
|
+
# RDF::List[*(1..10)].fourth #=> RDF::Literal(4)
|
411
414
|
#
|
412
415
|
# @return [RDF::Term]
|
413
416
|
def fourth
|
@@ -418,7 +421,7 @@ module RDF
|
|
418
421
|
# Returns the fifth element in this list.
|
419
422
|
#
|
420
423
|
# @example
|
421
|
-
# RDF::List[*(1..10)].fifth #=> 5
|
424
|
+
# RDF::List[*(1..10)].fifth #=> RDF::Literal(5)
|
422
425
|
#
|
423
426
|
# @return [RDF::Term]
|
424
427
|
def fifth
|
@@ -429,7 +432,7 @@ module RDF
|
|
429
432
|
# Returns the sixth element in this list.
|
430
433
|
#
|
431
434
|
# @example
|
432
|
-
# RDF::List[*(1..10)].sixth #=> 6
|
435
|
+
# RDF::List[*(1..10)].sixth #=> RDF::Literal(6)
|
433
436
|
#
|
434
437
|
# @return [RDF::Term]
|
435
438
|
def sixth
|
@@ -440,7 +443,7 @@ module RDF
|
|
440
443
|
# Returns the seventh element in this list.
|
441
444
|
#
|
442
445
|
# @example
|
443
|
-
# RDF::List[*(1..10)].seventh #=> 7
|
446
|
+
# RDF::List[*(1..10)].seventh #=> RDF::Literal(7)
|
444
447
|
#
|
445
448
|
# @return [RDF::Term]
|
446
449
|
def seventh
|
@@ -451,7 +454,7 @@ module RDF
|
|
451
454
|
# Returns the eighth element in this list.
|
452
455
|
#
|
453
456
|
# @example
|
454
|
-
# RDF::List[*(1..10)].eighth #=> 8
|
457
|
+
# RDF::List[*(1..10)].eighth #=> RDF::Literal(8)
|
455
458
|
#
|
456
459
|
# @return [RDF::Term]
|
457
460
|
def eighth
|
@@ -462,7 +465,7 @@ module RDF
|
|
462
465
|
# Returns the ninth element in this list.
|
463
466
|
#
|
464
467
|
# @example
|
465
|
-
# RDF::List[*(1..10)].ninth #=> 9
|
468
|
+
# RDF::List[*(1..10)].ninth #=> RDF::Literal(9)
|
466
469
|
#
|
467
470
|
# @return [RDF::Term]
|
468
471
|
def ninth
|
@@ -473,7 +476,7 @@ module RDF
|
|
473
476
|
# Returns the tenth element in this list.
|
474
477
|
#
|
475
478
|
# @example
|
476
|
-
# RDF::List[*(1..10)].tenth #=> 10
|
479
|
+
# RDF::List[*(1..10)].tenth #=> RDF::Literal(10)
|
477
480
|
#
|
478
481
|
# @return [RDF::Term]
|
479
482
|
def tenth
|
@@ -484,7 +487,7 @@ module RDF
|
|
484
487
|
# Returns the last element in this list.
|
485
488
|
#
|
486
489
|
# @example
|
487
|
-
# RDF::List[1
|
490
|
+
# RDF::List[*(1..10)].last #=> RDF::Literal(10)
|
488
491
|
#
|
489
492
|
# @return [RDF::Term]
|
490
493
|
# @see http://ruby-doc.org/core-1.9/classes/Array.html#M000422
|
@@ -676,7 +679,7 @@ module RDF
|
|
676
679
|
#
|
677
680
|
# @example
|
678
681
|
# RDF::List[].to_a #=> []
|
679
|
-
# RDF::List[1, 2, 3].to_a #=> [1, 2, 3]
|
682
|
+
# RDF::List[1, 2, 3].to_a #=> [RDF::Literal(1), RDF::Literal(2), RDF::Literal(3)]
|
680
683
|
#
|
681
684
|
# @return [Array]
|
682
685
|
def to_a
|
@@ -687,7 +690,7 @@ module RDF
|
|
687
690
|
# Returns the elements in this list as a set.
|
688
691
|
#
|
689
692
|
# @example
|
690
|
-
# RDF::List[1, 2, 3].to_set #=> Set[1, 2, 3]
|
693
|
+
# RDF::List[1, 2, 3].to_set #=> Set[RDF::Literal(1), RDF::Literal(2), RDF::Literal(3)]
|
691
694
|
#
|
692
695
|
# @return [Set]
|
693
696
|
def to_set
|
@@ -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 # Ruby 1.9+
|
@@ -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
|
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
|
-
|
132
|
+
self.class.new(to_f.ceil)
|
133
133
|
end
|
134
134
|
|
135
135
|
##
|
136
|
-
# Returns the largest
|
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
|
-
|
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 :
|
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 :
|
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
|
#
|
data/lib/rdf/model/literal.rb
CHANGED
@@ -53,7 +53,7 @@ module RDF
|
|
53
53
|
# RDF::Literal.new(123).datatype #=> XSD.integer
|
54
54
|
# RDF::Literal.new(9223372036854775807).datatype #=> XSD.integer
|
55
55
|
# RDF::Literal.new(3.1415).datatype #=> XSD.double
|
56
|
-
# RDF::Literal.new(Time.now).datatype #=> XSD.
|
56
|
+
# RDF::Literal.new(Time.now).datatype #=> XSD.time
|
57
57
|
# RDF::Literal.new(Date.new(2010)).datatype #=> XSD.date
|
58
58
|
# RDF::Literal.new(DateTime.new(2010)).datatype #=> XSD.dateTime
|
59
59
|
#
|
@@ -97,6 +97,8 @@ module RDF
|
|
97
97
|
##
|
98
98
|
# @private
|
99
99
|
def self.new(value, options = {})
|
100
|
+
raise ArgumentError, "datatype with language" if options[:language] && (options[:datatype] || RDF.langString).to_s != RDF.langString.to_s
|
101
|
+
|
100
102
|
klass = case
|
101
103
|
when !self.equal?(RDF::Literal)
|
102
104
|
self # subclasses can be directly constructed without type dispatch
|
@@ -122,9 +124,9 @@ module RDF
|
|
122
124
|
literal
|
123
125
|
end
|
124
126
|
|
125
|
-
TRUE = RDF::Literal.new(true)
|
126
|
-
FALSE = RDF::Literal.new(false)
|
127
|
-
ZERO = RDF::Literal.new(0)
|
127
|
+
TRUE = RDF::Literal.new(true)
|
128
|
+
FALSE = RDF::Literal.new(false)
|
129
|
+
ZERO = RDF::Literal.new(0)
|
128
130
|
|
129
131
|
# @return [Symbol] The language tag (optional).
|
130
132
|
attr_accessor :language
|
@@ -142,6 +144,11 @@ module RDF
|
|
142
144
|
# @option options [URI] :datatype (nil)
|
143
145
|
# @option options [Boolean] :validate (false)
|
144
146
|
# @option options [Boolean] :canonicalize (false)
|
147
|
+
# @raise [ArgumentError]
|
148
|
+
# if there is a language and datatype is no rdf:langString
|
149
|
+
# or datatype is rdf:langString and there is no language
|
150
|
+
# @see http://www.w3.org/TR/rdf11-concepts/#section-Graph-Literal
|
151
|
+
# @see http://www.w3.org/TR/rdf11-concepts/#section-Datatypes
|
145
152
|
def initialize(value, options = {})
|
146
153
|
@object = value
|
147
154
|
@string = options[:lexical] if options[:lexical]
|
@@ -149,6 +156,10 @@ module RDF
|
|
149
156
|
@language = options[:language].to_s.to_sym if options[:language]
|
150
157
|
@datatype = RDF::URI(options[:datatype]) if options[:datatype]
|
151
158
|
@datatype ||= self.class.const_get(:DATATYPE) if self.class.const_defined?(:DATATYPE)
|
159
|
+
|
160
|
+
# Ignore rdf:langString if there is a language
|
161
|
+
@datatype = nil if @language && @datatype == RDF.langString
|
162
|
+
raise ArgumentError, "datatype of rdf:langString requires a language" if !@language && @datatype == RDF::langString
|
152
163
|
end
|
153
164
|
|
154
165
|
##
|
@@ -186,7 +197,24 @@ module RDF
|
|
186
197
|
#
|
187
198
|
# @return [Fixnum]
|
188
199
|
def hash
|
189
|
-
to_s.hash
|
200
|
+
@hash ||= to_s.hash
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
##
|
205
|
+
# Returns a hash code for the value.
|
206
|
+
#
|
207
|
+
# @return [Fixnum]
|
208
|
+
def value_hash
|
209
|
+
@value_hash ||= value.hash
|
210
|
+
end
|
211
|
+
|
212
|
+
##
|
213
|
+
# @private
|
214
|
+
def freeze
|
215
|
+
hash.freeze
|
216
|
+
value_hash.freeze
|
217
|
+
super
|
190
218
|
end
|
191
219
|
|
192
220
|
##
|
@@ -224,9 +252,9 @@ module RDF
|
|
224
252
|
true
|
225
253
|
when self.has_language? && self.language.to_s.downcase == other.language.to_s.downcase
|
226
254
|
# Literals with languages can compare if languages are identical
|
227
|
-
self.value == other.value
|
255
|
+
self.value_hash == other.value_hash && self.value == other.value
|
228
256
|
when (self.simple? || self.datatype == XSD.string) && (other.simple? || other.datatype == XSD.string)
|
229
|
-
self.value == other.value
|
257
|
+
self.value_hash == other.value_hash && self.value == other.value
|
230
258
|
when other.comperable_datatype?(self) || self.comperable_datatype?(other)
|
231
259
|
# Comoparing plain with undefined datatypes does not generate an error, but returns false
|
232
260
|
# From data-r2/expr-equal/eq-2-2.
|
@@ -235,21 +263,35 @@ module RDF
|
|
235
263
|
type_error("unable to determine whether #{self.inspect} and #{other.inspect} are equivalent")
|
236
264
|
end
|
237
265
|
when String
|
238
|
-
self.
|
266
|
+
self.simple? && self.value.eql?(other)
|
239
267
|
else false
|
240
268
|
end
|
241
269
|
end
|
242
270
|
alias_method :===, :==
|
243
271
|
|
244
272
|
##
|
245
|
-
# Returns `true` if this is a plain literal.
|
273
|
+
# Returns `true` if this is a plain literal. A plain literal
|
274
|
+
# may have a language, but may not have a datatype. For
|
275
|
+
# all practical purposes, this includes xsd:string literals
|
276
|
+
# too.
|
246
277
|
#
|
247
278
|
# @return [Boolean] `true` or `false`
|
248
279
|
# @see http://www.w3.org/TR/rdf-concepts/#dfn-plain-literal
|
249
280
|
def plain?
|
250
|
-
|
281
|
+
has_language? ?
|
282
|
+
(datatype || RDF.langString) == RDF.langString :
|
283
|
+
(datatype || XSD.string) == XSD.string
|
284
|
+
end
|
285
|
+
|
286
|
+
##
|
287
|
+
# Returns `true` if this is a simple literal.
|
288
|
+
# A simple literal has no datatype or language.
|
289
|
+
#
|
290
|
+
# @return [Boolean] `true` or `false`
|
291
|
+
# @see http://www.w3.org/TR/sparql11-query/#simple_literal
|
292
|
+
def simple?
|
293
|
+
!has_language? && !has_datatype?
|
251
294
|
end
|
252
|
-
alias_method :simple?, :plain?
|
253
295
|
|
254
296
|
##
|
255
297
|
# Returns `true` if this is a language-tagged literal.
|
data/lib/rdf/model/node.rb
CHANGED
@@ -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? &&
|
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 :===, :==
|
data/lib/rdf/model/statement.rb
CHANGED
data/lib/rdf/model/uri.rb
CHANGED
@@ -522,7 +522,7 @@ module RDF
|
|
522
522
|
# @param [RDF::URI] other
|
523
523
|
# @return [Boolean] `true` or `false`
|
524
524
|
def eql?(other)
|
525
|
-
other.is_a?(URI) && self == other
|
525
|
+
other.is_a?(URI) && self.hash == other.hash && self == other
|
526
526
|
end
|
527
527
|
|
528
528
|
##
|
@@ -544,6 +544,7 @@ module RDF
|
|
544
544
|
# If other is a Literal, reverse test to consolodate complex type checking logic
|
545
545
|
other == self
|
546
546
|
when String then to_s == other
|
547
|
+
when URI then hash == other.hash && to_s == other.to_s
|
547
548
|
when URI, Addressable::URI then to_s == other.to_s
|
548
549
|
else other.respond_to?(:to_uri) && to_s == other.to_uri.to_s
|
549
550
|
end
|
data/lib/rdf/query/pattern.rb
CHANGED
@@ -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('
|
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.
|
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
|
data/lib/rdf/query/solution.rb
CHANGED
@@ -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
|
##
|
data/lib/rdf/query/solutions.rb
CHANGED
@@ -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 => "
|
8
|
-
# solutions.filter(:author => [RDF::URI("http://ar.to/#self"), "
|
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
|
-
|
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
|
data/lib/rdf/query/variable.rb
CHANGED
@@ -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
|
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 =
|
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
|
|
data/lib/rdf/repository.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-
|
14
|
+
date: 2013-05-01 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: addressable
|
@@ -45,6 +45,24 @@ dependencies:
|
|
45
45
|
none: false
|
46
46
|
prerelease: false
|
47
47
|
type: :development
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rdf-rdfxml
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: !binary |-
|
55
|
+
MA==
|
56
|
+
none: false
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: !binary |-
|
62
|
+
MA==
|
63
|
+
none: false
|
64
|
+
prerelease: false
|
65
|
+
type: :development
|
48
66
|
- !ruby/object:Gem::Dependency
|
49
67
|
name: rspec
|
50
68
|
version_requirements: !ruby/object:Gem::Requirement
|