hydra-mods 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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