Class: ActiveFedora::RDFDatastream

Inherits:
Datastream
  • Object
show all
Defined in:
lib/active_fedora/rdf_datastream.rb

Direct Known Subclasses

NtriplesRDFDatastream, RdfxmlRDFDatastream

Defined Under Namespace

Classes: IndexObject, TermProxy

Class Attribute Summary collapse

Instance Attribute Summary collapse

Attributes inherited from Datastream

#digital_object, #last_modified

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Datastream

#create, #dirty, #dirty=, #dirty?, from_xml, #initialize, #inspect, #new_object?, #profile_from_hash, #save, #serialize!, #solrize_profile, #to_param, #validate_content_present

Constructor Details

This class inherits a constructor from ActiveFedora::Datastream

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object



329
330
331
332
333
334
335
336
337
338
339
# File 'lib/active_fedora/rdf_datastream.rb', line 329

def method_missing(name, *args)
  if (md = /^([^=]+)=$/.match(name.to_s)) && pred = find_predicate(md[1])
    set_value(rdf_subject, pred, *args)  
   elsif pred = find_predicate(name)
    get_values(rdf_subject, name)
  else 
    super
  end
rescue ActiveFedora::UnregisteredPredicateError
  super
end

Class Attribute Details

.vocabulariesObject

Returns the value of attribute vocabularies.



30
31
32
# File 'lib/active_fedora/rdf_datastream.rb', line 30

def vocabularies
  @vocabularies
end

Instance Attribute Details

#loadedObject

Returns the value of attribute loaded.



158
159
160
# File 'lib/active_fedora/rdf_datastream.rb', line 158

def loaded
  @loaded
end

Class Method Details

.configObject



31
32
33
# File 'lib/active_fedora/rdf_datastream.rb', line 31

def config
  ActiveFedora::Predicates.predicate_config
end

.map_predicates {|_self| ... } ⇒ Object

Yields:

  • (_self)

Yield Parameters:



65
66
67
# File 'lib/active_fedora/rdf_datastream.rb', line 65

def map_predicates(&block)
  yield self
end

.method_missing(name, *args, &block) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/active_fedora/rdf_datastream.rb', line 68

def method_missing(name, *args, &block)
  args = args.first if args.respond_to? :first
  raise "mapping must specify RDF vocabulary as :in argument" unless args.has_key? :in
  vocab = args[:in]
  predicate = args.fetch(:to, name)
  raise "Vocabulary '#{vocab.inspect}' does not define property '#{predicate.inspect}'" unless vocab.respond_to? predicate
  indexing = false
  if block_given?
    # needed for solrizer integration
    indexing = true
    iobj = IndexObject.new
    yield iobj
    data_type = iobj.data_type
    behaviors = iobj.behaviors
  end
  # needed for AF::Predicates integration & drives all other
  # functionality below
  vocab = vocab.to_s
  name = self.prefix(name)
  if config
    if config[:predicate_mapping].has_key? vocab
      config[:predicate_mapping][vocab][name] = predicate
    else
      config[:predicate_mapping][vocab] = { name => predicate } 
    end
    # stuff data_type and behaviors in there for to_solr support
    config[:predicate_mapping][vocab]["#{name}__type".to_sym] = data_type if indexing
    config[:predicate_mapping][vocab]["#{name}__behaviors".to_sym] = behaviors if indexing
  else
    config = {
      :default_namespace => vocab,
      :predicate_mapping => {
        vocab => { name => predicate }
      }
    }
    # stuff data_type and behaviors in there for to_solr support
    config[:predicate_mapping][vocab]["#{name}__type".to_sym] = data_type if indexing
    config[:predicate_mapping][vocab]["#{name}__behaviors".to_sym] = behaviors if indexing
  end
end

.prefix(name) ⇒ Object



34
35
36
37
38
# File 'lib/active_fedora/rdf_datastream.rb', line 34

def prefix(name)
  name = name.to_s unless name.is_a? String
  pre = self.to_s.sub(/RDFDatastream$/i, '').underscore
  return "#{pre}__#{name}".to_sym
end

.rdf_subject {|ds| ... } ⇒ Object

Register a ruby block that evaluates to the subject of the graph By default, the block returns the current object’s pid

Yields:

  • (ds)

    ‘ds’ is the datastream instance



44
45
46
47
48
49
50
# File 'lib/active_fedora/rdf_datastream.rb', line 44

def rdf_subject &block
  if block_given?
     return @subject_block = block
  end

  @subject_block ||= lambda { |ds| RDF::URI.new("info:fedora/#{ds.pid}") }
end

.register_vocabularies(*vocabs) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/active_fedora/rdf_datastream.rb', line 52

def register_vocabularies(*vocabs)
  @vocabularies ||= {}
  vocabs.each do |v|
    if v.is_a?(RDF::Vocabulary) or (v.respond_to? :property and v.respond_to? :to_uri)
      @vocabularies[v.to_uri] = v 
    else
      raise "not an RDF vocabulary: #{v}"
    end
  end
  ActiveFedora::Predicates.vocabularies(@vocabularies)
  @vocabularies
end

Instance Method Details

#append(subject, predicate, args) ⇒ Object

append a value

Parameters:

  • predicate (Symbol, RDF::URI)

    the predicate to insert into the graph



318
319
320
321
322
323
# File 'lib/active_fedora/rdf_datastream.rb', line 318

def append(subject, predicate, args)
  graph.insert([subject, predicate, args])


  return TermProxy.new(self, subject, predicate)
end

#changed?Boolean

Returns:

  • (Boolean)


179
180
181
# File 'lib/active_fedora/rdf_datastream.rb', line 179

def changed?
  super || content_changed?
end

#contentObject



165
166
167
# File 'lib/active_fedora/rdf_datastream.rb', line 165

def content
  serialize
end

#content=(content) ⇒ Object



169
170
171
172
# File 'lib/active_fedora/rdf_datastream.rb', line 169

def content=(content)
  self.loaded = true
  @graph = deserialize(content)
end

#content_changed?Boolean

Returns:

  • (Boolean)


174
175
176
177
# File 'lib/active_fedora/rdf_datastream.rb', line 174

def content_changed?
  return false if new? and !loaded
  super
end

#delete_predicate(subject, predicate, values = nil) ⇒ Object



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/active_fedora/rdf_datastream.rb', line 297

def delete_predicate(subject, predicate, values = nil)
  predicate = find_predicate(predicate) unless predicate.kind_of? RDF::URI

  if values.nil?
    query = RDF::Query.new do
      pattern [subject, predicate, :value]
    end

    query.execute(graph).each do |solution|
      graph.delete [subject, predicate, solution.value]
    end
  else
    Array(values).each do |v|
      graph.delete [subject, predicate, v]
    end
  end

end

#deserialize(data = nil) ⇒ Object

Populate a RDFDatastream object based on the “datastream” content Assumes that the datastream contains RDF content

Parameters:

  • data (String) (defaults to: nil)

    the “rdf” node



238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/active_fedora/rdf_datastream.rb', line 238

def deserialize(data = nil)
  repository = RDF::Repository.new
  return repository if new? and data.nil?

  data ||= datastream_content

  RDF::Reader.for(serialization_format).new(data) do |reader|
    reader.each_statement do |statement|
      repository << statement
    end
  end

  repository
end

#ensure_loadedObject



162
163
# File 'lib/active_fedora/rdf_datastream.rb', line 162

def ensure_loaded
end

#fieldsObject

returns a Hash, e.g.: => {:values => [], :type => :something, :behaviors => [], …}



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/active_fedora/rdf_datastream.rb', line 184

def fields
  field_map = {}

  rdf_subject = self.rdf_subject
  query = RDF::Query.new do
    pattern [rdf_subject, :predicate, :value]
  end

  query.execute(graph).each do |solution|
    predicate = solution.predicate
    value = solution.value
    
    vocab_sym, name = predicate.qname
    uri, vocab = self.class.vocabularies.select { |ns, v| v.__prefix__ == vocab_sym }.first
    next unless vocab

    config = self.class.config[:predicate_mapping][vocab.to_s]

    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
    next unless name and config.has_key?("#{name}__type".to_sym) and config.has_key?("#{name}__behaviors".to_sym)
    type = config["#{name}__type".to_sym]
    behaviors = config["#{name}__behaviors".to_sym]
    field_map[name.to_sym] ||= {:values => [], :type => type, :behaviors => behaviors}
    field_map[name.to_sym][:values] << value.to_s
  end
  field_map
end

#find_predicate(predicate) ⇒ Object

Parameters:

  • predicate (Symbol, RDF::URI)

    the predicate to insert into the graph



229
230
231
232
233
# File 'lib/active_fedora/rdf_datastream.rb', line 229

def find_predicate(predicate)
  predicate = self.class.prefix(predicate) unless predicate.kind_of? RDF::URI
  result = ActiveFedora::Predicates.find_predicate(predicate)
  RDF::URI(result.reverse.join)
end

#get_values(subject, predicate) ⇒ Object

Parameters:

  • predicate (Symbol, RDF::URI)

    the predicate to insert into the graph



271
272
273
274
275
276
# File 'lib/active_fedora/rdf_datastream.rb', line 271

def get_values(subject, predicate)

  predicate = find_predicate(predicate) unless predicate.kind_of? RDF::URI

  return TermProxy.new(self, subject, predicate)
end

#graphObject



253
254
255
256
257
258
# File 'lib/active_fedora/rdf_datastream.rb', line 253

def graph
  @graph ||= begin
    self.loaded = true
    deserialize
  end      
end

#metadata?Boolean

Returns:

  • (Boolean)


159
160
161
# File 'lib/active_fedora/rdf_datastream.rb', line 159

def metadata?
  true
end

#query(subject, predicate, &block) ⇒ Object



260
261
262
263
264
265
266
267
268
# File 'lib/active_fedora/rdf_datastream.rb', line 260

def query subject, predicate, &block
  predicate = find_predicate(predicate) unless predicate.kind_of? RDF::URI
  
  q = RDF::Query.new do
    pattern [subject, predicate, :value]
  end

  q.execute(graph, &block)
end

#rdf_subjectObject

Get the subject for this rdf/xml datastream



343
344
345
346
347
348
349
# File 'lib/active_fedora/rdf_datastream.rb', line 343

def rdf_subject
  @subject ||= begin
    s = self.class.rdf_subject.call(self)
    s &&= RDF::URI.new(s) if s.is_a? String
    s
  end
end

#reset_rdf_subject!Object



351
352
353
# File 'lib/active_fedora/rdf_datastream.rb', line 351

def reset_rdf_subject!
  @subject = nil
end

#serialization_formatObject



325
326
327
# File 'lib/active_fedora/rdf_datastream.rb', line 325

def serialization_format
  raise "you must override the `serialization_format' method in a subclass"
end

#serializeObject

Creates a RDF datastream for insertion into a Fedora Object Note: This method is implemented on SemanticNode instead of RelsExtDatastream because SemanticNode contains the relationships array



357
358
359
360
# File 'lib/active_fedora/rdf_datastream.rb', line 357

def serialize
  update_subjects_to_use_a_real_pid!
  RDF::Writer.for(serialization_format).dump(graph)
end

#set_value(subject, predicate, values) ⇒ Object

if there are any existing statements with this predicate, replace them

Parameters:

  • predicate (Symbol, RDF::URI)

    the predicate to insert into the graph



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/active_fedora/rdf_datastream.rb', line 281

def set_value(subject, predicate, values)
  
  predicate = find_predicate(predicate) unless predicate.kind_of? RDF::URI

  delete_predicate(subject, predicate)

  Array(values).each do |arg|
    arg = arg.to_s if arg.kind_of? RDF::Literal
    next if arg.empty?

    graph.insert([subject, predicate, arg])
  end

  return TermProxy.new(self, subject, predicate)
end

#to_solr(solr_doc = Hash.new) ⇒ Object

:nodoc:



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/active_fedora/rdf_datastream.rb', line 212

def to_solr(solr_doc = Hash.new) # :nodoc:
  fields.each do |field_key, field_info|
    values = field_info.fetch(:values, false)
    if values
      field_info[:behaviors].each do |index_type|
        field_symbol = ActiveFedora::SolrService.solr_name(field_key, field_info[:type], index_type)
        values = [values] unless values.respond_to? :each
        values.each do |val|    
          ::Solrizer::Extractor.insert_solr_field_value(solr_doc, field_symbol, val)         
        end
      end
    end
  end
  solr_doc
end

#update_subjects_to_use_a_real_pid!Object



362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/active_fedora/rdf_datastream.rb', line 362

def update_subjects_to_use_a_real_pid!
  return unless new?

  bad_subject = rdf_subject
  reset_rdf_subject!
  new_subject = rdf_subject

  new_repository = RDF::Repository.new

  graph.each_statement do |statement|
      subject = statement.subject

      subject &&= new_subject if subject == bad_subject
      new_repository << [subject, statement.predicate, statement.object]
  end

  @graph = new_repository
end