active-triples 0.10.2 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/CHANGES.md +17 -11
- data/README.md +72 -39
- data/lib/active_triples/configurable.rb +6 -1
- data/lib/active_triples/list.rb +1 -4
- data/lib/active_triples/nested_attributes.rb +10 -7
- data/lib/active_triples/persistable.rb +13 -0
- data/lib/active_triples/persistence_strategies/parent_strategy.rb +47 -34
- data/lib/active_triples/persistence_strategies/persistence_strategy.rb +14 -1
- data/lib/active_triples/properties.rb +19 -4
- data/lib/active_triples/property_builder.rb +4 -4
- data/lib/active_triples/rdf_source.rb +142 -189
- data/lib/active_triples/relation.rb +307 -156
- data/lib/active_triples/util/buffered_transaction.rb +126 -0
- data/lib/active_triples/util/extended_bounded_description.rb +75 -0
- data/lib/active_triples/version.rb +1 -1
- data/spec/active_triples/configurable_spec.rb +35 -7
- data/spec/active_triples/identifiable_spec.rb +19 -6
- data/spec/active_triples/list_spec.rb +15 -7
- data/spec/active_triples/nested_attributes_spec.rb +12 -10
- data/spec/active_triples/persistable_spec.rb +0 -4
- data/spec/active_triples/persistence_strategies/parent_strategy_spec.rb +57 -10
- data/spec/active_triples/rdf_source_spec.rb +137 -97
- data/spec/active_triples/relation_spec.rb +436 -132
- data/spec/active_triples/resource_spec.rb +8 -23
- data/spec/active_triples/util/buffered_transaction_spec.rb +187 -0
- data/spec/active_triples/util/extended_bounded_description_spec.rb +98 -0
- data/spec/integration/reciprocal_properties_spec.rb +10 -10
- data/spec/support/matchers.rb +13 -1
- metadata +7 -3
@@ -24,7 +24,7 @@ module ActiveTriples
|
|
24
24
|
# @return [Boolean] true if the resource was sucessfully destroyed
|
25
25
|
def destroy(&block)
|
26
26
|
yield if block_given?
|
27
|
-
|
27
|
+
|
28
28
|
persist!
|
29
29
|
@destroyed = true
|
30
30
|
end
|
@@ -57,6 +57,19 @@ module ActiveTriples
|
|
57
57
|
raise NotImplementedError, 'Abstract method #persist! is unimplemented'
|
58
58
|
end
|
59
59
|
|
60
|
+
##
|
61
|
+
# @param graph [RDF::Graph]
|
62
|
+
# @return [RDF::Graph]
|
63
|
+
def graph=(graph)
|
64
|
+
@graph = graph
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# @return [RDF::Graph]
|
69
|
+
def graph
|
70
|
+
@graph ||= RDF::Graph.new
|
71
|
+
end
|
72
|
+
|
60
73
|
##
|
61
74
|
# @abstract Clear out any old assertions in the datastore / repository
|
62
75
|
# about this node or statement thus preparing to receive the updated
|
@@ -8,10 +8,19 @@ module ActiveTriples
|
|
8
8
|
#
|
9
9
|
# Collaborates closely with ActiveTriples::Reflection
|
10
10
|
#
|
11
|
-
#
|
11
|
+
# @example define properties at the class level
|
12
12
|
#
|
13
13
|
# property :title, predicate: RDF::DC.title, class_name: ResourceClass
|
14
14
|
#
|
15
|
+
# @example using property setters & getters
|
16
|
+
# resource.property :title, predicate: RDF::DC.title,
|
17
|
+
# class_name: ResourceClass
|
18
|
+
#
|
19
|
+
# resource.title = 'Comet in Moominland'
|
20
|
+
#
|
21
|
+
# resource.title # => ['Comet in Moominland']
|
22
|
+
# resource.title(literal: true) # => [RDF::Literal('Comet in Moominland')]
|
23
|
+
#
|
15
24
|
# @see {ActiveTriples::Reflection}
|
16
25
|
# @see {ActiveTriples::PropertyBuilder}
|
17
26
|
module Properties
|
@@ -54,9 +63,15 @@ module ActiveTriples
|
|
54
63
|
#
|
55
64
|
# @return [Array<RDF::URI>]
|
56
65
|
def unregistered_predicates
|
57
|
-
|
58
|
-
|
59
|
-
|
66
|
+
registered_preds = registered_predicates << RDF.type
|
67
|
+
unregistered_preds = []
|
68
|
+
|
69
|
+
query(subject: rdf_subject) do |stmt|
|
70
|
+
unregistered_preds << stmt.predicate unless
|
71
|
+
registered_preds.include? stmt.predicate
|
72
|
+
end
|
73
|
+
|
74
|
+
unregistered_preds
|
60
75
|
end
|
61
76
|
|
62
77
|
public
|
@@ -42,7 +42,7 @@ module ActiveTriples
|
|
42
42
|
raise ArgumentError, "property names must be a Symbol" unless
|
43
43
|
name.kind_of?(Symbol)
|
44
44
|
|
45
|
-
options[:predicate] = RDF::URI.
|
45
|
+
options[:predicate] = RDF::URI.intern(options[:predicate])
|
46
46
|
raise ArgumentError, "must provide an RDF::URI to :predicate" unless
|
47
47
|
options[:predicate].valid?
|
48
48
|
|
@@ -67,15 +67,15 @@ module ActiveTriples
|
|
67
67
|
def self.define_readers(mixin, name)
|
68
68
|
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
69
69
|
def #{name}(*args)
|
70
|
-
get_values(:#{name})
|
70
|
+
get_values(:#{name}, *args)
|
71
71
|
end
|
72
72
|
CODE
|
73
73
|
end
|
74
74
|
|
75
75
|
def self.define_id_reader(mixin, name)
|
76
76
|
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
77
|
-
def #{name}_ids(*
|
78
|
-
get_values(:#{name}, :
|
77
|
+
def #{name}_ids(*)
|
78
|
+
get_values(:#{name}, cast: false)
|
79
79
|
end
|
80
80
|
CODE
|
81
81
|
end
|
@@ -75,8 +75,8 @@ module ActiveTriples
|
|
75
75
|
define_model_callbacks :persist
|
76
76
|
end
|
77
77
|
|
78
|
-
delegate :query, :each, :load!, :count, :has_statement?, :
|
79
|
-
delegate :to_base, :term?, :escape, :
|
78
|
+
delegate :query, :each, :load!, :count, :has_statement?, to: :graph
|
79
|
+
delegate :to_base, :term?, :escape, to: :to_term
|
80
80
|
|
81
81
|
##
|
82
82
|
# Initialize an instance of this resource class. Defaults to a
|
@@ -93,21 +93,19 @@ module ActiveTriples
|
|
93
93
|
resource_uri = args.shift unless args.first.is_a?(Hash)
|
94
94
|
@rdf_subject = get_uri(resource_uri) if resource_uri
|
95
95
|
|
96
|
-
|
96
|
+
if args.first.is_a?(Hash) || args.empty?
|
97
|
+
set_persistence_strategy(RepositoryStrategy)
|
98
|
+
else
|
97
99
|
set_persistence_strategy(ParentStrategy)
|
98
100
|
persistence_strategy.parent = args.shift
|
99
|
-
else
|
100
|
-
set_persistence_strategy(RepositoryStrategy)
|
101
101
|
end
|
102
102
|
|
103
|
-
|
103
|
+
persistence_strategy.graph = RDF::Graph.new(*args, &block)
|
104
104
|
reload
|
105
105
|
|
106
106
|
# Append type to graph if necessary.
|
107
107
|
Array.wrap(self.class.type).each do |type|
|
108
|
-
unless
|
109
|
-
self.get_values(:type) << type
|
110
|
-
end
|
108
|
+
get_values(:type) << type unless get_values(:type).include?(type)
|
111
109
|
end
|
112
110
|
end
|
113
111
|
|
@@ -128,12 +126,12 @@ module ActiveTriples
|
|
128
126
|
##
|
129
127
|
# Gives a hash containing both the registered and unregistered attributes of
|
130
128
|
# the resource. Unregistered attributes are given with full URIs.
|
131
|
-
#
|
132
|
-
# @example
|
129
|
+
#
|
130
|
+
# @example
|
133
131
|
# class WithProperties
|
134
132
|
# include ActiveTriples::RDFSource
|
135
133
|
# property :title, predicate: RDF::Vocab::DC.title
|
136
|
-
# property :creator, predicate: RDF::Vocab::DC.creator,
|
134
|
+
# property :creator, predicate: RDF::Vocab::DC.creator,
|
137
135
|
# class_name: 'Agent'
|
138
136
|
# end
|
139
137
|
#
|
@@ -146,7 +144,7 @@ module ActiveTriples
|
|
146
144
|
#
|
147
145
|
# resource.creator.build
|
148
146
|
# resource.title << ['Comet in Moominland', 'Christmas in Moominvalley']
|
149
|
-
|
147
|
+
#
|
150
148
|
# resource.attributes
|
151
149
|
# # => {"id"=>"g47123700054720",
|
152
150
|
# # "title"=>["Comet in Moominland", "Christmas in Moominvalley"],
|
@@ -171,25 +169,33 @@ module ActiveTriples
|
|
171
169
|
end
|
172
170
|
|
173
171
|
def attributes=(values)
|
174
|
-
raise
|
172
|
+
raise(ArgumentError, "values must be a Hash. Got: #{values.class}") unless
|
173
|
+
values.is_a? Hash
|
174
|
+
|
175
175
|
values = values.with_indifferent_access
|
176
176
|
id = values.delete(:id)
|
177
|
-
set_subject!(id) if node?
|
177
|
+
set_subject!(id) if node? && id && get_uri(id).uri?
|
178
|
+
|
178
179
|
values.each do |key, value|
|
179
180
|
if reflections.has_property?(key)
|
180
|
-
set_value(
|
181
|
-
elsif nested_attributes_options
|
181
|
+
set_value(key, value)
|
182
|
+
elsif nested_attributes_options
|
183
|
+
.keys.any? { |k| key == "#{k}_attributes" }
|
182
184
|
send("#{key}=".to_sym, value)
|
183
185
|
else
|
184
|
-
raise ArgumentError, "No association found for name `#{key}'.
|
186
|
+
raise ArgumentError, "No association found for name `#{key}'. " \
|
187
|
+
'Has it been defined yet?'
|
185
188
|
end
|
186
189
|
end
|
187
190
|
end
|
188
191
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
+
##
|
193
|
+
# @return [Hash]
|
194
|
+
def serializable_hash(*)
|
195
|
+
attrs = fields.map(&:to_s) << 'id'
|
196
|
+
hash = super(only: attrs)
|
192
197
|
unregistered_predicates.map { |uri| hash[uri.to_s] = get_values(uri) }
|
198
|
+
|
193
199
|
hash
|
194
200
|
end
|
195
201
|
|
@@ -204,7 +210,7 @@ module ActiveTriples
|
|
204
210
|
# @param args [Array<Object>]
|
205
211
|
# @return [String]
|
206
212
|
def dump(*args)
|
207
|
-
if args.first == :jsonld
|
213
|
+
if args.first == :jsonld && respond_to?(:jsonld_context)
|
208
214
|
args << {} unless args.last.is_a?(Hash)
|
209
215
|
args.last[:context] ||= jsonld_context
|
210
216
|
end
|
@@ -214,17 +220,23 @@ module ActiveTriples
|
|
214
220
|
##
|
215
221
|
# Delegate parent to the persistence strategy if possible
|
216
222
|
#
|
217
|
-
# @todo establish a better pattern for this. `#parent` has been a public
|
223
|
+
# @todo establish a better pattern for this. `#parent` has been a public
|
218
224
|
# method in the past, but it's probably time to deprecate it.
|
219
225
|
def parent
|
220
|
-
|
226
|
+
return persistence_strategy.parent if
|
227
|
+
persistence_strategy.respond_to?(:parent)
|
228
|
+
|
229
|
+
nil
|
221
230
|
end
|
222
231
|
|
223
232
|
##
|
224
233
|
# @todo deprecate/remove
|
225
234
|
# @see #parent
|
226
235
|
def parent=(parent)
|
227
|
-
|
236
|
+
return persistence_strategy.parent = parent if
|
237
|
+
persistence_strategy.respond_to?(:parent=)
|
238
|
+
|
239
|
+
nil
|
228
240
|
end
|
229
241
|
|
230
242
|
##
|
@@ -237,15 +249,15 @@ module ActiveTriples
|
|
237
249
|
def rdf_subject
|
238
250
|
@rdf_subject ||= RDF::Node.new
|
239
251
|
end
|
240
|
-
|
252
|
+
alias to_term rdf_subject
|
241
253
|
|
242
254
|
##
|
243
255
|
# Returns `nil` as the `graph_name`. This behavior mimics an `RDF::Graph`
|
244
256
|
# with no graph name, or one without named graph support.
|
245
257
|
#
|
246
|
-
# @note: it's possible to think of an `RDFSource` as "supporting named
|
258
|
+
# @note: it's possible to think of an `RDFSource` as "supporting named
|
247
259
|
# graphs" in the sense that the `#rdf_subject` is an implied graph name.
|
248
|
-
# For RDF.rb's purposes, however, it has a nil graph name: when
|
260
|
+
# For RDF.rb's purposes, however, it has a nil graph name: when
|
249
261
|
# enumerating statements, we treat them as triples.
|
250
262
|
#
|
251
263
|
# @return [nil]
|
@@ -253,7 +265,7 @@ module ActiveTriples
|
|
253
265
|
def graph_name
|
254
266
|
nil
|
255
267
|
end
|
256
|
-
|
268
|
+
|
257
269
|
##
|
258
270
|
# @return [String] A string identifier for the resource; '' if the
|
259
271
|
# resource is a node
|
@@ -299,12 +311,15 @@ module ActiveTriples
|
|
299
311
|
end
|
300
312
|
|
301
313
|
def type
|
302
|
-
|
314
|
+
get_values(:type)
|
303
315
|
end
|
304
316
|
|
305
317
|
def type=(type)
|
306
|
-
raise
|
307
|
-
|
318
|
+
raise(ArgumentError,
|
319
|
+
"Type must be an RDF::URI. Got: #{type.class}, #{type}") unless
|
320
|
+
type.is_a? RDF::URI
|
321
|
+
|
322
|
+
update(RDF::Statement.new(rdf_subject, RDF.type, type))
|
308
323
|
end
|
309
324
|
|
310
325
|
##
|
@@ -322,16 +337,6 @@ module ActiveTriples
|
|
322
337
|
node? ? [] : [rdf_subject.to_s]
|
323
338
|
end
|
324
339
|
|
325
|
-
##
|
326
|
-
# @return [Array<RDF::URI>] a group of properties to use for default labels.
|
327
|
-
def default_labels
|
328
|
-
[RDF::SKOS.prefLabel,
|
329
|
-
RDF::DC.title,
|
330
|
-
RDF::RDFS.label,
|
331
|
-
RDF::SKOS.altLabel,
|
332
|
-
RDF::SKOS.hiddenLabel]
|
333
|
-
end
|
334
|
-
|
335
340
|
##
|
336
341
|
# Load data from the #rdf_subject URI. Retrieved data will be
|
337
342
|
# parsed into the Resource's graph from available RDF::Readers
|
@@ -353,15 +358,15 @@ module ActiveTriples
|
|
353
358
|
# @yieldparam [ActiveTriples::RDFSource] resource self
|
354
359
|
#
|
355
360
|
# @return [ActiveTriples::RDFSource] self
|
356
|
-
def fetch(*args, &
|
361
|
+
def fetch(*args, &_block)
|
357
362
|
begin
|
358
363
|
load(rdf_subject, *args)
|
359
364
|
rescue => e
|
360
365
|
if block_given?
|
361
366
|
yield(self)
|
362
367
|
else
|
363
|
-
raise "#{self} is a blank node;
|
364
|
-
|
368
|
+
raise "#{self} is a blank node; " \
|
369
|
+
'Cannot fetch a resource without a URI' if node?
|
365
370
|
raise e
|
366
371
|
end
|
367
372
|
end
|
@@ -404,12 +409,12 @@ module ActiveTriples
|
|
404
409
|
#
|
405
410
|
# @overload set_value(subject, property, values)
|
406
411
|
# Updates the values for the property, using the given term as the subject
|
407
|
-
#
|
408
|
-
# @param [RDF::Term] subject the term representing the
|
412
|
+
#
|
413
|
+
# @param [RDF::Term] subject the term representing the
|
409
414
|
# @param [RDF::Term, #to_sym] property a symbol with the property name
|
410
415
|
# or an RDF::Term to use as a predicate.
|
411
416
|
# @param [Array<RDF::Resource>, RDF::Resource] values an array of values
|
412
|
-
# or a single value. If not an {RDF::Resource}, the values will be
|
417
|
+
# or a single value. If not an {RDF::Resource}, the values will be
|
413
418
|
# coerced to an {RDF::Literal} or {RDF::Node} by {RDF::Statement}
|
414
419
|
#
|
415
420
|
# @return [ActiveTriples::Relation] an array {Relation} containing the
|
@@ -421,16 +426,17 @@ module ActiveTriples
|
|
421
426
|
# @note This method will delete existing statements with the given
|
422
427
|
# subject and predicate from the graph
|
423
428
|
#
|
424
|
-
# @see http://www.rubydoc.info/github/ruby-rdf/rdf/RDF/Statement For
|
425
|
-
# documentation on {RDF::Statement} and the handling of
|
429
|
+
# @see http://www.rubydoc.info/github/ruby-rdf/rdf/RDF/Statement For
|
430
|
+
# documentation on {RDF::Statement} and the handling of
|
426
431
|
# non-{RDF::Resource} values.
|
427
432
|
def set_value(*args)
|
428
433
|
# Add support for legacy 3-parameter syntax
|
429
434
|
if args.length > 3 || args.length < 2
|
430
|
-
raise ArgumentError,
|
435
|
+
raise ArgumentError,
|
436
|
+
"wrong number of arguments (#{args.length} for 2-3)"
|
431
437
|
end
|
432
438
|
values = args.pop
|
433
|
-
|
439
|
+
get_values(*args).set(values)
|
434
440
|
end
|
435
441
|
|
436
442
|
##
|
@@ -442,7 +448,7 @@ module ActiveTriples
|
|
442
448
|
# properties directly on this RDFSource, is:
|
443
449
|
# get_values(property)
|
444
450
|
#
|
445
|
-
# @overload get_values(property)
|
451
|
+
# @overload get_values(property)
|
446
452
|
# Gets values on the RDFSource for the given property
|
447
453
|
# @param [String, #to_term] property the property for the values
|
448
454
|
#
|
@@ -452,22 +458,25 @@ module ActiveTriples
|
|
452
458
|
# @param [RDF::Term] uri the term to use as the subject
|
453
459
|
# @param [String, #to_term] property the property for the values
|
454
460
|
#
|
455
|
-
# @return [ActiveTriples::Relation] an array {Relation} containing the
|
461
|
+
# @return [ActiveTriples::Relation] an array {Relation} containing the
|
456
462
|
# values of the property
|
457
463
|
#
|
458
|
-
# @todo should this raise an error when the property argument is not an
|
464
|
+
# @todo should this raise an error when the property argument is not an
|
459
465
|
# {RDF::Term} or a registered property key?
|
460
466
|
def get_values(*args)
|
461
|
-
|
467
|
+
@relation_cache ||= {}
|
468
|
+
rel = Relation.new(self, args)
|
469
|
+
@relation_cache["#{rel.send(:rdf_subject)}/#{rel.property}/#{rel.rel_args}"] ||= rel
|
470
|
+
@relation_cache["#{rel.send(:rdf_subject)}/#{rel.property}/#{rel.rel_args}"]
|
462
471
|
end
|
463
472
|
|
464
473
|
##
|
465
474
|
# Returns an array of values belonging to the property requested. Elements
|
466
475
|
# in the array may RdfResource objects or a valid datatype.
|
467
|
-
#
|
476
|
+
#
|
468
477
|
# @param [RDF::Term, :to_s] term_or_property
|
469
478
|
def [](term_or_property)
|
470
|
-
|
479
|
+
get_values(term_or_property)
|
471
480
|
end
|
472
481
|
|
473
482
|
##
|
@@ -475,23 +484,21 @@ module ActiveTriples
|
|
475
484
|
#
|
476
485
|
# @param [RDF::Term, :to_s] term_or_property
|
477
486
|
# @param [Array<RDF::Resource>, RDF::Resource] values an array of values
|
478
|
-
# or a single value to set the property to.
|
487
|
+
# or a single value to set the property to.
|
479
488
|
#
|
480
|
-
# @note This method will delete existing statements with the correct
|
489
|
+
# @note This method will delete existing statements with the correct
|
481
490
|
# subject and predicate from the graph
|
482
491
|
def []=(term_or_property, value)
|
483
492
|
self[term_or_property].set(value)
|
484
493
|
end
|
485
494
|
|
486
495
|
##
|
496
|
+
# @deprecated for removal in 1.0; use `#get_values` instead.
|
487
497
|
# @see #get_values
|
488
|
-
# @todo deprecate and remove? this is an alias to `#get_values`
|
489
498
|
def get_relation(args)
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
@relation_cache["#{rel.send(:rdf_subject)}/#{rel.property}/#{rel.rel_args}"] ||= rel
|
494
|
-
@relation_cache["#{rel.send(:rdf_subject)}/#{rel.property}/#{rel.rel_args}"]
|
499
|
+
warn 'DEPRECATION: `ActiveTriples::RDFSource#get_relation` will be' \
|
500
|
+
'removed in 1.0; use `#get_values` instead.'
|
501
|
+
get_values(*args)
|
495
502
|
end
|
496
503
|
|
497
504
|
##
|
@@ -508,13 +515,12 @@ module ActiveTriples
|
|
508
515
|
# the param. Otherwise it creates a URI for the resource and
|
509
516
|
# rebuilds the graph with the updated URI.
|
510
517
|
def set_subject!(uri_or_str)
|
511
|
-
raise
|
518
|
+
raise 'Refusing to update URI when one is already assigned!' unless
|
512
519
|
node? || rdf_subject == RDF::URI(nil)
|
513
|
-
|
514
|
-
return
|
515
|
-
|
516
|
-
|
517
|
-
|
520
|
+
|
521
|
+
return if uri_or_str.nil? ||
|
522
|
+
(uri_or_str.to_s.empty? && !uri_or_str.is_a?(RDF::URI))
|
523
|
+
|
518
524
|
new_subject = get_uri(uri_or_str)
|
519
525
|
rewrite_statement_uris(rdf_subject, new_subject)
|
520
526
|
|
@@ -526,7 +532,7 @@ module ActiveTriples
|
|
526
532
|
#
|
527
533
|
# @return [Boolean]
|
528
534
|
def new_record?
|
529
|
-
|
535
|
+
!persisted?
|
530
536
|
end
|
531
537
|
|
532
538
|
def mark_for_destruction
|
@@ -539,126 +545,73 @@ module ActiveTriples
|
|
539
545
|
|
540
546
|
private
|
541
547
|
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
def graph
|
552
|
-
@graph
|
553
|
-
end
|
554
|
-
|
555
|
-
##
|
556
|
-
|
557
|
-
# Lists fields registered as properties on the object.
|
558
|
-
#
|
559
|
-
# @return [Array<Symbol>] the list of registered properties.
|
560
|
-
def fields
|
561
|
-
properties.keys.map(&:to_sym).reject{ |x| x == :type }
|
562
|
-
end
|
548
|
+
##
|
549
|
+
# @return [Array<RDF::URI>] a group of properties to use for default labels.
|
550
|
+
def default_labels
|
551
|
+
[RDF::Vocab::SKOS.prefLabel,
|
552
|
+
RDF::Vocab::DC.title,
|
553
|
+
RDF::RDFS.label,
|
554
|
+
RDF::Vocab::SKOS.altLabel,
|
555
|
+
RDF::Vocab::SKOS.hiddenLabel]
|
556
|
+
end
|
563
557
|
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
558
|
+
##
|
559
|
+
# Rewrites the subject and object of each statement containing
|
560
|
+
# `old_subject` in either position. Used when setting the subject to
|
561
|
+
# remove the placeholder blank node subjects.
|
562
|
+
#
|
563
|
+
# @param [RDF::Term] old_subject
|
564
|
+
# @param [RDF::Term] new_subject
|
565
|
+
# @return [void]
|
566
|
+
def rewrite_statement_uris(old_subject, new_subject)
|
567
|
+
graph.query(subject: old_subject).each do |st|
|
568
|
+
graph.delete(st)
|
571
569
|
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
# @return [Array<RDF::URI>]
|
576
|
-
def registered_predicates
|
577
|
-
properties.values.map { |config| config.predicate }
|
570
|
+
st.subject = new_subject
|
571
|
+
st.object = new_subject if st.object == old_subject
|
572
|
+
graph.insert(st)
|
578
573
|
end
|
579
574
|
|
580
|
-
|
581
|
-
|
582
|
-
# mapped to any property or accessor methods.
|
583
|
-
#
|
584
|
-
# @return [Array<RDF::URI>]
|
585
|
-
def unregistered_predicates
|
586
|
-
registered_preds = registered_predicates
|
587
|
-
registered_preds << RDF.type
|
588
|
-
unregistered_preds = []
|
589
|
-
|
590
|
-
query(subject: rdf_subject) do |stmt|
|
591
|
-
unregistered_preds << stmt.predicate unless
|
592
|
-
registered_preds.include? stmt.predicate
|
593
|
-
end
|
575
|
+
graph.query(object: old_subject).each do |st|
|
576
|
+
graph.delete(st)
|
594
577
|
|
595
|
-
|
578
|
+
st.object = new_subject
|
579
|
+
graph.insert(st)
|
596
580
|
end
|
581
|
+
end
|
597
582
|
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
583
|
+
##
|
584
|
+
# Takes a URI or String and aggressively tries to convert it into
|
585
|
+
# an RDF term. If a String is given, first tries to interpret it
|
586
|
+
# as a valid URI, then tries to append it to base_uri. Finally,
|
587
|
+
# raises an error if no valid term can be built.
|
588
|
+
#
|
589
|
+
# The argument must be an RDF::Node, an object that responds to
|
590
|
+
# #to_uri, a String that represents a valid URI, or a String that
|
591
|
+
# appends to the Resource's base_uri to create a valid URI.
|
592
|
+
#
|
593
|
+
# @TODO: URI.scheme_list is naive and incomplete. Find a better
|
594
|
+
# way to check for an existing scheme.
|
595
|
+
#
|
596
|
+
# @param uri_or_str [RDF::Resource, String]
|
597
|
+
#
|
598
|
+
# @return [RDF::Resource] A term
|
599
|
+
# @raise [RuntimeError] no valid RDF term could be built
|
600
|
+
def get_uri(uri_or_str)
|
601
|
+
return uri_or_str.to_term if uri_or_str.respond_to? :to_term
|
605
602
|
|
606
|
-
|
607
|
-
|
608
|
-
# `old_subject` in either position. Used when setting the subject to
|
609
|
-
# remove the placeholder blank node subjects.
|
610
|
-
#
|
611
|
-
# @param [RDF::Term] old_subject
|
612
|
-
# @param [RDF::Term] new_subject
|
613
|
-
# @return [void]
|
614
|
-
def rewrite_statement_uris(old_subject, new_subject)
|
615
|
-
graph.transaction(mutable: true) do |tx|
|
616
|
-
tx.query(subject: old_subject).each do |st|
|
617
|
-
tx.delete(st)
|
618
|
-
|
619
|
-
st.subject = new_subject
|
620
|
-
st.object = new_subject if st.object == old_subject
|
621
|
-
tx.insert(st)
|
622
|
-
end
|
623
|
-
|
624
|
-
tx.query(object: old_subject).each do |st|
|
625
|
-
tx.delete(st)
|
626
|
-
|
627
|
-
st.object = new_subject
|
628
|
-
tx.insert(st)
|
629
|
-
end
|
630
|
-
end
|
631
|
-
end
|
603
|
+
uri_or_node = RDF::Resource.new(uri_or_str)
|
604
|
+
return uri_or_node if uri_or_node.valid?
|
632
605
|
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
# as a valid URI, then tries to append it to base_uri. Finally,
|
637
|
-
# raises an error if no valid term can be built.
|
638
|
-
#
|
639
|
-
# The argument must be an RDF::Node, an object that responds to
|
640
|
-
# #to_uri, a String that represents a valid URI, or a String that
|
641
|
-
# appends to the Resource's base_uri to create a valid URI.
|
642
|
-
#
|
643
|
-
# @TODO: URI.scheme_list is naive and incomplete. Find a better
|
644
|
-
# way to check for an existing scheme.
|
645
|
-
#
|
646
|
-
# @param uri_or_str [RDF::Resource, String]
|
647
|
-
#
|
648
|
-
# @return [RDF::Resource] A term
|
649
|
-
# @raise [RuntimeError] no valid RDF term could be built
|
650
|
-
def get_uri(uri_or_str)
|
651
|
-
return uri_or_str.to_term if uri_or_str.respond_to? :to_term
|
652
|
-
return uri_or_str if uri_or_str.is_a? RDF::Node
|
653
|
-
uri_or_node = RDF::Resource.new(uri_or_str)
|
654
|
-
return uri_or_node if uri_or_node.valid?
|
655
|
-
uri_or_str = uri_or_str.to_s
|
656
|
-
return RDF::URI(base_uri.to_s) / uri_or_str if base_uri && !uri_or_str.start_with?(base_uri.to_s)
|
657
|
-
raise RuntimeError, "could not make a valid RDF::URI from #{uri_or_str}"
|
658
|
-
end
|
606
|
+
uri_or_str = uri_or_str.to_s
|
607
|
+
return RDF::URI.intern(base_uri.to_s) / uri_or_str if
|
608
|
+
base_uri && !uri_or_str.start_with?(base_uri.to_s)
|
659
609
|
|
660
|
-
|
610
|
+
raise "could not make a valid RDF::URI from #{uri_or_str}"
|
611
|
+
end
|
661
612
|
|
613
|
+
##
|
614
|
+
# Class methods for RDFSource, included via ActiveSupport
|
662
615
|
module ClassMethods
|
663
616
|
##
|
664
617
|
# Adapter for a consistent interface for creating a new Resource
|
@@ -679,10 +632,8 @@ module ActiveTriples
|
|
679
632
|
# @param [ActiveTriples::Schema, #properties] schema A schema to apply.
|
680
633
|
# @param [#apply!] strategy A strategy for applying. Defaults
|
681
634
|
# to ActiveTriples::ExtensionStrategy
|
682
|
-
def apply_schema(schema, strategy=ActiveTriples::ExtensionStrategy)
|
683
|
-
schema.properties.each
|
684
|
-
strategy.apply(self, property)
|
685
|
-
end
|
635
|
+
def apply_schema(schema, strategy = ActiveTriples::ExtensionStrategy)
|
636
|
+
schema.properties.each { |property| strategy.apply(self, property) }
|
686
637
|
end
|
687
638
|
|
688
639
|
##
|
@@ -697,7 +648,8 @@ module ActiveTriples
|
|
697
648
|
# persisted, false will be returned presenting
|
698
649
|
# a window of opportunity for an ID clash.
|
699
650
|
def id_persisted?(test_id)
|
700
|
-
rdf_subject =
|
651
|
+
rdf_subject = new(test_id).rdf_subject
|
652
|
+
|
701
653
|
ActiveTriples::Repositories.has_subject?(rdf_subject)
|
702
654
|
end
|
703
655
|
|
@@ -713,8 +665,9 @@ module ActiveTriples
|
|
713
665
|
# persisted, false will be returned presenting
|
714
666
|
# a window of opportunity for an ID clash.
|
715
667
|
def uri_persisted?(test_uri)
|
716
|
-
|
717
|
-
|
668
|
+
test_uri = RDF::URI.intern(test_uri) unless test_uri.is_a?(RDF::URI)
|
669
|
+
|
670
|
+
ActiveTriples::Repositories.has_subject?(test_uri)
|
718
671
|
end
|
719
672
|
end
|
720
673
|
end
|