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.
@@ -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