rdf 0.1.10 → 0.2.0
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.
- data/CONTRIBUTORS +3 -0
- data/README +68 -34
- data/VERSION +1 -1
- data/etc/doap.nt +16 -0
- data/lib/rdf.rb +24 -18
- data/lib/rdf/format.rb +47 -22
- data/lib/rdf/mixin/countable.rb +42 -0
- data/lib/rdf/mixin/durable.rb +2 -0
- data/lib/rdf/mixin/enumerable.rb +72 -50
- data/lib/rdf/mixin/inferable.rb +2 -3
- data/lib/rdf/mixin/mutable.rb +51 -107
- data/lib/rdf/mixin/queryable.rb +43 -11
- data/lib/rdf/mixin/readable.rb +2 -0
- data/lib/rdf/mixin/writable.rb +130 -0
- data/lib/rdf/model/graph.rb +47 -14
- data/lib/rdf/model/literal.rb +12 -2
- data/lib/rdf/model/node.rb +51 -2
- data/lib/rdf/model/resource.rb +7 -10
- data/lib/rdf/model/statement.rb +59 -41
- data/lib/rdf/model/uri.rb +68 -8
- data/lib/rdf/model/value.rb +26 -31
- data/lib/rdf/ntriples/reader.rb +7 -6
- data/lib/rdf/ntriples/writer.rb +90 -0
- data/lib/rdf/query.rb +6 -6
- data/lib/rdf/query/pattern.rb +13 -15
- data/lib/rdf/query/solution.rb +1 -1
- data/lib/rdf/query/variable.rb +3 -1
- data/lib/rdf/reader.rb +2 -1
- data/lib/rdf/repository.rb +97 -47
- data/lib/rdf/util.rb +4 -0
- data/lib/rdf/util/aliasing.rb +51 -0
- data/lib/rdf/util/cache.rb +131 -0
- data/lib/rdf/version.rb +3 -4
- data/lib/rdf/vocab.rb +11 -10
- data/lib/rdf/vocab/cert.rb +13 -0
- data/lib/rdf/vocab/geo.rb +13 -0
- data/lib/rdf/vocab/rsa.rb +12 -0
- data/lib/rdf/writer.rb +102 -109
- metadata +23 -15
data/lib/rdf/mixin/queryable.rb
CHANGED
@@ -13,35 +13,67 @@ module RDF
|
|
13
13
|
##
|
14
14
|
# Queries `self` for RDF statements matching the given `pattern`.
|
15
15
|
#
|
16
|
+
# This method delegates to the protected {#query_pattern} method for the
|
17
|
+
# actual lower-level query pattern matching implementation.
|
18
|
+
#
|
16
19
|
# @example
|
17
20
|
# queryable.query([nil, RDF::DOAP.developer, nil])
|
18
21
|
# queryable.query(:predicate => RDF::DOAP.developer)
|
19
22
|
#
|
20
23
|
# @param [Query, Statement, Array(Value), Hash] pattern
|
21
24
|
# @yield [statement]
|
22
|
-
# @yieldparam [Statement]
|
23
|
-
# @return [
|
25
|
+
# @yieldparam [RDF::Statement]
|
26
|
+
# @return [Enumerator<RDF::Statement>]
|
27
|
+
# @see RDF::Queryable#query_pattern
|
24
28
|
def query(pattern, &block)
|
25
29
|
raise TypeError.new("#{self} is not readable") if respond_to?(:readable?) && !readable?
|
26
30
|
|
27
31
|
case pattern
|
28
32
|
when Query
|
29
33
|
pattern.execute(self, &block)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
34
|
+
else
|
35
|
+
pattern = case pattern
|
36
|
+
when Query::Pattern, Statement then pattern
|
37
|
+
when Array then Query::Pattern.new(*pattern)
|
38
|
+
when Hash then Query::Pattern.new(pattern)
|
39
|
+
else raise ArgumentError.new("expected RDF::Query, RDF::Query::Pattern, Array, or Hash, but got #{pattern.inspect}")
|
40
|
+
end
|
41
|
+
|
35
42
|
if block_given?
|
36
|
-
|
43
|
+
query_pattern(pattern, &block)
|
44
|
+
return nil
|
37
45
|
else
|
38
|
-
|
46
|
+
enum = enum_for(:query_pattern, pattern)
|
47
|
+
enum.extend(RDF::Queryable, RDF::Enumerable, RDF::Countable)
|
48
|
+
def enum.to_a
|
49
|
+
super.extend(RDF::Queryable, RDF::Enumerable, RDF::Countable)
|
50
|
+
end
|
51
|
+
return enum
|
39
52
|
end
|
40
|
-
else
|
41
|
-
raise ArgumentError.new("expected RDF::Query, RDF::Pattern, Array or Hash, but got #{pattern.inspect}")
|
42
53
|
end
|
43
54
|
end
|
44
55
|
|
56
|
+
##
|
57
|
+
# Queries `self` for RDF statements matching the given `pattern`,
|
58
|
+
# yielding each matched statement to the given block.
|
59
|
+
#
|
60
|
+
# Since RDF.rb 0.2.0, this is the preferred method that subclasses of
|
61
|
+
# `RDF::Repository` should override in order to provide an optimized
|
62
|
+
# query implementation.
|
63
|
+
#
|
64
|
+
# @param [RDF::Query::Pattern] pattern
|
65
|
+
# @yield [statement]
|
66
|
+
# @yieldparam [RDF::Statement]
|
67
|
+
# @return [void]
|
68
|
+
# @see RDF::Queryable#query
|
69
|
+
# @since 0.2.0
|
70
|
+
def query_pattern(pattern, &block)
|
71
|
+
# @see http://ruby-doc.org/core/classes/Enumerable.html#M003121
|
72
|
+
grep(pattern, &block)
|
73
|
+
end
|
74
|
+
|
75
|
+
protected :query_pattern
|
76
|
+
|
45
77
|
##
|
46
78
|
# Queries `self` for an RDF statement matching the given `pattern` and
|
47
79
|
# returns that statement if found.
|
data/lib/rdf/mixin/readable.rb
CHANGED
data/lib/rdf/mixin/writable.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module RDF
|
2
2
|
##
|
3
3
|
module Writable
|
4
|
+
extend RDF::Util::Aliasing::LateBound
|
5
|
+
|
4
6
|
##
|
5
7
|
# Returns `true` if `self` is writable.
|
6
8
|
#
|
@@ -9,5 +11,133 @@ module RDF
|
|
9
11
|
def writable?
|
10
12
|
true
|
11
13
|
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Inserts RDF data into `self`.
|
17
|
+
#
|
18
|
+
# @param [RDF::Enumerable, RDF::Statement, #to_rdf] data
|
19
|
+
# @return [Writable]
|
20
|
+
def <<(data)
|
21
|
+
case data
|
22
|
+
when RDF::Graph
|
23
|
+
insert_graph(data)
|
24
|
+
when RDF::Enumerable
|
25
|
+
insert_statements(data)
|
26
|
+
when RDF::Statement
|
27
|
+
insert_statement(data)
|
28
|
+
else case
|
29
|
+
when data.respond_to?(:to_rdf) && !data.equal?(rdf = data.to_rdf)
|
30
|
+
self << rdf
|
31
|
+
else
|
32
|
+
insert_statement(create_statement(data))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
return self
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Inserts RDF statements into `self`.
|
41
|
+
#
|
42
|
+
# @param [Array<RDF::Statement>] statements
|
43
|
+
# @return [Writable]
|
44
|
+
def insert(*statements)
|
45
|
+
statements.map! do |value|
|
46
|
+
case
|
47
|
+
when value.respond_to?(:each_statement)
|
48
|
+
insert_statements(value)
|
49
|
+
nil
|
50
|
+
when (statement = create_statement(value)).valid?
|
51
|
+
statement
|
52
|
+
else
|
53
|
+
raise ArgumentError.new("not a valid statement: #{value.inspect}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
statements.compact!
|
57
|
+
insert_statements(statements) unless statements.empty?
|
58
|
+
|
59
|
+
return self
|
60
|
+
end
|
61
|
+
|
62
|
+
alias_method :insert!, :insert
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
##
|
67
|
+
# Inserts the given RDF graph into the underlying storage or output
|
68
|
+
# stream.
|
69
|
+
#
|
70
|
+
# Defaults to passing the graph to the {#insert_statements} method.
|
71
|
+
#
|
72
|
+
# Subclasses of {RDF::Repository} may wish to override this method in
|
73
|
+
# case their underlying storage architecture is graph-centric rather
|
74
|
+
# than statement-oriented.
|
75
|
+
#
|
76
|
+
# Subclasses of {RDF::Writer} may wish to override this method if the
|
77
|
+
# output format they implement supports named graphs, in which case
|
78
|
+
# implementing this method may help in producing prettier and more
|
79
|
+
# concise output.
|
80
|
+
#
|
81
|
+
# @param [RDF::Graph] graph
|
82
|
+
# @return [void]
|
83
|
+
def insert_graph(graph)
|
84
|
+
insert_statements(graph)
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Inserts the given RDF statements into the underlying storage or output
|
89
|
+
# stream.
|
90
|
+
#
|
91
|
+
# Defaults to invoking {#insert_statement} for each given statement.
|
92
|
+
#
|
93
|
+
# Subclasses of {RDF::Repository} may wish to override this method if
|
94
|
+
# they are capable of more efficiently inserting multiple statements at
|
95
|
+
# once.
|
96
|
+
#
|
97
|
+
# Subclasses of {RDF::Writer} don't generally need to implement this
|
98
|
+
# method.
|
99
|
+
#
|
100
|
+
# @param [RDF::Enumerable] statements
|
101
|
+
# @return [void]
|
102
|
+
def insert_statements(statements)
|
103
|
+
each = statements.respond_to?(:each_statement) ? :each_statement : :each
|
104
|
+
statements.__send__(each) do |statement|
|
105
|
+
insert_statement(statement)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Inserts an RDF statement into the underlying storage or output stream.
|
111
|
+
#
|
112
|
+
# Subclasses of {RDF::Repository} must implement this method, except if
|
113
|
+
# they are immutable.
|
114
|
+
#
|
115
|
+
# Subclasses of {RDF::Writer} must implement this method.
|
116
|
+
#
|
117
|
+
# @param [RDF::Statement] statement
|
118
|
+
# @return [void]
|
119
|
+
# @abstract
|
120
|
+
def insert_statement(statement)
|
121
|
+
raise NotImplementedError.new("#{self.class}#insert_statement")
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Transforms various input into an `RDF::Statement` instance.
|
126
|
+
#
|
127
|
+
# @param [RDF::Statement, Hash, Array, #to_a] statement
|
128
|
+
# @return [RDF::Statement]
|
129
|
+
def create_statement(statement)
|
130
|
+
# TODO: move this to RDF::Statement.construct or the like.
|
131
|
+
case statement
|
132
|
+
when Statement then statement
|
133
|
+
when Hash then Statement.new(statement)
|
134
|
+
when Array then Statement.new(*statement)
|
135
|
+
else raise ArgumentError.new # FIXME
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
protected :insert_statements
|
140
|
+
protected :insert_statement
|
141
|
+
protected :create_statement
|
12
142
|
end
|
13
143
|
end
|
data/lib/rdf/model/graph.rb
CHANGED
@@ -19,17 +19,26 @@ module RDF
|
|
19
19
|
#
|
20
20
|
# graph = RDF::Graph.load("http://www.bbc.co.uk/programmes/b0081dq5.rdf")
|
21
21
|
#
|
22
|
-
class Graph
|
22
|
+
class Graph
|
23
|
+
include RDF::Resource
|
24
|
+
|
25
|
+
include RDF::Countable
|
23
26
|
include RDF::Enumerable
|
24
|
-
include RDF::Mutable
|
25
27
|
include RDF::Queryable
|
28
|
+
include RDF::Mutable
|
26
29
|
|
27
30
|
##
|
28
|
-
#
|
31
|
+
# Returns the options passed to this graph when it was constructed.
|
32
|
+
#
|
33
|
+
# @return [Hash{Symbol => Object}]
|
34
|
+
attr_reader :options
|
35
|
+
|
36
|
+
##
|
37
|
+
# @return [RDF::Resource]
|
29
38
|
attr_accessor :context
|
30
39
|
|
31
40
|
##
|
32
|
-
# @return [
|
41
|
+
# @return [RDF::Queryable]
|
33
42
|
attr_accessor :data
|
34
43
|
|
35
44
|
##
|
@@ -56,7 +65,7 @@ module RDF
|
|
56
65
|
end
|
57
66
|
|
58
67
|
##
|
59
|
-
# @param [Resource]
|
68
|
+
# @param [RDF::Resource] context
|
60
69
|
# @param [Hash{Symbol => Object}] options
|
61
70
|
# @yield [graph]
|
62
71
|
# @yieldparam [Graph]
|
@@ -68,7 +77,7 @@ module RDF
|
|
68
77
|
end
|
69
78
|
|
70
79
|
@options = options.dup
|
71
|
-
@data = @options.delete(:data) ||
|
80
|
+
@data = @options.delete(:data) || RDF::Repository.new
|
72
81
|
|
73
82
|
if block_given?
|
74
83
|
case block.arity
|
@@ -115,15 +124,15 @@ module RDF
|
|
115
124
|
##
|
116
125
|
# Returns all unique RDF contexts for this graph.
|
117
126
|
#
|
118
|
-
# @return [
|
127
|
+
# @return [Enumerator<RDF::Resource>]
|
119
128
|
def contexts
|
120
|
-
named? ? [context] : []
|
129
|
+
(named? ? [context] : []).to_enum.extend(RDF::Countable)
|
121
130
|
end
|
122
131
|
|
123
132
|
##
|
124
133
|
# Returns the URI representation of this graph.
|
125
134
|
#
|
126
|
-
# @return [URI]
|
135
|
+
# @return [RDF::URI]
|
127
136
|
def to_uri
|
128
137
|
context
|
129
138
|
end
|
@@ -145,13 +154,21 @@ module RDF
|
|
145
154
|
@data.empty?
|
146
155
|
end
|
147
156
|
|
157
|
+
##
|
158
|
+
# Returns `true` if this graph has an anonymous context, `false` otherwise.
|
159
|
+
#
|
160
|
+
# @return [Boolean]
|
161
|
+
def anonymous?
|
162
|
+
context.nil? ? false : context.anonymous?
|
163
|
+
end
|
164
|
+
|
148
165
|
##
|
149
166
|
# Returns the number of RDF statements in this graph.
|
150
167
|
#
|
151
168
|
# @return [Integer]
|
152
169
|
# @see RDF::Enumerable#count
|
153
170
|
def count
|
154
|
-
@data.
|
171
|
+
@data.query(:context => context).count
|
155
172
|
end
|
156
173
|
|
157
174
|
##
|
@@ -163,7 +180,7 @@ module RDF
|
|
163
180
|
def has_statement?(statement)
|
164
181
|
statement = statement.dup
|
165
182
|
statement.context = context
|
166
|
-
@data.
|
183
|
+
@data.has_statement?(statement)
|
167
184
|
end
|
168
185
|
|
169
186
|
##
|
@@ -174,7 +191,7 @@ module RDF
|
|
174
191
|
# @return [Enumerator]
|
175
192
|
# @see RDF::Enumerable#each_statement
|
176
193
|
def each(&block)
|
177
|
-
@data.each(&block)
|
194
|
+
@data.query(:context => context).each(&block)
|
178
195
|
end
|
179
196
|
|
180
197
|
##
|
@@ -186,7 +203,7 @@ module RDF
|
|
186
203
|
def insert_statement(statement)
|
187
204
|
statement = statement.dup
|
188
205
|
statement.context = context
|
189
|
-
@data.
|
206
|
+
@data.insert(statement)
|
190
207
|
end
|
191
208
|
|
192
209
|
##
|
@@ -207,11 +224,27 @@ module RDF
|
|
207
224
|
# @return [void]
|
208
225
|
# @see RDF::Mutable#clear
|
209
226
|
def clear_statements
|
210
|
-
@data.
|
227
|
+
@data.delete(:context => context)
|
211
228
|
end
|
212
229
|
|
213
230
|
protected :insert_statement
|
214
231
|
protected :delete_statement
|
215
232
|
protected :clear_statements
|
233
|
+
|
234
|
+
##
|
235
|
+
# @private
|
236
|
+
# @see RDF::Enumerable#graphs
|
237
|
+
# @since 0.2.0
|
238
|
+
def graphs
|
239
|
+
enum_graph
|
240
|
+
end
|
241
|
+
|
242
|
+
##
|
243
|
+
# @private
|
244
|
+
# @see RDF::Enumerable#each_graph
|
245
|
+
# @since 0.2.0
|
246
|
+
def each_graph(&block)
|
247
|
+
block_given? ? block.call(self) : enum_graph
|
248
|
+
end
|
216
249
|
end
|
217
250
|
end
|
data/lib/rdf/model/literal.rb
CHANGED
@@ -38,7 +38,9 @@ module RDF
|
|
38
38
|
#
|
39
39
|
# @see http://www.w3.org/TR/rdf-concepts/#section-Literals
|
40
40
|
# @see http://www.w3.org/TR/rdf-concepts/#section-Datatypes-intro
|
41
|
-
class Literal
|
41
|
+
class Literal
|
42
|
+
include RDF::Value
|
43
|
+
|
42
44
|
# @return [String] The normalized string representation of the value.
|
43
45
|
attr_accessor :value
|
44
46
|
|
@@ -57,7 +59,7 @@ module RDF
|
|
57
59
|
@language = options[:language] ? options[:language].to_s.to_sym : nil
|
58
60
|
|
59
61
|
if datatype = options[:datatype]
|
60
|
-
@datatype = datatype.respond_to?(:to_uri) ? datatype.to_uri : URI.
|
62
|
+
@datatype = datatype.respond_to?(:to_uri) ? datatype.to_uri : URI.intern(datatype.to_s)
|
61
63
|
else
|
62
64
|
@datatype = case value
|
63
65
|
when String then nil # implicit XSD.string
|
@@ -137,6 +139,14 @@ module RDF
|
|
137
139
|
true
|
138
140
|
end
|
139
141
|
|
142
|
+
##
|
143
|
+
# Returns `false`.
|
144
|
+
#
|
145
|
+
# @return [Boolean]
|
146
|
+
def anonymous?
|
147
|
+
false
|
148
|
+
end
|
149
|
+
|
140
150
|
##
|
141
151
|
# @return [Boolean]
|
142
152
|
def eql?(other)
|
data/lib/rdf/model/node.rb
CHANGED
@@ -11,7 +11,9 @@ module RDF
|
|
11
11
|
#
|
12
12
|
# @see http://rubygems.org/gems/uuid
|
13
13
|
# @see http://rubygems.org/gems/uuidtools
|
14
|
-
class Node
|
14
|
+
class Node
|
15
|
+
include RDF::Resource
|
16
|
+
|
15
17
|
##
|
16
18
|
# Returns a blank node with a random UUID-based identifier.
|
17
19
|
#
|
@@ -30,6 +32,17 @@ module RDF
|
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
35
|
+
##
|
36
|
+
# Alias for `RDF::Node.new`, at the moment.
|
37
|
+
#
|
38
|
+
# @private
|
39
|
+
# @param [#to_s] id
|
40
|
+
# @return [RDF::Node]
|
41
|
+
# @since 0.2.0
|
42
|
+
def self.intern(id)
|
43
|
+
self.new(id)
|
44
|
+
end
|
45
|
+
|
33
46
|
# @return [String]
|
34
47
|
attr_accessor :id
|
35
48
|
|
@@ -65,12 +78,48 @@ module RDF
|
|
65
78
|
!unlabeled?
|
66
79
|
end
|
67
80
|
|
81
|
+
##
|
82
|
+
# Returns a hash code for this blank node.
|
83
|
+
#
|
84
|
+
# @return [Fixnum]
|
85
|
+
def hash
|
86
|
+
@id.hash
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Checks whether this blank node is equal to `other`.
|
91
|
+
#
|
92
|
+
# @param [Node] other
|
93
|
+
# @return [Boolean]
|
94
|
+
def eql?(other)
|
95
|
+
other.is_a?(Node) && self == other
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Checks whether this blank node is equal to `other`.
|
100
|
+
#
|
101
|
+
# @param [Object] other
|
102
|
+
# @return [Boolean]
|
103
|
+
def ==(other)
|
104
|
+
other.respond_to?(:node?) && other.node? &&
|
105
|
+
other.respond_to?(:id) && @id == other.id
|
106
|
+
end
|
107
|
+
|
68
108
|
##
|
69
109
|
# Returns a string representation of this blank node.
|
70
110
|
#
|
71
111
|
# @return [String]
|
72
112
|
def to_s
|
73
|
-
"_:%s" % id.to_s
|
113
|
+
"_:%s" % @id.to_s
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
# Returns a symbol representation of this blank node.
|
118
|
+
#
|
119
|
+
# @return [Symbol]
|
120
|
+
# @since 0.2.0
|
121
|
+
def to_sym
|
122
|
+
@id.to_s.to_sym
|
74
123
|
end
|
75
124
|
end
|
76
125
|
end
|