rdf 0.1.10 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|