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 ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'rake/testtask'
2
+ require 'bundler'
3
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,47 @@
1
+ # Provides some helper methods for indexing compound or non-standard facets
2
+ #
3
+ # this code will move to lib/hydra/datastream/mods_name_behavior.rb (with the appropriate namespace changes) in Hydra 5.0
4
+ #
5
+ # == Methods
6
+ #
7
+ # extract_person_full_names
8
+ # This method returns a Hash of person_full_name_facet values which combine Lastname, Firstname
9
+ # extract_person_organizations
10
+ # This method returns a Hash of person_full_name_facet values which extract the persons affiliation and puts it in an mods_organization_facet
11
+
12
+ module Hydra
13
+ module Datastream
14
+ module CommonModsIndexMethods
15
+ # Extracts the first and last names of persons and creates Solr::Field objects with for person_full_name_facet
16
+ #
17
+ # == Returns:
18
+ # An array of Solr::Field objects
19
+ #
20
+ def extract_person_full_names
21
+ names = {}
22
+ self.find_by_terms(:person).each do |person|
23
+ name_parts = person.children.inject({}) do |hash,child|
24
+ hash[child.get_attribute(:type)] = child.text if ["family","given"].include? child.get_attribute(:type)
25
+ hash
26
+ end
27
+ ::Solrizer::Extractor.insert_solr_field_value(names, "person_full_name_facet", [name_parts["family"], name_parts["given"]].join(", ") ) if name_parts.keys.sort == ["family","given"]
28
+ names
29
+ end
30
+ return names
31
+ end
32
+
33
+ # Extracts the affiliations of persons and creates Solr::Field objects for them
34
+ #
35
+ # == Returns:
36
+ # An array of Solr::Field objects
37
+ #
38
+ def extract_person_organizations
39
+ orgs = {}
40
+ self.find_by_terms(:person,:affiliation).each do |org|
41
+ ::Solrizer::Extractor.insert_solr_field_value(orgs, "mods_organization_facet", org.text)
42
+ end
43
+ return orgs
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,533 @@
1
+ require 'active_fedora'
2
+ require 'hydra/datastream/common_mods_index_methods'
3
+
4
+ # @deprecated Leftover from Hydrangea. Please use Hydra::Datastream::ModsGenericContent instead. This will be removed no later than release 6.x
5
+ # this should be moved to documentation as an EXAMPLE
6
+ module Hydra
7
+ module Datastream
8
+ class ModsArticle < 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
+
15
+ t.title_info(:path=>"titleInfo") {
16
+ t.main_title(:index_as=>[:facetable],:path=>"title", :label=>"title")
17
+ t.language(:index_as=>[:facetable],:path=>{:attribute=>"lang"})
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(:index_as=>[:facetable])
25
+ }
26
+ t.topic_tag(:proxy=>[:subject, :topic])
27
+ # t.topic_tag(:index_as=>[:facetable],:path=>"subject", :default_content_path=>"topic")
28
+ # This is a mods:name. The underscore is purely to avoid namespace conflicts.
29
+ t.name_ {
30
+ # this is a namepart
31
+ t.namePart(:type=>:string, :label=>"generic name")
32
+ # affiliations are great
33
+ t.affiliation
34
+ t.institution(:path=>"affiliation", :index_as=>[:facetable], :label=>"organization")
35
+ t.displayForm
36
+ t.role(:ref=>[:role])
37
+ t.description(:index_as=>[:facetable])
38
+ t.date(:path=>"namePart", :attributes=>{:type=>"date"})
39
+ t.last_name(:path=>"namePart", :attributes=>{:type=>"family"})
40
+ t.first_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
41
+ t.terms_of_address(:path=>"namePart", :attributes=>{:type=>"termsOfAddress"})
42
+ t.computing_id
43
+ }
44
+ # lookup :person, :first_name
45
+ t.person(:ref=>:name, :attributes=>{:type=>"personal"}, :index_as=>[:facetable])
46
+ t.department(:proxy=>[:person,:description],:index_as=>[:facetable])
47
+ t.organization(:ref=>:name, :attributes=>{:type=>"corporate"}, :index_as=>[:facetable])
48
+ t.conference(:ref=>:name, :attributes=>{:type=>"conference"}, :index_as=>[:facetable])
49
+ t.role {
50
+ t.text(:path=>"roleTerm",:attributes=>{:type=>"text"})
51
+ t.code(:path=>"roleTerm",:attributes=>{:type=>"code"})
52
+ }
53
+ t.journal(:path=>'relatedItem', :attributes=>{:type=>"host"}) {
54
+ t.title_info(:index_as=>[:facetable],:ref=>[:title_info])
55
+ t.origin_info(:path=>"originInfo") {
56
+ t.publisher
57
+ t.date_issued(:path=>"dateIssued")
58
+ t.issuance(:index_as=>[:facetable])
59
+ }
60
+ t.issn(:path=>"identifier", :attributes=>{:type=>"issn"})
61
+ t.issue(:path=>"part") {
62
+ t.volume(:path=>"detail", :attributes=>{:type=>"volume"}, :default_content_path=>"number")
63
+ t.level(:path=>"detail", :attributes=>{:type=>"number"}, :default_content_path=>"number")
64
+ t.extent
65
+ t.pages(:path=>"extent", :attributes=>{:unit=>"pages"}) {
66
+ t.start
67
+ t.end
68
+ }
69
+ t.start_page(:proxy=>[:pages, :start])
70
+ t.end_page(:proxy=>[:pages, :end])
71
+ t.publication_date(:path=>"date")
72
+ }
73
+ }
74
+ t.note
75
+ t.location(:path=>"location") {
76
+ t.url(:path=>"url")
77
+ }
78
+ t.publication_url(:proxy=>[:location,:url])
79
+ t.peer_reviewed(:proxy=>[:journal,:origin_info,:issuance], :index_as=>[:facetable])
80
+ t.title(:proxy=>[:mods,:title_info, :main_title])
81
+ end
82
+
83
+ # Generates an empty Mods Article (used when you call ModsArticle.new without passing in existing xml)
84
+ def self.xml_template
85
+ builder = Nokogiri::XML::Builder.new do |xml|
86
+ xml.mods(:version=>"3.3", "xmlns:xlink"=>"http://www.w3.org/1999/xlink",
87
+ "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
88
+ "xmlns"=>"http://www.loc.gov/mods/v3",
89
+ "xsi:schemaLocation"=>"http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd") {
90
+ xml.titleInfo(:lang=>"") {
91
+ xml.title
92
+ }
93
+ xml.name(:type=>"personal") {
94
+ xml.namePart(:type=>"given")
95
+ xml.namePart(:type=>"family")
96
+ xml.affiliation
97
+ xml.computing_id
98
+ xml.description
99
+ xml.role {
100
+ xml.roleTerm("Author", :authority=>"marcrelator", :type=>"text")
101
+ }
102
+ }
103
+ xml.typeOfResource
104
+ xml.genre(:authority=>"marcgt")
105
+ xml.language {
106
+ xml.languageTerm(:authority=>"iso639-2b", :type=>"code")
107
+ }
108
+ xml.abstract
109
+ xml.subject {
110
+ xml.topic
111
+ }
112
+ xml.relatedItem(:type=>"host") {
113
+ xml.titleInfo {
114
+ xml.title
115
+ }
116
+ xml.identifier(:type=>"issn")
117
+ xml.originInfo {
118
+ xml.publisher
119
+ xml.dateIssued
120
+ xml.issuance
121
+ }
122
+ xml.part {
123
+ xml.detail(:type=>"volume") {
124
+ xml.number
125
+ }
126
+ xml.detail(:type=>"number") {
127
+ xml.number
128
+ }
129
+ xml.extent(:unit=>"pages") {
130
+ xml.start
131
+ xml.end
132
+ }
133
+ xml.date
134
+ }
135
+ }
136
+ xml.location {
137
+ xml.url
138
+ }
139
+ }
140
+ end
141
+ return builder.doc
142
+ end
143
+
144
+ # Generates a new Person node
145
+ def self.person_template
146
+ builder = Nokogiri::XML::Builder.new do |xml|
147
+ xml.name(:type=>"personal") {
148
+ xml.namePart(:type=>"family")
149
+ xml.namePart(:type=>"given")
150
+ xml.affiliation
151
+ xml.computing_id
152
+ xml.description
153
+ xml.role {
154
+ xml.roleTerm("Author", :type=>"text")
155
+ }
156
+ }
157
+ end
158
+ return builder.doc.root
159
+ end
160
+
161
+ def self.full_name_template
162
+ builder = Nokogiri::XML::Builder.new do |xml|
163
+ xml.full_name(:type => "personal")
164
+ end
165
+ return builder.doc.root
166
+ end
167
+
168
+ # Generates a new Organization node
169
+ # Uses mods:name[@type="corporate"]
170
+ def self.organization_template
171
+ builder = Nokogiri::XML::Builder.new do |xml|
172
+ xml.name(:type=>"corporate") {
173
+ xml.namePart
174
+ xml.role {
175
+ xml.roleTerm(:authority=>"marcrelator", :type=>"text")
176
+ }
177
+ }
178
+ end
179
+ return builder.doc.root
180
+ end
181
+
182
+ # Generates a new Conference node
183
+ def self.conference_template
184
+ builder = Nokogiri::XML::Builder.new do |xml|
185
+ xml.name(:type=>"conference") {
186
+ xml.namePart
187
+ xml.role {
188
+ xml.roleTerm(:authority=>"marcrelator", :type=>"text")
189
+ }
190
+ }
191
+ end
192
+ return builder.doc.root
193
+ end
194
+
195
+ # Inserts a new contributor (mods:name) into the mods document
196
+ # creates contributors of type :person, :organization, or :conference
197
+ def insert_contributor(type, opts={})
198
+ case type.to_sym
199
+ when :person
200
+ node = Hydra::Datastream::ModsArticle.person_template
201
+ nodeset = self.find_by_terms(:person)
202
+ when :organization
203
+ node = Hydra::Datastream::ModsArticle.organization_template
204
+ nodeset = self.find_by_terms(:organization)
205
+ when :conference
206
+ node = Hydra::Datastream::ModsArticle.conference_template
207
+ nodeset = self.find_by_terms(:conference)
208
+ else
209
+ ActiveFedora.logger.warn("#{type} is not a valid argument for Hydra::ModsArticle.insert_contributor")
210
+ node = nil
211
+ index = nil
212
+ end
213
+
214
+ unless nodeset.nil?
215
+ if nodeset.empty?
216
+ self.ng_xml.root.add_child(node)
217
+ index = 0
218
+ else
219
+ nodeset.after(node)
220
+ index = nodeset.length
221
+ end
222
+ self.dirty = true
223
+ end
224
+
225
+ return node, index
226
+ end
227
+
228
+ # Remove the contributor entry identified by @contributor_type and @index
229
+ def remove_contributor(contributor_type, index)
230
+ contributor = self.find_by_terms( {contributor_type.to_sym => index.to_i} ).first
231
+ unless contributor.nil?
232
+ contributor.remove
233
+ self.dirty = true
234
+ end
235
+ end
236
+
237
+ def self.common_relator_terms
238
+ {"aut" => "Author",
239
+ "clb" => "Collaborator",
240
+ "com" => "Compiler",
241
+ "ctb" => "Contributor",
242
+ "cre" => "Creator",
243
+ "edt" => "Editor",
244
+ "ill" => "Illustrator",
245
+ "oth" => "Other",
246
+ "trl" => "Translator",
247
+ }
248
+ end
249
+
250
+ def self.person_relator_terms
251
+ {"aut" => "Author",
252
+ "clb" => "Collaborator",
253
+ "com" => "Compiler",
254
+ "cre" => "Creator",
255
+ "ctb" => "Contributor",
256
+ "edt" => "Editor",
257
+ "ill" => "Illustrator",
258
+ "res" => "Researcher",
259
+ "rth" => "Research team head",
260
+ "rtm" => "Research team member",
261
+ "trl" => "Translator"
262
+ }
263
+ end
264
+
265
+ def self.conference_relator_terms
266
+ {
267
+ "hst" => "Host"
268
+ }
269
+ end
270
+
271
+ def self.organization_relator_terms
272
+ {
273
+ "fnd" => "Funder",
274
+ "hst" => "Host"
275
+ }
276
+ end
277
+
278
+ def self.dc_relator_terms
279
+ {"acp" => "Art copyist",
280
+ "act" => "Actor",
281
+ "adp" => "Adapter",
282
+ "aft" => "Author of afterword, colophon, etc.",
283
+ "anl" => "Analyst",
284
+ "anm" => "Animator",
285
+ "ann" => "Annotator",
286
+ "ant" => "Bibliographic antecedent",
287
+ "app" => "Applicant",
288
+ "aqt" => "Author in quotations or text abstracts",
289
+ "arc" => "Architect",
290
+ "ard" => "Artistic director ",
291
+ "arr" => "Arranger",
292
+ "art" => "Artist",
293
+ "asg" => "Assignee",
294
+ "asn" => "Associated name",
295
+ "att" => "Attributed name",
296
+ "auc" => "Auctioneer",
297
+ "aud" => "Author of dialog",
298
+ "aui" => "Author of introduction",
299
+ "aus" => "Author of screenplay",
300
+ "aut" => "Author",
301
+ "bdd" => "Binding designer",
302
+ "bjd" => "Bookjacket designer",
303
+ "bkd" => "Book designer",
304
+ "bkp" => "Book producer",
305
+ "bnd" => "Binder",
306
+ "bpd" => "Bookplate designer",
307
+ "bsl" => "Bookseller",
308
+ "ccp" => "Conceptor",
309
+ "chr" => "Choreographer",
310
+ "clb" => "Collaborator",
311
+ "cli" => "Client",
312
+ "cll" => "Calligrapher",
313
+ "clt" => "Collotyper",
314
+ "cmm" => "Commentator",
315
+ "cmp" => "Composer",
316
+ "cmt" => "Compositor",
317
+ "cng" => "Cinematographer",
318
+ "cnd" => "Conductor",
319
+ "cns" => "Censor",
320
+ "coe" => "Contestant -appellee",
321
+ "col" => "Collector",
322
+ "com" => "Compiler",
323
+ "cos" => "Contestant",
324
+ "cot" => "Contestant -appellant",
325
+ "cov" => "Cover designer",
326
+ "cpc" => "Copyright claimant",
327
+ "cpe" => "Complainant-appellee",
328
+ "cph" => "Copyright holder",
329
+ "cpl" => "Complainant",
330
+ "cpt" => "Complainant-appellant",
331
+ "cre" => "Creator",
332
+ "crp" => "Correspondent",
333
+ "crr" => "Corrector",
334
+ "csl" => "Consultant",
335
+ "csp" => "Consultant to a project",
336
+ "cst" => "Costume designer",
337
+ "ctb" => "Contributor",
338
+ "cte" => "Contestee-appellee",
339
+ "ctg" => "Cartographer",
340
+ "ctr" => "Contractor",
341
+ "cts" => "Contestee",
342
+ "ctt" => "Contestee-appellant",
343
+ "cur" => "Curator",
344
+ "cwt" => "Commentator for written text",
345
+ "dfd" => "Defendant",
346
+ "dfe" => "Defendant-appellee",
347
+ "dft" => "Defendant-appellant",
348
+ "dgg" => "Degree grantor",
349
+ "dis" => "Dissertant",
350
+ "dln" => "Delineator",
351
+ "dnc" => "Dancer",
352
+ "dnr" => "Donor",
353
+ "dpc" => "Depicted",
354
+ "dpt" => "Depositor",
355
+ "drm" => "Draftsman",
356
+ "drt" => "Director",
357
+ "dsr" => "Designer",
358
+ "dst" => "Distributor",
359
+ "dtc" => "Data contributor ",
360
+ "dte" => "Dedicatee",
361
+ "dtm" => "Data manager ",
362
+ "dto" => "Dedicator",
363
+ "dub" => "Dubious author",
364
+ "edt" => "Editor",
365
+ "egr" => "Engraver",
366
+ "elg" => "Electrician ",
367
+ "elt" => "Electrotyper",
368
+ "eng" => "Engineer",
369
+ "etr" => "Etcher",
370
+ "exp" => "Expert",
371
+ "fac" => "Facsimilist",
372
+ "fld" => "Field director ",
373
+ "flm" => "Film editor",
374
+ "fmo" => "Former owner",
375
+ "fpy" => "First party",
376
+ "fnd" => "Funder",
377
+ "frg" => "Forger",
378
+ "gis" => "Geographic information specialist ",
379
+ "grt" => "Graphic technician",
380
+ "hnr" => "Honoree",
381
+ "hst" => "Host",
382
+ "ill" => "Illustrator",
383
+ "ilu" => "Illuminator",
384
+ "ins" => "Inscriber",
385
+ "inv" => "Inventor",
386
+ "itr" => "Instrumentalist",
387
+ "ive" => "Interviewee",
388
+ "ivr" => "Interviewer",
389
+ "lbr" => "Laboratory ",
390
+ "lbt" => "Librettist",
391
+ "ldr" => "Laboratory director ",
392
+ "led" => "Lead",
393
+ "lee" => "Libelee-appellee",
394
+ "lel" => "Libelee",
395
+ "len" => "Lender",
396
+ "let" => "Libelee-appellant",
397
+ "lgd" => "Lighting designer",
398
+ "lie" => "Libelant-appellee",
399
+ "lil" => "Libelant",
400
+ "lit" => "Libelant-appellant",
401
+ "lsa" => "Landscape architect",
402
+ "lse" => "Licensee",
403
+ "lso" => "Licensor",
404
+ "ltg" => "Lithographer",
405
+ "lyr" => "Lyricist",
406
+ "mcp" => "Music copyist",
407
+ "mfr" => "Manufacturer",
408
+ "mdc" => "Metadata contact",
409
+ "mod" => "Moderator",
410
+ "mon" => "Monitor",
411
+ "mrk" => "Markup editor",
412
+ "msd" => "Musical director",
413
+ "mte" => "Metal-engraver",
414
+ "mus" => "Musician",
415
+ "nrt" => "Narrator",
416
+ "opn" => "Opponent",
417
+ "org" => "Originator",
418
+ "orm" => "Organizer of meeting",
419
+ "oth" => "Other",
420
+ "own" => "Owner",
421
+ "pat" => "Patron",
422
+ "pbd" => "Publishing director",
423
+ "pbl" => "Publisher",
424
+ "pdr" => "Project director",
425
+ "pfr" => "Proofreader",
426
+ "pht" => "Photographer",
427
+ "plt" => "Platemaker",
428
+ "pma" => "Permitting agency",
429
+ "pmn" => "Production manager",
430
+ "pop" => "Printer of plates",
431
+ "ppm" => "Papermaker",
432
+ "ppt" => "Puppeteer",
433
+ "prc" => "Process contact",
434
+ "prd" => "Production personnel",
435
+ "prf" => "Performer",
436
+ "prg" => "Programmer",
437
+ "prm" => "Printmaker",
438
+ "pro" => "Producer",
439
+ "prt" => "Printer",
440
+ "pta" => "Patent applicant",
441
+ "pte" => "Plaintiff -appellee",
442
+ "ptf" => "Plaintiff",
443
+ "pth" => "Patent holder",
444
+ "ptt" => "Plaintiff-appellant",
445
+ "rbr" => "Rubricator",
446
+ "rce" => "Recording engineer",
447
+ "rcp" => "Recipient",
448
+ "red" => "Redactor",
449
+ "ren" => "Renderer",
450
+ "res" => "Researcher",
451
+ "rev" => "Reviewer",
452
+ "rps" => "Repository",
453
+ "rpt" => "Reporter",
454
+ "rpy" => "Responsible party",
455
+ "rse" => "Respondent-appellee",
456
+ "rsg" => "Restager",
457
+ "rsp" => "Respondent",
458
+ "rst" => "Respondent-appellant",
459
+ "rth" => "Research team head",
460
+ "rtm" => "Research team member",
461
+ "sad" => "Scientific advisor",
462
+ "sce" => "Scenarist",
463
+ "scl" => "Sculptor",
464
+ "scr" => "Scribe",
465
+ "sds" => "Sound designer",
466
+ "sec" => "Secretary",
467
+ "sgn" => "Signer",
468
+ "sht" => "Supporting host",
469
+ "sng" => "Singer",
470
+ "spk" => "Speaker",
471
+ "spn" => "Sponsor",
472
+ "spy" => "Second party",
473
+ "srv" => "Surveyor",
474
+ "std" => "Set designer",
475
+ "stl" => "Storyteller",
476
+ "stm" => "Stage manager",
477
+ "stn" => "Standards body",
478
+ "str" => "Stereotyper",
479
+ "tcd" => "Technical director",
480
+ "tch" => "Teacher",
481
+ "ths" => "Thesis advisor",
482
+ "trc" => "Transcriber",
483
+ "trl" => "Translator",
484
+ "tyd" => "Type designer",
485
+ "tyg" => "Typographer",
486
+ "vdg" => "Videographer",
487
+ "voc" => "Vocalist",
488
+ "wam" => "Writer of accompanying material",
489
+ "wdc" => "Woodcutter",
490
+ "wde" => "Wood -engraver",
491
+ "wit" => "Witness"}
492
+ end
493
+
494
+ def self.valid_child_types
495
+ ["data", "supporting file", "profile", "lorem ipsum", "dolor"]
496
+ end
497
+
498
+ def to_solr(solr_doc=Hash.new)
499
+ super(solr_doc)
500
+
501
+ extract_person_full_names.each_pair {|n,v| ::Solrizer::Extractor.insert_solr_field_value(solr_doc, n, v) }
502
+ extract_person_organizations.each_pair {|n,v| ::Solrizer::Extractor.insert_solr_field_value(solr_doc, n, v) }
503
+ extract_person_full_names_and_computing_ids.each_pair {|n,v| ::Solrizer::Extractor.insert_solr_field_value(solr_doc, n, v) }
504
+
505
+ ::Solrizer::Extractor.insert_solr_field_value(solr_doc, "object_type_facet", "Article")
506
+ ::Solrizer::Extractor.insert_solr_field_value(solr_doc, "mods_journal_title_info_facet", "Unknown") if solr_doc["mods_journal_title_info_facet"].nil? || solr_doc["mods_journal_title_info_facet"].blank?
507
+
508
+ solr_doc
509
+ end
510
+
511
+ # extracts the last_name##full_name##computing_id to be used by home view
512
+ def extract_person_full_names_and_computing_ids
513
+ names = {}
514
+ self.find_by_terms(:person).each do |person|
515
+ name_parts = person.children.inject({}) do |hash,child|
516
+ hash[child.get_attribute(:type)] = child.text if ["family","given"].include? child.get_attribute(:type)
517
+ hash["computing_id"] = child.text if child.name == 'computing_id'
518
+ hash
519
+ end
520
+ if name_parts.length == 3 and person.search(:roleTerm).children.text.include?("Author")
521
+ if name_parts["family"].blank? && name_parts["given"].blank? && name_parts["computing_id"].blank?
522
+ value = "Unknown Author"
523
+ else
524
+ value = "#{name_parts["family"]}, #{name_parts["given"]} (#{name_parts["computing_id"]})"
525
+ end
526
+ ::Solrizer::Extractor.insert_solr_field_value(names, "person_full_name_cid_facet", value) if name_parts.length == 3
527
+ end
528
+ end
529
+ names
530
+ end
531
+ end
532
+ end
533
+ end