active-triples 0.6.1 → 0.7.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.
- checksums.yaml +4 -4
- data/.travis.yml +7 -3
- data/CHANGES.md +20 -0
- data/Gemfile +2 -0
- data/README.md +21 -17
- data/lib/active_triples.rb +6 -1
- data/lib/active_triples/configurable.rb +18 -19
- data/lib/active_triples/configuration.rb +72 -0
- data/lib/active_triples/configuration/item.rb +20 -0
- data/lib/active_triples/configuration/item_factory.rb +27 -0
- data/lib/active_triples/configuration/merge_item.rb +14 -0
- data/lib/active_triples/identifiable.rb +3 -3
- data/lib/active_triples/list.rb +6 -4
- data/lib/active_triples/property_builder.rb +10 -2
- data/lib/active_triples/rdf_source.rb +582 -0
- data/lib/active_triples/{term.rb → relation.rb} +40 -15
- data/lib/active_triples/resource.rb +9 -534
- data/lib/active_triples/version.rb +1 -1
- data/spec/active_triples/configurable_spec.rb +18 -2
- data/spec/active_triples/configuration_spec.rb +59 -0
- data/spec/active_triples/identifiable_spec.rb +12 -11
- data/spec/active_triples/list_spec.rb +13 -7
- data/spec/active_triples/nested_attributes_spec.rb +12 -6
- data/spec/active_triples/properties_spec.rb +19 -1
- data/spec/active_triples/rdf_source_spec.rb +5 -0
- data/spec/active_triples/{term_spec.rb → relation_spec.rb} +9 -7
- data/spec/active_triples/repositories_spec.rb +7 -4
- data/spec/active_triples/resource_spec.rb +24 -26
- data/spec/active_triples_spec.rb +9 -0
- data/spec/pragmatic_context_spec.rb +6 -4
- data/spec/spec_helper.rb +1 -0
- metadata +14 -5
@@ -1,23 +1,34 @@
|
|
1
1
|
require 'active_support/core_ext/module/delegation'
|
2
2
|
|
3
3
|
module ActiveTriples
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
##
|
5
|
+
# A `Relation` represents the values of a specific property/predicate on an
|
6
|
+
# {RDFSource}. Each relation is a set ({Array}) of {RDF::Terms} that are
|
7
|
+
# objects in the of source's triples of the form:
|
8
|
+
#
|
9
|
+
# <{#parent}> <{#predicate}> [term] .
|
10
|
+
#
|
11
|
+
# Relations, then, express n binary relationships between the parent node and
|
12
|
+
# a term.
|
13
|
+
#
|
14
|
+
# @see RDF::Term
|
15
|
+
class Relation
|
16
|
+
|
17
|
+
attr_accessor :parent, :value_arguments, :node_cache, :rel_args
|
7
18
|
attr_reader :reflections
|
8
19
|
|
9
20
|
delegate *(Array.public_instance_methods - [:send, :__send__, :__id__, :class, :object_id] + [:as_json]), :to => :result
|
10
21
|
|
11
|
-
def initialize(
|
12
|
-
self.parent =
|
13
|
-
@reflections =
|
14
|
-
self.
|
22
|
+
def initialize(parent_source, value_arguments)
|
23
|
+
self.parent = parent_source
|
24
|
+
@reflections = parent_source.reflections
|
25
|
+
self.rel_args ||= {}
|
15
26
|
self.value_arguments = value_arguments
|
16
27
|
end
|
17
28
|
|
18
29
|
def value_arguments=(value_args)
|
19
30
|
if value_args.kind_of?(Array) && value_args.last.kind_of?(Hash)
|
20
|
-
self.
|
31
|
+
self.rel_args = value_args.pop
|
21
32
|
end
|
22
33
|
@value_arguments = value_args
|
23
34
|
end
|
@@ -36,7 +47,7 @@ module ActiveTriples
|
|
36
47
|
|
37
48
|
def set(values)
|
38
49
|
values = [values].compact unless values.kind_of?(Array)
|
39
|
-
values = values.to_a if values.class ==
|
50
|
+
values = values.to_a if values.class == Relation
|
40
51
|
empty_property
|
41
52
|
values.each do |val|
|
42
53
|
set_value(val)
|
@@ -91,7 +102,7 @@ module ActiveTriples
|
|
91
102
|
end
|
92
103
|
|
93
104
|
def property_config
|
94
|
-
return type_property if (property == RDF.type || property.to_s == "type") && (!reflections.kind_of?(
|
105
|
+
return type_property if (property == RDF.type || property.to_s == "type") && (!reflections.kind_of?(RDFSource) || !reflections.reflect_on_property(property))
|
95
106
|
reflections.reflect_on_property(property)
|
96
107
|
end
|
97
108
|
|
@@ -116,7 +127,7 @@ module ActiveTriples
|
|
116
127
|
object = val
|
117
128
|
val = val.resource if val.respond_to?(:resource)
|
118
129
|
val = value_to_node(val)
|
119
|
-
if val.kind_of?
|
130
|
+
if val.kind_of? RDFSource
|
120
131
|
node_cache[val.rdf_subject] = nil
|
121
132
|
add_child_node(val, object)
|
122
133
|
return
|
@@ -178,13 +189,13 @@ module ActiveTriples
|
|
178
189
|
end
|
179
190
|
|
180
191
|
def cast?
|
181
|
-
return true unless property_config || (
|
182
|
-
return
|
192
|
+
return true unless property_config || (rel_args && rel_args[:cast])
|
193
|
+
return rel_args[:cast] if rel_args.has_key?(:cast)
|
183
194
|
!!property_config[:cast]
|
184
195
|
end
|
185
196
|
|
186
197
|
def return_literals?
|
187
|
-
|
198
|
+
rel_args && rel_args[:literal]
|
188
199
|
end
|
189
200
|
|
190
201
|
def final_parent
|
@@ -211,7 +222,8 @@ module ActiveTriples
|
|
211
222
|
def class_for_property
|
212
223
|
klass = property_config[:class_name] if property_config
|
213
224
|
klass ||= Resource
|
214
|
-
klass = ActiveTriples.class_from_string(klass, final_parent.class) if
|
225
|
+
klass = ActiveTriples.class_from_string(klass, final_parent.class) if
|
226
|
+
klass.kind_of? String
|
215
227
|
klass
|
216
228
|
end
|
217
229
|
|
@@ -223,6 +235,19 @@ module ActiveTriples
|
|
223
235
|
parent.rdf_subject
|
224
236
|
end
|
225
237
|
end
|
238
|
+
end
|
226
239
|
|
240
|
+
class Term < Relation
|
241
|
+
def self.inherited(*)
|
242
|
+
warn 'ActiveTriples::Term is deprecated! ' \
|
243
|
+
'Use ActiveTriples::Relation instead.'
|
244
|
+
super
|
245
|
+
end
|
246
|
+
|
247
|
+
def initialize(*)
|
248
|
+
warn 'ActiveTriples::Term is deprecated! ' \
|
249
|
+
'Use ActiveTriples::Relation instead.'
|
250
|
+
super
|
251
|
+
end
|
227
252
|
end
|
228
253
|
end
|
@@ -1,547 +1,22 @@
|
|
1
1
|
require 'deprecation'
|
2
|
-
require 'active_model'
|
3
|
-
require 'active_support/core_ext/hash'
|
4
2
|
|
5
3
|
module ActiveTriples
|
6
4
|
##
|
7
|
-
# Defines a generic RDF `Resource` as an
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
# Resources can be instances of ActiveTriples::Resource
|
13
|
-
# directly, but more often they will be instances of subclasses with
|
14
|
-
# registered properties and configuration. e.g.
|
15
|
-
#
|
16
|
-
# class License < Resource
|
17
|
-
# configure repository: :default
|
18
|
-
# property :title, predicate: RDF::DC.title, class_name: RDF::Literal do |index|
|
19
|
-
# index.as :displayable, :facetable
|
20
|
-
# end
|
21
|
-
# end
|
22
|
-
class Resource < RDF::Graph
|
23
|
-
extend Configurable
|
24
|
-
include Properties
|
25
|
-
extend Deprecation
|
26
|
-
extend ActiveModel::Naming
|
27
|
-
extend ActiveModel::Translation
|
28
|
-
extend ActiveModel::Callbacks
|
29
|
-
include ActiveModel::Validations
|
30
|
-
include ActiveModel::Conversion
|
31
|
-
include ActiveModel::Serialization
|
32
|
-
include ActiveModel::Serializers::JSON
|
33
|
-
include NestedAttributes
|
34
|
-
include Reflection
|
35
|
-
attr_accessor :parent
|
36
|
-
define_model_callbacks :persist
|
5
|
+
# Defines a generic RDF `Resource` as an `ActiveTriples::Entity`. This
|
6
|
+
# provides a basic `Entity` type for classless resources.
|
7
|
+
class Resource
|
8
|
+
include RDFSource
|
37
9
|
|
38
10
|
class << self
|
39
11
|
def type_registry
|
40
|
-
|
12
|
+
RDFSource.type_registry
|
41
13
|
end
|
42
14
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
#
|
48
|
-
# @param uri [#to_uri, String]
|
49
|
-
# @param vals values to pass as arguments to ::new
|
50
|
-
#
|
51
|
-
# @return [ActiveTriples::Resource] a Resource with
|
52
|
-
def from_uri(uri,vals=nil)
|
53
|
-
new(uri, vals)
|
15
|
+
def property(*)
|
16
|
+
raise "Properties not definable directly on ActiveTriples::Resource, use a subclass" if
|
17
|
+
self == ActiveTriples::Resource
|
18
|
+
super
|
54
19
|
end
|
55
20
|
end
|
56
|
-
|
57
|
-
##
|
58
|
-
# Specifies whether the object is currently writable.
|
59
|
-
#
|
60
|
-
# @return [true, false]
|
61
|
-
def writable?
|
62
|
-
!frozen?
|
63
|
-
end
|
64
|
-
|
65
|
-
##
|
66
|
-
# Initialize an instance of this resource class. Defaults to a
|
67
|
-
# blank node subject. In addition to RDF::Graph parameters, you
|
68
|
-
# can pass in a URI and/or a parent to build a resource from a
|
69
|
-
# existing data.
|
70
|
-
#
|
71
|
-
# You can pass in only a parent with:
|
72
|
-
# Resource.new(nil, parent)
|
73
|
-
#
|
74
|
-
# @see RDF::Graph
|
75
|
-
def initialize(*args, &block)
|
76
|
-
resource_uri = args.shift unless args.first.is_a?(Hash)
|
77
|
-
self.parent = args.shift unless args.first.is_a?(Hash)
|
78
|
-
set_subject!(resource_uri) if resource_uri
|
79
|
-
super(*args, &block)
|
80
|
-
reload
|
81
|
-
# Append type to graph if necessary.
|
82
|
-
self.get_values(:type) << self.class.type if self.class.type.kind_of?(RDF::URI) && type.empty?
|
83
|
-
end
|
84
|
-
|
85
|
-
##
|
86
|
-
# Returns the current object.
|
87
|
-
#
|
88
|
-
# @deprecated redundant, simply returns self.
|
89
|
-
#
|
90
|
-
# @return [self]
|
91
|
-
def graph
|
92
|
-
Deprecation.warn Resource, "graph is redundant & deprecated. It will be removed in ActiveTriples 0.2.0.", caller
|
93
|
-
self
|
94
|
-
end
|
95
|
-
|
96
|
-
def final_parent
|
97
|
-
@final_parent ||= begin
|
98
|
-
parent = self.parent
|
99
|
-
while parent && parent.parent && parent.parent != parent
|
100
|
-
parent = parent.parent
|
101
|
-
end
|
102
|
-
parent
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def attributes
|
107
|
-
attrs = {}
|
108
|
-
attrs['id'] = id if id
|
109
|
-
fields.map { |f| attrs[f.to_s] = get_values(f) }
|
110
|
-
unregistered_predicates.map { |uri| attrs[uri.to_s] = get_values(uri) }
|
111
|
-
attrs
|
112
|
-
end
|
113
|
-
|
114
|
-
def serializable_hash(options = nil)
|
115
|
-
attrs = (fields.map { |f| f.to_s }) << 'id'
|
116
|
-
hash = super(:only => attrs)
|
117
|
-
unregistered_predicates.map { |uri| hash[uri.to_s] = get_values(uri) }
|
118
|
-
hash
|
119
|
-
end
|
120
|
-
|
121
|
-
def reflections
|
122
|
-
self.class
|
123
|
-
end
|
124
|
-
|
125
|
-
def attributes=(values)
|
126
|
-
raise ArgumentError, "values must be a Hash, you provided #{values.class}" unless values.kind_of? Hash
|
127
|
-
values = values.with_indifferent_access
|
128
|
-
id = values.delete(:id)
|
129
|
-
set_subject!(id) if id && node?
|
130
|
-
values.each do |key, value|
|
131
|
-
if reflections.reflect_on_property(key)
|
132
|
-
set_value(rdf_subject, key, value)
|
133
|
-
elsif nested_attributes_options.keys.map { |k| "#{k}_attributes" }.include?(key)
|
134
|
-
send("#{key}=".to_sym, value)
|
135
|
-
else
|
136
|
-
raise ArgumentError, "No association found for name `#{key}'. Has it been defined yet?"
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
##
|
142
|
-
# Returns a serialized string representation of self.
|
143
|
-
# Extends the base implementation builds a JSON-LD context if the
|
144
|
-
# specified format is :jsonld and a context is provided by
|
145
|
-
# #jsonld_context
|
146
|
-
#
|
147
|
-
# @see RDF::Enumerable#dump
|
148
|
-
#
|
149
|
-
# @param args [Array<Object>]
|
150
|
-
# @return [String]
|
151
|
-
def dump(*args)
|
152
|
-
if args.first == :jsonld and respond_to?(:jsonld_context)
|
153
|
-
args << {} unless args.last.is_a?(Hash)
|
154
|
-
args.last[:context] ||= jsonld_context
|
155
|
-
end
|
156
|
-
super
|
157
|
-
end
|
158
|
-
|
159
|
-
##
|
160
|
-
# @return [RDF::URI, RDF::Node] a URI or Node which the resource's
|
161
|
-
# properties are about.
|
162
|
-
def rdf_subject
|
163
|
-
@rdf_subject ||= RDF::Node.new
|
164
|
-
end
|
165
|
-
alias_method :to_term, :rdf_subject
|
166
|
-
|
167
|
-
##
|
168
|
-
# A string identifier for the resource
|
169
|
-
def id
|
170
|
-
node? ? nil : rdf_subject.to_s
|
171
|
-
end
|
172
|
-
|
173
|
-
def node?
|
174
|
-
return true if rdf_subject.kind_of? RDF::Node
|
175
|
-
false
|
176
|
-
end
|
177
|
-
|
178
|
-
##
|
179
|
-
# @return [String, nil] the base URI the resource will use when
|
180
|
-
# setting its subject. `nil` if none is used.
|
181
|
-
def base_uri
|
182
|
-
self.class.base_uri
|
183
|
-
end
|
184
|
-
|
185
|
-
def type
|
186
|
-
self.get_values(:type).to_a
|
187
|
-
end
|
188
|
-
|
189
|
-
def type=(type)
|
190
|
-
raise "Type must be an RDF::URI" unless type.kind_of? RDF::URI
|
191
|
-
self.update(RDF::Statement.new(rdf_subject, RDF.type, type))
|
192
|
-
end
|
193
|
-
|
194
|
-
##
|
195
|
-
# Looks for labels in various default fields, prioritizing
|
196
|
-
# configured label fields.
|
197
|
-
def rdf_label
|
198
|
-
labels = Array(self.class.rdf_label)
|
199
|
-
labels += default_labels
|
200
|
-
labels.each do |label|
|
201
|
-
values = get_values(label)
|
202
|
-
return values unless values.empty?
|
203
|
-
end
|
204
|
-
node? ? [] : [rdf_subject.to_s]
|
205
|
-
end
|
206
|
-
|
207
|
-
##
|
208
|
-
# Lists fields registered as properties on the object.
|
209
|
-
#
|
210
|
-
# @return [Array<Symbol>] the list of registered properties.
|
211
|
-
def fields
|
212
|
-
properties.keys.map(&:to_sym).reject{|x| x == :type}
|
213
|
-
end
|
214
|
-
|
215
|
-
##
|
216
|
-
# Load data from the #rdf_subject URI. Retrieved data will be
|
217
|
-
# parsed into the Resource's graph from available RDF::Readers
|
218
|
-
# and available from property accessors if if predicates are
|
219
|
-
# registered.
|
220
|
-
#
|
221
|
-
# osu = ActiveTriples::Resource.new('http://dbpedia.org/resource/Oregon_State_University')
|
222
|
-
# osu.fetch
|
223
|
-
# osu.rdf_label.first
|
224
|
-
# # => "Oregon State University"
|
225
|
-
#
|
226
|
-
# @return [ActiveTriples::Resource] self
|
227
|
-
def fetch
|
228
|
-
load(rdf_subject)
|
229
|
-
self
|
230
|
-
end
|
231
|
-
|
232
|
-
def persist!(opts={})
|
233
|
-
return if @persisting
|
234
|
-
return false if opts[:validate] && !valid?
|
235
|
-
@persisting = true
|
236
|
-
run_callbacks :persist do
|
237
|
-
raise "failed when trying to persist to non-existant repository or parent resource" unless repository
|
238
|
-
erase_old_resource
|
239
|
-
repository << self
|
240
|
-
@persisted = true
|
241
|
-
end
|
242
|
-
@persisting = false
|
243
|
-
true
|
244
|
-
end
|
245
|
-
|
246
|
-
##
|
247
|
-
# Indicates if the resource is persisted.
|
248
|
-
#
|
249
|
-
# @see #persist
|
250
|
-
# @return [true, false]
|
251
|
-
def persisted?
|
252
|
-
@persisted ||= false
|
253
|
-
return (@persisted and parent.persisted?) if parent
|
254
|
-
@persisted
|
255
|
-
end
|
256
|
-
|
257
|
-
##
|
258
|
-
# Repopulates the graph from the repository or parent resource.
|
259
|
-
#
|
260
|
-
# @return [true, false]
|
261
|
-
def reload
|
262
|
-
@term_cache ||= {}
|
263
|
-
return false unless repository
|
264
|
-
self << repository.query(subject: rdf_subject)
|
265
|
-
unless empty?
|
266
|
-
@persisted = true
|
267
|
-
end
|
268
|
-
true
|
269
|
-
end
|
270
|
-
|
271
|
-
##
|
272
|
-
# Adds or updates a property with supplied values.
|
273
|
-
#
|
274
|
-
# Handles two argument patterns. The recommended pattern is:
|
275
|
-
# set_value(property, values)
|
276
|
-
#
|
277
|
-
# For backwards compatibility, there is support for explicitly
|
278
|
-
# passing the rdf_subject to be used in the statement:
|
279
|
-
# set_value(uri, property, values)
|
280
|
-
#
|
281
|
-
# @note This method will delete existing statements with the correct subject and predicate from the graph
|
282
|
-
def set_value(*args)
|
283
|
-
# Add support for legacy 3-parameter syntax
|
284
|
-
if args.length > 3 || args.length < 2
|
285
|
-
raise ArgumentError, "wrong number of arguments (#{args.length} for 2-3)"
|
286
|
-
end
|
287
|
-
values = args.pop
|
288
|
-
get_term(args).set(values)
|
289
|
-
end
|
290
|
-
|
291
|
-
##
|
292
|
-
# Adds or updates a property with supplied values.
|
293
|
-
#
|
294
|
-
# @note This method will delete existing statements with the correct subject and predicate from the graph
|
295
|
-
def []=(uri_or_term_property, value)
|
296
|
-
self[uri_or_term_property].set(value)
|
297
|
-
end
|
298
|
-
|
299
|
-
##
|
300
|
-
# Returns an array of values belonging to the property
|
301
|
-
# requested. Elements in the array may RdfResource objects or a
|
302
|
-
# valid datatype.
|
303
|
-
#
|
304
|
-
# Handles two argument patterns. The recommended pattern is:
|
305
|
-
# get_values(property)
|
306
|
-
#
|
307
|
-
# For backwards compatibility, there is support for explicitly
|
308
|
-
# passing the rdf_subject to be used in th statement:
|
309
|
-
# get_values(uri, property)
|
310
|
-
def get_values(*args)
|
311
|
-
get_term(args)
|
312
|
-
end
|
313
|
-
|
314
|
-
##
|
315
|
-
# Returns an array of values belonging to the property
|
316
|
-
# requested. Elements in the array may RdfResource objects or a
|
317
|
-
# valid datatype.
|
318
|
-
def [](uri_or_term_property)
|
319
|
-
get_term([uri_or_term_property])
|
320
|
-
end
|
321
|
-
|
322
|
-
|
323
|
-
def get_term(args)
|
324
|
-
@term_cache ||= {}
|
325
|
-
term = Term.new(self, args)
|
326
|
-
@term_cache["#{term.send(:rdf_subject)}/#{term.property}/#{term.term_args}"] ||= term
|
327
|
-
@term_cache["#{term.send(:rdf_subject)}/#{term.property}/#{term.term_args}"]
|
328
|
-
end
|
329
|
-
|
330
|
-
##
|
331
|
-
# Set a new rdf_subject for the resource.
|
332
|
-
#
|
333
|
-
# This raises an error if the current subject is not a blank node,
|
334
|
-
# and returns false if it can't figure out how to make a URI from
|
335
|
-
# the param. Otherwise it creates a URI for the resource and
|
336
|
-
# rebuilds the graph with the updated URI.
|
337
|
-
#
|
338
|
-
# Will try to build a uri as an extension of the class's base_uri
|
339
|
-
# if appropriate.
|
340
|
-
#
|
341
|
-
# @param [#to_uri, #to_s] uri_or_str the uri or string to use
|
342
|
-
def set_subject!(uri_or_str)
|
343
|
-
raise "Refusing update URI when one is already assigned!" unless node? or rdf_subject == RDF::URI(nil)
|
344
|
-
# Refusing set uri to an empty string.
|
345
|
-
return false if uri_or_str.nil? or (uri_or_str.to_s.empty? and not uri_or_str.kind_of? RDF::URI)
|
346
|
-
# raise "Refusing update URI! This object is persisted to a datastream." if persisted?
|
347
|
-
old_subject = rdf_subject
|
348
|
-
@rdf_subject = get_uri(uri_or_str)
|
349
|
-
|
350
|
-
each_statement do |statement|
|
351
|
-
if statement.subject == old_subject
|
352
|
-
delete(statement)
|
353
|
-
self << RDF::Statement.new(rdf_subject, statement.predicate, statement.object)
|
354
|
-
elsif statement.object == old_subject
|
355
|
-
delete(statement)
|
356
|
-
self << RDF::Statement.new(statement.subject, statement.predicate, rdf_subject)
|
357
|
-
end
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
361
|
-
def destroy
|
362
|
-
clear
|
363
|
-
persist! if repository
|
364
|
-
parent.destroy_child(self) if parent
|
365
|
-
@destroyed = true
|
366
|
-
end
|
367
|
-
alias_method :destroy!, :destroy
|
368
|
-
|
369
|
-
##
|
370
|
-
# Indicates if the Resource has been destroyed.
|
371
|
-
#
|
372
|
-
# @return [true, false]
|
373
|
-
def destroyed?
|
374
|
-
@destroyed ||= false
|
375
|
-
end
|
376
|
-
|
377
|
-
def destroy_child(child)
|
378
|
-
statements.each do |statement|
|
379
|
-
delete_statement(statement) if statement.subject == child.rdf_subject || statement.object == child.rdf_subject
|
380
|
-
end
|
381
|
-
end
|
382
|
-
|
383
|
-
##
|
384
|
-
# Indicates if the record is 'new' (has not yet been persisted).
|
385
|
-
#
|
386
|
-
# @return [true, false]
|
387
|
-
def new_record?
|
388
|
-
not persisted?
|
389
|
-
end
|
390
|
-
|
391
|
-
##
|
392
|
-
# @return [String] the string representation of the resource
|
393
|
-
def solrize
|
394
|
-
node? ? rdf_label : rdf_subject.to_s
|
395
|
-
end
|
396
|
-
|
397
|
-
def mark_for_destruction
|
398
|
-
@marked_for_destruction = true
|
399
|
-
end
|
400
|
-
|
401
|
-
def marked_for_destruction?
|
402
|
-
@marked_for_destruction
|
403
|
-
end
|
404
|
-
|
405
|
-
protected
|
406
|
-
|
407
|
-
#Clear out any old assertions in the repository about this node or statement
|
408
|
-
# thus preparing to receive the updated assertions.
|
409
|
-
def erase_old_resource
|
410
|
-
if node?
|
411
|
-
repository.statements.each do |statement|
|
412
|
-
repository.send(:delete_statement, statement) if statement.subject == rdf_subject
|
413
|
-
end
|
414
|
-
else
|
415
|
-
repository.delete [rdf_subject, nil, nil]
|
416
|
-
end
|
417
|
-
end
|
418
|
-
|
419
|
-
##
|
420
|
-
# Test if the rdf_subject that would be generated using a
|
421
|
-
# specific ID is already in use in the triplestore.
|
422
|
-
#
|
423
|
-
# @param [Integer, #read] ID to test
|
424
|
-
#
|
425
|
-
# @return [TrueClass, FalseClass] true, if the ID is in
|
426
|
-
# use in the triplestore; otherwise, false.
|
427
|
-
# NOTE: If the ID is in use in an object not yet
|
428
|
-
# persisted, false will be returned presenting
|
429
|
-
# a window of opportunity for an ID clash.
|
430
|
-
def self.id_persisted?(test_id)
|
431
|
-
rdf_subject = self.new(test_id).rdf_subject
|
432
|
-
ActiveTriples::Repositories.has_subject?(rdf_subject)
|
433
|
-
end
|
434
|
-
|
435
|
-
##
|
436
|
-
# Test if the rdf_subject that would be generated using a
|
437
|
-
# specific URI is already in use in the triplestore.
|
438
|
-
#
|
439
|
-
# @param [String, RDF::URI, #read] URI to test
|
440
|
-
#
|
441
|
-
# @return [TrueClass, FalseClass] true, if the URI is in
|
442
|
-
# use in the triplestore; otherwise, false.
|
443
|
-
# NOTE: If the URI is in use in an object not yet
|
444
|
-
# persisted, false will be returned presenting
|
445
|
-
# a window of opportunity for an ID clash.
|
446
|
-
def self.uri_persisted?(test_uri)
|
447
|
-
rdf_subject = test_uri.kind_of?(RDF::URI) ? test_uri : RDF::URI(test_uri)
|
448
|
-
ActiveTriples::Repositories.has_subject?(rdf_subject)
|
449
|
-
end
|
450
|
-
|
451
|
-
private
|
452
|
-
|
453
|
-
##
|
454
|
-
# Returns the properties registered and their configurations.
|
455
|
-
#
|
456
|
-
# @return [ActiveSupport::HashWithIndifferentAccess{String => ActiveTriples::NodeConfig}]
|
457
|
-
def properties
|
458
|
-
_active_triples_config
|
459
|
-
end
|
460
|
-
|
461
|
-
##
|
462
|
-
# List of RDF predicates registered as properties on the object.
|
463
|
-
#
|
464
|
-
# @return [Array<RDF::URI>]
|
465
|
-
def registered_predicates
|
466
|
-
properties.values.map { |config| config.predicate }
|
467
|
-
end
|
468
|
-
|
469
|
-
##
|
470
|
-
# List of RDF predicates used in the Resource's triples, but not
|
471
|
-
# mapped to any property or accessor methods.
|
472
|
-
#
|
473
|
-
# @return [Array<RDF::URI>]
|
474
|
-
def unregistered_predicates
|
475
|
-
preds = registered_predicates
|
476
|
-
preds << RDF.type
|
477
|
-
predicates.select { |p| !preds.include? p }
|
478
|
-
end
|
479
|
-
|
480
|
-
##
|
481
|
-
# Given a predicate which has been registered to a property,
|
482
|
-
# returns the name of the matching property.
|
483
|
-
#
|
484
|
-
# @param predicate [RDF::URI]
|
485
|
-
#
|
486
|
-
# @return [String, nil] the name of the property mapped to the
|
487
|
-
# predicate provided
|
488
|
-
def property_for_predicate(predicate)
|
489
|
-
properties.each do |property, values|
|
490
|
-
return property if values[:predicate] == predicate
|
491
|
-
end
|
492
|
-
return nil
|
493
|
-
end
|
494
|
-
|
495
|
-
def default_labels
|
496
|
-
[RDF::SKOS.prefLabel,
|
497
|
-
RDF::DC.title,
|
498
|
-
RDF::RDFS.label,
|
499
|
-
RDF::SKOS.altLabel,
|
500
|
-
RDF::SKOS.hiddenLabel]
|
501
|
-
end
|
502
|
-
|
503
|
-
##
|
504
|
-
# Return the repository (or parent) that this resource should
|
505
|
-
# write to when persisting.
|
506
|
-
#
|
507
|
-
# @return [RDF::Repository, ActiveTriples::Resource] the target
|
508
|
-
# repository
|
509
|
-
def repository
|
510
|
-
@repository ||=
|
511
|
-
if self.class.repository == :parent
|
512
|
-
final_parent
|
513
|
-
else
|
514
|
-
repo = Repositories.repositories[self.class.repository]
|
515
|
-
raise RepositoryNotFoundError, "The class #{self.class} expects a repository called #{self.class.repository}, but none was declared" unless repo
|
516
|
-
repo
|
517
|
-
end
|
518
|
-
end
|
519
|
-
|
520
|
-
##
|
521
|
-
# Takes a URI or String and aggressively tries to convert it into
|
522
|
-
# an RDF term. If a String is given, first tries to interpret it
|
523
|
-
# as a valid URI, then tries to append it to base_uri. Finally,
|
524
|
-
# raises an error if no valid term can be built.
|
525
|
-
#
|
526
|
-
# The argument must be an RDF::Node, an object that responds to
|
527
|
-
# #to_uri, a String that represents a valid URI, or a String that
|
528
|
-
# appends to the Resource's base_uri to create a valid URI.
|
529
|
-
#
|
530
|
-
# @TODO: URI.scheme_list is naive and incomplete. Find a better
|
531
|
-
# way to check for an existing scheme.
|
532
|
-
#
|
533
|
-
# @param uri_or_str [RDF::Resource, String]
|
534
|
-
#
|
535
|
-
# @return [RDF::Resource] A term
|
536
|
-
# @raise [RuntimeError] no valid RDF term could be built
|
537
|
-
def get_uri(uri_or_str)
|
538
|
-
return uri_or_str.to_uri if uri_or_str.respond_to? :to_uri
|
539
|
-
return uri_or_str if uri_or_str.kind_of? RDF::Node
|
540
|
-
uri_or_str = uri_or_str.to_s
|
541
|
-
return RDF::Node(uri_or_str[2..-1]) if uri_or_str.start_with? '_:'
|
542
|
-
return RDF::URI(uri_or_str) if RDF::URI(uri_or_str).valid? and (URI.scheme_list.include?(RDF::URI.new(uri_or_str).scheme.upcase) or RDF::URI.new(uri_or_str).scheme == 'info')
|
543
|
-
return RDF::URI(self.base_uri.to_s + (self.base_uri.to_s[-1,1] =~ /(\/|#)/ ? '' : '/') + uri_or_str) if base_uri && !uri_or_str.start_with?(base_uri.to_s)
|
544
|
-
raise RuntimeError, "could not make a valid RDF::URI from #{uri_or_str}"
|
545
|
-
end
|
546
21
|
end
|
547
22
|
end
|