openlogic-rdf 0.3.6
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/AUTHORS +3 -0
- data/CREDITS +9 -0
- data/README +361 -0
- data/UNLICENSE +24 -0
- data/VERSION +1 -0
- data/bin/rdf +18 -0
- data/etc/doap.nt +62 -0
- data/lib/df.rb +1 -0
- data/lib/rdf/cli.rb +200 -0
- data/lib/rdf/format.rb +383 -0
- data/lib/rdf/mixin/countable.rb +39 -0
- data/lib/rdf/mixin/durable.rb +31 -0
- data/lib/rdf/mixin/enumerable.rb +637 -0
- data/lib/rdf/mixin/indexable.rb +26 -0
- data/lib/rdf/mixin/inferable.rb +5 -0
- data/lib/rdf/mixin/mutable.rb +191 -0
- data/lib/rdf/mixin/queryable.rb +265 -0
- data/lib/rdf/mixin/readable.rb +15 -0
- data/lib/rdf/mixin/type_check.rb +21 -0
- data/lib/rdf/mixin/writable.rb +152 -0
- data/lib/rdf/model/graph.rb +263 -0
- data/lib/rdf/model/list.rb +731 -0
- data/lib/rdf/model/literal/boolean.rb +121 -0
- data/lib/rdf/model/literal/date.rb +73 -0
- data/lib/rdf/model/literal/datetime.rb +72 -0
- data/lib/rdf/model/literal/decimal.rb +86 -0
- data/lib/rdf/model/literal/double.rb +189 -0
- data/lib/rdf/model/literal/integer.rb +126 -0
- data/lib/rdf/model/literal/numeric.rb +184 -0
- data/lib/rdf/model/literal/time.rb +87 -0
- data/lib/rdf/model/literal/token.rb +47 -0
- data/lib/rdf/model/literal/xml.rb +39 -0
- data/lib/rdf/model/literal.rb +373 -0
- data/lib/rdf/model/node.rb +156 -0
- data/lib/rdf/model/resource.rb +28 -0
- data/lib/rdf/model/statement.rb +296 -0
- data/lib/rdf/model/term.rb +77 -0
- data/lib/rdf/model/uri.rb +570 -0
- data/lib/rdf/model/value.rb +133 -0
- data/lib/rdf/nquads.rb +152 -0
- data/lib/rdf/ntriples/format.rb +48 -0
- data/lib/rdf/ntriples/reader.rb +239 -0
- data/lib/rdf/ntriples/writer.rb +219 -0
- data/lib/rdf/ntriples.rb +104 -0
- data/lib/rdf/query/pattern.rb +329 -0
- data/lib/rdf/query/solution.rb +252 -0
- data/lib/rdf/query/solutions.rb +237 -0
- data/lib/rdf/query/variable.rb +221 -0
- data/lib/rdf/query.rb +404 -0
- data/lib/rdf/reader.rb +511 -0
- data/lib/rdf/repository.rb +389 -0
- data/lib/rdf/transaction.rb +161 -0
- data/lib/rdf/util/aliasing.rb +63 -0
- data/lib/rdf/util/cache.rb +139 -0
- data/lib/rdf/util/file.rb +38 -0
- data/lib/rdf/util/uuid.rb +36 -0
- data/lib/rdf/util.rb +6 -0
- data/lib/rdf/version.rb +19 -0
- data/lib/rdf/vocab/cc.rb +18 -0
- data/lib/rdf/vocab/cert.rb +13 -0
- data/lib/rdf/vocab/dc.rb +63 -0
- data/lib/rdf/vocab/dc11.rb +23 -0
- data/lib/rdf/vocab/doap.rb +45 -0
- data/lib/rdf/vocab/exif.rb +168 -0
- data/lib/rdf/vocab/foaf.rb +69 -0
- data/lib/rdf/vocab/geo.rb +13 -0
- data/lib/rdf/vocab/http.rb +26 -0
- data/lib/rdf/vocab/owl.rb +59 -0
- data/lib/rdf/vocab/rdfs.rb +17 -0
- data/lib/rdf/vocab/rsa.rb +12 -0
- data/lib/rdf/vocab/rss.rb +14 -0
- data/lib/rdf/vocab/sioc.rb +93 -0
- data/lib/rdf/vocab/skos.rb +36 -0
- data/lib/rdf/vocab/wot.rb +21 -0
- data/lib/rdf/vocab/xhtml.rb +9 -0
- data/lib/rdf/vocab/xsd.rb +58 -0
- data/lib/rdf/vocab.rb +215 -0
- data/lib/rdf/writer.rb +475 -0
- data/lib/rdf.rb +192 -0
- metadata +173 -0
@@ -0,0 +1,389 @@
|
|
1
|
+
module RDF
|
2
|
+
##
|
3
|
+
# An RDF repository.
|
4
|
+
#
|
5
|
+
# @example Creating a transient in-memory repository
|
6
|
+
# repository = RDF::Repository.new
|
7
|
+
#
|
8
|
+
# @example Checking whether a repository is readable/writable
|
9
|
+
# repository.readable?
|
10
|
+
# repository.writable?
|
11
|
+
#
|
12
|
+
# @example Checking whether a repository is persistent or transient
|
13
|
+
# repository.persistent?
|
14
|
+
# repository.transient?
|
15
|
+
#
|
16
|
+
# @example Checking whether a repository is empty
|
17
|
+
# repository.empty?
|
18
|
+
#
|
19
|
+
# @example Checking how many statements a repository contains
|
20
|
+
# repository.count
|
21
|
+
#
|
22
|
+
# @example Checking whether a repository contains a specific statement
|
23
|
+
# repository.has_statement?(statement)
|
24
|
+
#
|
25
|
+
# @example Enumerating statements in a repository
|
26
|
+
# repository.each_statement { |statement| statement.inspect! }
|
27
|
+
#
|
28
|
+
# @example Inserting statements into a repository
|
29
|
+
# repository.insert(*statements)
|
30
|
+
# repository.insert(statement)
|
31
|
+
# repository.insert([subject, predicate, object])
|
32
|
+
# repository << statement
|
33
|
+
# repository << [subject, predicate, object]
|
34
|
+
#
|
35
|
+
# @example Deleting statements from a repository
|
36
|
+
# repository.delete(*statements)
|
37
|
+
# repository.delete(statement)
|
38
|
+
# repository.delete([subject, predicate, object])
|
39
|
+
#
|
40
|
+
# @example Deleting all statements from a repository
|
41
|
+
# repository.clear!
|
42
|
+
#
|
43
|
+
class Repository
|
44
|
+
include RDF::Countable
|
45
|
+
include RDF::Enumerable
|
46
|
+
include RDF::Queryable
|
47
|
+
include RDF::Mutable
|
48
|
+
include RDF::Durable
|
49
|
+
|
50
|
+
##
|
51
|
+
# Returns the options passed to this repository when it was constructed.
|
52
|
+
#
|
53
|
+
# @return [Hash{Symbol => Object}]
|
54
|
+
attr_reader :options
|
55
|
+
|
56
|
+
##
|
57
|
+
# Returns the {URI} of this repository.
|
58
|
+
#
|
59
|
+
# @return [URI]
|
60
|
+
attr_reader :uri
|
61
|
+
alias_method :url, :uri
|
62
|
+
|
63
|
+
##
|
64
|
+
# Returns the title of this repository.
|
65
|
+
#
|
66
|
+
# @return [String]
|
67
|
+
attr_reader :title
|
68
|
+
|
69
|
+
##
|
70
|
+
# Loads one or more RDF files into a new transient in-memory repository.
|
71
|
+
#
|
72
|
+
# @param [String, Array<String>] filenames
|
73
|
+
# @param [Hash{Symbol => Object}] options
|
74
|
+
# Options from {RDF::Reader#initialize}, {RDF::Format.for} and {RDF::Repository#initialize}
|
75
|
+
# @yield [repository]
|
76
|
+
# @yieldparam [Repository]
|
77
|
+
# @return [void]
|
78
|
+
def self.load(filenames, options = {}, &block)
|
79
|
+
self.new(options) do |repository|
|
80
|
+
[filenames].flatten.each do |filename|
|
81
|
+
repository.load(filename, options)
|
82
|
+
end
|
83
|
+
|
84
|
+
if block_given?
|
85
|
+
case block.arity
|
86
|
+
when 1 then block.call(repository)
|
87
|
+
else repository.instance_eval(&block)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# Initializes this repository instance.
|
95
|
+
#
|
96
|
+
# @param [Hash{Symbol => Object}] options
|
97
|
+
# @option options [URI, #to_s] :uri (nil)
|
98
|
+
# @option options [String, #to_s] :title (nil)
|
99
|
+
# @yield [repository]
|
100
|
+
# @yieldparam [Repository] repository
|
101
|
+
def initialize(options = {}, &block)
|
102
|
+
@options = options.dup
|
103
|
+
@uri = @options.delete(:uri)
|
104
|
+
@title = @options.delete(:title)
|
105
|
+
|
106
|
+
# Provide a default in-memory implementation:
|
107
|
+
send(:extend, Implementation) if self.class.equal?(RDF::Repository)
|
108
|
+
|
109
|
+
if block_given?
|
110
|
+
case block.arity
|
111
|
+
when 1 then block.call(self)
|
112
|
+
else instance_eval(&block)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
# Returns a developer-friendly representation of this object.
|
119
|
+
#
|
120
|
+
# @return [String]
|
121
|
+
def inspect
|
122
|
+
sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, uri.to_s)
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Outputs a developer-friendly representation of this object to
|
127
|
+
# `stderr`.
|
128
|
+
#
|
129
|
+
# @return [void]
|
130
|
+
def inspect!
|
131
|
+
each_statement { |statement| statement.inspect! }
|
132
|
+
nil
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# Executes the given block in a transaction.
|
137
|
+
#
|
138
|
+
# @example
|
139
|
+
# repository.transaction do |tx|
|
140
|
+
# tx.insert [RDF::URI("http://rdf.rubyforge.org/"), RDF::DC.title, "RDF.rb"]
|
141
|
+
# end
|
142
|
+
#
|
143
|
+
# @param [RDF::Resource] context
|
144
|
+
# @yield [tx]
|
145
|
+
# @yieldparam [RDF::Transaction] tx
|
146
|
+
# @yieldreturn [void] ignored
|
147
|
+
# @return [void] `self`
|
148
|
+
# @see RDF::Transaction
|
149
|
+
# @since 0.3.0
|
150
|
+
def transaction(context = nil, &block)
|
151
|
+
tx = begin_transaction(context)
|
152
|
+
begin
|
153
|
+
case block.arity
|
154
|
+
when 1 then block.call(tx)
|
155
|
+
else tx.instance_eval(&block)
|
156
|
+
end
|
157
|
+
rescue => error
|
158
|
+
rollback_transaction(tx)
|
159
|
+
raise error
|
160
|
+
end
|
161
|
+
commit_transaction(tx)
|
162
|
+
self
|
163
|
+
end
|
164
|
+
alias_method :transact, :transaction
|
165
|
+
|
166
|
+
protected
|
167
|
+
|
168
|
+
##
|
169
|
+
# Begins a new transaction.
|
170
|
+
#
|
171
|
+
# Subclasses implementing transaction-capable storage adapters may wish
|
172
|
+
# to override this method in order to begin a transaction against the
|
173
|
+
# underlying storage.
|
174
|
+
#
|
175
|
+
# @param [RDF::Resource] context
|
176
|
+
# @return [RDF::Transaction]
|
177
|
+
# @since 0.3.0
|
178
|
+
def begin_transaction(context)
|
179
|
+
RDF::Transaction.new(:context => context)
|
180
|
+
end
|
181
|
+
|
182
|
+
##
|
183
|
+
# Rolls back the given transaction.
|
184
|
+
#
|
185
|
+
# Subclasses implementing transaction-capable storage adapters may wish
|
186
|
+
# to override this method in order to roll back the given transaction in
|
187
|
+
# the underlying storage.
|
188
|
+
#
|
189
|
+
# @param [RDF::Transaction] tx
|
190
|
+
# @return [void] ignored
|
191
|
+
# @since 0.3.0
|
192
|
+
def rollback_transaction(tx)
|
193
|
+
# nothing to do
|
194
|
+
end
|
195
|
+
|
196
|
+
##
|
197
|
+
# Commits the given transaction.
|
198
|
+
#
|
199
|
+
# Subclasses implementing transaction-capable storage adapters may wish
|
200
|
+
# to override this method in order to commit the given transaction to
|
201
|
+
# the underlying storage.
|
202
|
+
#
|
203
|
+
# @param [RDF::Transaction] tx
|
204
|
+
# @return [void] ignored
|
205
|
+
# @since 0.3.0
|
206
|
+
def commit_transaction(tx)
|
207
|
+
tx.execute(self)
|
208
|
+
end
|
209
|
+
|
210
|
+
##
|
211
|
+
# @see RDF::Repository
|
212
|
+
module Implementation
|
213
|
+
DEFAULT_CONTEXT = false
|
214
|
+
|
215
|
+
##
|
216
|
+
# @private
|
217
|
+
def self.extend_object(obj)
|
218
|
+
obj.instance_variable_set(:@data, obj.options.delete(:data) || {})
|
219
|
+
super
|
220
|
+
end
|
221
|
+
|
222
|
+
##
|
223
|
+
# @private
|
224
|
+
# @see RDF::Readable#supports?
|
225
|
+
def supports?(feature)
|
226
|
+
case feature.to_sym
|
227
|
+
when :context then true # statement contexts / named graphs
|
228
|
+
when :inference then false # forward-chaining inference
|
229
|
+
else false
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
##
|
234
|
+
# @private
|
235
|
+
# @see RDF::Durable#durable?
|
236
|
+
def durable?
|
237
|
+
false
|
238
|
+
end
|
239
|
+
|
240
|
+
##
|
241
|
+
# @private
|
242
|
+
# @see RDF::Countable#empty?
|
243
|
+
def empty?
|
244
|
+
@data.empty?
|
245
|
+
end
|
246
|
+
|
247
|
+
##
|
248
|
+
# @private
|
249
|
+
# @see RDF::Countable#count
|
250
|
+
def count
|
251
|
+
count = 0
|
252
|
+
@data.each do |c, ss|
|
253
|
+
ss.each do |s, ps|
|
254
|
+
ps.each do |p, os|
|
255
|
+
count += os.size
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
count
|
260
|
+
end
|
261
|
+
|
262
|
+
##
|
263
|
+
# @private
|
264
|
+
# @see RDF::Enumerable#has_statement?
|
265
|
+
def has_statement?(statement)
|
266
|
+
s, p, o, c = statement.to_quad
|
267
|
+
c ||= DEFAULT_CONTEXT
|
268
|
+
@data.has_key?(c) &&
|
269
|
+
@data[c].has_key?(s) &&
|
270
|
+
@data[c][s].has_key?(p) &&
|
271
|
+
@data[c][s][p].include?(o)
|
272
|
+
end
|
273
|
+
|
274
|
+
##
|
275
|
+
# @private
|
276
|
+
# @see RDF::Enumerable#each_statement
|
277
|
+
def each_statement(&block)
|
278
|
+
if block_given?
|
279
|
+
# Note that to iterate in a more consistent fashion despite
|
280
|
+
# possible concurrent mutations to `@data`, we use `#dup` to make
|
281
|
+
# shallow copies of the nested hashes before beginning the
|
282
|
+
# iteration over their keys and values.
|
283
|
+
@data.dup.each do |c, ss|
|
284
|
+
ss.dup.each do |s, ps|
|
285
|
+
ps.dup.each do |p, os|
|
286
|
+
os.dup.each do |o|
|
287
|
+
block.call(RDF::Statement.new(s, p, o, :context => c.equal?(DEFAULT_CONTEXT) ? nil : c))
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
enum_statement
|
294
|
+
end
|
295
|
+
alias_method :each, :each_statement
|
296
|
+
|
297
|
+
##
|
298
|
+
# @private
|
299
|
+
# @see RDF::Enumerable#has_context?
|
300
|
+
def has_context?(value)
|
301
|
+
@data.keys.include?(value)
|
302
|
+
end
|
303
|
+
|
304
|
+
##
|
305
|
+
# @private
|
306
|
+
# @see RDF::Enumerable#each_context
|
307
|
+
def each_context(&block)
|
308
|
+
if block_given?
|
309
|
+
contexts = @data.keys
|
310
|
+
contexts.delete(DEFAULT_CONTEXT)
|
311
|
+
contexts.each(&block)
|
312
|
+
end
|
313
|
+
enum_context
|
314
|
+
end
|
315
|
+
|
316
|
+
protected
|
317
|
+
|
318
|
+
##
|
319
|
+
# Match elements with eql?, not ==
|
320
|
+
# Context of `false` matches default context. Unbound variable matches non-false context
|
321
|
+
# @private
|
322
|
+
# @see RDF::Queryable#query
|
323
|
+
def query_pattern(pattern, &block)
|
324
|
+
context = pattern.context
|
325
|
+
subject = pattern.subject
|
326
|
+
predicate = pattern.predicate
|
327
|
+
object = pattern.object
|
328
|
+
|
329
|
+
cs = @data.has_key?(context) ? {context => @data[context]} : @data.dup
|
330
|
+
cs.each do |c, ss|
|
331
|
+
next unless context.nil? || context == false && !c || context.eql?(c)
|
332
|
+
ss = ss.has_key?(subject) ? {subject => ss[subject]} : ss.dup
|
333
|
+
ss.each do |s, ps|
|
334
|
+
next unless subject.nil? || subject.eql?(s)
|
335
|
+
ps = ps.has_key?(predicate) ? {predicate => ps[predicate]} : ps.dup
|
336
|
+
ps.each do |p, os|
|
337
|
+
next unless predicate.nil? || predicate.eql?(p)
|
338
|
+
os = os.dup # TODO: is this really needed?
|
339
|
+
os.each do |o|
|
340
|
+
next unless object.nil? || object.eql?(o)
|
341
|
+
block.call(RDF::Statement.new(s, p, o, :context => c.equal?(DEFAULT_CONTEXT) ? nil : c))
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
##
|
349
|
+
# @private
|
350
|
+
# @see RDF::Mutable#insert
|
351
|
+
def insert_statement(statement)
|
352
|
+
unless has_statement?(statement)
|
353
|
+
s, p, o, c = statement.to_quad
|
354
|
+
c ||= DEFAULT_CONTEXT
|
355
|
+
@data[c] ||= {}
|
356
|
+
@data[c][s] ||= {}
|
357
|
+
@data[c][s][p] ||= []
|
358
|
+
@data[c][s][p] << o
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
##
|
363
|
+
# @private
|
364
|
+
# @see RDF::Mutable#delete
|
365
|
+
def delete_statement(statement)
|
366
|
+
if has_statement?(statement)
|
367
|
+
s, p, o, c = statement.to_quad
|
368
|
+
c ||= DEFAULT_CONTEXT
|
369
|
+
@data[c][s][p].delete(o)
|
370
|
+
@data[c][s].delete(p) if @data[c][s][p].empty?
|
371
|
+
@data[c].delete(s) if @data[c][s].empty?
|
372
|
+
@data.delete(c) if @data[c].empty?
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
##
|
377
|
+
# @private
|
378
|
+
# @see RDF::Mutable#clear
|
379
|
+
def clear_statements
|
380
|
+
@data.clear
|
381
|
+
end
|
382
|
+
|
383
|
+
protected :query_pattern
|
384
|
+
protected :insert_statement
|
385
|
+
protected :delete_statement
|
386
|
+
protected :clear_statements
|
387
|
+
end # Implementation
|
388
|
+
end # Repository
|
389
|
+
end # RDF
|
@@ -0,0 +1,161 @@
|
|
1
|
+
module RDF
|
2
|
+
##
|
3
|
+
# An RDF transaction.
|
4
|
+
#
|
5
|
+
# Transactions consist of a sequence of RDF statements to delete from and
|
6
|
+
# a sequence of RDF statements to insert into a given named graph.
|
7
|
+
#
|
8
|
+
# @example Executing a transaction against a repository
|
9
|
+
# repository = ...
|
10
|
+
# RDF::Transaction.execute(repository) do |tx|
|
11
|
+
# subject = RDF::URI("http://example.org/article")
|
12
|
+
# tx.delete [subject, RDF::DC.title, "Old title"]
|
13
|
+
# tx.insert [subject, RDF::DC.title, "New title"]
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# @since 0.3.0
|
17
|
+
class Transaction
|
18
|
+
include RDF::Mutable
|
19
|
+
|
20
|
+
##
|
21
|
+
# Executes a transaction against the given RDF repository.
|
22
|
+
#
|
23
|
+
# @param [RDF::Repository] repository
|
24
|
+
# @param [Hash{Symbol => Object}] options
|
25
|
+
# @yield [tx]
|
26
|
+
# @yieldparam [RDF::Transaction] tx
|
27
|
+
# @return [void]
|
28
|
+
def self.execute(repository, options = {}, &block)
|
29
|
+
self.new(&block).execute(repository, options)
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# RDF graph to modify when executed.
|
34
|
+
#
|
35
|
+
# @return [RDF::Resource]
|
36
|
+
attr_reader :graph
|
37
|
+
|
38
|
+
##
|
39
|
+
# RDF statements to delete when executed.
|
40
|
+
#
|
41
|
+
# @return [RDF::Enumerable]
|
42
|
+
attr_reader :deletes
|
43
|
+
|
44
|
+
##
|
45
|
+
# RDF statements to insert when executed.
|
46
|
+
#
|
47
|
+
# @return [RDF::Enumerable]
|
48
|
+
attr_reader :inserts
|
49
|
+
|
50
|
+
##
|
51
|
+
# Any additional options for this transaction.
|
52
|
+
#
|
53
|
+
# @return [Hash{Symbol => Object}]
|
54
|
+
attr_reader :options
|
55
|
+
|
56
|
+
##
|
57
|
+
# Initializes this transaction.
|
58
|
+
#
|
59
|
+
# @param [Hash{Symbol => Object}] options
|
60
|
+
# @option options [RDF::Resource] :graph (nil)
|
61
|
+
# @option options [RDF::Enumerable] :insert (RDF::Graph.new)
|
62
|
+
# @option options [RDF::Enumerable] :delete (RDF::Graph.new)
|
63
|
+
# @yield [tx]
|
64
|
+
# @yieldparam [RDF::Transaction] tx
|
65
|
+
def initialize(options = {}, &block)
|
66
|
+
@options = options.dup
|
67
|
+
@graph = @options.delete(:graph) || @options.delete(:context)
|
68
|
+
@inserts = @options.delete(:insert) || RDF::Graph.new
|
69
|
+
@deletes = @options.delete(:delete) || RDF::Graph.new
|
70
|
+
@inserts.extend(RDF::Enumerable) unless @inserts.kind_of?(RDF::Enumerable)
|
71
|
+
@deletes.extend(RDF::Enumerable) unless @deletes.kind_of?(RDF::Enumerable)
|
72
|
+
|
73
|
+
if block_given?
|
74
|
+
case block.arity
|
75
|
+
when 1 then block.call(self)
|
76
|
+
else instance_eval(&block)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Returns `false` to indicate that this transaction is append-only.
|
83
|
+
#
|
84
|
+
# Transactions do not support the `RDF::Enumerable` protocol directly.
|
85
|
+
# To enumerate the RDF statements to be inserted or deleted, use the
|
86
|
+
# {#inserts} and {#deletes} accessors.
|
87
|
+
#
|
88
|
+
# @return [Boolean]
|
89
|
+
# @see RDF::Readable#readable?
|
90
|
+
def readable?
|
91
|
+
false
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Executes this transaction against the given RDF repository.
|
96
|
+
#
|
97
|
+
# @param [RDF::Repository] repository
|
98
|
+
# @param [Hash{Symbol => Object}] options
|
99
|
+
# @return [void]
|
100
|
+
def execute(repository, options = {})
|
101
|
+
before_execute(repository, options) if respond_to?(:before_execute)
|
102
|
+
|
103
|
+
deletes.each_statement do |statement|
|
104
|
+
statement = statement.dup
|
105
|
+
statement.context = graph
|
106
|
+
repository.delete(statement)
|
107
|
+
end
|
108
|
+
|
109
|
+
inserts.each_statement do |statement|
|
110
|
+
statement = statement.dup
|
111
|
+
statement.context = graph
|
112
|
+
repository.insert(statement)
|
113
|
+
end
|
114
|
+
|
115
|
+
after_execute(repository, options) if respond_to?(:after_execute)
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
##
|
120
|
+
# Returns a developer-friendly representation of this transaction.
|
121
|
+
#
|
122
|
+
# @return [String]
|
123
|
+
def inspect
|
124
|
+
sprintf("#<%s:%#0x(graph: %s, deletes: %d, inserts: %d)>", self.class.name, __id__,
|
125
|
+
graph ? graph.to_s : 'nil', deletes.count, inserts.count)
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Outputs a developer-friendly representation of this transaction to
|
130
|
+
# `stderr`.
|
131
|
+
#
|
132
|
+
# @return [void]
|
133
|
+
def inspect!
|
134
|
+
warn(inspect)
|
135
|
+
end
|
136
|
+
|
137
|
+
##
|
138
|
+
# Appends an RDF statement to the sequence to insert when executed.
|
139
|
+
#
|
140
|
+
# @param [RDF::Statement] statement
|
141
|
+
# @return [void]
|
142
|
+
# @see RDF::Writable#insert_statement
|
143
|
+
def insert_statement(statement)
|
144
|
+
inserts << statement
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# Appends an RDF statement to the sequence to delete when executed.
|
149
|
+
#
|
150
|
+
# @param [RDF::Statement] statement
|
151
|
+
# @return [void]
|
152
|
+
# @see RDF::Mutable#delete_statement
|
153
|
+
def delete_statement(statement)
|
154
|
+
deletes << statement
|
155
|
+
end
|
156
|
+
|
157
|
+
undef_method :load, :update, :clear
|
158
|
+
protected :insert_statement
|
159
|
+
protected :delete_statement
|
160
|
+
end # Transaction
|
161
|
+
end # RDF
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module RDF; module Util
|
2
|
+
module Aliasing
|
3
|
+
##
|
4
|
+
# Helpers for late-bound instance method aliasing.
|
5
|
+
#
|
6
|
+
# Anything that extends this module will obtain an `alias_method` class
|
7
|
+
# method that creates late-bound instance method aliases instead of the
|
8
|
+
# default early-bound aliases created by Ruby's `Module#alias_method`.
|
9
|
+
#
|
10
|
+
# This is useful because RDF.rb mixins typically alias a number of
|
11
|
+
# overridable methods. For example, `RDF::Enumerable#count` has the
|
12
|
+
# aliases `#size` and `#length`. Normally if implementing classes were
|
13
|
+
# to override the default method, the aliased methods would still be
|
14
|
+
# bound to the mixin's original reference implementation rather than the
|
15
|
+
# new overridden method. Mixing in this module into the implementing
|
16
|
+
# class fixes this problem.
|
17
|
+
#
|
18
|
+
# @example Using late-bound aliasing in a module
|
19
|
+
# module MyModule
|
20
|
+
# extend RDF::Util::Aliasing::LateBound
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# @example Using late-bound aliasing in a class
|
24
|
+
# class MyClass
|
25
|
+
# extend RDF::Util::Aliasing::LateBound
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @see http://en.wikipedia.org/wiki/Name_binding
|
29
|
+
# @since 0.2.0
|
30
|
+
module LateBound
|
31
|
+
##
|
32
|
+
# Makes `new_name` a late-bound alias of the method `old_name`.
|
33
|
+
#
|
34
|
+
# @example Aliasing the `#count` method to `#size` and `#length`
|
35
|
+
# alias_method :size, :count
|
36
|
+
# alias_method :length, :count
|
37
|
+
#
|
38
|
+
# @param [Symbol, #to_sym] new_name
|
39
|
+
# @param [Symbol, #to_sym] old_name
|
40
|
+
# @return [void]
|
41
|
+
# @see http://ruby-doc.org/core/classes/Module.html#M001653
|
42
|
+
def alias_method(new_name, old_name)
|
43
|
+
new_name, old_name = new_name.to_sym, old_name.to_sym
|
44
|
+
|
45
|
+
class_eval(<<-EOF)
|
46
|
+
def #{new_name}(*args, &block)
|
47
|
+
#{old_name}(*args, &block)
|
48
|
+
end
|
49
|
+
EOF
|
50
|
+
|
51
|
+
# NOTE: the following eval-less (and hence slightly less evil)
|
52
|
+
# implementation only works on Ruby 1.8.7+ due to the |&block|
|
53
|
+
# syntax that was introduced in 1.9 and then backported to 1.8.7;
|
54
|
+
# it is a syntax error in earlier versions of Ruby:
|
55
|
+
#self.__send__(:define_method, new_name) do |*args, &block|
|
56
|
+
# __send__(old_name, *args, &block)
|
57
|
+
#end
|
58
|
+
|
59
|
+
return self
|
60
|
+
end
|
61
|
+
end # LateBound
|
62
|
+
end # Aliasing
|
63
|
+
end; end # RDF::Util
|