blacklight-marc 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +19 -0
  4. data/Gemfile +15 -0
  5. data/LICENSE +15 -0
  6. data/README.md +40 -0
  7. data/Rakefile +68 -0
  8. data/app/helpers/blacklight_marc_helper.rb +24 -0
  9. data/app/views/bookmarks/_endnote.html.erb +3 -0
  10. data/app/views/bookmarks/_refworks.html.erb +3 -0
  11. data/app/views/catalog/_marc_view.html.erb +32 -0
  12. data/app/views/catalog/endnote.endnote.erb +1 -0
  13. data/app/views/catalog/librarian_view.html.erb +10 -0
  14. data/blacklight-marc.gemspec +31 -0
  15. data/config/jetty.yml +4 -0
  16. data/config/locales/blacklight.en.yml +13 -0
  17. data/config/locales/blacklight.fr.yml +13 -0
  18. data/config/routes.rb +17 -0
  19. data/lib/SolrMarc.jar +0 -0
  20. data/lib/blacklight/marc.rb +18 -0
  21. data/lib/blacklight/marc/catalog.rb +20 -0
  22. data/lib/blacklight/marc/engine.rb +8 -0
  23. data/lib/blacklight/marc/railtie.rb +17 -0
  24. data/lib/blacklight/marc/routes.rb +43 -0
  25. data/lib/blacklight/marc/version.rb +5 -0
  26. data/lib/blacklight/solr/document/marc.rb +72 -0
  27. data/lib/blacklight/solr/document/marc_export.rb +587 -0
  28. data/lib/generators/blacklight_marc/marc_generator.rb +57 -0
  29. data/lib/generators/blacklight_marc/templates/config/SolrMarc/config-test.properties +37 -0
  30. data/lib/generators/blacklight_marc/templates/config/SolrMarc/config.properties +37 -0
  31. data/lib/generators/blacklight_marc/templates/config/SolrMarc/index.properties +97 -0
  32. data/lib/generators/blacklight_marc/templates/config/SolrMarc/index_scripts/dewey.bsh +47 -0
  33. data/lib/generators/blacklight_marc/templates/config/SolrMarc/index_scripts/format.bsh +126 -0
  34. data/lib/generators/blacklight_marc/templates/config/SolrMarc/translation_maps/README_MAPS +1 -0
  35. data/lib/generators/blacklight_marc/templates/config/SolrMarc/translation_maps/callnumber_map.properties +407 -0
  36. data/lib/generators/blacklight_marc/templates/config/SolrMarc/translation_maps/composition_era_map.properties +56 -0
  37. data/lib/generators/blacklight_marc/templates/config/SolrMarc/translation_maps/country_map.properties +379 -0
  38. data/lib/generators/blacklight_marc/templates/config/SolrMarc/translation_maps/format_map.properties +50 -0
  39. data/lib/generators/blacklight_marc/templates/config/SolrMarc/translation_maps/instrument_map.properties +101 -0
  40. data/lib/generators/blacklight_marc/templates/config/SolrMarc/translation_maps/language_map.properties +490 -0
  41. data/lib/railties/solr_marc.rake +158 -0
  42. data/spec/controllers/catalog_controller_spec.rb +23 -0
  43. data/spec/features/librarian_view_spec.rb +13 -0
  44. data/spec/helpers/blacklight_marc_helper_spec.rb +26 -0
  45. data/spec/integration/solr_document_spec.rb +59 -0
  46. data/spec/lib/blacklight_solr_document_marc_spec.rb +89 -0
  47. data/spec/lib/marc_export_spec.rb +743 -0
  48. data/spec/lib/tasks/solr_marc_task_spec.rb +60 -0
  49. data/spec/routing/routes_spec.rb +16 -0
  50. data/spec/spec_helper.rb +27 -0
  51. data/spec/test_app_templates/Gemfile.extra +21 -0
  52. data/spec/test_app_templates/lib/generators/test_app_generator.rb +35 -0
  53. data/spec/test_app_templates/lib/tasks/blacklight_test_app.rake +14 -0
  54. data/spec/views/bookmarks/_endnote.html.erb_spec.rb +9 -0
  55. data/spec/views/bookmarks/_refworks.html.erb_spec.rb +10 -0
  56. data/test_support/data/test_data.utf8.mrc +1 -0
  57. metadata +231 -0
@@ -0,0 +1,5 @@
1
+ module Blacklight
2
+ module Marc
3
+ VERSION = "5.0.0"
4
+ end
5
+ end
@@ -0,0 +1,72 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ # This is a document extension meant to be mixed into a
4
+ # Blacklight::Solr::Document class, such as SolrDocument. It provides support
5
+ # for restoration of MARC data (xml or binary) from a Solr stored field, and
6
+ # then provides various transformations/exports of that Marc via the included
7
+ # Blacklight::Solr::Document::MarcExport module.
8
+ #
9
+ # This extension would normally be registered using
10
+ # Blacklight::Solr::Document#use_extension. eg:
11
+ #
12
+ # SolrDocument.use_extension( Blacklight::Solr::Document::Marc ) { |document| my_logic_for_document_has_marc?( document ) }
13
+ #
14
+ # This extension also expects a :marc_source_field and :marc_format_type to
15
+ # be registered with the hosting classes extension_parameters. In an initializer
16
+ # or other startup code:
17
+ # SolrDocument.extension_paramters[:marc_source_field] = "name_of_solr_stored_field"
18
+ # SolrDocument.extension_parameters[:marc_format_type] = :marc21 # or :marcxml
19
+ require 'marc'
20
+
21
+ module Blacklight::Solr::Document::Marc
22
+
23
+ include Blacklight::Solr::Document::MarcExport # All our export_as stuff based on to_marc.
24
+
25
+ class UnsupportedMarcFormatType < RuntimeError; end
26
+
27
+ def self.extended(document)
28
+ # Register our exportable formats, we inherit these from MarcExport
29
+ Blacklight::Solr::Document::MarcExport.register_export_formats( document )
30
+ end
31
+
32
+ # ruby-marc object
33
+ def to_marc
34
+ @_ruby_marc_obj ||= load_marc
35
+ end
36
+
37
+
38
+ protected
39
+ def marc_source
40
+ @_marc_source ||= fetch(_marc_source_field)
41
+ end
42
+
43
+ def load_marc
44
+ case _marc_format_type.to_s
45
+ when 'marcxml'
46
+ records = MARC::XMLReader.new(StringIO.new( fetch(_marc_source_field) )).to_a
47
+ return records[0]
48
+ when 'marc21'
49
+ return MARC::Record.new_from_marc( fetch(_marc_source_field) )
50
+ else
51
+
52
+ raise UnsupportedMarcFormatType.new("Only marcxml and marc21 are supported, this documents format is #{_marc_format_type} and the current extension parameters are #{self.class.extension_parameters.inspect}")
53
+ end
54
+ end
55
+
56
+
57
+
58
+ def _marc_helper
59
+ @_marc_helper ||= (
60
+ Blacklight::Marc::Document.new fetch(_marc_source_field), _marc_format_type )
61
+ end
62
+
63
+ def _marc_source_field
64
+ self.class.extension_parameters[:marc_source_field]
65
+ end
66
+
67
+ def _marc_format_type
68
+ #TODO: Raise if not present
69
+ self.class.extension_parameters[:marc_format_type]
70
+ end
71
+
72
+ end
@@ -0,0 +1,587 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # -*- coding: utf-8 -*-
3
+ # Written for use with Blacklight::Solr::Document::Marc, but you can use
4
+ # it for your own custom Blacklight document Marc extension too -- just
5
+ # include this module in any document extension (or any other class)
6
+ # that provides a #to_marc returning a ruby-marc object. This module will add
7
+ # in export_as translation methods for a variety of formats.
8
+ module Blacklight::Solr::Document::MarcExport
9
+
10
+ def self.register_export_formats(document)
11
+ document.will_export_as(:xml)
12
+ document.will_export_as(:marc, "application/marc")
13
+ # marcxml content type:
14
+ # http://tools.ietf.org/html/draft-denenberg-mods-etc-media-types-00
15
+ document.will_export_as(:marcxml, "application/marcxml+xml")
16
+ document.will_export_as(:openurl_ctx_kev, "application/x-openurl-ctx-kev")
17
+ document.will_export_as(:refworks_marc_txt, "text/plain")
18
+ document.will_export_as(:endnote, "application/x-endnote-refer")
19
+ end
20
+
21
+
22
+ def export_as_marc
23
+ to_marc.to_marc
24
+ end
25
+
26
+ def export_as_marcxml
27
+ to_marc.to_xml.to_s
28
+ end
29
+ alias_method :export_as_xml, :export_as_marcxml
30
+
31
+
32
+ # TODO This exporting as formatted citation thing should be re-thought
33
+ # redesigned at some point to be more general purpose, but this
34
+ # is in-line with what we had before, but at least now attached
35
+ # to the document extension where it belongs.
36
+ def export_as_apa_citation_txt
37
+ apa_citation( to_marc )
38
+ end
39
+
40
+ def export_as_mla_citation_txt
41
+ mla_citation( to_marc )
42
+ end
43
+
44
+ def export_as_chicago_citation_txt
45
+ chicago_citation( to_marc )
46
+ end
47
+
48
+ # Exports as an OpenURL KEV (key-encoded value) query string.
49
+ # For use to create COinS, among other things. COinS are
50
+ # for Zotero, among other things. TODO: This is wierd and fragile
51
+ # code, it should use ruby OpenURL gem instead to work a lot
52
+ # more sensibly. The "format" argument was in the old marc.marc.to_zotero
53
+ # call, but didn't neccesarily do what it thought it did anyway. Left in
54
+ # for now for backwards compatibilty, but should be replaced by
55
+ # just ruby OpenURL.
56
+ def export_as_openurl_ctx_kev(format = nil)
57
+ title = to_marc.find{|field| field.tag == '245'}
58
+ author = to_marc.find{|field| field.tag == '100'}
59
+ corp_author = to_marc.find{|field| field.tag == '110'}
60
+ publisher_info = to_marc.find{|field| field.tag == '260'}
61
+ edition = to_marc.find{|field| field.tag == '250'}
62
+ isbn = to_marc.find{|field| field.tag == '020'}
63
+ issn = to_marc.find{|field| field.tag == '022'}
64
+ unless format.nil?
65
+ format.is_a?(Array) ? format = format[0].downcase.strip : format = format.downcase.strip
66
+ end
67
+ export_text = ""
68
+ if format == 'book'
69
+ export_text << "ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rfr_id=info%3Asid%2Fblacklight.rubyforge.org%3Agenerator&amp;rft.genre=book&amp;"
70
+ export_text << "rft.btitle=#{(title.nil? or title['a'].nil?) ? "" : CGI::escape(title['a'])}+#{(title.nil? or title['b'].nil?) ? "" : CGI::escape(title['b'])}&amp;"
71
+ export_text << "rft.title=#{(title.nil? or title['a'].nil?) ? "" : CGI::escape(title['a'])}+#{(title.nil? or title['b'].nil?) ? "" : CGI::escape(title['b'])}&amp;"
72
+ export_text << "rft.au=#{(author.nil? or author['a'].nil?) ? "" : CGI::escape(author['a'])}&amp;"
73
+ export_text << "rft.aucorp=#{CGI::escape(corp_author['a']) if corp_author['a']}+#{CGI::escape(corp_author['b']) if corp_author['b']}&amp;" unless corp_author.blank?
74
+ export_text << "rft.date=#{(publisher_info.nil? or publisher_info['c'].nil?) ? "" : CGI::escape(publisher_info['c'])}&amp;"
75
+ export_text << "rft.place=#{(publisher_info.nil? or publisher_info['a'].nil?) ? "" : CGI::escape(publisher_info['a'])}&amp;"
76
+ export_text << "rft.pub=#{(publisher_info.nil? or publisher_info['b'].nil?) ? "" : CGI::escape(publisher_info['b'])}&amp;"
77
+ export_text << "rft.edition=#{(edition.nil? or edition['a'].nil?) ? "" : CGI::escape(edition['a'])}&amp;"
78
+ export_text << "rft.isbn=#{(isbn.nil? or isbn['a'].nil?) ? "" : isbn['a']}"
79
+ elsif (format =~ /journal/i) # checking using include because institutions may use formats like Journal or Journal/Magazine
80
+ export_text << "ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rfr_id=info%3Asid%2Fblacklight.rubyforge.org%3Agenerator&amp;rft.genre=article&amp;"
81
+ export_text << "rft.title=#{(title.nil? or title['a'].nil?) ? "" : CGI::escape(title['a'])}+#{(title.nil? or title['b'].nil?) ? "" : CGI::escape(title['b'])}&amp;"
82
+ export_text << "rft.atitle=#{(title.nil? or title['a'].nil?) ? "" : CGI::escape(title['a'])}+#{(title.nil? or title['b'].nil?) ? "" : CGI::escape(title['b'])}&amp;"
83
+ export_text << "rft.aucorp=#{CGI::escape(corp_author['a']) if corp_author['a']}+#{CGI::escape(corp_author['b']) if corp_author['b']}&amp;" unless corp_author.blank?
84
+ export_text << "rft.date=#{(publisher_info.nil? or publisher_info['c'].nil?) ? "" : CGI::escape(publisher_info['c'])}&amp;"
85
+ export_text << "rft.issn=#{(issn.nil? or issn['a'].nil?) ? "" : issn['a']}"
86
+ else
87
+ export_text << "ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Fblacklight.rubyforge.org%3Agenerator&amp;"
88
+ export_text << "rft.title=" + ((title.nil? or title['a'].nil?) ? "" : CGI::escape(title['a']))
89
+ export_text << ((title.nil? or title['b'].nil?) ? "" : CGI.escape(" ") + CGI::escape(title['b']))
90
+ export_text << "&amp;rft.creator=" + ((author.nil? or author['a'].nil?) ? "" : CGI::escape(author['a']))
91
+ export_text << "&amp;rft.aucorp=#{CGI::escape(corp_author['a']) if corp_author['a']}+#{CGI::escape(corp_author['b']) if corp_author['b']}" unless corp_author.blank?
92
+ export_text << "&amp;rft.date=" + ((publisher_info.nil? or publisher_info['c'].nil?) ? "" : CGI::escape(publisher_info['c']))
93
+ export_text << "&amp;rft.place=" + ((publisher_info.nil? or publisher_info['a'].nil?) ? "" : CGI::escape(publisher_info['a']))
94
+ export_text << "&amp;rft.pub=" + ((publisher_info.nil? or publisher_info['b'].nil?) ? "" : CGI::escape(publisher_info['b']))
95
+ export_text << "&amp;rft.format=" + (format.nil? ? "" : CGI::escape(format))
96
+ end
97
+ export_text.html_safe unless export_text.blank?
98
+ end
99
+
100
+
101
+ # This format used to be called 'refworks', which wasn't really
102
+ # accurate, sounds more like 'refworks tagged format'. Which this
103
+ # is not, it's instead some weird under-documented Refworks
104
+ # proprietary marc-ish in text/plain format. See
105
+ # http://robotlibrarian.billdueber.com/sending-marcish-data-to-refworks/
106
+ def export_as_refworks_marc_txt
107
+ fields = to_marc.find_all { |f| ('000'..'999') === f.tag }
108
+ text = "LEADER #{to_marc.leader}"
109
+ fields.each do |field|
110
+ unless ["940","999"].include?(field.tag)
111
+ if field.is_a?(MARC::ControlField)
112
+ text << "#{field.tag} #{field.value}\n"
113
+ else
114
+ text << "#{field.tag} "
115
+ text << (field.indicator1 ? field.indicator1 : " ")
116
+ text << (field.indicator2 ? field.indicator2 : " ")
117
+ text << " "
118
+ field.each {|s| s.code == 'a' ? text << "#{s.value}" : text << " |#{s.code}#{s.value}"}
119
+ text << "\n"
120
+ end
121
+ end
122
+ end
123
+
124
+ # As of 11 May 2010, Refworks has a problem with UTF-8 if it's decomposed,
125
+ # it seems to want C form normalization, although RefWorks support
126
+ # couldn't tell me that. -jrochkind
127
+ text = ActiveSupport::Multibyte::Unicode.normalize(text, :c)
128
+
129
+ return text
130
+ end
131
+
132
+ # Endnote Import Format. See the EndNote User Guide at:
133
+ # http://www.endnote.com/support/enx3man-terms-win.asp
134
+ # Chapter 7: Importing Reference Data into EndNote / Creating a Tagged “EndNote Import” File
135
+ #
136
+ # Note: This code is copied from what used to be in the previous version
137
+ # in ApplicationHelper#render_to_endnote. It does NOT produce very good
138
+ # endnote import format; the %0 is likely to be entirely illegal, the
139
+ # rest of the data is barely correct but messy. TODO, a new version of this,
140
+ # or better yet just an export_as_ris instead, which will be more general
141
+ # purpose.
142
+ def export_as_endnote()
143
+ end_note_format = {
144
+ "%A" => "100.a",
145
+ "%C" => "260.a",
146
+ "%D" => "260.c",
147
+ "%E" => "700.a",
148
+ "%I" => "260.b",
149
+ "%J" => "440.a",
150
+ "%@" => "020.a",
151
+ "%_@" => "022.a",
152
+ "%T" => "245.a,245.b",
153
+ "%U" => "856.u",
154
+ "%7" => "250.a"
155
+ }
156
+ marc_obj = to_marc
157
+
158
+ # TODO. This should be rewritten to guess
159
+ # from actual Marc instead, probably.
160
+ format_str = 'Generic'
161
+
162
+ text = ''
163
+ text << "%0 #{ format_str }\n"
164
+ # If there is some reliable way of getting the language of a record we can add it here
165
+ #text << "%G #{record['language'].first}\n"
166
+ end_note_format.each do |key,value|
167
+ values = value.split(",")
168
+ first_value = values[0].split('.')
169
+ if values.length > 1
170
+ second_value = values[1].split('.')
171
+ else
172
+ second_value = []
173
+ end
174
+
175
+ if marc_obj[first_value[0].to_s]
176
+ marc_obj.find_all{|f| (first_value[0].to_s) === f.tag}.each do |field|
177
+ if field[first_value[1]].to_s or field[second_value[1]].to_s
178
+ text << "#{key.gsub('_','')}"
179
+ if field[first_value[1]].to_s
180
+ text << " #{field[first_value[1]].to_s}"
181
+ end
182
+ if field[second_value[1]].to_s
183
+ text << " #{field[second_value[1]].to_s}"
184
+ end
185
+ text << "\n"
186
+ end
187
+ end
188
+ end
189
+ end
190
+ text
191
+ end
192
+
193
+ ## DEPRECATED stuff left in for backwards compatibility, but should
194
+ # be gotten rid of eventually.
195
+
196
+ def to_zotero(format)
197
+ warn("[DEPRECATION] Simply call document.export_as_openurl_kev to get an openURL kev context object suitable for including in a COinS; then have view code make the span for the COinS. ")
198
+ "<span class=\"Z3988\" title=\"#{export_as_openurl_kev(format)}\"></span>"
199
+ end
200
+
201
+ def to_apa
202
+ warn("[DEPRECATION] Call document.export_as_apa_citation instead.")
203
+ export_as_apa_citation
204
+ end
205
+
206
+ def to_mla
207
+ warn("[DEPRECATION] Call document.export_as_mla_citation instead.")
208
+ end
209
+
210
+
211
+
212
+ protected
213
+
214
+ # Main method for defining chicago style citation. If we don't end up converting to using a citation formatting service
215
+ # we should make this receive a semantic document and not MARC so we can use this with other formats.
216
+ def chicago_citation(marc)
217
+ authors = get_all_authors(marc)
218
+ author_text = ""
219
+ unless authors[:primary_authors].blank?
220
+ if authors[:primary_authors].length > 10
221
+ authors[:primary_authors].each_with_index do |author,index|
222
+ if index < 7
223
+ if index == 0
224
+ author_text << "#{author}"
225
+ if author.ends_with?(",")
226
+ author_text << " "
227
+ else
228
+ author_text << ", "
229
+ end
230
+ else
231
+ author_text << "#{name_reverse(author)}, "
232
+ end
233
+ end
234
+ end
235
+ author_text << " et al."
236
+ elsif authors[:primary_authors].length > 1
237
+ authors[:primary_authors].each_with_index do |author,index|
238
+ if index == 0
239
+ author_text << "#{author}"
240
+ if author.ends_with?(",")
241
+ author_text << " "
242
+ else
243
+ author_text << ", "
244
+ end
245
+ elsif index + 1 == authors[:primary_authors].length
246
+ author_text << "and #{name_reverse(author)}."
247
+ else
248
+ author_text << "#{name_reverse(author)}, "
249
+ end
250
+ end
251
+ else
252
+ author_text << authors[:primary_authors].first
253
+ end
254
+ else
255
+ temp_authors = []
256
+ authors[:translators].each do |translator|
257
+ temp_authors << [translator, "trans."]
258
+ end
259
+ authors[:editors].each do |editor|
260
+ temp_authors << [editor, "ed."]
261
+ end
262
+ authors[:compilers].each do |compiler|
263
+ temp_authors << [compiler, "comp."]
264
+ end
265
+
266
+ unless temp_authors.blank?
267
+ if temp_authors.length > 10
268
+ temp_authors.each_with_index do |author,index|
269
+ if index < 7
270
+ author_text << "#{author.first} #{author.last} "
271
+ end
272
+ end
273
+ author_text << " et al."
274
+ elsif temp_authors.length > 1
275
+ temp_authors.each_with_index do |author,index|
276
+ if index == 0
277
+ author_text << "#{author.first} #{author.last}, "
278
+ elsif index + 1 == temp_authors.length
279
+ author_text << "and #{name_reverse(author.first)} #{author.last}"
280
+ else
281
+ author_text << "#{name_reverse(author.first)} #{author.last}, "
282
+ end
283
+ end
284
+ else
285
+ author_text << "#{temp_authors.first.first} #{temp_authors.first.last}"
286
+ end
287
+ end
288
+ end
289
+ title = ""
290
+ additional_title = ""
291
+ section_title = ""
292
+ if marc["245"] and (marc["245"]["a"] or marc["245"]["b"])
293
+ title << citation_title(clean_end_punctuation(marc["245"]["a"]).strip) if marc["245"]["a"]
294
+ title << ": #{citation_title(clean_end_punctuation(marc["245"]["b"]).strip)}" if marc["245"]["b"]
295
+ end
296
+ if marc["245"] and (marc["245"]["n"] or marc["245"]["p"])
297
+ section_title << citation_title(clean_end_punctuation(marc["245"]["n"])) if marc["245"]["n"]
298
+ if marc["245"]["p"]
299
+ section_title << ", <i>#{citation_title(clean_end_punctuation(marc["245"]["p"]))}.</i>"
300
+ elsif marc["245"]["n"]
301
+ section_title << "."
302
+ end
303
+ end
304
+
305
+ if !authors[:primary_authors].blank? and (!authors[:translators].blank? or !authors[:editors].blank? or !authors[:compilers].blank?)
306
+ additional_title << "Translated by #{authors[:translators].collect{|name| name_reverse(name)}.join(" and ")}. " unless authors[:translators].blank?
307
+ additional_title << "Edited by #{authors[:editors].collect{|name| name_reverse(name)}.join(" and ")}. " unless authors[:editors].blank?
308
+ additional_title << "Compiled by #{authors[:compilers].collect{|name| name_reverse(name)}.join(" and ")}. " unless authors[:compilers].blank?
309
+ end
310
+
311
+ edition = ""
312
+ edition << setup_edition(marc) unless setup_edition(marc).nil?
313
+
314
+ pub_info = ""
315
+ if marc["260"] and (marc["260"]["a"] or marc["260"]["b"])
316
+ pub_info << clean_end_punctuation(marc["260"]["a"]).strip if marc["260"]["a"]
317
+ pub_info << ": #{clean_end_punctuation(marc["260"]["b"]).strip}" if marc["260"]["b"]
318
+ pub_info << ", #{setup_pub_date(marc)}" if marc["260"]["c"]
319
+ elsif marc["502"] and marc["502"]["a"] # MARC 502 is the Dissertation Note. This holds the correct pub info for these types of records.
320
+ pub_info << marc["502"]["a"]
321
+ elsif marc["502"] and (marc["502"]["b"] or marc["502"]["c"] or marc["502"]["d"]) #sometimes the dissertation note is encoded in pieces in the $b $c and $d sub fields instead of lumped into the $a
322
+ pub_info << "#{marc["502"]["b"]}, #{marc["502"]["c"]}, #{clean_end_punctuation(marc["502"]["d"])}"
323
+ end
324
+
325
+ citation = ""
326
+ citation << "#{author_text} " unless author_text.blank?
327
+ citation << "<i>#{title}.</i> " unless title.blank?
328
+ citation << "#{section_title} " unless section_title.blank?
329
+ citation << "#{additional_title} " unless additional_title.blank?
330
+ citation << "#{edition} " unless edition.blank?
331
+ citation << "#{pub_info}." unless pub_info.blank?
332
+ citation
333
+ end
334
+
335
+
336
+
337
+ def mla_citation(record)
338
+ text = ''
339
+ authors_final = []
340
+
341
+ #setup formatted author list
342
+ authors = get_author_list(record)
343
+
344
+ if authors.length < 4
345
+ authors.each do |l|
346
+ if l == authors.first #first
347
+ authors_final.push(l)
348
+ elsif l == authors.last #last
349
+ authors_final.push(", and " + name_reverse(l) + ".")
350
+ else #all others
351
+ authors_final.push(", " + name_reverse(l))
352
+ end
353
+ end
354
+ text += authors_final.join
355
+ unless text.blank?
356
+ if text[-1,1] != "."
357
+ text += ". "
358
+ else
359
+ text += " "
360
+ end
361
+ end
362
+ else
363
+ text += authors.first + ", et al. "
364
+ end
365
+ # setup title
366
+ title = setup_title_info(record)
367
+ if !title.nil?
368
+ text += "<i>" + mla_citation_title(title) + "</i> "
369
+ end
370
+
371
+ # Edition
372
+ edition_data = setup_edition(record)
373
+ text += edition_data + " " unless edition_data.nil?
374
+
375
+ # Publication
376
+ text += setup_pub_info(record) + ", " unless setup_pub_info(record).nil?
377
+
378
+ # Get Pub Date
379
+ text += setup_pub_date(record) unless setup_pub_date(record).nil?
380
+ if text[-1,1] != "."
381
+ text += "." unless text.nil? or text.blank?
382
+ end
383
+ text
384
+ end
385
+
386
+ def apa_citation(record)
387
+ text = ''
388
+ authors_list = []
389
+ authors_list_final = []
390
+
391
+ #setup formatted author list
392
+ authors = get_author_list(record)
393
+ authors.each do |l|
394
+ authors_list.push(abbreviate_name(l)) unless l.blank?
395
+ end
396
+ authors_list.each do |l|
397
+ if l == authors_list.first #first
398
+ authors_list_final.push(l.strip)
399
+ elsif l == authors_list.last #last
400
+ authors_list_final.push(", &amp; " + l.strip)
401
+ else #all others
402
+ authors_list_final.push(", " + l.strip)
403
+ end
404
+ end
405
+ text += authors_list_final.join
406
+ unless text.blank?
407
+ if text[-1,1] != "."
408
+ text += ". "
409
+ else
410
+ text += " "
411
+ end
412
+ end
413
+ # Get Pub Date
414
+ text += "(" + setup_pub_date(record) + "). " unless setup_pub_date(record).nil?
415
+
416
+ # setup title info
417
+ title = setup_title_info(record)
418
+ text += "<i>" + title + "</i> " unless title.nil?
419
+
420
+ # Edition
421
+ edition_data = setup_edition(record)
422
+ text += edition_data + " " unless edition_data.nil?
423
+
424
+ # Publisher info
425
+ text += setup_pub_info(record) unless setup_pub_info(record).nil?
426
+ unless text.blank?
427
+ if text[-1,1] != "."
428
+ text += "."
429
+ end
430
+ end
431
+ text
432
+ end
433
+ def setup_pub_date(record)
434
+ if !record.find{|f| f.tag == '260'}.nil?
435
+ pub_date = record.find{|f| f.tag == '260'}
436
+ if pub_date.find{|s| s.code == 'c'}
437
+ date_value = pub_date.find{|s| s.code == 'c'}.value.gsub(/[^0-9|n\.d\.]/, "")[0,4] unless pub_date.find{|s| s.code == 'c'}.value.gsub(/[^0-9|n\.d\.]/, "")[0,4].blank?
438
+ end
439
+ return nil if date_value.nil?
440
+ end
441
+ clean_end_punctuation(date_value) if date_value
442
+ end
443
+ def setup_pub_info(record)
444
+ text = ''
445
+ pub_info_field = record.find{|f| f.tag == '260'}
446
+ if !pub_info_field.nil?
447
+ a_pub_info = pub_info_field.find{|s| s.code == 'a'}
448
+ b_pub_info = pub_info_field.find{|s| s.code == 'b'}
449
+ a_pub_info = clean_end_punctuation(a_pub_info.value.strip) unless a_pub_info.nil?
450
+ b_pub_info = b_pub_info.value.strip unless b_pub_info.nil?
451
+ text += a_pub_info.strip unless a_pub_info.nil?
452
+ if !a_pub_info.nil? and !b_pub_info.nil?
453
+ text += ": "
454
+ end
455
+ text += b_pub_info.strip unless b_pub_info.nil?
456
+ end
457
+ return nil if text.strip.blank?
458
+ clean_end_punctuation(text.strip)
459
+ end
460
+
461
+ def mla_citation_title(text)
462
+ no_upcase = ["a","an","and","but","by","for","it","of","the","to","with"]
463
+ new_text = []
464
+ word_parts = text.split(" ")
465
+ word_parts.each do |w|
466
+ if !no_upcase.include? w
467
+ new_text.push(w.capitalize)
468
+ else
469
+ new_text.push(w)
470
+ end
471
+ end
472
+ new_text.join(" ")
473
+ end
474
+
475
+ # This will replace the mla_citation_title method with a better understanding of how MLA and Chicago citation titles are formatted.
476
+ # This method will take in a string and capitalize all of the non-prepositions.
477
+ def citation_title(title_text)
478
+ prepositions = ["a","about","across","an","and","before","but","by","for","it","of","the","to","with","without"]
479
+ new_text = []
480
+ title_text.split(" ").each_with_index do |word,index|
481
+ if (index == 0 and word != word.upcase) or (word.length > 1 and word != word.upcase and !prepositions.include?(word))
482
+ # the split("-") will handle the capitalization of hyphenated words
483
+ new_text << word.split("-").map!{|w| w.capitalize }.join("-")
484
+ else
485
+ new_text << word
486
+ end
487
+ end
488
+ new_text.join(" ")
489
+ end
490
+
491
+ def setup_title_info(record)
492
+ text = ''
493
+ title_info_field = record.find{|f| f.tag == '245'}
494
+ if !title_info_field.nil?
495
+ a_title_info = title_info_field.find{|s| s.code == 'a'}
496
+ b_title_info = title_info_field.find{|s| s.code == 'b'}
497
+ a_title_info = clean_end_punctuation(a_title_info.value.strip) unless a_title_info.nil?
498
+ b_title_info = clean_end_punctuation(b_title_info.value.strip) unless b_title_info.nil?
499
+ text += a_title_info unless a_title_info.nil?
500
+ if !a_title_info.nil? and !b_title_info.nil?
501
+ text += ": "
502
+ end
503
+ text += b_title_info unless b_title_info.nil?
504
+ end
505
+
506
+ return nil if text.strip.blank?
507
+ clean_end_punctuation(text.strip) + "."
508
+
509
+ end
510
+
511
+ def clean_end_punctuation(text)
512
+ if [".",",",":",";","/"].include? text[-1,1]
513
+ return text[0,text.length-1]
514
+ end
515
+ text
516
+ end
517
+
518
+ def setup_edition(record)
519
+ edition_field = record.find{|f| f.tag == '250'}
520
+ edition_code = edition_field.find{|s| s.code == 'a'} unless edition_field.nil?
521
+ edition_data = edition_code.value unless edition_code.nil?
522
+ if edition_data.nil? or edition_data == '1st ed.'
523
+ return nil
524
+ else
525
+ return edition_data
526
+ end
527
+ end
528
+
529
+ def get_author_list(record)
530
+ author_list = []
531
+ authors_primary = record.find{|f| f.tag == '100'}
532
+ author_primary = authors_primary.find{|s| s.code == 'a'}.value unless authors_primary.nil? rescue ''
533
+ author_list.push(clean_end_punctuation(author_primary)) unless author_primary.nil?
534
+ authors_secondary = record.find_all{|f| ('700') === f.tag}
535
+ if !authors_secondary.nil?
536
+ authors_secondary.each do |l|
537
+ author_list.push(clean_end_punctuation(l.find{|s| s.code == 'a'}.value)) unless l.find{|s| s.code == 'a'}.value.nil?
538
+ end
539
+ end
540
+
541
+ author_list.uniq!
542
+ author_list
543
+ end
544
+
545
+ # This is a replacement method for the get_author_list method. This new method will break authors out into primary authors, translators, editors, and compilers
546
+ def get_all_authors(record)
547
+ translator_code = "trl"; editor_code = "edt"; compiler_code = "com"
548
+ primary_authors = []; translators = []; editors = []; compilers = []
549
+ record.find_all{|f| f.tag === "100" }.each do |field|
550
+ primary_authors << field["a"] if field["a"]
551
+ end
552
+ record.find_all{|f| f.tag === "700" }.each do |field|
553
+ if field["a"]
554
+ relators = []
555
+ relators << clean_end_punctuation(field["e"]) if field["e"]
556
+ relators << clean_end_punctuation(field["4"]) if field["4"]
557
+ if relators.include?(translator_code)
558
+ translators << field["a"]
559
+ elsif relators.include?(editor_code)
560
+ editors << field["a"]
561
+ elsif relators.include?(compiler_code)
562
+ compilers << field["a"]
563
+ else
564
+ primary_authors << field["a"]
565
+ end
566
+ end
567
+ end
568
+ {:primary_authors => primary_authors, :translators => translators, :editors => editors, :compilers => compilers}
569
+ end
570
+
571
+ def abbreviate_name(name)
572
+ name_parts = name.split(", ")
573
+ first_name_parts = name_parts.last.split(" ")
574
+ temp_name = name_parts.first + ", " + first_name_parts.first[0,1] + "."
575
+ first_name_parts.shift
576
+ temp_name += " " + first_name_parts.join(" ") unless first_name_parts.empty?
577
+ temp_name
578
+ end
579
+
580
+ def name_reverse(name)
581
+ name = clean_end_punctuation(name)
582
+ return name unless name =~ /,/
583
+ temp_name = name.split(", ")
584
+ return temp_name.last + " " + temp_name.first
585
+ end
586
+
587
+ end