hydra-mods 0.0.1
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.
- data/Gemfile +3 -0
- data/Rakefile +3 -0
- data/app/models/hydra/datastream/common_mods_index_methods.rb +47 -0
- data/app/models/hydra/datastream/mods_article.rb +533 -0
- data/app/models/hydra/datastream/mods_basic.rb +235 -0
- data/app/models/hydra/datastream/mods_dataset.rb +176 -0
- data/app/models/hydra/datastream/mods_generic_content.rb +501 -0
- data/app/models/hydra/datastream/mods_image.rb +500 -0
- data/app/models/mods_asset.rb +24 -0
- data/hydra-mods.gemspec +20 -0
- data/lib/hydra-mods.rb +9 -0
- data/lib/hydra/common_mods_index_methods.rb +46 -0
- data/lib/hydra/model_mixins/mods_object.rb +19 -0
- data/lib/hydra/mods.rb +14 -0
- data/lib/hydra/mods_article.rb +535 -0
- data/lib/hydra/mods_dataset.rb +177 -0
- data/lib/hydra/mods_generic_content.rb +500 -0
- data/lib/hydra/mods_image.rb +500 -0
- data/lib/uva/mods_index_methods.rb +30 -0
- metadata +82 -0
@@ -0,0 +1,235 @@
|
|
1
|
+
require 'active_fedora'
|
2
|
+
require 'hydra/datastream/common_mods_index_methods'
|
3
|
+
|
4
|
+
# Datastream that uses a Generic MODS Terminology; essentially an exemplar.
|
5
|
+
module Hydra
|
6
|
+
module Datastream
|
7
|
+
class ModsBasic < ActiveFedora::NokogiriDatastream
|
8
|
+
include Hydra::Datastream::CommonModsIndexMethods
|
9
|
+
|
10
|
+
# MODS XML constants.
|
11
|
+
MODS_NS = 'http://www.loc.gov/mods/v3'
|
12
|
+
MODS_SCHEMA = 'http://www.loc.gov/standards/mods/v3/mods-3-4.xsd'
|
13
|
+
|
14
|
+
# OM terminology
|
15
|
+
# this is meant to be a fairly simple MODS example. For more complex MODS and other XML, look at the
|
16
|
+
# OM integration tests https://github.com/projecthydra/om/tree/master/spec/integration
|
17
|
+
# and at OM documentation
|
18
|
+
set_terminology do |t|
|
19
|
+
t.root(:path=>"mods", :xmlns => MODS_NS, :schema => MODS_SCHEMA)
|
20
|
+
|
21
|
+
t.title_info(:path=>"titleInfo", :index_as => [:not_searchable]) {
|
22
|
+
t.title
|
23
|
+
t.subtitle(:path=>"subTitle")
|
24
|
+
}
|
25
|
+
t.main_title(:proxy => [:title_info, :title])
|
26
|
+
|
27
|
+
t.identifier
|
28
|
+
t.doi(:ref=>:identifier, :attributes=>{:type=>"doi"})
|
29
|
+
t.uri(:ref=>:identifier, :attributes=>{:type=>"uri"})
|
30
|
+
|
31
|
+
t.abstract
|
32
|
+
|
33
|
+
t.subject(:index_as => [:not_searchable]) {
|
34
|
+
t.topic
|
35
|
+
}
|
36
|
+
t.topic_tag(:path=>"subject", :default_content_path=>"topic", :index_as=>[:facetable])
|
37
|
+
|
38
|
+
# This is a mods:name. The underscore is purely to avoid namespace conflicts.
|
39
|
+
t.name_(:index_as => [:not_searchable]) {
|
40
|
+
t.namePart(:type=>:string, :label=>"generic name")
|
41
|
+
t.role(:ref=>[:role]) # see role below
|
42
|
+
t.date(:path=>"namePart", :attributes=>{:type=>"date"})
|
43
|
+
t.last_name(:path=>"namePart", :attributes=>{:type=>"family"})
|
44
|
+
t.first_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
|
45
|
+
}
|
46
|
+
|
47
|
+
t.role(:index_as => [:not_searchable]) {
|
48
|
+
t.text(:path=>"roleTerm",:attributes=>{:type=>"text"})
|
49
|
+
t.code(:path=>"roleTerm",:attributes=>{:type=>"code"})
|
50
|
+
}
|
51
|
+
|
52
|
+
# :ref and :proxy can be used for convenience
|
53
|
+
t.person(:ref=>:name, :attributes=>{:type=>"personal"}, :index_as=>[:facetable])
|
54
|
+
t.organization(:ref=>:name, :attributes=>{:type=>"corporate"}, :index_as=>[:facetable])
|
55
|
+
t.conference(:ref=>:name, :attributes=>{:type=>"conference"}, :index_as=>[:facetable])
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
# accessor :title, :term=>[:mods, :title_info, :main_title]
|
60
|
+
|
61
|
+
# Generates an empty Mods Generic Content (used when you call ModsGenericContent.new without passing in existing xml)
|
62
|
+
# this is necessary to create new objects
|
63
|
+
def self.xml_template
|
64
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
65
|
+
xml.mods(:version=>"3.4", "xmlns:xlink"=>"http://www.w3.org/1999/xlink",
|
66
|
+
"xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
|
67
|
+
"xmlns"=>MODS_NS,
|
68
|
+
"xsi:schemaLocation"=>"#{MODS_NS} #{MODS_SCHEMA}") {
|
69
|
+
xml.titleInfo(:lang=>"") {
|
70
|
+
xml.title
|
71
|
+
}
|
72
|
+
xml.name(:type=>"personal") {
|
73
|
+
xml.namePart(:type=>"given")
|
74
|
+
xml.namePart(:type=>"family")
|
75
|
+
xml.role {
|
76
|
+
xml.roleTerm(:authority=>"marcrelator", :type=>"text")
|
77
|
+
}
|
78
|
+
}
|
79
|
+
xml.abstract
|
80
|
+
xml.identifier(:type=>"uri")
|
81
|
+
xml.subject {
|
82
|
+
xml.topic
|
83
|
+
}
|
84
|
+
}
|
85
|
+
end
|
86
|
+
return builder.doc
|
87
|
+
end
|
88
|
+
|
89
|
+
# create a new :person node in the xml
|
90
|
+
def insert_person
|
91
|
+
insert_new_node(:person)
|
92
|
+
end
|
93
|
+
|
94
|
+
# create a new :organization node in the xml
|
95
|
+
def insert_organization
|
96
|
+
insert_new_node(:organization)
|
97
|
+
end
|
98
|
+
|
99
|
+
# create a new :conference node in the xml
|
100
|
+
def insert_conference
|
101
|
+
insert_new_node(:conference)
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
# FIXME: this method should probably get pushed down to OM
|
106
|
+
# Create a new node and insert it into the document after existing term nodes, or as a child of root if no such term nodes exist
|
107
|
+
# PREREQ: term_template method must exist and should return node ready for insertion into DOM
|
108
|
+
# @param term the symbol for an OM term with a corresponding _template method
|
109
|
+
def insert_new_node(term)
|
110
|
+
node = self.class.send("#{term.to_s}_template")
|
111
|
+
nodeset = self.find_by_terms(term)
|
112
|
+
|
113
|
+
unless nodeset.nil?
|
114
|
+
if nodeset.empty?
|
115
|
+
self.ng_xml.root.add_child(node)
|
116
|
+
index = 0
|
117
|
+
else
|
118
|
+
nodeset.after(node)
|
119
|
+
index = nodeset.length
|
120
|
+
end
|
121
|
+
self.dirty = true
|
122
|
+
end
|
123
|
+
return node, index
|
124
|
+
end
|
125
|
+
|
126
|
+
# FIXME: this method should probably get pushed down to OM
|
127
|
+
# a model might have a wrapping method like remove_organization
|
128
|
+
# Remove the node identified by the OM term and index
|
129
|
+
# @param term the OM term to be removed
|
130
|
+
# @param index the index of the OM term (e.g. the 2nd :person node)
|
131
|
+
def remove_node(term, index)
|
132
|
+
node = self.find_by_terms(term.to_sym => index.to_i).first
|
133
|
+
unless node.nil?
|
134
|
+
node.remove
|
135
|
+
self.dirty = true
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
# These templates are used when a non-trivial node needs to be added to the mods xml. See insert_new_node above
|
141
|
+
|
142
|
+
# Generates a new :person node
|
143
|
+
# Uses mods:name[@type="personal"]
|
144
|
+
def self.person_template
|
145
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
146
|
+
xml.name(:type=>"personal") {
|
147
|
+
xml.namePart(:type=>"family")
|
148
|
+
xml.namePart(:type=>"given")
|
149
|
+
xml.affiliation
|
150
|
+
xml.role {
|
151
|
+
xml.roleTerm(:type=>"text")
|
152
|
+
}
|
153
|
+
}
|
154
|
+
end
|
155
|
+
return builder.doc.root
|
156
|
+
end
|
157
|
+
|
158
|
+
# Generates a new :organization node
|
159
|
+
# Uses mods:name[@type="corporate"]
|
160
|
+
def self.organization_template
|
161
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
162
|
+
xml.name(:type=>"corporate") {
|
163
|
+
xml.namePart
|
164
|
+
xml.role {
|
165
|
+
xml.roleTerm(:authority=>"marcrelator", :type=>"text")
|
166
|
+
}
|
167
|
+
}
|
168
|
+
end
|
169
|
+
return builder.doc.root
|
170
|
+
end
|
171
|
+
|
172
|
+
# Generates a new :conference node
|
173
|
+
# Uses mods:name[@type="conference"]
|
174
|
+
def self.conference_template
|
175
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
176
|
+
xml.name(:type=>"conference") {
|
177
|
+
xml.namePart
|
178
|
+
xml.role {
|
179
|
+
xml.roleTerm(:authority=>"marcrelator", :type=>"text")
|
180
|
+
}
|
181
|
+
}
|
182
|
+
end
|
183
|
+
return builder.doc.root
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
# override OM method for (FIXME: why?) some reason
|
188
|
+
def to_solr(solr_doc=Hash.new)
|
189
|
+
super(solr_doc)
|
190
|
+
solr_doc.merge!(extract_person_full_names)
|
191
|
+
solr_doc.merge!(extract_person_organizations)
|
192
|
+
solr_doc.merge!(:object_type_facet => "Generic Mods content")
|
193
|
+
solr_doc
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
# additional methods specific to this model
|
198
|
+
|
199
|
+
# FIXME: this should move to mods behavior module and/or mods gem ?
|
200
|
+
# these are a selected subset from http://id.loc.gov/vocabulary/relators.html
|
201
|
+
def self.person_relator_terms
|
202
|
+
{"aut" => "Author",
|
203
|
+
"clb" => "Collaborator",
|
204
|
+
"com" => "Compiler",
|
205
|
+
"cre" => "Creator",
|
206
|
+
"ctb" => "Contributor",
|
207
|
+
"edt" => "Editor",
|
208
|
+
"ill" => "Illustrator",
|
209
|
+
"res" => "Researcher",
|
210
|
+
"rth" => "Research team head",
|
211
|
+
"rtm" => "Research team member",
|
212
|
+
"trl" => "Translator"
|
213
|
+
}
|
214
|
+
end
|
215
|
+
|
216
|
+
# FIXME: this should move to mods behavior module and/or mods gem ?
|
217
|
+
# these are a selected subset from http://id.loc.gov/vocabulary/relators.html
|
218
|
+
def self.conference_relator_terms
|
219
|
+
{"hst" => "Host"
|
220
|
+
}
|
221
|
+
end
|
222
|
+
|
223
|
+
# FIXME: this should move to mods behavior module and/or mods gem ?
|
224
|
+
# these are a selected subset from http://id.loc.gov/vocabulary/relators.html
|
225
|
+
def self.organization_relator_terms
|
226
|
+
{"fnd" => "Funder",
|
227
|
+
"hst" => "Host"
|
228
|
+
}
|
229
|
+
end
|
230
|
+
|
231
|
+
end # class ModsBasic
|
232
|
+
end # module Datastream
|
233
|
+
end # module Hydra
|
234
|
+
|
235
|
+
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'active_fedora'
|
2
|
+
require 'hydra/datastream/common_mods_index_methods'
|
3
|
+
|
4
|
+
# @deprecated Leftover from Hydrangea work; this should be moved to documentation as an EXAMPLE, and will be removed no later than release 6.x
|
5
|
+
module Hydra
|
6
|
+
module Datastream
|
7
|
+
class ModsDataset < ActiveFedora::NokogiriDatastream
|
8
|
+
include Hydra::Datastream::CommonModsIndexMethods
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
ActiveSupport::Deprecation.warn("Hydra:Datastream:ModsDataset is deprecated and will be removed in release 5 or 6. It has been moved into wiki documentation here: https://github.com/projecthydra/hydra-head/wiki/Models---Some-Examples")
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
set_terminology do |t|
|
16
|
+
t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3", :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd")
|
17
|
+
|
18
|
+
# Common MODS info -- might eventually be put into its own shared terminology.
|
19
|
+
|
20
|
+
t.title_info(:path=>"titleInfo") {
|
21
|
+
t.main_title(:path=>"title", :label=>"title")
|
22
|
+
t.language(:path=>{:attribute=>"lang"})
|
23
|
+
}
|
24
|
+
t.title(:proxy=>[:title_info, :main_title])
|
25
|
+
t.abstract
|
26
|
+
t.subject {
|
27
|
+
t.topic(:index_as=>[:facetable])
|
28
|
+
}
|
29
|
+
t.topic_tag(:path=>"subject", :default_content_path=>"topic")
|
30
|
+
t.identifier {
|
31
|
+
t.type_(:path=>{:attribute=>"type"})
|
32
|
+
}
|
33
|
+
# This is a mods:name. The underscore is purely to avoid namespace conflicts.
|
34
|
+
t.name_ {
|
35
|
+
t.namePart(:index_as=>[:searchable, :displayable, :facetable, :sortable], :required=>:true, :type=>:string, :label=>"generic name")
|
36
|
+
t.affiliation
|
37
|
+
t.institution(:path=>"affiliation")
|
38
|
+
t.displayForm
|
39
|
+
t.role(:ref=>[:role])
|
40
|
+
t.description
|
41
|
+
t.date(:path=>"namePart", :attributes=>{:type=>"date"})
|
42
|
+
t.last_name(:path=>"namePart", :attributes=>{:type=>"family"})
|
43
|
+
t.first_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
|
44
|
+
t.terms_of_address(:path=>"namePart", :attributes=>{:type=>"termsOfAddress"})
|
45
|
+
}
|
46
|
+
# lookup :person, :first_name
|
47
|
+
t.person(:ref=>:name, :attributes=>{:type=>"personal"})
|
48
|
+
t.organization(:ref=>:name, :attributes=>{:type=>"institutional"})
|
49
|
+
t.conference(:ref=>:name, :attributes=>{:type=>"conference"})
|
50
|
+
|
51
|
+
t.role {
|
52
|
+
t.text(:path=>"roleTerm",:attributes=>{:type=>"text"})
|
53
|
+
t.code(:path=>"roleTerm",:attributes=>{:type=>"code"})
|
54
|
+
}
|
55
|
+
|
56
|
+
# Dataset-specific Terms
|
57
|
+
|
58
|
+
# In datasets, we're calling the abstract "methodology"
|
59
|
+
t.methodology(:path=>"abstract")
|
60
|
+
|
61
|
+
# Most of these are forcing non-bibliographic information into mods by using the note field pretty freely
|
62
|
+
t.note
|
63
|
+
t.gps(:index_as=>[:facetable],:path=>"note",:attributes=>{:type=>"location"})
|
64
|
+
t.timespan_start(:path=>"note",:attributes=>{:type=>"timespan-start"})
|
65
|
+
t.timespan_end(:path=>"note",:attributes=>{:type=>"timespan-end"})
|
66
|
+
t.region(:index_as=>[:facetable],:path=>"note",:attributes=>{:type=>"region"})
|
67
|
+
t.site(:index_as=>[:facetable],:path=>"note",:attributes=>{:type=>"site"})
|
68
|
+
t.ecosystem(:index_as=>[:facetable],:path=>"note",:attributes=>{:type=>"ecosystem"})
|
69
|
+
end
|
70
|
+
|
71
|
+
# It would be nice if we could declare properties with refined info like this
|
72
|
+
# accessor :grant_agency, :relative_xpath=>'oxns:mods/oxns:name[contains(oxns:role/oxns:roleTerm, "Funder")]'
|
73
|
+
|
74
|
+
# Generates an empty Mods Article (used when you call ModsArticle.new without passing in existing xml)
|
75
|
+
def self.xml_template
|
76
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
77
|
+
xml.mods(:version=>"3.3", "xmlns:xlink"=>"http://www.w3.org/1999/xlink",
|
78
|
+
"xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
|
79
|
+
"xmlns"=>"http://www.loc.gov/mods/v3",
|
80
|
+
"xsi:schemaLocation"=>"http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd") {
|
81
|
+
xml.titleInfo(:lang=>"") {
|
82
|
+
xml.title
|
83
|
+
}
|
84
|
+
xml.name(:type=>"personal") {
|
85
|
+
xml.namePart(:type=>"given")
|
86
|
+
xml.namePart(:type=>"family")
|
87
|
+
xml.affiliation
|
88
|
+
xml.role {
|
89
|
+
xml.roleTerm(:authority=>"marcrelator", :type=>"text")
|
90
|
+
}
|
91
|
+
}
|
92
|
+
xml.name(:type=>"corporate") {
|
93
|
+
xml.namePart
|
94
|
+
xml.affiliation
|
95
|
+
xml.role {
|
96
|
+
xml.roleTerm("Funder", :authority=>"marcrelator", :type=>"text")
|
97
|
+
}
|
98
|
+
}
|
99
|
+
xml.typeOfResource "software, multimedia"
|
100
|
+
xml.genre("dataset", :authority=>"dct")
|
101
|
+
xml.language {
|
102
|
+
xml.languageTerm("eng", :authority=>"iso639-2b", :type=>"code")
|
103
|
+
}
|
104
|
+
xml.abstract
|
105
|
+
xml.subject {
|
106
|
+
xml.topic
|
107
|
+
}
|
108
|
+
xml.note(:type=>"completeness")
|
109
|
+
xml.note(:type=>"interval")
|
110
|
+
xml.note(:type=>"datatype")
|
111
|
+
xml.note(:type=>"timespan-start")
|
112
|
+
xml.note(:type=>"timespan-end")
|
113
|
+
xml.note(:type=>"location")
|
114
|
+
xml.note(:type=>"grant")
|
115
|
+
xml.note(:type=>"data quality")
|
116
|
+
xml.note(:type=>"contact-name")
|
117
|
+
xml.note(:type=>"contact-email")
|
118
|
+
}
|
119
|
+
end
|
120
|
+
return builder.doc
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.person_relator_terms
|
124
|
+
{"anl" => "Analyst",
|
125
|
+
"aut" => "Author",
|
126
|
+
"clb" => "Collaborator",
|
127
|
+
"com" => "Compiler",
|
128
|
+
"cre" => "Creator",
|
129
|
+
"ctb" => "Contributor",
|
130
|
+
"dpt" => "Depositor",
|
131
|
+
"dtc" => "Data contributor ",
|
132
|
+
"dtm" => "Data manager ",
|
133
|
+
"edt" => "Editor",
|
134
|
+
"lbr" => "Laboratory ",
|
135
|
+
"ldr" => "Laboratory director ",
|
136
|
+
"pdr" => "Project director",
|
137
|
+
"prg" => "Programmer",
|
138
|
+
"res" => "Researcher",
|
139
|
+
"rth" => "Research team head",
|
140
|
+
"rtm" => "Research team member"
|
141
|
+
}
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.completed_choices
|
145
|
+
["Time Series",
|
146
|
+
"Snapshot / Sample"
|
147
|
+
]
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
def self.interval_choices
|
152
|
+
["Monthly",
|
153
|
+
"Quarterly",
|
154
|
+
"Semi-annually",
|
155
|
+
"Annually",
|
156
|
+
"Irregular"
|
157
|
+
]
|
158
|
+
end
|
159
|
+
|
160
|
+
def self.data_type_choices
|
161
|
+
["transect","observation","data logging","remote sensing"]
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.valid_child_types
|
165
|
+
["data", "supporting file", "profile", "lorem ipsum", "dolor"]
|
166
|
+
end
|
167
|
+
def to_solr(solr_doc=Hash.new)
|
168
|
+
super(solr_doc)
|
169
|
+
solr_doc.merge!(extract_person_full_names)
|
170
|
+
solr_doc.merge!(extract_person_organizations)
|
171
|
+
solr_doc.merge!(:object_type_facet => "Dataset")
|
172
|
+
solr_doc
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,501 @@
|
|
1
|
+
require 'active_fedora'
|
2
|
+
require 'hydra/datastream/common_mods_index_methods'
|
3
|
+
|
4
|
+
# Datastream that uses a Generic MODS Terminology; essentially an exemplar.
|
5
|
+
# this class will be renamed to Hydra::Datastream::ModsBasic in Hydra 5.0
|
6
|
+
module Hydra
|
7
|
+
module Datastream
|
8
|
+
class ModsGenericContent < ActiveFedora::NokogiriDatastream
|
9
|
+
include Hydra::Datastream::CommonModsIndexMethods
|
10
|
+
|
11
|
+
set_terminology do |t|
|
12
|
+
t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3", :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd")
|
13
|
+
|
14
|
+
t.title_info(:path=>"titleInfo") {
|
15
|
+
t.main_title(:path=>"title", :label=>"title")
|
16
|
+
t.language(:index_as=>[:facetable],:path=>{:attribute=>"lang"})
|
17
|
+
}
|
18
|
+
|
19
|
+
t.language{
|
20
|
+
t.lang_code(:index_as=>[:facetable], :path=>"languageTerm", :attributes=>{:type=>"code"})
|
21
|
+
}
|
22
|
+
t.abstract
|
23
|
+
t.subject {
|
24
|
+
t.topic
|
25
|
+
}
|
26
|
+
t.topic_tag(:index_as=>[:facetable],:path=>"subject", :default_content_path=>"topic")
|
27
|
+
|
28
|
+
# mods:physicaldescription/mods:extent - used for storing file size in human-readable form.
|
29
|
+
t.physical_description(:path => "physicalDescription") {
|
30
|
+
t.extent( :path => "extent")
|
31
|
+
}
|
32
|
+
|
33
|
+
# This is a mods:name. The underscore is purely to avoid namespace conflicts.
|
34
|
+
t.name_ {
|
35
|
+
# this is a namepart
|
36
|
+
t.namePart(:type=>:string, :label=>"generic name")
|
37
|
+
# affiliations are great
|
38
|
+
t.affiliation
|
39
|
+
t.institution(:path=>"affiliation", :index_as=>[:facetable], :label=>"organization")
|
40
|
+
t.displayForm
|
41
|
+
t.role(:ref=>[:role])
|
42
|
+
t.description
|
43
|
+
t.date(:path=>"namePart", :attributes=>{:type=>"date"})
|
44
|
+
t.last_name(:path=>"namePart", :attributes=>{:type=>"family"})
|
45
|
+
t.first_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
|
46
|
+
t.terms_of_address(:path=>"namePart", :attributes=>{:type=>"termsOfAddress"})
|
47
|
+
}
|
48
|
+
# lookup :person, :first_name
|
49
|
+
t.person(:ref=>:name, :attributes=>{:type=>"personal"}, :index_as=>[:facetable])
|
50
|
+
t.organization(:ref=>:name, :attributes=>{:type=>"corporate"}, :index_as=>[:facetable])
|
51
|
+
t.conference(:ref=>:name, :attributes=>{:type=>"conference"}, :index_as=>[:facetable])
|
52
|
+
t.role {
|
53
|
+
t.text(:path=>"roleTerm",:attributes=>{:type=>"text"})
|
54
|
+
t.code(:path=>"roleTerm",:attributes=>{:type=>"code"})
|
55
|
+
}
|
56
|
+
t.journal(:path=>'relatedItem', :attributes=>{:type=>"host"}) {
|
57
|
+
t.title_info(:index_as=>[:facetable],:ref=>[:title_info])
|
58
|
+
t.origin_info(:path=>"originInfo") {
|
59
|
+
t.publisher
|
60
|
+
t.date_issued(:path=>"dateIssued")
|
61
|
+
}
|
62
|
+
t.issn(:path=>"identifier", :attributes=>{:type=>"issn"})
|
63
|
+
t.issue(:path=>"part") {
|
64
|
+
t.volume(:path=>"detail", :attributes=>{:type=>"volume"}, :default_content_path=>"number")
|
65
|
+
t.level(:path=>"detail", :attributes=>{:type=>"number"}, :default_content_path=>"number")
|
66
|
+
t.extent
|
67
|
+
t.pages(:path=>"extent", :attributes=>{:unit=>"pages"}) {
|
68
|
+
t.start
|
69
|
+
t.end
|
70
|
+
}
|
71
|
+
t.start_page(:proxy=>[:pages, :start])
|
72
|
+
t.end_page(:proxy=>[:pages, :end])
|
73
|
+
t.publication_date(:path=>"date")
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
# accessor :title, :term=>[:mods, :title_info, :main_title]
|
79
|
+
|
80
|
+
# Generates an empty Mods Generic Content (used when you call ModsGenericContent.new without passing in existing xml)
|
81
|
+
def self.xml_template
|
82
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
83
|
+
xml.mods(:version=>"3.3", "xmlns:xlink"=>"http://www.w3.org/1999/xlink",
|
84
|
+
"xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
|
85
|
+
"xmlns"=>"http://www.loc.gov/mods/v3",
|
86
|
+
"xsi:schemaLocation"=>"http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd") {
|
87
|
+
xml.titleInfo(:lang=>"") {
|
88
|
+
xml.title
|
89
|
+
}
|
90
|
+
xml.name(:type=>"personal") {
|
91
|
+
xml.namePart(:type=>"given")
|
92
|
+
xml.namePart(:type=>"family")
|
93
|
+
xml.affiliation
|
94
|
+
xml.role {
|
95
|
+
xml.roleTerm(:authority=>"marcrelator", :type=>"text")
|
96
|
+
}
|
97
|
+
}
|
98
|
+
xml.typeOfResource
|
99
|
+
xml.genre(:authority=>"marcgt")
|
100
|
+
xml.language {
|
101
|
+
xml.languageTerm(:authority=>"iso639-2b", :type=>"code")
|
102
|
+
}
|
103
|
+
# mods:physicaldescription/mods:extent - used for storing file size in human-readable form.
|
104
|
+
xml.physicalDescription {
|
105
|
+
xml.extent
|
106
|
+
}
|
107
|
+
xml.abstract
|
108
|
+
xml.subject {
|
109
|
+
xml.topic
|
110
|
+
}
|
111
|
+
xml.relatedItem(:type=>"host") {
|
112
|
+
xml.titleInfo {
|
113
|
+
xml.title
|
114
|
+
}
|
115
|
+
xml.identifier(:type=>"issn")
|
116
|
+
xml.originInfo {
|
117
|
+
xml.publisher
|
118
|
+
xml.dateIssued
|
119
|
+
}
|
120
|
+
xml.part {
|
121
|
+
xml.detail(:type=>"volume") {
|
122
|
+
xml.number
|
123
|
+
}
|
124
|
+
xml.detail(:type=>"number") {
|
125
|
+
xml.number
|
126
|
+
}
|
127
|
+
xml.extent(:unit=>"pages") {
|
128
|
+
xml.start
|
129
|
+
xml.end
|
130
|
+
}
|
131
|
+
xml.date
|
132
|
+
}
|
133
|
+
}
|
134
|
+
xml.location {
|
135
|
+
xml.url
|
136
|
+
}
|
137
|
+
}
|
138
|
+
end
|
139
|
+
return builder.doc
|
140
|
+
end
|
141
|
+
|
142
|
+
# Generates a new Person node
|
143
|
+
def self.person_template
|
144
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
145
|
+
xml.name(:type=>"personal") {
|
146
|
+
xml.namePart(:type=>"family")
|
147
|
+
xml.namePart(:type=>"given")
|
148
|
+
xml.affiliation
|
149
|
+
xml.role {
|
150
|
+
xml.roleTerm(:type=>"text")
|
151
|
+
}
|
152
|
+
}
|
153
|
+
end
|
154
|
+
return builder.doc.root
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.full_name_template
|
158
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
159
|
+
xml.full_name(:type => "personal")
|
160
|
+
end
|
161
|
+
return builder.doc.root
|
162
|
+
end
|
163
|
+
|
164
|
+
# Generates a new Organization node
|
165
|
+
# Uses mods:name[@type="corporate"]
|
166
|
+
def self.organization_template
|
167
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
168
|
+
xml.name(:type=>"corporate") {
|
169
|
+
xml.namePart
|
170
|
+
xml.role {
|
171
|
+
xml.roleTerm(:authority=>"marcrelator", :type=>"text")
|
172
|
+
}
|
173
|
+
}
|
174
|
+
end
|
175
|
+
return builder.doc.root
|
176
|
+
end
|
177
|
+
|
178
|
+
# Generates a new Conference node
|
179
|
+
def self.conference_template
|
180
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
181
|
+
xml.name(:type=>"conference") {
|
182
|
+
xml.namePart
|
183
|
+
xml.role {
|
184
|
+
xml.roleTerm(:authority=>"marcrelator", :type=>"text")
|
185
|
+
}
|
186
|
+
}
|
187
|
+
end
|
188
|
+
return builder.doc.root
|
189
|
+
end
|
190
|
+
|
191
|
+
# Inserts a new contributor (mods:name) into the mods document
|
192
|
+
# creates contributors of type :person, :organization, or :conference
|
193
|
+
def insert_contributor(type, opts={})
|
194
|
+
case type.to_sym
|
195
|
+
when :person
|
196
|
+
node = Hydra::Datastream::ModsGenericContent.person_template
|
197
|
+
nodeset = self.find_by_terms(:person)
|
198
|
+
when :organization
|
199
|
+
node = Hydra::Datastream::ModsGenericContent.organization_template
|
200
|
+
nodeset = self.find_by_terms(:organization)
|
201
|
+
when :conference
|
202
|
+
node = Hydra::Datastream::ModsGenericContent.conference_template
|
203
|
+
nodeset = self.find_by_terms(:conference)
|
204
|
+
else
|
205
|
+
ActiveFedora.logger.warn("#{type} is not a valid argument for Hydra::Datastream::ModsGenericContent.insert_contributor")
|
206
|
+
node = nil
|
207
|
+
index = nil
|
208
|
+
end
|
209
|
+
|
210
|
+
unless nodeset.nil?
|
211
|
+
if nodeset.empty?
|
212
|
+
self.ng_xml.root.add_child(node)
|
213
|
+
index = 0
|
214
|
+
else
|
215
|
+
nodeset.after(node)
|
216
|
+
index = nodeset.length
|
217
|
+
end
|
218
|
+
self.dirty = true
|
219
|
+
end
|
220
|
+
|
221
|
+
return node, index
|
222
|
+
end
|
223
|
+
|
224
|
+
# Remove the contributor entry identified by @contributor_type and @index
|
225
|
+
def remove_contributor(contributor_type, index)
|
226
|
+
self.find_by_terms( {contributor_type.to_sym => index.to_i} ).first.remove
|
227
|
+
self.dirty = true
|
228
|
+
end
|
229
|
+
|
230
|
+
def self.common_relator_terms
|
231
|
+
{"aut" => "Author",
|
232
|
+
"clb" => "Collaborator",
|
233
|
+
"com" => "Compiler",
|
234
|
+
"ctb" => "Contributor",
|
235
|
+
"cre" => "Creator",
|
236
|
+
"edt" => "Editor",
|
237
|
+
"ill" => "Illustrator",
|
238
|
+
"oth" => "Other",
|
239
|
+
"trl" => "Translator",
|
240
|
+
}
|
241
|
+
end
|
242
|
+
|
243
|
+
def self.person_relator_terms
|
244
|
+
{"aut" => "Author",
|
245
|
+
"clb" => "Collaborator",
|
246
|
+
"com" => "Compiler",
|
247
|
+
"cre" => "Creator",
|
248
|
+
"ctb" => "Contributor",
|
249
|
+
"edt" => "Editor",
|
250
|
+
"ill" => "Illustrator",
|
251
|
+
"res" => "Researcher",
|
252
|
+
"rth" => "Research team head",
|
253
|
+
"rtm" => "Research team member",
|
254
|
+
"trl" => "Translator"
|
255
|
+
}
|
256
|
+
end
|
257
|
+
|
258
|
+
def self.conference_relator_terms
|
259
|
+
{
|
260
|
+
"hst" => "Host"
|
261
|
+
}
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.organization_relator_terms
|
265
|
+
{
|
266
|
+
"fnd" => "Funder",
|
267
|
+
"hst" => "Host"
|
268
|
+
}
|
269
|
+
end
|
270
|
+
|
271
|
+
def self.dc_relator_terms
|
272
|
+
{"acp" => "Art copyist",
|
273
|
+
"act" => "Actor",
|
274
|
+
"adp" => "Adapter",
|
275
|
+
"aft" => "Author of afterword, colophon, etc.",
|
276
|
+
"anl" => "Analyst",
|
277
|
+
"anm" => "Animator",
|
278
|
+
"ann" => "Annotator",
|
279
|
+
"ant" => "Bibliographic antecedent",
|
280
|
+
"app" => "Applicant",
|
281
|
+
"aqt" => "Author in quotations or text abstracts",
|
282
|
+
"arc" => "Architect",
|
283
|
+
"ard" => "Artistic director ",
|
284
|
+
"arr" => "Arranger",
|
285
|
+
"art" => "Artist",
|
286
|
+
"asg" => "Assignee",
|
287
|
+
"asn" => "Associated name",
|
288
|
+
"att" => "Attributed name",
|
289
|
+
"auc" => "Auctioneer",
|
290
|
+
"aud" => "Author of dialog",
|
291
|
+
"aui" => "Author of introduction",
|
292
|
+
"aus" => "Author of screenplay",
|
293
|
+
"aut" => "Author",
|
294
|
+
"bdd" => "Binding designer",
|
295
|
+
"bjd" => "Bookjacket designer",
|
296
|
+
"bkd" => "Book designer",
|
297
|
+
"bkp" => "Book producer",
|
298
|
+
"bnd" => "Binder",
|
299
|
+
"bpd" => "Bookplate designer",
|
300
|
+
"bsl" => "Bookseller",
|
301
|
+
"ccp" => "Conceptor",
|
302
|
+
"chr" => "Choreographer",
|
303
|
+
"clb" => "Collaborator",
|
304
|
+
"cli" => "Client",
|
305
|
+
"cll" => "Calligrapher",
|
306
|
+
"clt" => "Collotyper",
|
307
|
+
"cmm" => "Commentator",
|
308
|
+
"cmp" => "Composer",
|
309
|
+
"cmt" => "Compositor",
|
310
|
+
"cng" => "Cinematographer",
|
311
|
+
"cnd" => "Conductor",
|
312
|
+
"cns" => "Censor",
|
313
|
+
"coe" => "Contestant -appellee",
|
314
|
+
"col" => "Collector",
|
315
|
+
"com" => "Compiler",
|
316
|
+
"cos" => "Contestant",
|
317
|
+
"cot" => "Contestant -appellant",
|
318
|
+
"cov" => "Cover designer",
|
319
|
+
"cpc" => "Copyright claimant",
|
320
|
+
"cpe" => "Complainant-appellee",
|
321
|
+
"cph" => "Copyright holder",
|
322
|
+
"cpl" => "Complainant",
|
323
|
+
"cpt" => "Complainant-appellant",
|
324
|
+
"cre" => "Creator",
|
325
|
+
"crp" => "Correspondent",
|
326
|
+
"crr" => "Corrector",
|
327
|
+
"csl" => "Consultant",
|
328
|
+
"csp" => "Consultant to a project",
|
329
|
+
"cst" => "Costume designer",
|
330
|
+
"ctb" => "Contributor",
|
331
|
+
"cte" => "Contestee-appellee",
|
332
|
+
"ctg" => "Cartographer",
|
333
|
+
"ctr" => "Contractor",
|
334
|
+
"cts" => "Contestee",
|
335
|
+
"ctt" => "Contestee-appellant",
|
336
|
+
"cur" => "Curator",
|
337
|
+
"cwt" => "Commentator for written text",
|
338
|
+
"dfd" => "Defendant",
|
339
|
+
"dfe" => "Defendant-appellee",
|
340
|
+
"dft" => "Defendant-appellant",
|
341
|
+
"dgg" => "Degree grantor",
|
342
|
+
"dis" => "Dissertant",
|
343
|
+
"dln" => "Delineator",
|
344
|
+
"dnc" => "Dancer",
|
345
|
+
"dnr" => "Donor",
|
346
|
+
"dpc" => "Depicted",
|
347
|
+
"dpt" => "Depositor",
|
348
|
+
"drm" => "Draftsman",
|
349
|
+
"drt" => "Director",
|
350
|
+
"dsr" => "Designer",
|
351
|
+
"dst" => "Distributor",
|
352
|
+
"dtc" => "Data contributor ",
|
353
|
+
"dte" => "Dedicatee",
|
354
|
+
"dtm" => "Data manager ",
|
355
|
+
"dto" => "Dedicator",
|
356
|
+
"dub" => "Dubious author",
|
357
|
+
"edt" => "Editor",
|
358
|
+
"egr" => "Engraver",
|
359
|
+
"elg" => "Electrician ",
|
360
|
+
"elt" => "Electrotyper",
|
361
|
+
"eng" => "Engineer",
|
362
|
+
"etr" => "Etcher",
|
363
|
+
"exp" => "Expert",
|
364
|
+
"fac" => "Facsimilist",
|
365
|
+
"fld" => "Field director ",
|
366
|
+
"flm" => "Film editor",
|
367
|
+
"fmo" => "Former owner",
|
368
|
+
"fpy" => "First party",
|
369
|
+
"fnd" => "Funder",
|
370
|
+
"frg" => "Forger",
|
371
|
+
"gis" => "Geographic information specialist ",
|
372
|
+
"grt" => "Graphic technician",
|
373
|
+
"hnr" => "Honoree",
|
374
|
+
"hst" => "Host",
|
375
|
+
"ill" => "Illustrator",
|
376
|
+
"ilu" => "Illuminator",
|
377
|
+
"ins" => "Inscriber",
|
378
|
+
"inv" => "Inventor",
|
379
|
+
"itr" => "Instrumentalist",
|
380
|
+
"ive" => "Interviewee",
|
381
|
+
"ivr" => "Interviewer",
|
382
|
+
"lbr" => "Laboratory ",
|
383
|
+
"lbt" => "Librettist",
|
384
|
+
"ldr" => "Laboratory director ",
|
385
|
+
"led" => "Lead",
|
386
|
+
"lee" => "Libelee-appellee",
|
387
|
+
"lel" => "Libelee",
|
388
|
+
"len" => "Lender",
|
389
|
+
"let" => "Libelee-appellant",
|
390
|
+
"lgd" => "Lighting designer",
|
391
|
+
"lie" => "Libelant-appellee",
|
392
|
+
"lil" => "Libelant",
|
393
|
+
"lit" => "Libelant-appellant",
|
394
|
+
"lsa" => "Landscape architect",
|
395
|
+
"lse" => "Licensee",
|
396
|
+
"lso" => "Licensor",
|
397
|
+
"ltg" => "Lithographer",
|
398
|
+
"lyr" => "Lyricist",
|
399
|
+
"mcp" => "Music copyist",
|
400
|
+
"mfr" => "Manufacturer",
|
401
|
+
"mdc" => "Metadata contact",
|
402
|
+
"mod" => "Moderator",
|
403
|
+
"mon" => "Monitor",
|
404
|
+
"mrk" => "Markup editor",
|
405
|
+
"msd" => "Musical director",
|
406
|
+
"mte" => "Metal-engraver",
|
407
|
+
"mus" => "Musician",
|
408
|
+
"nrt" => "Narrator",
|
409
|
+
"opn" => "Opponent",
|
410
|
+
"org" => "Originator",
|
411
|
+
"orm" => "Organizer of meeting",
|
412
|
+
"oth" => "Other",
|
413
|
+
"own" => "Owner",
|
414
|
+
"pat" => "Patron",
|
415
|
+
"pbd" => "Publishing director",
|
416
|
+
"pbl" => "Publisher",
|
417
|
+
"pdr" => "Project director",
|
418
|
+
"pfr" => "Proofreader",
|
419
|
+
"pht" => "Photographer",
|
420
|
+
"plt" => "Platemaker",
|
421
|
+
"pma" => "Permitting agency",
|
422
|
+
"pmn" => "Production manager",
|
423
|
+
"pop" => "Printer of plates",
|
424
|
+
"ppm" => "Papermaker",
|
425
|
+
"ppt" => "Puppeteer",
|
426
|
+
"prc" => "Process contact",
|
427
|
+
"prd" => "Production personnel",
|
428
|
+
"prf" => "Performer",
|
429
|
+
"prg" => "Programmer",
|
430
|
+
"prm" => "Printmaker",
|
431
|
+
"pro" => "Producer",
|
432
|
+
"prt" => "Printer",
|
433
|
+
"pta" => "Patent applicant",
|
434
|
+
"pte" => "Plaintiff -appellee",
|
435
|
+
"ptf" => "Plaintiff",
|
436
|
+
"pth" => "Patent holder",
|
437
|
+
"ptt" => "Plaintiff-appellant",
|
438
|
+
"rbr" => "Rubricator",
|
439
|
+
"rce" => "Recording engineer",
|
440
|
+
"rcp" => "Recipient",
|
441
|
+
"red" => "Redactor",
|
442
|
+
"ren" => "Renderer",
|
443
|
+
"res" => "Researcher",
|
444
|
+
"rev" => "Reviewer",
|
445
|
+
"rps" => "Repository",
|
446
|
+
"rpt" => "Reporter",
|
447
|
+
"rpy" => "Responsible party",
|
448
|
+
"rse" => "Respondent-appellee",
|
449
|
+
"rsg" => "Restager",
|
450
|
+
"rsp" => "Respondent",
|
451
|
+
"rst" => "Respondent-appellant",
|
452
|
+
"rth" => "Research team head",
|
453
|
+
"rtm" => "Research team member",
|
454
|
+
"sad" => "Scientific advisor",
|
455
|
+
"sce" => "Scenarist",
|
456
|
+
"scl" => "Sculptor",
|
457
|
+
"scr" => "Scribe",
|
458
|
+
"sds" => "Sound designer",
|
459
|
+
"sec" => "Secretary",
|
460
|
+
"sgn" => "Signer",
|
461
|
+
"sht" => "Supporting host",
|
462
|
+
"sng" => "Singer",
|
463
|
+
"spk" => "Speaker",
|
464
|
+
"spn" => "Sponsor",
|
465
|
+
"spy" => "Second party",
|
466
|
+
"srv" => "Surveyor",
|
467
|
+
"std" => "Set designer",
|
468
|
+
"stl" => "Storyteller",
|
469
|
+
"stm" => "Stage manager",
|
470
|
+
"stn" => "Standards body",
|
471
|
+
"str" => "Stereotyper",
|
472
|
+
"tcd" => "Technical director",
|
473
|
+
"tch" => "Teacher",
|
474
|
+
"ths" => "Thesis advisor",
|
475
|
+
"trc" => "Transcriber",
|
476
|
+
"trl" => "Translator",
|
477
|
+
"tyd" => "Type designer",
|
478
|
+
"tyg" => "Typographer",
|
479
|
+
"vdg" => "Videographer",
|
480
|
+
"voc" => "Vocalist",
|
481
|
+
"wam" => "Writer of accompanying material",
|
482
|
+
"wdc" => "Woodcutter",
|
483
|
+
"wde" => "Wood -engraver",
|
484
|
+
"wit" => "Witness"}
|
485
|
+
end
|
486
|
+
|
487
|
+
def self.valid_child_types
|
488
|
+
["data", "supporting file", "profile", "lorem ipsum", "dolor"]
|
489
|
+
end
|
490
|
+
|
491
|
+
def to_solr(solr_doc=Hash.new)
|
492
|
+
super(solr_doc)
|
493
|
+
solr_doc.merge!(extract_person_full_names)
|
494
|
+
solr_doc.merge!(extract_person_organizations)
|
495
|
+
solr_doc.merge!(:object_type_facet => "Generic content")
|
496
|
+
solr_doc
|
497
|
+
end
|
498
|
+
|
499
|
+
end
|
500
|
+
end
|
501
|
+
end
|