active-fedora 7.0.4 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/History.txt +51 -1
  4. data/active-fedora.gemspec +19 -19
  5. data/lib/active_fedora.rb +1 -6
  6. data/lib/active_fedora/associations/builder/has_and_belongs_to_many.rb +1 -1
  7. data/lib/active_fedora/associations/collection_association.rb +1 -1
  8. data/lib/active_fedora/associations/has_and_belongs_to_many_association.rb +1 -1
  9. data/lib/active_fedora/attributes.rb +8 -0
  10. data/lib/active_fedora/base.rb +1 -1
  11. data/lib/active_fedora/callbacks.rb +1 -1
  12. data/lib/active_fedora/core.rb +13 -5
  13. data/lib/active_fedora/datastream_attribute.rb +1 -1
  14. data/lib/active_fedora/datastream_hash.rb +12 -6
  15. data/lib/active_fedora/fedora_attributes.rb +1 -1
  16. data/lib/active_fedora/file_configurator.rb +3 -3
  17. data/lib/active_fedora/fixture_loader.rb +2 -2
  18. data/lib/active_fedora/model.rb +2 -2
  19. data/lib/active_fedora/om_datastream.rb +2 -2
  20. data/lib/active_fedora/persistence.rb +22 -18
  21. data/lib/active_fedora/railtie.rb +5 -1
  22. data/lib/active_fedora/rdf.rb +11 -9
  23. data/lib/active_fedora/rdf/indexing.rb +1 -1
  24. data/lib/active_fedora/rdf/object_resource.rb +1 -1
  25. data/lib/active_fedora/rdf/rdf_datastream.rb +3 -3
  26. data/lib/active_fedora/relation/finder_methods.rb +16 -10
  27. data/lib/active_fedora/solr_instance_loader.rb +1 -1
  28. data/lib/active_fedora/solr_service.rb +1 -3
  29. data/lib/active_fedora/version.rb +1 -1
  30. data/spec/integration/attributes_spec.rb +4 -4
  31. data/spec/integration/base_spec.rb +32 -13
  32. data/spec/integration/complex_rdf_datastream_spec.rb +4 -4
  33. data/spec/integration/delete_all_spec.rb +1 -1
  34. data/spec/integration/load_from_solr_spec.rb +1 -1
  35. data/spec/integration/rdf_nested_attributes_spec.rb +4 -4
  36. data/spec/integration/scoped_query_spec.rb +6 -6
  37. data/spec/spec_helper.rb +5 -3
  38. data/spec/unit/attributes_spec.rb +19 -1
  39. data/spec/unit/builder/has_and_belongs_to_many_spec.rb +9 -0
  40. data/spec/unit/datastreams_spec.rb +4 -0
  41. data/spec/unit/file_configurator_spec.rb +5 -5
  42. data/spec/unit/logger_spec.rb +20 -0
  43. data/spec/unit/om_datastream_spec.rb +1 -1
  44. data/spec/unit/persistence_spec.rb +50 -0
  45. data/spec/unit/query_spec.rb +15 -5
  46. data/spec/unit/rdf_resource_datastream_spec.rb +3 -3
  47. data/spec/unit/rdfxml_rdf_datastream_spec.rb +1 -1
  48. data/spec/unit/solr_config_options_spec.rb +1 -1
  49. data/spec/unit/solr_service_spec.rb +1 -1
  50. metadata +33 -168
  51. data/lib/active_fedora/rdf/configurable.rb +0 -59
  52. data/lib/active_fedora/rdf/list.rb +0 -155
  53. data/lib/active_fedora/rdf/nested_attributes.rb +0 -130
  54. data/lib/active_fedora/rdf/node_config.rb +0 -57
  55. data/lib/active_fedora/rdf/properties.rb +0 -94
  56. data/lib/active_fedora/rdf/repositories.rb +0 -36
  57. data/lib/active_fedora/rdf/resource.rb +0 -328
  58. data/lib/active_fedora/rdf/term.rb +0 -188
  59. data/spec/unit/rdf_configurable_spec.rb +0 -37
  60. data/spec/unit/rdf_list_nested_attributes_spec.rb +0 -99
  61. data/spec/unit/rdf_list_spec.rb +0 -180
  62. data/spec/unit/rdf_properties_spec.rb +0 -81
  63. data/spec/unit/rdf_repositories_spec.rb +0 -28
  64. data/spec/unit/rdf_resource_spec.rb +0 -345
@@ -1,36 +0,0 @@
1
- module ActiveFedora::Rdf
2
- ##
3
- # Defines module methods for registering an RDF::Repository for
4
- # persistence of Resources.
5
- #
6
- # This allows any triplestore (or other storage platform) with an
7
- # RDF::Repository implementation to be used for persistence of
8
- # resources that will be shared between ActiveFedora::Base objects.
9
- #
10
- # ActiveFedora::Rdf::Repositories.add_repository :blah, RDF::Repository.new
11
- #
12
- # Multiple repositories can be registered to keep different kinds of
13
- # resources seperate. This is configurable on subclasses of Resource
14
- # at the class level.
15
- #
16
- # @see Configurable
17
- module Repositories
18
-
19
- def add_repository(name, repo)
20
- raise "Repositories must be an RDF::Repository" unless repo.kind_of? RDF::Repository
21
- repositories[name] = repo
22
- end
23
- module_function :add_repository
24
-
25
- def clear_repositories!
26
- @repositories = {}
27
- end
28
- module_function :clear_repositories!
29
-
30
- def repositories
31
- @repositories ||= {}
32
- end
33
- module_function :repositories
34
-
35
- end
36
- end
@@ -1,328 +0,0 @@
1
- module ActiveFedora::Rdf
2
- ##
3
- # Defines a generic RDF `Resource` as an RDF::Graph with property
4
- # configuration, accessors, and some other methods for managing
5
- # resources as discrete subgraphs which can be maintained by a Hydra
6
- # datastream model.
7
- #
8
- # Resources can be instances of ActiveFedora::Rdf::Resource
9
- # directly, but more often they will be instances of subclasses with
10
- # registered properties and configuration. e.g.
11
- #
12
- # class License < Resource
13
- # configure repository: :default
14
- # property :title, predicate: RDF::DC.title, class_name: RDF::Literal do |index|
15
- # index.as :displayable, :facetable
16
- # end
17
- # end
18
- class Resource < RDF::Graph
19
- @@type_registry
20
- extend Configurable
21
- extend Properties
22
- extend Deprecation
23
- include ActiveFedora::Rdf::NestedAttributes
24
- attr_accessor :parent
25
-
26
- class << self
27
- def type_registry
28
- @@type_registry ||= {}
29
- end
30
-
31
- ##
32
- # Adapter for a consistent interface for creating a new node from a URI.
33
- # Similar functionality should exist in all objects which can become a node.
34
- def from_uri(uri,vals=nil)
35
- new(uri, vals)
36
- end
37
- end
38
-
39
- def writable?
40
- !frozen?
41
- end
42
-
43
- ##
44
- # Initialize an instance of this resource class. Defaults to a
45
- # blank node subject. In addition to RDF::Graph parameters, you
46
- # can pass in a URI and/or a parent to build a resource from a
47
- # existing data.
48
- #
49
- # You can pass in only a parent with:
50
- # Resource.new(nil, parent)
51
- #
52
- # @see RDF::Graph
53
- def initialize(*args, &block)
54
- resource_uri = args.shift unless args.first.is_a?(Hash)
55
- self.parent = args.shift unless args.first.is_a?(Hash)
56
- set_subject!(resource_uri) if resource_uri
57
- super(*args, &block)
58
- reload
59
- # Append type to graph if necessary.
60
- self.get_values(:type) << self.class.type if self.class.type.kind_of?(RDF::URI) && type.empty?
61
- end
62
-
63
- def graph
64
- Deprecation.warn Resource, "graph is redundant & deprecated. It will be removed in active-fedora 8.0.0.", caller
65
- self
66
- end
67
-
68
- def final_parent
69
- @final_parent ||= begin
70
- parent = self.parent
71
- while parent && parent.parent && parent.parent != parent
72
- parent = parent.parent
73
- end
74
- parent
75
- end
76
- end
77
-
78
- def attributes=(values)
79
- raise ArgumentError, "values must be a Hash, you provided #{values.class}" unless values.kind_of? Hash
80
- values = values.with_indifferent_access
81
- set_subject!(values.delete(:id)) if values.has_key?(:id) and node?
82
- values.each do |key, value|
83
- if properties.keys.include?(key)
84
- set_value(rdf_subject, key, value)
85
- elsif self.singleton_class.nested_attributes_options.keys.map{ |k| "#{k}_attributes"}.include?(key)
86
- send("#{key}=".to_sym, value)
87
- else
88
- raise ArgumentError, "No association found for name `#{key}'. Has it been defined yet?"
89
- end
90
- end
91
- end
92
-
93
- def rdf_subject
94
- @rdf_subject ||= RDF::Node.new
95
- end
96
-
97
- def node?
98
- return true if rdf_subject.kind_of? RDF::Node
99
- false
100
- end
101
-
102
- def to_term
103
- rdf_subject
104
- end
105
-
106
- def base_uri
107
- self.class.base_uri
108
- end
109
-
110
- def type
111
- self.get_values(:type).to_a.map{|x| x.rdf_subject}
112
- end
113
-
114
- def type=(type)
115
- raise "Type must be an RDF::URI" unless type.kind_of? RDF::URI
116
- self.update(RDF::Statement.new(rdf_subject, RDF.type, type))
117
- end
118
-
119
- ##
120
- # Look for labels in various default fields, prioritizing
121
- # configured label fields
122
- def rdf_label
123
- labels = Array(self.class.rdf_label)
124
- labels += default_labels
125
- labels.each do |label|
126
- values = get_values(label)
127
- return values unless values.empty?
128
- end
129
- node? ? [] : [rdf_subject.to_s]
130
- end
131
-
132
- def fields
133
- properties.keys.map(&:to_sym).reject{|x| x == :type}
134
- end
135
-
136
- ##
137
- # Load data from URI
138
- def fetch
139
- load(rdf_subject)
140
- self
141
- end
142
-
143
- def persist!
144
- raise "failed when trying to persist to non-existant repository or parent resource" unless repository
145
- repository.delete [rdf_subject,nil,nil] unless node?
146
- if node?
147
- repository.statements.each do |statement|
148
- repository.send(:delete_statement, statement) if statement.subject == rdf_subject
149
- end
150
- end
151
- repository << self
152
- @persisted = true
153
- end
154
-
155
- def persisted?
156
- @persisted ||= false
157
- return (@persisted and parent.persisted?) if parent
158
- @persisted
159
- end
160
-
161
- ##
162
- # Repopulates the graph from the repository or parent resource.
163
- def reload
164
- @term_cache ||= {}
165
- if self.class.repository == :parent
166
- return false if final_parent.nil?
167
- end
168
- self << repository.query(subject: rdf_subject)
169
- unless empty?
170
- @persisted = true
171
- end
172
- true
173
- end
174
-
175
- ##
176
- # Adds or updates a property with supplied values.
177
- #
178
- # Handles two argument patterns. The recommended pattern is:
179
- # set_value(property, values)
180
- #
181
- # For backwards compatibility, there is support for explicitly
182
- # passing the rdf_subject to be used in the statement:
183
- # set_value(uri, property, values)
184
- #
185
- # @note This method will delete existing statements with the correct subject and predicate from the graph
186
- def set_value(*args)
187
- # Add support for legacy 3-parameter syntax
188
- if args.length > 3 || args.length < 2
189
- raise ArgumentError("wrong number of arguments (#{args.length} for 2-3)")
190
- end
191
- values = args.pop
192
- get_term(args).set(values)
193
- end
194
-
195
- ##
196
- # Returns an array of values belonging to the property
197
- # requested. Elements in the array may RdfResource objects or a
198
- # valid datatype.
199
- #
200
- # Handles two argument patterns. The recommended pattern is:
201
- # get_values(property)
202
- #
203
- # For backwards compatibility, there is support for explicitly
204
- # passing the rdf_subject to be used in th statement:
205
- # get_values(uri, property)
206
- def get_values(*args)
207
- get_term(args)
208
- end
209
-
210
- def get_term(args)
211
- @term_cache ||= {}
212
- term = ActiveFedora::Rdf::Term.new(self, args)
213
- @term_cache["#{term.rdf_subject}/#{term.property}"] ||= term
214
- @term_cache["#{term.rdf_subject}/#{term.property}"]
215
- end
216
-
217
- ##
218
- # Set a new rdf_subject for the resource.
219
- #
220
- # This raises an error if the current subject is not a blank node,
221
- # and returns false if it can't figure out how to make a URI from
222
- # the param. Otherwise it creates a URI for the resource and
223
- # rebuilds the graph with the updated URI.
224
- #
225
- # Will try to build a uri as an extension of the class's base_uri
226
- # if appropriate.
227
- #
228
- # @param [#to_uri, #to_s] uri_or_str the uri or string to use
229
- def set_subject!(uri_or_str)
230
- raise "Refusing update URI when one is already assigned!" unless node?
231
- # Refusing set uri to an empty string.
232
- return false if uri_or_str.nil? or uri_or_str.to_s.empty?
233
- # raise "Refusing update URI! This object is persisted to a datastream." if persisted?
234
- old_subject = rdf_subject
235
- @rdf_subject = get_uri(uri_or_str)
236
-
237
- each_statement do |statement|
238
- if statement.subject == old_subject
239
- delete(statement)
240
- self << RDF::Statement.new(rdf_subject, statement.predicate, statement.object)
241
- elsif statement.object == old_subject
242
- delete(statement)
243
- self << RDF::Statement.new(statement.subject, statement.predicate, rdf_subject)
244
- end
245
- end
246
- end
247
-
248
- def destroy
249
- clear
250
- persist!
251
- parent.destroy_child(self)
252
- end
253
-
254
- def destroy_child(child)
255
- statements.each do |statement|
256
- delete_statement(statement) if statement.subject == child.rdf_subject || statement.object == child.rdf_subject
257
- end
258
- end
259
-
260
- def new_record?
261
- not persisted?
262
- end
263
-
264
- ##
265
- # @return [String] the string to index in solr
266
- def solrize
267
- node? ? rdf_label : rdf_subject.to_s
268
- end
269
-
270
- def mark_for_destruction
271
- @marked_for_destruction = true
272
- end
273
-
274
- def marked_for_destruction?
275
- @marked_for_destruction
276
- end
277
-
278
- private
279
-
280
- def properties
281
- self.singleton_class.properties
282
- end
283
-
284
- def property_for_predicate(predicate)
285
- properties.each do |property, values|
286
- return property if values[:predicate] == predicate
287
- end
288
- return nil
289
- end
290
-
291
- def default_labels
292
- [RDF::SKOS.prefLabel,
293
- RDF::DC.title,
294
- RDF::RDFS.label,
295
- RDF::SKOS.altLabel,
296
- RDF::SKOS.hiddenLabel]
297
- end
298
-
299
- ##
300
- # Return the repository (or parent) that this resource should
301
- # write to when persisting.
302
- def repository
303
- @repository ||=
304
- if self.class.repository == :parent
305
- final_parent
306
- else
307
- ActiveFedora::Rdf::Repositories.repositories[self.class.repository]
308
- end
309
- end
310
-
311
- private
312
-
313
- ##
314
- # Takes a URI or String and aggressively tries to create a valid RDF URI.
315
- # Combines the input with base_uri if appropriate.
316
- #
317
- # @TODO: URI.scheme_list is naive and incomplete. Find a better way to check for an existing scheme.
318
- def get_uri(uri_or_str)
319
- return uri_or_str.to_uri if uri_or_str.respond_to? :to_uri
320
- return uri_or_str if uri_or_str.kind_of? RDF::Node
321
- uri_or_str = uri_or_str.to_s
322
- return RDF::Node(uri_or_str[2..-1]) if uri_or_str.start_with? '_:'
323
- 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')
324
- 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)
325
- raise RuntimeError, "could not make a valid RDF::URI from #{uri_or_str}"
326
- end
327
- end
328
- end
@@ -1,188 +0,0 @@
1
- module ActiveFedora::Rdf
2
- class Term
3
- attr_accessor :parent, :value_arguments, :node_cache
4
- delegate *(Array.public_instance_methods - [:__send__, :__id__, :class, :object_id] + [:as_json]), :to => :result
5
- def initialize(parent, value_arguments)
6
- self.parent = parent
7
- self.value_arguments = value_arguments
8
- end
9
-
10
- def clear
11
- set(nil)
12
- end
13
-
14
- def result
15
- result = parent.query(:subject => rdf_subject, :predicate => predicate)
16
- .map{|x| convert_object(x.object)}
17
- .reject(&:nil?)
18
- return result if !property_config || property_config[:multivalue]
19
- result.first
20
- end
21
-
22
- def set(values)
23
- values = [values].compact unless values.kind_of?(Array)
24
- empty_property
25
- values.each do |val|
26
- set_value(val)
27
- end
28
- parent.persist! if parent.class.repository == :parent && parent.send(:repository)
29
- end
30
-
31
- def empty_property
32
- parent.query([rdf_subject, predicate, nil]).each_statement do |statement|
33
- if !uri_class(statement.object) || uri_class(statement.object) == class_for_property
34
- parent.delete(statement)
35
- end
36
- end
37
- end
38
-
39
- def build(attributes={})
40
- new_subject = attributes.key?('id') ? attributes.delete('id') : RDF::Node.new
41
- node = make_node(new_subject)
42
- node.attributes = attributes
43
- if parent.kind_of? List::ListResource
44
- parent.list << node
45
- return node
46
- elsif node.kind_of? RDF::List
47
- self.push node.rdf_subject
48
- return node
49
- end
50
- self.push node
51
- node
52
- end
53
-
54
- def first_or_create(attributes={})
55
- result.first || build(attributes)
56
- end
57
-
58
- def delete(*values)
59
- values.each do |value|
60
- parent.delete([rdf_subject, predicate, value])
61
- end
62
- end
63
-
64
- def << (values)
65
- values = Array.wrap(result) | Array.wrap(values)
66
- self.set(values)
67
- end
68
-
69
- alias_method :push, :<<
70
-
71
- def property_config
72
- return type_property if (property == RDF.type || property.to_s == "type") && !parent.send(:properties)[property]
73
- parent.send(:properties)[property]
74
- end
75
-
76
- def type_property
77
- {:multivalue => true, :predicate => RDF.type}
78
- end
79
-
80
- def reset!
81
- end
82
-
83
- def property
84
- value_arguments.last
85
- end
86
-
87
- def rdf_subject
88
- raise ArgumentError("wrong number of arguments (#{value_arguments.length} for 1-2)") if value_arguments.length < 1 || value_arguments.length > 2
89
- if value_arguments.length > 1
90
- value_arguments.first
91
- else
92
- parent.rdf_subject
93
- end
94
- end
95
-
96
- protected
97
-
98
- def node_cache
99
- @node_cache ||= {}
100
- end
101
-
102
- def set_value(val)
103
- object = val
104
- val = val.resource if val.respond_to?(:resource)
105
- val = value_to_node(val)
106
- if val.kind_of? Resource
107
- node_cache[val.rdf_subject] = nil
108
- add_child_node(val, object)
109
- return
110
- end
111
- val = val.to_uri if val.respond_to? :to_uri
112
- raise 'value must be an RDF URI, Node, Literal, or a valid datatype. See RDF::Literal' unless
113
- val.kind_of? RDF::Value or val.kind_of? RDF::Literal
114
- parent.insert [rdf_subject, predicate, val]
115
- end
116
-
117
- def value_to_node(val)
118
- valid_datatype?(val) ? RDF::Literal(val) : val
119
- end
120
-
121
- def add_child_node(resource,object=nil)
122
- parent.insert [rdf_subject, predicate, resource.rdf_subject]
123
- resource.parent = parent unless resource.frozen?
124
- self.node_cache[resource.rdf_subject] = (object ? object : resource)
125
- resource.persist! if resource.class.repository == :parent
126
- end
127
-
128
- def predicate
129
- return property_config[:predicate] unless property.kind_of? RDF::URI
130
- property
131
- end
132
-
133
- def valid_datatype?(val)
134
- val.is_a? String or val.is_a? Date or val.is_a? Time or val.is_a? Numeric or val.is_a? Symbol or val == !!val
135
- end
136
-
137
- # Converts an object to the appropriate class.
138
- def convert_object(value)
139
- value = value.object if value.kind_of? RDF::Literal
140
- value = make_node(value) if value.kind_of? RDF::Resource
141
- value
142
- end
143
-
144
- ##
145
- # Build a child resource or return it from this object's cache
146
- #
147
- # Builds the resource from the class_name specified for the
148
- # property.
149
- def make_node(value)
150
- klass = class_for_value(value)
151
- value = RDF::Node.new if value.nil?
152
- node = node_cache[value] if node_cache[value]
153
- node ||= klass.from_uri(value,parent)
154
- return nil if property_config[:class_name] && class_for_value(value) != class_for_property
155
- self.node_cache[value] ||= node
156
- node
157
- end
158
-
159
- def final_parent
160
- @final_parent ||= begin
161
- parent = self.parent
162
- while parent != parent.parent && parent.parent
163
- parent = parent.parent
164
- end
165
- return parent.datastream if parent.respond_to?(:datastream) && parent.datastream
166
- parent
167
- end
168
- end
169
-
170
- def class_for_value(v)
171
- uri_class(v) || class_for_property
172
- end
173
-
174
- def uri_class(v)
175
- v = RDF::URI.new(v) if v.kind_of? String
176
- type_uri = parent.query([v, RDF.type, nil]).to_a.first.try(:object)
177
- ActiveFedora::Rdf::Resource.type_registry[type_uri]
178
- end
179
-
180
- def class_for_property
181
- klass = property_config[:class_name]
182
- klass ||= ActiveFedora::Rdf::Resource
183
- klass = ActiveFedora.class_from_string(klass, final_parent.class) if klass.kind_of? String
184
- klass
185
- end
186
-
187
- end
188
- end