active-fedora 5.4.0 → 5.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -10,4 +10,3 @@ group :development, :test do
10
10
  end
11
11
 
12
12
  gem 'jruby-openssl', :platform=> :jruby
13
- gem 'nom-xml', '>=0.5.1'
@@ -17,7 +17,8 @@ Gem::Specification.new do |s|
17
17
 
18
18
  s.add_dependency('rsolr')
19
19
  s.add_dependency('om', '~> 1.8.0')
20
- s.add_dependency('solrizer', '~>2.0.0')
20
+ s.add_dependency('nom-xml', '>=0.5.1')
21
+ s.add_dependency('solrizer', '~>2.1.0.rc1')
21
22
  s.add_dependency("activeresource", '>= 3.0.0')
22
23
  s.add_dependency("activesupport", '>= 3.0.0')
23
24
  s.add_dependency("builder", '~> 3.0.0')
@@ -6,4 +6,4 @@ searchable:
6
6
  displayable: _display
7
7
  facetable: _facet
8
8
  sortable: _sort
9
- unstemmed_searchable: _unstem_search
9
+ unstemmed_searchable: _unstem_search
@@ -14,4 +14,4 @@ searchable:
14
14
  displayable: _display
15
15
  facetable: _facet
16
16
  sortable: _sort
17
- unstemmed_searchable: _unstem_search
17
+ unstemmed_searchable: _unstem_search
data/lib/active_fedora.rb CHANGED
@@ -1,13 +1,14 @@
1
1
  require "loggable"
2
2
  require 'active_support'
3
- require 'active_fedora/solr_service'
3
+ require "solrizer"
4
+ require 'active_fedora/file_configurator'
4
5
  require 'active_fedora/rubydora_connection'
5
6
  require 'active_support/core_ext/class/attribute'
6
7
  require 'active_support/core_ext/object'
7
8
  require 'active_support/core_ext/hash/indifferent_access'
8
9
  require 'rdf'
9
10
 
10
- SOLR_DOCUMENT_ID = ActiveFedora::SolrService.id_field unless defined?(SOLR_DOCUMENT_ID)
11
+ SOLR_DOCUMENT_ID = ActiveFedora::FileConfigurator.id_field unless defined?(SOLR_DOCUMENT_ID)
11
12
  ENABLE_SOLR_UPDATES = true unless defined?(ENABLE_SOLR_UPDATES)
12
13
 
13
14
  module ActiveFedora #:nodoc:
@@ -52,12 +53,15 @@ module ActiveFedora #:nodoc:
52
53
  autoload :QualifiedDublinCoreDatastream
53
54
  autoload :Querying
54
55
  autoload :RDFDatastream
56
+ autoload :RdfNode
57
+ autoload :RdfObject
55
58
  autoload :RdfxmlRDFDatastream
56
59
  autoload :Relation
57
60
  autoload :RelsExtDatastream
58
61
  autoload :ServiceDefinitions
59
62
  autoload :SemanticNode
60
63
  autoload :SimpleDatastream
64
+ autoload :SolrService
61
65
  autoload :NestedAttributes
62
66
  autoload :FixtureLoader
63
67
  autoload :FixtureExporter
@@ -4,11 +4,10 @@ module ActiveFedora
4
4
  class Datastream < Rubydora::Datastream
5
5
  extend Deprecation
6
6
  attr_writer :digital_object
7
- attr_accessor :last_modified, :fields
7
+ attr_accessor :last_modified
8
8
 
9
9
  def initialize(digital_object=nil, dsid=nil, options={})
10
10
  ## When you use the versions feature of rubydora (0.5.x), you need to have a 3 argument constructor
11
- self.fields={}
12
11
  super
13
12
  end
14
13
 
@@ -46,6 +46,7 @@ module ActiveFedora
46
46
  # url: http://127.0.0.1:8983/fedora2
47
47
  #
48
48
 
49
+ include Solrizer::FieldNameMapper
49
50
  attr_accessor :config_env
50
51
  attr_reader :config_options, :fedora_config_path, :solr_config_path
51
52
 
@@ -100,6 +101,7 @@ module ActiveFedora
100
101
 
101
102
  load_fedora_config
102
103
  load_solr_config
104
+ load_solrizer_config
103
105
  @config_loaded = true
104
106
  end
105
107
 
@@ -148,6 +150,20 @@ module ActiveFedora
148
150
  @solr_config = {:url=> get_solr_url(config[ActiveFedora.environment.to_sym].symbolize_keys)}
149
151
  end
150
152
 
153
+ def load_solrizer_config
154
+ if solrizer_config_path
155
+ logger.warn "loading_solrizer_config at #{solrizer_config_path}, this overwrites the default field mapper class."
156
+ ActiveFedora::SolrService.load_mappings
157
+ end
158
+ end
159
+
160
+ def solrizer_config_path
161
+ begin
162
+ get_config_path('solr_mappings')
163
+ rescue ActiveFedora::ConfigurationError
164
+ end
165
+ end
166
+
151
167
  # Given the solr_config that's been loaded for this environment,
152
168
  # determine which solr url to use
153
169
  def get_solr_url(solr_config)
@@ -194,9 +210,12 @@ module ActiveFedora
194
210
 
195
211
  # Last choice, check for the default config file
196
212
  config_path = File.join(ActiveFedora.root, "config", "#{config_type}.yml")
197
- logger.warn "Using the default #{config_type}.yml that comes with active-fedora. If you want to override this, pass the path to #{config_type}.yml to ActiveFedora - ie. ActiveFedora.init(:#{config_type}_config_path => '/path/to/#{config_type}.yml') - or set Rails.root and put #{config_type}.yml into \#{Rails.root}/config."
198
- return config_path if File.file? config_path
199
- raise ConfigurationError "Couldn't load #{config_type} config file!"
213
+ if File.file? config_path
214
+ logger.warn "Using the default #{config_type}.yml that comes with active-fedora. If you want to override this, pass the path to #{config_type}.yml to ActiveFedora - ie. ActiveFedora.init(:#{config_type}_config_path => '/path/to/#{config_type}.yml') - or set Rails.root and put #{config_type}.yml into \#{Rails.root}/config."
215
+ return config_path
216
+ else
217
+ raise ConfigurationError, "Couldn't load #{config_type} config file!"
218
+ end
200
219
  end
201
220
 
202
221
  # Checks the existing fedora_config.path to see if there is a solr.yml there
@@ -285,7 +285,7 @@ module ActiveFedora
285
285
  end
286
286
 
287
287
  def generate_solr_symbol(base, data_type)
288
- Solrizer::XML::TerminologyBasedSolrizer.default_field_mapper.solr_name(base.to_sym, data_type)
288
+ Solrizer.default_field_mapper.solr_name(base.to_sym, data_type)
289
289
  end
290
290
 
291
291
  # ** Experimental **
@@ -2,10 +2,15 @@ require "nom"
2
2
 
3
3
  module ActiveFedora
4
4
  class NomDatastream < Datastream
5
- def self.set_terminology &block
5
+ def self.set_terminology(options = {}, &block)
6
+ @terminology_options = options || {}
6
7
  @terminology = block
7
8
  end
8
9
 
10
+ def self.terminology_options
11
+ @terminology_options
12
+ end
13
+
9
14
  def self.terminology
10
15
  @terminology
11
16
  end
@@ -27,7 +32,7 @@ module ActiveFedora
27
32
  def ng_xml
28
33
  @ng_xml ||= begin
29
34
  xml = Nokogiri::XML content
30
- xml.set_terminology &self.class.terminology
35
+ xml.set_terminology self.class.terminology_options, &self.class.terminology
31
36
  xml.nom!
32
37
  xml
33
38
  end
@@ -35,7 +40,7 @@ module ActiveFedora
35
40
 
36
41
  def ng_xml= ng_xml
37
42
  @ng_xml = ng_xml
38
- @ng_xml.set_terminology &self.class.terminology
43
+ @ng_xml.set_terminology self.class.terminology_options, &self.class.terminology
39
44
  content_will_change!
40
45
  @ng_xml
41
46
  end
@@ -7,6 +7,7 @@ module ActiveFedora
7
7
  #Fields can still be overridden if more specificity is desired (see ActiveFedora::Datastream#fields method).
8
8
  class QualifiedDublinCoreDatastream < OmDatastream
9
9
 
10
+ attr_accessor :fields
10
11
  class_attribute :class_fields
11
12
  self.class_fields = []
12
13
 
@@ -31,6 +32,7 @@ module ActiveFedora
31
32
  #when this method returns. Each term is marked as a multivalue string.
32
33
  def initialize(digital_object=nil, dsid=nil, options={})
33
34
  super
35
+ self.fields={}
34
36
  DCTERMS.each do |el|
35
37
  field el, :string, :multiple=>true
36
38
  end
@@ -1,46 +1,22 @@
1
1
  module ActiveFedora
2
2
  class RDFDatastream < Datastream
3
3
 
4
+ include Solrizer::Common
5
+
4
6
  before_save do
5
7
  if content.blank?
6
8
  logger.warn "Cowardly refusing to save a datastream with empty content: #{self.inspect}"
7
9
  false
8
10
  end
9
11
  end
12
+ include RdfNode
10
13
 
11
- # this enables a cleaner API for solr integration
12
- class IndexObject
13
- attr_accessor :data_type, :behaviors
14
- def initialize
15
- @behaviors = [:searchable]
16
- @data_type = :string
17
- end
18
- def as(*args)
19
- @behaviors = args
20
- end
21
- def type(sym)
22
- @data_type = sym
23
- end
24
- def defaults
25
- :noop
26
- end
27
- end
28
-
29
14
  class << self
30
- attr_accessor :vocabularies
31
- def config
32
- ActiveFedora::Predicates.predicate_config
33
- end
34
- def prefix(name)
35
- name = name.to_s unless name.is_a? String
36
- pre = self.to_s.sub(/RDFDatastream$/i, '').underscore
37
- return "#{pre}__#{name}".to_sym
38
- end
39
-
40
15
  ##
41
16
  # Register a ruby block that evaluates to the subject of the graph
42
17
  # By default, the block returns the current object's pid
43
18
  # @yield [ds] 'ds' is the datastream instance
19
+ # This should override the method in rdf_object, which just creates a b-node by default
44
20
  def rdf_subject &block
45
21
  if block_given?
46
22
  return @subject_block = block
@@ -50,117 +26,20 @@ module ActiveFedora
50
26
  end
51
27
 
52
28
  def register_vocabularies(*vocabs)
53
- @vocabularies ||= {}
54
- vocabs.each do |v|
55
- if v.is_a?(RDF::Vocabulary) or (v.respond_to? :property and v.respond_to? :to_uri)
56
- @vocabularies[v.to_uri] = v
57
- else
58
- raise "not an RDF vocabulary: #{v}"
59
- end
60
- end
61
- ActiveFedora::Predicates.vocabularies(@vocabularies)
62
- @vocabularies
29
+ Deprecation.warn(RDFDatastream, "register_vocabularies no longer has any effect and will be removed in active-fedora 6.0", caller)
63
30
  end
64
31
 
65
- def map_predicates(&block)
66
- yield self
67
- end
68
- def method_missing(name, *args, &block)
69
- args = args.first if args.respond_to? :first
70
- raise "mapping must specify RDF vocabulary as :in argument" unless args.has_key? :in
71
- vocab = args[:in]
72
- predicate = args.fetch(:to, name)
73
- raise "Vocabulary '#{vocab.inspect}' does not define property '#{predicate.inspect}'" unless vocab.respond_to? predicate
74
- indexing = false
75
- if block_given?
76
- # needed for solrizer integration
77
- indexing = true
78
- iobj = IndexObject.new
79
- yield iobj
80
- data_type = iobj.data_type
81
- behaviors = iobj.behaviors
82
- end
83
- # needed for AF::Predicates integration & drives all other
84
- # functionality below
85
- vocab = vocab.to_s
86
- name = self.prefix(name)
87
- if config
88
- if config[:predicate_mapping].has_key? vocab
89
- config[:predicate_mapping][vocab][name] = predicate
90
- else
91
- config[:predicate_mapping][vocab] = { name => predicate }
92
- end
93
- # stuff data_type and behaviors in there for to_solr support
94
- config[:predicate_mapping][vocab]["#{name}__type".to_sym] = data_type if indexing
95
- config[:predicate_mapping][vocab]["#{name}__behaviors".to_sym] = behaviors if indexing
96
- else
97
- config = {
98
- :default_namespace => vocab,
99
- :predicate_mapping => {
100
- vocab => { name => predicate }
101
- }
102
- }
103
- # stuff data_type and behaviors in there for to_solr support
104
- config[:predicate_mapping][vocab]["#{name}__type".to_sym] = data_type if indexing
105
- config[:predicate_mapping][vocab]["#{name}__behaviors".to_sym] = behaviors if indexing
106
- end
32
+ def prefix(name)
33
+ name = name.to_s unless name.is_a? String
34
+ pre = self.to_s.sub(/RDFDatastream$/i, '').underscore
35
+ return "#{pre}__#{name}".to_sym
107
36
  end
108
37
  end
109
38
 
110
-
111
- class TermProxy
112
-
113
- attr_reader :graph, :subject, :predicate
114
- delegate :class, :to_s, :==, :kind_of?, :each, :map, :empty?, :as_json, :is_a?, :to => :values
115
-
116
- def initialize(graph, subject, predicate)
117
- @graph = graph
118
-
119
- @subject = subject
120
- @predicate = predicate
121
- end
122
-
123
- def <<(*values)
124
- values.each { |value| graph.append(subject, predicate, value) }
125
- values
126
- end
127
-
128
- def delete(*values)
129
- values.each do |value|
130
- graph.delete_predicate(subject, predicate, value)
131
- end
132
-
133
- values
134
- end
135
-
136
- def values
137
- values = []
138
-
139
- graph.query(subject, predicate).each do |solution|
140
- v = solution.value
141
- v = v.to_s if v.is_a? RDF::Literal
142
- values << v
143
- end
144
-
145
- values
146
- end
147
-
148
- def method_missing(method, *args, &block)
149
-
150
- if values.respond_to? method
151
- values.send(method, *args, &block)
152
- else
153
- super
154
- end
155
- end
156
- end
157
-
158
39
  attr_accessor :loaded
159
40
  def metadata?
160
41
  true
161
42
  end
162
- def ensure_loaded
163
- end
164
43
 
165
44
  def content
166
45
  serialize
@@ -180,57 +59,21 @@ module ActiveFedora
180
59
  super || content_changed?
181
60
  end
182
61
 
183
- # returns a Hash, e.g.: {field => {:values => [], :type => :something, :behaviors => []}, ...}
184
- def fields
185
- field_map = {}
186
-
187
- rdf_subject = self.rdf_subject
188
- query = RDF::Query.new do
189
- pattern [rdf_subject, :predicate, :value]
190
- end
191
-
192
- query.execute(graph).each do |solution|
193
- predicate = solution.predicate
194
- value = solution.value
195
-
196
- vocab_sym, name = predicate.qname
197
- uri, vocab = self.class.vocabularies.select { |ns, v| v.__prefix__ == vocab_sym }.first
198
- next unless vocab
199
-
200
- config = self.class.config[:predicate_mapping][vocab.to_s]
201
-
202
- name, indexed_as = config.select { |k, v| name.to_s == v.to_s && k.to_s.split("__")[0] == self.class.prefix(name).to_s.split("__")[0]}.first
203
- next unless name and config.has_key?("#{name}__type".to_sym) and config.has_key?("#{name}__behaviors".to_sym)
204
- type = config["#{name}__type".to_sym]
205
- behaviors = config["#{name}__behaviors".to_sym]
206
- field_map[name.to_sym] ||= {:values => [], :type => type, :behaviors => behaviors}
207
- field_map[name.to_sym][:values] << value.to_s
208
- end
209
- field_map
210
- end
211
62
 
212
63
  def to_solr(solr_doc = Hash.new) # :nodoc:
213
64
  fields.each do |field_key, field_info|
214
- values = field_info.fetch(:values, false)
65
+ values = get_values(rdf_subject, field_key)
66
+ directive = Solrizer::Directive.new(field_info[:type], field_info[:behaviors])
215
67
  if values
216
- field_info[:behaviors].each do |index_type|
217
- field_symbol = ActiveFedora::SolrService.solr_name(field_key, field_info[:type], index_type)
218
- values = [values] unless values.respond_to? :each
219
- values.each do |val|
220
- ::Solrizer::Extractor.insert_solr_field_value(solr_doc, field_symbol, val)
221
- end
68
+ Array(values).each do |val|
69
+ val = val.to_s if val.kind_of? RDF::URI
70
+ self.class.create_and_insert_terms(self.class.prefix(field_key), val, directive, solr_doc)
222
71
  end
223
72
  end
224
73
  end
225
74
  solr_doc
226
75
  end
227
76
 
228
- # @param [Symbol, RDF::URI] predicate the predicate to insert into the graph
229
- def find_predicate(predicate)
230
- predicate = self.class.prefix(predicate) unless predicate.kind_of? RDF::URI
231
- result = ActiveFedora::Predicates.find_predicate(predicate)
232
- RDF::URI(result.reverse.join)
233
- end
234
77
 
235
78
  # Populate a RDFDatastream object based on the "datastream" content
236
79
  # Assumes that the datastream contains RDF content
@@ -257,101 +100,10 @@ module ActiveFedora
257
100
  end
258
101
  end
259
102
 
260
- def query subject, predicate, &block
261
- predicate = find_predicate(predicate) unless predicate.kind_of? RDF::URI
262
-
263
- q = RDF::Query.new do
264
- pattern [subject, predicate, :value]
265
- end
266
-
267
- q.execute(graph, &block)
268
- end
269
-
270
- # @param [Symbol, RDF::URI] predicate the predicate to insert into the graph
271
- def get_values(subject, predicate)
272
-
273
- predicate = find_predicate(predicate) unless predicate.kind_of? RDF::URI
274
-
275
- return TermProxy.new(self, subject, predicate)
276
- end
277
-
278
- # if there are any existing statements with this predicate, replace them
279
- # @param [Symbol, RDF::URI] predicate the predicate to insert into the graph
280
-
281
- def set_value(subject, predicate, values)
282
-
283
- predicate = find_predicate(predicate) unless predicate.kind_of? RDF::URI
284
-
285
- delete_predicate(subject, predicate)
286
-
287
- Array(values).each do |arg|
288
- arg = arg.to_s if arg.kind_of? RDF::Literal
289
- next if arg.empty?
290
-
291
- graph.insert([subject, predicate, arg])
292
- end
293
-
294
- return TermProxy.new(self, subject, predicate)
295
- end
296
-
297
- def delete_predicate(subject, predicate, values = nil)
298
- predicate = find_predicate(predicate) unless predicate.kind_of? RDF::URI
299
-
300
- if values.nil?
301
- query = RDF::Query.new do
302
- pattern [subject, predicate, :value]
303
- end
304
-
305
- query.execute(graph).each do |solution|
306
- graph.delete [subject, predicate, solution.value]
307
- end
308
- else
309
- Array(values).each do |v|
310
- graph.delete [subject, predicate, v]
311
- end
312
- end
313
-
314
- end
315
-
316
- # append a value
317
- # @param [Symbol, RDF::URI] predicate the predicate to insert into the graph
318
- def append(subject, predicate, args)
319
- graph.insert([subject, predicate, args])
320
-
321
-
322
- return TermProxy.new(self, subject, predicate)
323
- end
324
-
325
103
  def serialization_format
326
104
  raise "you must override the `serialization_format' method in a subclass"
327
105
  end
328
106
 
329
- def method_missing(name, *args)
330
- if (md = /^([^=]+)=$/.match(name.to_s)) && pred = find_predicate(md[1])
331
- set_value(rdf_subject, pred, *args)
332
- elsif pred = find_predicate(name)
333
- get_values(rdf_subject, name)
334
- else
335
- super
336
- end
337
- rescue ActiveFedora::UnregisteredPredicateError
338
- super
339
- end
340
-
341
- ##
342
- # Get the subject for this rdf/xml datastream
343
- def rdf_subject
344
- @subject ||= begin
345
- s = self.class.rdf_subject.call(self)
346
- s &&= RDF::URI.new(s) if s.is_a? String
347
- s
348
- end
349
- end
350
-
351
- def reset_rdf_subject!
352
- @subject = nil
353
- end
354
-
355
107
  # Creates a RDF datastream for insertion into a Fedora Object
356
108
  # Note: This method is implemented on SemanticNode instead of RelsExtDatastream because SemanticNode contains the relationships array
357
109
  def serialize
@@ -359,6 +111,9 @@ module ActiveFedora
359
111
  RDF::Writer.for(serialization_format).dump(graph)
360
112
  end
361
113
 
114
+
115
+ private
116
+
362
117
  def update_subjects_to_use_a_real_pid!
363
118
  return unless new?
364
119
 
@@ -377,6 +132,30 @@ module ActiveFedora
377
132
 
378
133
  @graph = new_repository
379
134
  end
135
+
136
+ # returns a Hash, e.g.: {field => {:values => [], :type => :something, :behaviors => []}, ...}
137
+ def fields
138
+ field_map = {}
139
+
140
+ rdf_subject = self.rdf_subject
141
+ query = RDF::Query.new do
142
+ pattern [rdf_subject, :predicate, :value]
143
+ end
144
+
145
+ query.execute(graph).each do |solution|
146
+ predicate = solution.predicate
147
+ value = solution.value
148
+
149
+ name, config = self.class.config_for_predicate(predicate)
150
+ next unless config
151
+ type = config[:type]
152
+ behaviors = config[:behaviors]
153
+ next unless type and behaviors
154
+ field_map[name] ||= {:values => [], :type => type, :behaviors => behaviors}
155
+ field_map[name][:values] << value.to_s
156
+ end
157
+ field_map
158
+ end
380
159
  end
381
160
  end
382
161