Class: ActiveFedora::Rdf::Resource

Inherits:
RDF::Graph
  • Object
show all
Extended by:
Configurable, Properties, Deprecation
Includes:
NestedAttributes
Defined in:
lib/active_fedora/rdf/resource.rb

Overview

Defines a generic RDF ‘Resource` as an RDF::Graph with property configuration, accessors, and some other methods for managing resources as discrete subgraphs which can be maintained by a Hydra datastream model.

Resources can be instances of ActiveFedora::Rdf::Resource directly, but more often they will be instances of subclasses with registered properties and configuration. e.g.

class License < Resource
  configure repository: :default
  property :title, predicate: RDF::DC.title, class_name: RDF::Literal do |index|
    index.as :displayable, :facetable
  end
end

Direct Known Subclasses

List::ListResource, ObjectResource

Instance Attribute Summary collapse

Attributes included from Properties

#config

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Configurable

configure, rdf_type, transform_type

Methods included from Properties

config_for_term_or_uri, map_predicates, property

Constructor Details

#initialize(*args, &block) ⇒ Resource

Initialize an instance of this resource class. Defaults to a blank node subject. In addition to RDF::Graph parameters, you can pass in a URI and/or a parent to build a resource from a existing data.

You can pass in only a parent with:

Resource.new(nil, parent)

See Also:

  • RDF::Graph


53
54
55
56
57
58
59
60
61
# File 'lib/active_fedora/rdf/resource.rb', line 53

def initialize(*args, &block)
  resource_uri = args.shift unless args.first.is_a?(Hash)
  self.parent = args.shift unless args.first.is_a?(Hash)
  set_subject!(resource_uri) if resource_uri
  super(*args, &block)
  reload
  # Append type to graph if necessary.
  self.get_values(:type) << self.class.type if self.class.type.kind_of?(RDF::URI) && type.empty?
end

Instance Attribute Details

#parentObject

Returns the value of attribute parent.



24
25
26
# File 'lib/active_fedora/rdf/resource.rb', line 24

def parent
  @parent
end

Class Method Details

.from_uri(uri, vals = nil) ⇒ Object

Adapter for a consistent interface for creating a new node from a URI. Similar functionality should exist in all objects which can become a node.



34
35
36
# File 'lib/active_fedora/rdf/resource.rb', line 34

def from_uri(uri,vals=nil)
  new(uri, vals)
end

.type_registryObject



27
28
29
# File 'lib/active_fedora/rdf/resource.rb', line 27

def type_registry
  @@type_registry ||= {}
end

Instance Method Details

#attributes=(values) ⇒ Object

Raises:

  • (ArgumentError)


78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/active_fedora/rdf/resource.rb', line 78

def attributes=(values)
  raise ArgumentError, "values must be a Hash, you provided #{values.class}" unless values.kind_of? Hash
  values = values.with_indifferent_access
  set_subject!(values.delete(:id)) if values.has_key?(:id) and node?
  values.each do |key, value|
    if properties.keys.include?(key)
      set_value(rdf_subject, key, value)
    elsif self.singleton_class.nested_attributes_options.keys.map{ |k| "#{k}_attributes"}.include?(key)
      send("#{key}=".to_sym, value)
    else
      raise ArgumentError, "No association found for name `#{key}'. Has it been defined yet?"
    end
  end
end

#base_uriObject



106
107
108
# File 'lib/active_fedora/rdf/resource.rb', line 106

def base_uri
  self.class.base_uri
end

#destroyObject



248
249
250
251
252
# File 'lib/active_fedora/rdf/resource.rb', line 248

def destroy
  clear
  persist!
  parent.destroy_child(self)
end

#destroy_child(child) ⇒ Object



254
255
256
257
258
# File 'lib/active_fedora/rdf/resource.rb', line 254

def destroy_child(child)
  statements.each do |statement|
    delete_statement(statement) if statement.subject == child.rdf_subject || statement.object == child.rdf_subject
  end
end

#fetchObject

Load data from URI



138
139
140
141
# File 'lib/active_fedora/rdf/resource.rb', line 138

def fetch
  load(rdf_subject)
  self
end

#fieldsObject



132
133
134
# File 'lib/active_fedora/rdf/resource.rb', line 132

def fields
  properties.keys.map(&:to_sym).reject{|x| x == :type}
end

#final_parentObject



68
69
70
71
72
73
74
75
76
# File 'lib/active_fedora/rdf/resource.rb', line 68

def final_parent
  @final_parent ||= begin
    parent = self.parent
    while parent && parent.parent && parent.parent != parent
      parent = parent.parent
    end
    parent
  end
end

#get_term(args) ⇒ Object



210
211
212
213
214
215
# File 'lib/active_fedora/rdf/resource.rb', line 210

def get_term(args)
  @term_cache ||= {}
  term = ActiveFedora::Rdf::Term.new(self, args)
  @term_cache["#{term.rdf_subject}/#{term.property}"] ||= term
  @term_cache["#{term.rdf_subject}/#{term.property}"]
end

#get_values(*args) ⇒ Object

Returns an array of values belonging to the property requested. Elements in the array may RdfResource objects or a valid datatype.

Handles two argument patterns. The recommended pattern is:

get_values(property)

For backwards compatibility, there is support for explicitly passing the rdf_subject to be used in th statement:

get_values(uri, property)


206
207
208
# File 'lib/active_fedora/rdf/resource.rb', line 206

def get_values(*args)
  get_term(args)
end

#graphObject



63
64
65
66
# File 'lib/active_fedora/rdf/resource.rb', line 63

def graph
  Deprecation.warn Resource, "graph is redundant & deprecated. It will be removed in active-fedora 8.0.0.", caller
  self
end

#mark_for_destructionObject



270
271
272
# File 'lib/active_fedora/rdf/resource.rb', line 270

def mark_for_destruction
  @marked_for_destruction = true
end

#marked_for_destruction?Boolean

Returns:

  • (Boolean)


274
275
276
# File 'lib/active_fedora/rdf/resource.rb', line 274

def marked_for_destruction?
  @marked_for_destruction
end

#new_record?Boolean

Returns:

  • (Boolean)


260
261
262
# File 'lib/active_fedora/rdf/resource.rb', line 260

def new_record?
  not persisted?
end

#node?Boolean

Returns:

  • (Boolean)


97
98
99
100
# File 'lib/active_fedora/rdf/resource.rb', line 97

def node?
  return true if rdf_subject.kind_of? RDF::Node
  false
end

#persist!Object



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/active_fedora/rdf/resource.rb', line 143

def persist!
  raise "failed when trying to persist to non-existant repository or parent resource" unless repository
  repository.delete [rdf_subject,nil,nil] unless node?
  if node?
    repository.statements.each do |statement|
      repository.send(:delete_statement, statement) if statement.subject == rdf_subject
    end
  end
  repository << self
  @persisted = true
end

#persisted?Boolean

Returns:

  • (Boolean)


155
156
157
158
159
# File 'lib/active_fedora/rdf/resource.rb', line 155

def persisted?
  @persisted ||= false
  return (@persisted and parent.persisted?) if parent
  @persisted
end

#rdf_labelObject

Look for labels in various default fields, prioritizing configured label fields



122
123
124
125
126
127
128
129
130
# File 'lib/active_fedora/rdf/resource.rb', line 122

def rdf_label
  labels = Array(self.class.rdf_label)
  labels += default_labels
  labels.each do |label|
    values = get_values(label)
    return values unless values.empty?
  end
  node? ? [] : [rdf_subject.to_s]
end

#rdf_subjectObject



93
94
95
# File 'lib/active_fedora/rdf/resource.rb', line 93

def rdf_subject
  @rdf_subject ||= RDF::Node.new
end

#reloadObject

Repopulates the graph from the repository or parent resource.



163
164
165
166
167
168
169
170
171
172
173
# File 'lib/active_fedora/rdf/resource.rb', line 163

def reload
  @term_cache ||= {}
  if self.class.repository == :parent
    return false if final_parent.nil?
  end
  self << repository.query(subject: rdf_subject)
  unless empty?
    @persisted = true
  end
  true
end

#set_subject!(uri_or_str) ⇒ Object

Set a new rdf_subject for the resource.

This raises an error if the current subject is not a blank node, and returns false if it can’t figure out how to make a URI from the param. Otherwise it creates a URI for the resource and rebuilds the graph with the updated URI.

Will try to build a uri as an extension of the class’s base_uri if appropriate.

Parameters:

  • uri_or_str (#to_uri, #to_s)

    the uri or string to use



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/active_fedora/rdf/resource.rb', line 229

def set_subject!(uri_or_str)
  raise "Refusing update URI when one is already assigned!" unless node?
  # Refusing set uri to an empty string.
  return false if uri_or_str.nil? or uri_or_str.to_s.empty?
  # raise "Refusing update URI! This object is persisted to a datastream." if persisted?
  old_subject = rdf_subject
  @rdf_subject = get_uri(uri_or_str)

  each_statement do |statement|
    if statement.subject == old_subject
      delete(statement)
      self << RDF::Statement.new(rdf_subject, statement.predicate, statement.object)
    elsif statement.object == old_subject
      delete(statement)
      self << RDF::Statement.new(statement.subject, statement.predicate, rdf_subject)
    end
  end
end

#set_value(*args) ⇒ Object

Note:

This method will delete existing statements with the correct subject and predicate from the graph

Adds or updates a property with supplied values.

Handles two argument patterns. The recommended pattern is:

set_value(property, values)

For backwards compatibility, there is support for explicitly passing the rdf_subject to be used in the statement:

set_value(uri, property, values)


186
187
188
189
190
191
192
193
# File 'lib/active_fedora/rdf/resource.rb', line 186

def set_value(*args)
  # Add support for legacy 3-parameter syntax
  if args.length > 3 || args.length < 2
    raise ArgumentError("wrong number of arguments (#{args.length} for 2-3)")
  end
  values = args.pop
  get_term(args).set(values)
end

#solrizeString

Returns the string to index in solr.

Returns:

  • (String)

    the string to index in solr



266
267
268
# File 'lib/active_fedora/rdf/resource.rb', line 266

def solrize
  node? ? rdf_label : rdf_subject.to_s
end

#to_termObject



102
103
104
# File 'lib/active_fedora/rdf/resource.rb', line 102

def to_term
  rdf_subject
end

#typeObject



110
111
112
# File 'lib/active_fedora/rdf/resource.rb', line 110

def type
  self.get_values(:type).to_a.map{|x| x.rdf_subject}
end

#type=(type) ⇒ Object



114
115
116
117
# File 'lib/active_fedora/rdf/resource.rb', line 114

def type=(type)
  raise "Type must be an RDF::URI" unless type.kind_of? RDF::URI
  self.update(RDF::Statement.new(rdf_subject, RDF.type, type))
end

#writable?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/active_fedora/rdf/resource.rb', line 39

def writable?
  !frozen?
end