public/app/models/archival_object.rb
class ArchivalObject < Record
include TreeNodes
include ResourceRequestItems
def parse_notes
rewrite_refs(json['notes'], resource_uri) if resource_uri
super
end
def resource_uri
resolved_resource && resolved_resource['uri']
end
def direct_component_id
if json.has_key?('component_id_inherited')
''
else
json.fetch('component_id', '')
end
end
def instances
json['instances']
end
def finding_aid
# as this shares the same template as resources,
# be clear that this object doesn't have a finding aid
nil
end
def cite
cite = note('prefercite')
unless cite.blank?
cite = strip_mixed_content(cite['note_text'])
else
cite = identifier.blank? ? '' : "#{identifier}, "
cite += strip_mixed_content(display_string)
cite += if container_display.blank? || container_display.length > 5
'.'
else
@citation_container_display ||= parse_container_display(:citation => true).join('; ')
", #{@citation_container_display}."
end
if resolved_resource
ttl = resolved_resource.dig('title')
cite += " #{strip_mixed_content(ttl)}, #{resource_identifier}."
end
cite += " #{ repository_information['top']['name']}." unless !repository_information.dig('top', 'name')
end
"#{cite} #{cite_url_and_timestamp}."
end
def cite_item
cite = note('prefercite')
if !cite.blank?
cite = strip_mixed_content(cite['note_text'])
else
cite = strip_mixed_content(display_string)
cite += identifier.blank? ? '' : ", #{identifier}"
cite += if container_display.blank? || container_display.length > 5
'.'
else
@citation_container_display ||= parse_container_display(:citation => true).join('; ')
", #{@citation_container_display}."
end
if resolved_resource
ttl = resolved_resource.dig('title')
cite += " #{strip_mixed_content(ttl)}, #{resource_identifier}."
end
unless repository_information['top']['name'].blank?
cite += " #{ repository_information['top']['name']}."
end
end
HTMLEntities.new.decode("#{cite}")
end
def cite_item_description
cite = note('prefercite')
if !cite.blank?
cite = strip_mixed_content(cite['note_text'])
else
cite = strip_mixed_content(display_string)
cite += identifier.blank? ? '' : ", #{identifier}"
cite += if container_display.blank? || container_display.length > 5
'.'
else
@citation_container_display ||= parse_container_display(:citation => true).join('; ')
", #{@citation_container_display}."
end
if resolved_resource
ttl = resolved_resource.dig('title')
cite += " #{strip_mixed_content(ttl)}, #{resource_identifier}."
end
unless repository_information['top']['name'].blank?
cite += " #{ repository_information['top']['name']}."
end
end
HTMLEntities.new.decode("#{cite} #{cite_url_and_timestamp}.")
end
def resource_identifier
@resource_identifier ||= resolved_resource ? (
(0..3).collect {|i| resolved_resource.dig("id_#{i}")}.compact.join('-')) : nil
end
def root_node_uri
json.fetch('resource').fetch('ref')
end
#should probably make these configurable options, but for now let's assume anything
#like a "series" or greater is a Collection of some kind.
#and Collections at the archival object level will be diffentiated from collections at the resource level
#in ASpace by the fact that the archival objects will be "partOf" something else.
def level_for_md_mapping
if ['recordgrp', 'subgrp', 'fonds', 'collection', 'series'].include?(json['level'].downcase)
['Collection', 'ArchiveComponent']
else
'ArchiveComponent'
end
end
def parent_for_md_mapping
if json['parent'].try(:any?)
json['parent']['ref']
else
json['resource']['ref']
end
end
def metadata
md = {
'@context' => "http://schema.org/",
'@id' => AppConfig[:public_proxy_url] + uri,
'@type' => level_for_md_mapping,
'name' => display_string,
'identifier' => json['identifier'],
'isPartOf' => AppConfig[:public_proxy_url] + parent_for_md_mapping
}.compact
md['description'] = json['notes'].select {|n| n['type'] == 'abstract'}.map {|abstract|
strip_mixed_content(abstract['content'].join(' '))
}
if md['description'].empty?
md['description'] = json['notes'].select {|n| n['type'] == 'scopecontent'}.map {|scope|
strip_mixed_content(scope['subnotes'].map {|s| s['content']}.join(' '))
}
end
md['description'] = md['description'][0] if md['description'].length == 1
md['creator'] = json['linked_agents'].select {|la| la['role'] == 'creator'}.map {|a| a['_resolved']}.map do |ag|
{
'@id' => AppConfig[:public_proxy_url] + ag['uri'],
'@type' => ag['jsonmodel_type'] == 'agent_person' ? 'Person' : 'Organization',
'name' => ag['title'],
'sameAs' => ag['display_name']['authority_id']
}.compact
end
md['dateCreated'] = @dates.select {|d| d['label'] == 'creation' && ['inclusive', 'single'].include?(d['date_type'])}
.reject {|d| d['_inherited']}
.map do |date| date['final_expression']
end
#just mapping the whole (and direct) extents for now.
md['materialExtent'] = json['extents'].select {|e| e['portion'] == 'whole'}
.reject {|e| e['_inherited']}
.map do |extent|
{
"@type": "QuantitativeValue",
"unitText": I18n.t("enumerations.extent_extent_type.#{extent['extent_type']}"),
"value": extent['number']
}
end
md['isRelatedTo'] = json['notes'].select {|n| n['type'] == 'relatedmaterial'}
.reject {|related| related['_inherited']}
.map {|related| strip_mixed_content(related['subnotes'].map {|text| text['content']}.join(' '))
}
term_type_to_about_type = {
'geographic' => 'Place',
'temporal' => 'TemporalCoverage',
'uniform_title' => 'CreativeWork',
'topical' => 'Intangible',
'occupation' => 'Intangible'
}
md['about'] = json['subjects'].select {|s|
term_type_to_about_type.keys.include?(s['_resolved']['terms'][0]['term_type'])
}.map {|s| s['_resolved']}.map {|subj|
hash = {'@type' => term_type_to_about_type[subj['terms'][0]['term_type']]}
hash['@id'] = subj['authority_id'] if subj['authority_id']
hash['name'] = subj['title']
hash
}
md['about'].concat(json['linked_agents'].select {|la| la['role'] == 'subject'}.map {|a| a['_resolved']}.map {|ag|
{
'@type' => ag['jsonmodel_type'] == 'agent_person' ? 'Person' : 'Organization',
'name' => strip_mixed_content(ag['title']),
}
})
md['genre'] = json['subjects'].select {|s|
s['_resolved']['terms'][0]['term_type'] == 'genre_form'
}.map {|s| s['_resolved']}.map {|subj|
subj['authority_id'] ? subj['authority_id'] : subj['title']
}
#will need to update once more than one language code is allowed
if raw['language']
md['inLanguage'] = {
'@type' => 'Language',
'name' => I18n.t("enumerations.language_iso639_2.#{raw['language']}", :default => raw['language'])
}
end
#will need to update here (and elsewhere) once ASpace allows more than one authority ID.
#also, are there any changes needed now that the PUI has the ability to override the database ids in the URIs?
md['holdingArchive'] = {
'@id' => AppConfig[:public_proxy_url] + raw['repository'],
'@type' => 'ArchiveOrganization',
'name' => json['repository']['_resolved']['name'],
'sameAs' => json['repository']['_resolved']['agent_representation']['_resolved']['display_name']['authority_id']
}.compact
# add repository address to holdingArchive
if repository_information["address"]
md['holdingArchive']["address"] = {
'@type' => 'PostalAddress',
'streetAddress' => repository_information["address"],
'addressLocality' => repository_information["city"],
'addressRegion' => repository_information["region"],
'postalCode' => repository_information["post_code"],
'addressCountry' => repository_information["country"],
}.compact
end
# add repository telephone to holdingArchive
if repository_information['telephones']
md['holdingArchive']['faxNumber'] = repository_information['telephones']
.select {|t| t['number_type'] == 'fax'}
.map {|f| f['number']}
md['holdingArchive']['telephone'] = repository_information['telephones']
.select {|t| t['number_type'] == 'business'}
.map {|b| b['number']}
end
md['holdingArchive'].delete_if { |key, value| value.empty? }
md.delete_if { |key, value| value.empty? }
end
end