active-fedora 7.0.4 → 7.1.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.
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