blacklight_marc 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/blacklight_marc.gemspec +3 -0
- data/lib/blacklight/solr/document/marc.rb +71 -0
- data/lib/blacklight/solr/document/marc_export.rb +602 -0
- data/lib/blacklight_marc/version.rb +1 -1
- data/lib/blacklight_marc.rb +5 -0
- metadata +23 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24c6e3dc1f7daff18432642867d570b2ffb4a6f5
|
4
|
+
data.tar.gz: 1f8bc8a88cb1e29c5605b9de140612c38d1d3588
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4625cf4d1a6a15db370f2c5fafcaa0b8d0a369d3a87bf009c4d46917af7d5539d5367d117a1c97cbeb35a977553d4c60519ecbca51b1114b97c5fe1a1334321a
|
7
|
+
data.tar.gz: 26ffce0d381dd7dd4cd1d5bf3b7dd772962d4257cbe4acef266853b9eb17b44af356c42376fa1842f79e3d459a6537bce26e5584202ca3a5a814787bc82ebd54
|
data/blacklight_marc.gemspec
CHANGED
@@ -21,4 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_dependency "railties", ">= 3.2.6", "< 5"
|
24
|
+
# Let's allow future versions of marc, count on
|
25
|
+
# them to be backwards compat until 1.1
|
26
|
+
spec.add_dependency "marc", ">= 0.4.3", "< 1.1" # Marc record parser.
|
24
27
|
end
|
@@ -0,0 +1,71 @@
|
|
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
|
+
module Blacklight::Solr::Document::Marc
|
21
|
+
|
22
|
+
include Blacklight::Solr::Document::MarcExport # All our export_as stuff based on to_marc.
|
23
|
+
|
24
|
+
class UnsupportedMarcFormatType < RuntimeError; end
|
25
|
+
|
26
|
+
def self.extended(document)
|
27
|
+
# Register our exportable formats, we inherit these from MarcExport
|
28
|
+
Blacklight::Solr::Document::MarcExport.register_export_formats( document )
|
29
|
+
end
|
30
|
+
|
31
|
+
# ruby-marc object
|
32
|
+
def to_marc
|
33
|
+
@_ruby_marc_obj ||= load_marc
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
protected
|
38
|
+
def marc_source
|
39
|
+
@_marc_source ||= fetch(_marc_source_field)
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_marc
|
43
|
+
case _marc_format_type.to_s
|
44
|
+
when 'marcxml'
|
45
|
+
records = MARC::XMLReader.new(StringIO.new( fetch(_marc_source_field) )).to_a
|
46
|
+
return records[0]
|
47
|
+
when 'marc21'
|
48
|
+
return MARC::Record.new_from_marc( fetch(_marc_source_field) )
|
49
|
+
else
|
50
|
+
|
51
|
+
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}")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
def _marc_helper
|
58
|
+
@_marc_helper ||= (
|
59
|
+
Blacklight::Marc::Document.new fetch(_marc_source_field), _marc_format_type )
|
60
|
+
end
|
61
|
+
|
62
|
+
def _marc_source_field
|
63
|
+
self.class.extension_parameters[:marc_source_field]
|
64
|
+
end
|
65
|
+
|
66
|
+
def _marc_format_type
|
67
|
+
#TODO: Raise if not present
|
68
|
+
self.class.extension_parameters[:marc_format_type]
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,602 @@
|
|
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&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&rfr_id=info%3Asid%2Fblacklight.rubyforge.org%3Agenerator&rft.genre=book&"
|
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'])}&"
|
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'])}&"
|
72
|
+
export_text << "rft.au=#{(author.nil? or author['a'].nil?) ? "" : CGI::escape(author['a'])}&"
|
73
|
+
export_text << "rft.aucorp=#{CGI::escape(corp_author['a']) if corp_author['a']}+#{CGI::escape(corp_author['b']) if corp_author['b']}&" unless corp_author.blank?
|
74
|
+
export_text << "rft.date=#{(publisher_info.nil? or publisher_info['c'].nil?) ? "" : CGI::escape(publisher_info['c'])}&"
|
75
|
+
export_text << "rft.place=#{(publisher_info.nil? or publisher_info['a'].nil?) ? "" : CGI::escape(publisher_info['a'])}&"
|
76
|
+
export_text << "rft.pub=#{(publisher_info.nil? or publisher_info['b'].nil?) ? "" : CGI::escape(publisher_info['b'])}&"
|
77
|
+
export_text << "rft.edition=#{(edition.nil? or edition['a'].nil?) ? "" : CGI::escape(edition['a'])}&"
|
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&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&rfr_id=info%3Asid%2Fblacklight.rubyforge.org%3Agenerator&rft.genre=article&"
|
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'])}&"
|
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'])}&"
|
83
|
+
export_text << "rft.aucorp=#{CGI::escape(corp_author['a']) if corp_author['a']}+#{CGI::escape(corp_author['b']) if corp_author['b']}&" unless corp_author.blank?
|
84
|
+
export_text << "rft.date=#{(publisher_info.nil? or publisher_info['c'].nil?) ? "" : CGI::escape(publisher_info['c'])}&"
|
85
|
+
export_text << "rft.issn=#{(issn.nil? or issn['a'].nil?) ? "" : issn['a']}"
|
86
|
+
else
|
87
|
+
export_text << "ctx_ver=Z39.88-2004&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&rfr_id=info%3Asid%2Fblacklight.rubyforge.org%3Agenerator&"
|
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 << "&rft.creator=" + ((author.nil? or author['a'].nil?) ? "" : CGI::escape(author['a']))
|
91
|
+
export_text << "&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 << "&rft.date=" + ((publisher_info.nil? or publisher_info['c'].nil?) ? "" : CGI::escape(publisher_info['c']))
|
93
|
+
export_text << "&rft.place=" + ((publisher_info.nil? or publisher_info['a'].nil?) ? "" : CGI::escape(publisher_info['a']))
|
94
|
+
export_text << "&rft.pub=" + ((publisher_info.nil? or publisher_info['b'].nil?) ? "" : CGI::escape(publisher_info['b']))
|
95
|
+
export_text << "&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
|
+
# plugin/gem weirdness means we do need to manually require
|
108
|
+
# here.
|
109
|
+
# As of 11 May 2010, Refworks has a problem with UTF-8 if it's decomposed,
|
110
|
+
# it seems to want C form normalization, although RefWorks support
|
111
|
+
# couldn't tell me that. -jrochkind
|
112
|
+
# DHF: moved this require a little lower in the method.
|
113
|
+
# require 'unicode'
|
114
|
+
|
115
|
+
fields = to_marc.find_all { |f| ('000'..'999') === f.tag }
|
116
|
+
text = "LEADER #{to_marc.leader}"
|
117
|
+
fields.each do |field|
|
118
|
+
unless ["940","999"].include?(field.tag)
|
119
|
+
if field.is_a?(MARC::ControlField)
|
120
|
+
text << "#{field.tag} #{field.value}\n"
|
121
|
+
else
|
122
|
+
text << "#{field.tag} "
|
123
|
+
text << (field.indicator1 ? field.indicator1 : " ")
|
124
|
+
text << (field.indicator2 ? field.indicator2 : " ")
|
125
|
+
text << " "
|
126
|
+
field.each {|s| s.code == 'a' ? text << "#{s.value}" : text << " |#{s.code}#{s.value}"}
|
127
|
+
text << "\n"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
if Blacklight.jruby?
|
133
|
+
require 'java'
|
134
|
+
java_import java.text.Normalizer
|
135
|
+
Normalizer.normalize(text, Normalizer::Form::NFC).to_s
|
136
|
+
else
|
137
|
+
begin
|
138
|
+
require 'unicode'
|
139
|
+
Unicode.normalize_C(text)
|
140
|
+
rescue LoadError
|
141
|
+
Blacklight.logger.warn "Unable to load unicode library in #export_as_refworks_marc_txt; skipping unicode normalization"
|
142
|
+
text
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Endnote Import Format. See the EndNote User Guide at:
|
148
|
+
# http://www.endnote.com/support/enx3man-terms-win.asp
|
149
|
+
# Chapter 7: Importing Reference Data into EndNote / Creating a Tagged “EndNote Import” File
|
150
|
+
#
|
151
|
+
# Note: This code is copied from what used to be in the previous version
|
152
|
+
# in ApplicationHelper#render_to_endnote. It does NOT produce very good
|
153
|
+
# endnote import format; the %0 is likely to be entirely illegal, the
|
154
|
+
# rest of the data is barely correct but messy. TODO, a new version of this,
|
155
|
+
# or better yet just an export_as_ris instead, which will be more general
|
156
|
+
# purpose.
|
157
|
+
def export_as_endnote()
|
158
|
+
end_note_format = {
|
159
|
+
"%A" => "100.a",
|
160
|
+
"%C" => "260.a",
|
161
|
+
"%D" => "260.c",
|
162
|
+
"%E" => "700.a",
|
163
|
+
"%I" => "260.b",
|
164
|
+
"%J" => "440.a",
|
165
|
+
"%@" => "020.a",
|
166
|
+
"%_@" => "022.a",
|
167
|
+
"%T" => "245.a,245.b",
|
168
|
+
"%U" => "856.u",
|
169
|
+
"%7" => "250.a"
|
170
|
+
}
|
171
|
+
marc_obj = to_marc
|
172
|
+
|
173
|
+
# TODO. This should be rewritten to guess
|
174
|
+
# from actual Marc instead, probably.
|
175
|
+
format_str = 'Generic'
|
176
|
+
|
177
|
+
text = ''
|
178
|
+
text << "%0 #{ format_str }\n"
|
179
|
+
# If there is some reliable way of getting the language of a record we can add it here
|
180
|
+
#text << "%G #{record['language'].first}\n"
|
181
|
+
end_note_format.each do |key,value|
|
182
|
+
values = value.split(",")
|
183
|
+
first_value = values[0].split('.')
|
184
|
+
if values.length > 1
|
185
|
+
second_value = values[1].split('.')
|
186
|
+
else
|
187
|
+
second_value = []
|
188
|
+
end
|
189
|
+
|
190
|
+
if marc_obj[first_value[0].to_s]
|
191
|
+
marc_obj.find_all{|f| (first_value[0].to_s) === f.tag}.each do |field|
|
192
|
+
if field[first_value[1]].to_s or field[second_value[1]].to_s
|
193
|
+
text << "#{key.gsub('_','')}"
|
194
|
+
if field[first_value[1]].to_s
|
195
|
+
text << " #{field[first_value[1]].to_s}"
|
196
|
+
end
|
197
|
+
if field[second_value[1]].to_s
|
198
|
+
text << " #{field[second_value[1]].to_s}"
|
199
|
+
end
|
200
|
+
text << "\n"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
text
|
206
|
+
end
|
207
|
+
|
208
|
+
## DEPRECATED stuff left in for backwards compatibility, but should
|
209
|
+
# be gotten rid of eventually.
|
210
|
+
|
211
|
+
def to_zotero(format)
|
212
|
+
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. ")
|
213
|
+
"<span class=\"Z3988\" title=\"#{export_as_openurl_kev(format)}\"></span>"
|
214
|
+
end
|
215
|
+
|
216
|
+
def to_apa
|
217
|
+
warn("[DEPRECATION] Call document.export_as_apa_citation instead.")
|
218
|
+
export_as_apa_citation
|
219
|
+
end
|
220
|
+
|
221
|
+
def to_mla
|
222
|
+
warn("[DEPRECATION] Call document.export_as_mla_citation instead.")
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
protected
|
228
|
+
|
229
|
+
# Main method for defining chicago style citation. If we don't end up converting to using a citation formatting service
|
230
|
+
# we should make this receive a semantic document and not MARC so we can use this with other formats.
|
231
|
+
def chicago_citation(marc)
|
232
|
+
authors = get_all_authors(marc)
|
233
|
+
author_text = ""
|
234
|
+
unless authors[:primary_authors].blank?
|
235
|
+
if authors[:primary_authors].length > 10
|
236
|
+
authors[:primary_authors].each_with_index do |author,index|
|
237
|
+
if index < 7
|
238
|
+
if index == 0
|
239
|
+
author_text << "#{author}"
|
240
|
+
if author.ends_with?(",")
|
241
|
+
author_text << " "
|
242
|
+
else
|
243
|
+
author_text << ", "
|
244
|
+
end
|
245
|
+
else
|
246
|
+
author_text << "#{name_reverse(author)}, "
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
author_text << " et al."
|
251
|
+
elsif authors[:primary_authors].length > 1
|
252
|
+
authors[:primary_authors].each_with_index do |author,index|
|
253
|
+
if index == 0
|
254
|
+
author_text << "#{author}"
|
255
|
+
if author.ends_with?(",")
|
256
|
+
author_text << " "
|
257
|
+
else
|
258
|
+
author_text << ", "
|
259
|
+
end
|
260
|
+
elsif index + 1 == authors[:primary_authors].length
|
261
|
+
author_text << "and #{name_reverse(author)}."
|
262
|
+
else
|
263
|
+
author_text << "#{name_reverse(author)}, "
|
264
|
+
end
|
265
|
+
end
|
266
|
+
else
|
267
|
+
author_text << authors[:primary_authors].first
|
268
|
+
end
|
269
|
+
else
|
270
|
+
temp_authors = []
|
271
|
+
authors[:translators].each do |translator|
|
272
|
+
temp_authors << [translator, "trans."]
|
273
|
+
end
|
274
|
+
authors[:editors].each do |editor|
|
275
|
+
temp_authors << [editor, "ed."]
|
276
|
+
end
|
277
|
+
authors[:compilers].each do |compiler|
|
278
|
+
temp_authors << [compiler, "comp."]
|
279
|
+
end
|
280
|
+
|
281
|
+
unless temp_authors.blank?
|
282
|
+
if temp_authors.length > 10
|
283
|
+
temp_authors.each_with_index do |author,index|
|
284
|
+
if index < 7
|
285
|
+
author_text << "#{author.first} #{author.last} "
|
286
|
+
end
|
287
|
+
end
|
288
|
+
author_text << " et al."
|
289
|
+
elsif temp_authors.length > 1
|
290
|
+
temp_authors.each_with_index do |author,index|
|
291
|
+
if index == 0
|
292
|
+
author_text << "#{author.first} #{author.last}, "
|
293
|
+
elsif index + 1 == temp_authors.length
|
294
|
+
author_text << "and #{name_reverse(author.first)} #{author.last}"
|
295
|
+
else
|
296
|
+
author_text << "#{name_reverse(author.first)} #{author.last}, "
|
297
|
+
end
|
298
|
+
end
|
299
|
+
else
|
300
|
+
author_text << "#{temp_authors.first.first} #{temp_authors.first.last}"
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
title = ""
|
305
|
+
additional_title = ""
|
306
|
+
section_title = ""
|
307
|
+
if marc["245"] and (marc["245"]["a"] or marc["245"]["b"])
|
308
|
+
title << citation_title(clean_end_punctuation(marc["245"]["a"]).strip) if marc["245"]["a"]
|
309
|
+
title << ": #{citation_title(clean_end_punctuation(marc["245"]["b"]).strip)}" if marc["245"]["b"]
|
310
|
+
end
|
311
|
+
if marc["245"] and (marc["245"]["n"] or marc["245"]["p"])
|
312
|
+
section_title << citation_title(clean_end_punctuation(marc["245"]["n"])) if marc["245"]["n"]
|
313
|
+
if marc["245"]["p"]
|
314
|
+
section_title << ", <i>#{citation_title(clean_end_punctuation(marc["245"]["p"]))}.</i>"
|
315
|
+
elsif marc["245"]["n"]
|
316
|
+
section_title << "."
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
if !authors[:primary_authors].blank? and (!authors[:translators].blank? or !authors[:editors].blank? or !authors[:compilers].blank?)
|
321
|
+
additional_title << "Translated by #{authors[:translators].collect{|name| name_reverse(name)}.join(" and ")}. " unless authors[:translators].blank?
|
322
|
+
additional_title << "Edited by #{authors[:editors].collect{|name| name_reverse(name)}.join(" and ")}. " unless authors[:editors].blank?
|
323
|
+
additional_title << "Compiled by #{authors[:compilers].collect{|name| name_reverse(name)}.join(" and ")}. " unless authors[:compilers].blank?
|
324
|
+
end
|
325
|
+
|
326
|
+
edition = ""
|
327
|
+
edition << setup_edition(marc) unless setup_edition(marc).nil?
|
328
|
+
|
329
|
+
pub_info = ""
|
330
|
+
if marc["260"] and (marc["260"]["a"] or marc["260"]["b"])
|
331
|
+
pub_info << clean_end_punctuation(marc["260"]["a"]).strip if marc["260"]["a"]
|
332
|
+
pub_info << ": #{clean_end_punctuation(marc["260"]["b"]).strip}" if marc["260"]["b"]
|
333
|
+
pub_info << ", #{setup_pub_date(marc)}" if marc["260"]["c"]
|
334
|
+
elsif marc["502"] and marc["502"]["a"] # MARC 502 is the Dissertation Note. This holds the correct pub info for these types of records.
|
335
|
+
pub_info << marc["502"]["a"]
|
336
|
+
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
|
337
|
+
pub_info << "#{marc["502"]["b"]}, #{marc["502"]["c"]}, #{clean_end_punctuation(marc["502"]["d"])}"
|
338
|
+
end
|
339
|
+
|
340
|
+
citation = ""
|
341
|
+
citation << "#{author_text} " unless author_text.blank?
|
342
|
+
citation << "<i>#{title}.</i> " unless title.blank?
|
343
|
+
citation << "#{section_title} " unless section_title.blank?
|
344
|
+
citation << "#{additional_title} " unless additional_title.blank?
|
345
|
+
citation << "#{edition} " unless edition.blank?
|
346
|
+
citation << "#{pub_info}." unless pub_info.blank?
|
347
|
+
citation
|
348
|
+
end
|
349
|
+
|
350
|
+
|
351
|
+
|
352
|
+
def mla_citation(record)
|
353
|
+
text = ''
|
354
|
+
authors_final = []
|
355
|
+
|
356
|
+
#setup formatted author list
|
357
|
+
authors = get_author_list(record)
|
358
|
+
|
359
|
+
if authors.length < 4
|
360
|
+
authors.each do |l|
|
361
|
+
if l == authors.first #first
|
362
|
+
authors_final.push(l)
|
363
|
+
elsif l == authors.last #last
|
364
|
+
authors_final.push(", and " + name_reverse(l) + ".")
|
365
|
+
else #all others
|
366
|
+
authors_final.push(", " + name_reverse(l))
|
367
|
+
end
|
368
|
+
end
|
369
|
+
text += authors_final.join
|
370
|
+
unless text.blank?
|
371
|
+
if text[-1,1] != "."
|
372
|
+
text += ". "
|
373
|
+
else
|
374
|
+
text += " "
|
375
|
+
end
|
376
|
+
end
|
377
|
+
else
|
378
|
+
text += authors.first + ", et al. "
|
379
|
+
end
|
380
|
+
# setup title
|
381
|
+
title = setup_title_info(record)
|
382
|
+
if !title.nil?
|
383
|
+
text += "<i>" + mla_citation_title(title) + "</i> "
|
384
|
+
end
|
385
|
+
|
386
|
+
# Edition
|
387
|
+
edition_data = setup_edition(record)
|
388
|
+
text += edition_data + " " unless edition_data.nil?
|
389
|
+
|
390
|
+
# Publication
|
391
|
+
text += setup_pub_info(record) + ", " unless setup_pub_info(record).nil?
|
392
|
+
|
393
|
+
# Get Pub Date
|
394
|
+
text += setup_pub_date(record) unless setup_pub_date(record).nil?
|
395
|
+
if text[-1,1] != "."
|
396
|
+
text += "." unless text.nil? or text.blank?
|
397
|
+
end
|
398
|
+
text
|
399
|
+
end
|
400
|
+
|
401
|
+
def apa_citation(record)
|
402
|
+
text = ''
|
403
|
+
authors_list = []
|
404
|
+
authors_list_final = []
|
405
|
+
|
406
|
+
#setup formatted author list
|
407
|
+
authors = get_author_list(record)
|
408
|
+
authors.each do |l|
|
409
|
+
authors_list.push(abbreviate_name(l)) unless l.blank?
|
410
|
+
end
|
411
|
+
authors_list.each do |l|
|
412
|
+
if l == authors_list.first #first
|
413
|
+
authors_list_final.push(l.strip)
|
414
|
+
elsif l == authors_list.last #last
|
415
|
+
authors_list_final.push(", & " + l.strip)
|
416
|
+
else #all others
|
417
|
+
authors_list_final.push(", " + l.strip)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
text += authors_list_final.join
|
421
|
+
unless text.blank?
|
422
|
+
if text[-1,1] != "."
|
423
|
+
text += ". "
|
424
|
+
else
|
425
|
+
text += " "
|
426
|
+
end
|
427
|
+
end
|
428
|
+
# Get Pub Date
|
429
|
+
text += "(" + setup_pub_date(record) + "). " unless setup_pub_date(record).nil?
|
430
|
+
|
431
|
+
# setup title info
|
432
|
+
title = setup_title_info(record)
|
433
|
+
text += "<i>" + title + "</i> " unless title.nil?
|
434
|
+
|
435
|
+
# Edition
|
436
|
+
edition_data = setup_edition(record)
|
437
|
+
text += edition_data + " " unless edition_data.nil?
|
438
|
+
|
439
|
+
# Publisher info
|
440
|
+
text += setup_pub_info(record) unless setup_pub_info(record).nil?
|
441
|
+
unless text.blank?
|
442
|
+
if text[-1,1] != "."
|
443
|
+
text += "."
|
444
|
+
end
|
445
|
+
end
|
446
|
+
text
|
447
|
+
end
|
448
|
+
def setup_pub_date(record)
|
449
|
+
if !record.find{|f| f.tag == '260'}.nil?
|
450
|
+
pub_date = record.find{|f| f.tag == '260'}
|
451
|
+
if pub_date.find{|s| s.code == 'c'}
|
452
|
+
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?
|
453
|
+
end
|
454
|
+
return nil if date_value.nil?
|
455
|
+
end
|
456
|
+
clean_end_punctuation(date_value) if date_value
|
457
|
+
end
|
458
|
+
def setup_pub_info(record)
|
459
|
+
text = ''
|
460
|
+
pub_info_field = record.find{|f| f.tag == '260'}
|
461
|
+
if !pub_info_field.nil?
|
462
|
+
a_pub_info = pub_info_field.find{|s| s.code == 'a'}
|
463
|
+
b_pub_info = pub_info_field.find{|s| s.code == 'b'}
|
464
|
+
a_pub_info = clean_end_punctuation(a_pub_info.value.strip) unless a_pub_info.nil?
|
465
|
+
b_pub_info = b_pub_info.value.strip unless b_pub_info.nil?
|
466
|
+
text += a_pub_info.strip unless a_pub_info.nil?
|
467
|
+
if !a_pub_info.nil? and !b_pub_info.nil?
|
468
|
+
text += ": "
|
469
|
+
end
|
470
|
+
text += b_pub_info.strip unless b_pub_info.nil?
|
471
|
+
end
|
472
|
+
return nil if text.strip.blank?
|
473
|
+
clean_end_punctuation(text.strip)
|
474
|
+
end
|
475
|
+
|
476
|
+
def mla_citation_title(text)
|
477
|
+
no_upcase = ["a","an","and","but","by","for","it","of","the","to","with"]
|
478
|
+
new_text = []
|
479
|
+
word_parts = text.split(" ")
|
480
|
+
word_parts.each do |w|
|
481
|
+
if !no_upcase.include? w
|
482
|
+
new_text.push(w.capitalize)
|
483
|
+
else
|
484
|
+
new_text.push(w)
|
485
|
+
end
|
486
|
+
end
|
487
|
+
new_text.join(" ")
|
488
|
+
end
|
489
|
+
|
490
|
+
# This will replace the mla_citation_title method with a better understanding of how MLA and Chicago citation titles are formatted.
|
491
|
+
# This method will take in a string and capitalize all of the non-prepositions.
|
492
|
+
def citation_title(title_text)
|
493
|
+
prepositions = ["a","about","across","an","and","before","but","by","for","it","of","the","to","with","without"]
|
494
|
+
new_text = []
|
495
|
+
title_text.split(" ").each_with_index do |word,index|
|
496
|
+
if (index == 0 and word != word.upcase) or (word.length > 1 and word != word.upcase and !prepositions.include?(word))
|
497
|
+
# the split("-") will handle the capitalization of hyphenated words
|
498
|
+
new_text << word.split("-").map!{|w| w.capitalize }.join("-")
|
499
|
+
else
|
500
|
+
new_text << word
|
501
|
+
end
|
502
|
+
end
|
503
|
+
new_text.join(" ")
|
504
|
+
end
|
505
|
+
|
506
|
+
def setup_title_info(record)
|
507
|
+
text = ''
|
508
|
+
title_info_field = record.find{|f| f.tag == '245'}
|
509
|
+
if !title_info_field.nil?
|
510
|
+
a_title_info = title_info_field.find{|s| s.code == 'a'}
|
511
|
+
b_title_info = title_info_field.find{|s| s.code == 'b'}
|
512
|
+
a_title_info = clean_end_punctuation(a_title_info.value.strip) unless a_title_info.nil?
|
513
|
+
b_title_info = clean_end_punctuation(b_title_info.value.strip) unless b_title_info.nil?
|
514
|
+
text += a_title_info unless a_title_info.nil?
|
515
|
+
if !a_title_info.nil? and !b_title_info.nil?
|
516
|
+
text += ": "
|
517
|
+
end
|
518
|
+
text += b_title_info unless b_title_info.nil?
|
519
|
+
end
|
520
|
+
|
521
|
+
return nil if text.strip.blank?
|
522
|
+
clean_end_punctuation(text.strip) + "."
|
523
|
+
|
524
|
+
end
|
525
|
+
|
526
|
+
def clean_end_punctuation(text)
|
527
|
+
if [".",",",":",";","/"].include? text[-1,1]
|
528
|
+
return text[0,text.length-1]
|
529
|
+
end
|
530
|
+
text
|
531
|
+
end
|
532
|
+
|
533
|
+
def setup_edition(record)
|
534
|
+
edition_field = record.find{|f| f.tag == '250'}
|
535
|
+
edition_code = edition_field.find{|s| s.code == 'a'} unless edition_field.nil?
|
536
|
+
edition_data = edition_code.value unless edition_code.nil?
|
537
|
+
if edition_data.nil? or edition_data == '1st ed.'
|
538
|
+
return nil
|
539
|
+
else
|
540
|
+
return edition_data
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
def get_author_list(record)
|
545
|
+
author_list = []
|
546
|
+
authors_primary = record.find{|f| f.tag == '100'}
|
547
|
+
author_primary = authors_primary.find{|s| s.code == 'a'}.value unless authors_primary.nil? rescue ''
|
548
|
+
author_list.push(clean_end_punctuation(author_primary)) unless author_primary.nil?
|
549
|
+
authors_secondary = record.find_all{|f| ('700') === f.tag}
|
550
|
+
if !authors_secondary.nil?
|
551
|
+
authors_secondary.each do |l|
|
552
|
+
author_list.push(clean_end_punctuation(l.find{|s| s.code == 'a'}.value)) unless l.find{|s| s.code == 'a'}.value.nil?
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
author_list.uniq!
|
557
|
+
author_list
|
558
|
+
end
|
559
|
+
|
560
|
+
# 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
|
561
|
+
def get_all_authors(record)
|
562
|
+
translator_code = "trl"; editor_code = "edt"; compiler_code = "com"
|
563
|
+
primary_authors = []; translators = []; editors = []; compilers = []
|
564
|
+
record.find_all{|f| f.tag === "100" }.each do |field|
|
565
|
+
primary_authors << field["a"] if field["a"]
|
566
|
+
end
|
567
|
+
record.find_all{|f| f.tag === "700" }.each do |field|
|
568
|
+
if field["a"]
|
569
|
+
relators = []
|
570
|
+
relators << clean_end_punctuation(field["e"]) if field["e"]
|
571
|
+
relators << clean_end_punctuation(field["4"]) if field["4"]
|
572
|
+
if relators.include?(translator_code)
|
573
|
+
translators << field["a"]
|
574
|
+
elsif relators.include?(editor_code)
|
575
|
+
editors << field["a"]
|
576
|
+
elsif relators.include?(compiler_code)
|
577
|
+
compilers << field["a"]
|
578
|
+
else
|
579
|
+
primary_authors << field["a"]
|
580
|
+
end
|
581
|
+
end
|
582
|
+
end
|
583
|
+
{:primary_authors => primary_authors, :translators => translators, :editors => editors, :compilers => compilers}
|
584
|
+
end
|
585
|
+
|
586
|
+
def abbreviate_name(name)
|
587
|
+
name_parts = name.split(", ")
|
588
|
+
first_name_parts = name_parts.last.split(" ")
|
589
|
+
temp_name = name_parts.first + ", " + first_name_parts.first[0,1] + "."
|
590
|
+
first_name_parts.shift
|
591
|
+
temp_name += " " + first_name_parts.join(" ") unless first_name_parts.empty?
|
592
|
+
temp_name
|
593
|
+
end
|
594
|
+
|
595
|
+
def name_reverse(name)
|
596
|
+
name = clean_end_punctuation(name)
|
597
|
+
return name unless name =~ /,/
|
598
|
+
temp_name = name.split(", ")
|
599
|
+
return temp_name.last + " " + temp_name.first
|
600
|
+
end
|
601
|
+
|
602
|
+
end
|
data/lib/blacklight_marc.rb
CHANGED
@@ -5,5 +5,10 @@ module BlacklightMarc
|
|
5
5
|
rake_tasks do
|
6
6
|
load "railties/solr_marc.rake"
|
7
7
|
end
|
8
|
+
|
9
|
+
initializer "blacklight MARC" do
|
10
|
+
Blacklight::Solr::Document.autoload :Marc, 'blacklight/solr/document/marc'
|
11
|
+
Blacklight::Solr::Document.autoload :MarcExport, 'blacklight/solr/document/marc_export'
|
12
|
+
end
|
8
13
|
end
|
9
14
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blacklight_marc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Coyne
|
@@ -58,6 +58,26 @@ dependencies:
|
|
58
58
|
- - <
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '5'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: marc
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.4.3
|
68
|
+
- - <
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '1.1'
|
71
|
+
type: :runtime
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.4.3
|
78
|
+
- - <
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '1.1'
|
61
81
|
description: SolrMarc support for Blacklight
|
62
82
|
email:
|
63
83
|
- justin@curationexperts.com
|
@@ -72,6 +92,8 @@ files:
|
|
72
92
|
- Rakefile
|
73
93
|
- blacklight_marc.gemspec
|
74
94
|
- lib/SolrMarc.jar
|
95
|
+
- lib/blacklight/solr/document/marc.rb
|
96
|
+
- lib/blacklight/solr/document/marc_export.rb
|
75
97
|
- lib/blacklight_marc.rb
|
76
98
|
- lib/blacklight_marc/version.rb
|
77
99
|
- lib/generators/blacklight_marc/marc_generator.rb
|