pennmarc 0.0.2 → 1.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/.rubocop_todo.yml +143 -0
- data/Gemfile +1 -1
- data/README.md +12 -2
- data/lib/pennmarc/helpers/creator.rb +59 -21
- data/lib/pennmarc/helpers/database.rb +8 -8
- data/lib/pennmarc/helpers/date.rb +16 -15
- data/lib/pennmarc/helpers/edition.rb +25 -20
- data/lib/pennmarc/helpers/format.rb +15 -4
- data/lib/pennmarc/helpers/genre.rb +13 -11
- data/lib/pennmarc/helpers/helper.rb +1 -0
- data/lib/pennmarc/helpers/identifier.rb +16 -7
- data/lib/pennmarc/helpers/language.rb +3 -3
- data/lib/pennmarc/helpers/link.rb +6 -0
- data/lib/pennmarc/helpers/location.rb +8 -8
- data/lib/pennmarc/helpers/note.rb +52 -2
- data/lib/pennmarc/helpers/relation.rb +4 -4
- data/lib/pennmarc/helpers/series.rb +171 -85
- data/lib/pennmarc/helpers/subject.rb +16 -17
- data/lib/pennmarc/helpers/title.rb +1 -1
- data/lib/pennmarc/mappers.rb +31 -0
- data/lib/pennmarc/parser.rb +34 -157
- data/lib/pennmarc/util.rb +15 -16
- data/pennmarc.gemspec +2 -2
- data/spec/lib/pennmarc/helpers/citation_spec.rb +1 -2
- data/spec/lib/pennmarc/helpers/creator_spec.rb +54 -19
- data/spec/lib/pennmarc/helpers/date_spec.rb +5 -5
- data/spec/lib/pennmarc/helpers/edition_spec.rb +4 -6
- data/spec/lib/pennmarc/helpers/format_spec.rb +30 -10
- data/spec/lib/pennmarc/helpers/genre_spec.rb +4 -4
- data/spec/lib/pennmarc/helpers/identifer_spec.rb +15 -0
- data/spec/lib/pennmarc/helpers/language_spec.rb +1 -1
- data/spec/lib/pennmarc/helpers/location_spec.rb +2 -1
- data/spec/lib/pennmarc/helpers/note_spec.rb +67 -2
- data/spec/lib/pennmarc/helpers/relation_spec.rb +2 -2
- data/spec/lib/pennmarc/helpers/series_spec.rb +54 -0
- data/spec/lib/pennmarc/helpers/subject_spec.rb +9 -9
- data/spec/lib/pennmarc/helpers/title_spec.rb +3 -1
- data/spec/lib/pennmarc/marc_util_spec.rb +9 -8
- data/spec/lib/pennmarc/parser_spec.rb +24 -3
- data/spec/spec_helper.rb +1 -1
- metadata +8 -20
- data/legacy/indexer.rb +0 -568
- data/legacy/marc.rb +0 -2964
- data/legacy/test_file_output.json +0 -49
@@ -11,9 +11,9 @@ module PennMARC
|
|
11
11
|
# @param [MARC::Record] record
|
12
12
|
# @return [Array<String>] array of genre values for search
|
13
13
|
def search(record)
|
14
|
-
record.fields('655').map
|
14
|
+
record.fields('655').map { |field|
|
15
15
|
join_subfields(field, &subfield_not_in?(%w[0 2 5 c]))
|
16
|
-
|
16
|
+
}.uniq
|
17
17
|
end
|
18
18
|
|
19
19
|
# Genre values for display. We display Genre/Term values if they fulfill the following criteria:
|
@@ -29,17 +29,18 @@ module PennMARC
|
|
29
29
|
# @param [MARC::Record] record
|
30
30
|
# @return [Array<String>] array of genre values for display
|
31
31
|
def show(record)
|
32
|
-
record.fields(%w[655 880]).filter_map
|
32
|
+
record.fields(%w[655 880]).filter_map { |field|
|
33
33
|
next unless allowed_genre_field?(field)
|
34
34
|
|
35
35
|
next if field.tag == '880' && subfield_values(field, '6').exclude?('655')
|
36
36
|
|
37
|
-
|
38
|
-
|
37
|
+
subfields = %w[a b]
|
38
|
+
sub_with_hyphens = field.find_all(&subfield_not_in?(%w[0 2 5 6 8 c e w])).map { |sf|
|
39
|
+
sep = subfields.exclude?(sf.code) ? ' -- ' : ' '
|
39
40
|
sep + sf.value
|
40
|
-
|
41
|
+
}.join.lstrip
|
41
42
|
"#{sub_with_hyphens} #{field.find_all(&subfield_in?(%w[e w])).join(' -- ')}".strip
|
42
|
-
|
43
|
+
}.uniq
|
43
44
|
end
|
44
45
|
|
45
46
|
# Genre values for faceting. We only set Genre facet values for movies (videos) and manuscripts(?)
|
@@ -48,15 +49,16 @@ module PennMARC
|
|
48
49
|
# @param [MARC::Record] record
|
49
50
|
# @param [Hash] location_map
|
50
51
|
# @return [Array<String>]
|
51
|
-
def facet(record, location_map)
|
52
|
-
locations = Location.location record: record, location_map: location_map,
|
52
|
+
def facet(record, location_map: Mappers.location)
|
53
|
+
locations = Location.location record: record, location_map: location_map,
|
54
|
+
display_value: :specific_location
|
53
55
|
manuscript = Format.include_manuscripts?(locations)
|
54
56
|
video = record.fields('007').any? { |field| field.value.starts_with? 'v' }
|
55
57
|
return [] unless manuscript || video
|
56
58
|
|
57
|
-
record.fields('655').filter_map
|
59
|
+
record.fields('655').filter_map { |field|
|
58
60
|
join_subfields field, &subfield_not_in?(%w[0 2 5 c])
|
59
|
-
|
61
|
+
}.uniq
|
60
62
|
end
|
61
63
|
|
62
64
|
private
|
@@ -19,13 +19,13 @@ module PennMARC
|
|
19
19
|
# @param [MARC::Record] record
|
20
20
|
# @return [Array<String>]
|
21
21
|
def isxn_search(record)
|
22
|
-
record.fields(%w[020 022]).filter_map
|
22
|
+
record.fields(%w[020 022]).filter_map { |field|
|
23
23
|
if field.tag == '020'
|
24
24
|
field.filter_map { |subfield| normalize_isbn(subfield.value) if subfield_in?(%w[a z]).call(subfield) }
|
25
25
|
else
|
26
26
|
field.filter_map { |subfield| subfield.value if subfield_in?(%w[a l z]).call(subfield) }
|
27
27
|
end
|
28
|
-
|
28
|
+
}.flatten.uniq
|
29
29
|
end
|
30
30
|
|
31
31
|
# Get ISBN values for display from the {https://www.oclc.org/bibformats/en/0xx/020.html 020 field}
|
@@ -37,7 +37,7 @@ module PennMARC
|
|
37
37
|
def isbn_show(record)
|
38
38
|
isbn_values = record.fields('020').filter_map do |field|
|
39
39
|
joined_isbn = join_subfields(field, &subfield_in?(%w[a z]))
|
40
|
-
joined_isbn
|
40
|
+
joined_isbn.presence
|
41
41
|
end
|
42
42
|
isbn_values += linked_alternate(record, '020', &subfield_in?(%w[a z]))
|
43
43
|
isbn_values
|
@@ -51,7 +51,7 @@ module PennMARC
|
|
51
51
|
def issn_show(record)
|
52
52
|
issn_values = record.fields('022').filter_map do |field|
|
53
53
|
joined_issn = join_subfields(field, &subfield_in?(%w[a z]))
|
54
|
-
joined_issn
|
54
|
+
joined_issn.presence
|
55
55
|
end
|
56
56
|
issn_values += linked_alternate(record, '022', &subfield_in?(%w[a z]))
|
57
57
|
issn_values
|
@@ -92,21 +92,30 @@ module PennMARC
|
|
92
92
|
def publisher_number_show(record)
|
93
93
|
publisher_numbers = record.fields(%w[024 028]).filter_map do |field|
|
94
94
|
joined_identifiers = join_subfields(field, &subfield_not_in?(%w[5 6]))
|
95
|
-
joined_identifiers
|
95
|
+
joined_identifiers.presence
|
96
96
|
end
|
97
97
|
publisher_numbers += linked_alternate(record, %w[024 028], &subfield_not_in?(%w[5 6]))
|
98
98
|
publisher_numbers
|
99
99
|
end
|
100
100
|
|
101
101
|
# Get publisher issued identifiers for searching of a record. Values extracted from fields
|
102
|
-
# {https://www.oclc.org/bibformats/en/0xx/024.html 024} and {https://www.oclc.org/bibformats/en/0xx/
|
102
|
+
# {https://www.oclc.org/bibformats/en/0xx/024.html 024} and {https://www.oclc.org/bibformats/en/0xx/028.html 028}.
|
103
103
|
#
|
104
104
|
# @param [MARC::Record] record
|
105
105
|
# @return [Array<String>]
|
106
106
|
def publisher_number_search(record)
|
107
107
|
record.fields(%w[024 028]).filter_map do |field|
|
108
108
|
joined_identifiers = join_subfields(field, &subfield_in?(%w[a]))
|
109
|
-
joined_identifiers
|
109
|
+
joined_identifiers.presence
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Retrieve fingerprint for display from the {https://www.oclc.org/bibformats/en/0xx/026.html 026} field
|
114
|
+
# @param [MARC::Record] record
|
115
|
+
# @return [Array<String>]
|
116
|
+
def fingerprint_show(record)
|
117
|
+
record.fields('026').map do |field|
|
118
|
+
join_subfields(field, &subfield_not_in?(%w[2 5 6 8]))
|
110
119
|
end
|
111
120
|
end
|
112
121
|
|
@@ -25,12 +25,12 @@ module PennMARC
|
|
25
25
|
# the 008 control field. Language facet and search values will typically be the same.
|
26
26
|
#
|
27
27
|
# @param [MARC::Record] record
|
28
|
-
# @param [Hash]
|
28
|
+
# @param [Hash] language_map hash for language code translation
|
29
29
|
# @return [String] nice value for language
|
30
|
-
def search(record,
|
30
|
+
def search(record, language_map: Mappers.language)
|
31
31
|
control_field = record['008']&.value
|
32
32
|
language_code = control_field[35..37]
|
33
|
-
|
33
|
+
language_map[language_code.to_sym || UNDETERMINED_CODE]
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -4,6 +4,12 @@ module PennMARC
|
|
4
4
|
# Do Link-y stuff
|
5
5
|
class Link < Helper
|
6
6
|
class << self
|
7
|
+
# @todo the legacy code here is a hot mess for a number of reasons, what do we need this field to do?
|
8
|
+
# @note port the needed parts from get_offsite_display, don't return HTML
|
9
|
+
# @param [MARC::Record] record
|
10
|
+
# @return [Object]
|
11
|
+
def offsite(record); end
|
12
|
+
|
7
13
|
def full_text(record:); end
|
8
14
|
|
9
15
|
def web(record:); end
|
@@ -12,7 +12,7 @@ module PennMARC
|
|
12
12
|
# @param [MARC::Record] record
|
13
13
|
# @param [Hash] location_map hash with location_code as key and location hash as value
|
14
14
|
# @return [Array<String>] Array of library locations retrieved from location_map
|
15
|
-
def library(record, location_map)
|
15
|
+
def library(record, location_map: Mappers.location)
|
16
16
|
location(record: record, location_map: location_map, display_value: 'library')
|
17
17
|
end
|
18
18
|
|
@@ -25,7 +25,7 @@ module PennMARC
|
|
25
25
|
# @param [MARC::Record] record
|
26
26
|
# @param [Hash] location_map hash with location_code as key and location hash as value
|
27
27
|
# @return [Array<String>] Array of specific locations retrieved from location_map
|
28
|
-
def specific_location(record, location_map)
|
28
|
+
def specific_location(record, location_map: Mappers.location)
|
29
29
|
location(record: record, location_map: location_map, display_value: 'specific_location')
|
30
30
|
end
|
31
31
|
|
@@ -35,15 +35,15 @@ module PennMARC
|
|
35
35
|
# @see https://developers.exlibrisgroup.com/alma/apis/docs/bibs/R0VUIC9hbG1hd3MvdjEvYmlicy97bW1zX2lkfQ==/
|
36
36
|
# Alma documentation for these added fields
|
37
37
|
# @param [MARC::Record] record
|
38
|
-
# @param [Hash] location_map hash with location_code as key and location hash as value
|
39
38
|
# @param [Symbol | String] display_value field in location hash to retrieve
|
39
|
+
# @param [Hash] location_map hash with location_code as key and location hash as value
|
40
40
|
# @return [Array<String>]
|
41
|
-
def location(record:,
|
41
|
+
def location(record:, display_value:, location_map:)
|
42
42
|
# get enriched marc location tag and subfield code
|
43
43
|
location_tag_and_subfield_code(record) => {tag:, subfield_code:}
|
44
44
|
|
45
|
-
locations = record.fields(tag).flat_map
|
46
|
-
field.filter_map
|
45
|
+
locations = record.fields(tag).flat_map { |field|
|
46
|
+
field.filter_map { |subfield|
|
47
47
|
# skip unless subfield code does not match enriched marc tag subfield code
|
48
48
|
next unless subfield.code == subfield_code
|
49
49
|
|
@@ -59,8 +59,8 @@ module PennMARC
|
|
59
59
|
next unless location_map.key?(subfield.value.to_sym)
|
60
60
|
|
61
61
|
location_map[subfield.value.to_sym][display_value.to_sym]
|
62
|
-
|
63
|
-
|
62
|
+
}.flatten.compact_blank
|
63
|
+
}.uniq
|
64
64
|
locations << 'Online library' if record.fields(PennMARC::EnrichedMarc::TAG_ELECTRONIC_INVENTORY).any?
|
65
65
|
locations
|
66
66
|
end
|
@@ -72,11 +72,11 @@ module PennMARC
|
|
72
72
|
# @param [MARC::Record] record
|
73
73
|
# @return [Array<String>]
|
74
74
|
def contents_show(record)
|
75
|
-
record.fields(%w[505 880]).filter_map
|
75
|
+
record.fields(%w[505 880]).filter_map { |field|
|
76
76
|
next if field.tag == '880' && subfield_value_not_in?(field, '6', %w[505])
|
77
77
|
|
78
78
|
join_subfields(field, &subfield_not_in?(%w[6 8])).split('--')
|
79
|
-
|
79
|
+
}.flatten
|
80
80
|
end
|
81
81
|
|
82
82
|
# Retrieve access restricted notes for display from field {https://www.oclc.org/bibformats/en/5xx/506.html 506}.
|
@@ -127,6 +127,56 @@ module PennMARC
|
|
127
127
|
def summary_show(record)
|
128
128
|
datafield_and_linked_alternate(record, '520')
|
129
129
|
end
|
130
|
+
|
131
|
+
# Retrieve arrangement values for display from field field {https://www.oclc.org/bibformats/en/3xx/351.html 351}.
|
132
|
+
# @param [MARC::Record] record
|
133
|
+
# @return [Array<String>]
|
134
|
+
def arrangement_show(record)
|
135
|
+
datafield_and_linked_alternate(record, '351')
|
136
|
+
end
|
137
|
+
|
138
|
+
# Retrieve system details notes for display from fields {https://www.oclc.org/bibformats/en/5xx/538.html 538},
|
139
|
+
# {https://www.oclc.org/bibformats/en/3xx/344.html 344}, {https://www.oclc.org/bibformats/en/3xx/345.html 345},
|
140
|
+
# {https://www.oclc.org/bibformats/en/3xx/346.html 346}, {https://www.oclc.org/bibformats/en/3xx/347.html 347},
|
141
|
+
# and their linked alternates.
|
142
|
+
# @param [MARC::Record] record
|
143
|
+
# @return [Array<String>]
|
144
|
+
def system_details_show(record)
|
145
|
+
system_details_notes = record.fields(%w[538 880]).filter_map do |field|
|
146
|
+
next if field.tag == '880' && subfield_value_not_in?(field, '6', ['538'])
|
147
|
+
|
148
|
+
sub3_and_other_subs(field, &subfield_in?(%w[a i u]))
|
149
|
+
end
|
150
|
+
system_details_notes += record.fields(%w[344 880]).filter_map do |field|
|
151
|
+
next if field.tag == '880' && subfield_value_not_in?(field, '6', ['344'])
|
152
|
+
|
153
|
+
sub3_and_other_subs(field, &subfield_in?(%w[a b c d e f g h]))
|
154
|
+
end
|
155
|
+
system_details_notes += record.fields(%w[345 346 880]).filter_map do |field|
|
156
|
+
next if field.tag == '880' && subfield_value_not_in?(field, '6', %w[345 346])
|
157
|
+
|
158
|
+
sub3_and_other_subs(field, &subfield_in?(%w[a b]))
|
159
|
+
end
|
160
|
+
system_details_notes += record.fields(%w[347 880]).filter_map do |field|
|
161
|
+
next if field.tag == '880' && subfield_value_not_in?(field, '6', ['347'])
|
162
|
+
|
163
|
+
sub3_and_other_subs(field, &subfield_in?(%w[a b c d e f]))
|
164
|
+
end
|
165
|
+
system_details_notes
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
|
170
|
+
# For system details: extract subfield ǂ3 plus other subfields as specified by passed-in block. Pays special
|
171
|
+
# attention to punctuation, joining subfield ǂ3 values with a colon-space (': ').
|
172
|
+
# @param [MARC::DataField] field
|
173
|
+
# @param [Proc] selector
|
174
|
+
# @return [String]
|
175
|
+
def sub3_and_other_subs(field, &)
|
176
|
+
sub3 = field.filter_map { |sf| trim_trailing('period', sf.value) if sf.code == '3' }.join(': ')
|
177
|
+
oth_subs = join_subfields(field, &)
|
178
|
+
[sub3, trim_trailing('semicolon', oth_subs)].join(' ')
|
179
|
+
end
|
130
180
|
end
|
131
181
|
end
|
132
182
|
end
|
@@ -48,16 +48,16 @@ module PennMARC
|
|
48
48
|
# @param [MARC::Record] record
|
49
49
|
# @param [Hash] relator_map
|
50
50
|
# @return [Array]
|
51
|
-
def related_work_show(record, relator_map)
|
51
|
+
def related_work_show(record, relator_map: Mappers.relator)
|
52
52
|
values = record.fields(RELATED_WORK_FIELDS).filter_map do |field|
|
53
|
-
next
|
53
|
+
next if field.indicator2.present?
|
54
54
|
|
55
55
|
next unless subfield_defined?(field, 't')
|
56
56
|
|
57
57
|
values_with_title_prefix(field, sf_exclude: %w[0 4 6 8 i], relator_map: relator_map)
|
58
58
|
end
|
59
59
|
values + record.fields('880').filter_map do |field|
|
60
|
-
next
|
60
|
+
next if field.indicator2.present?
|
61
61
|
|
62
62
|
next unless subfield_value?(field, '6', /^(#{RELATED_WORK_FIELDS.join('|')})/)
|
63
63
|
|
@@ -73,7 +73,7 @@ module PennMARC
|
|
73
73
|
# @param [MARC::Record] record
|
74
74
|
# @param [Hash] relator_map
|
75
75
|
# @return [Array]
|
76
|
-
def contains_show(record, relator_map)
|
76
|
+
def contains_show(record, relator_map: Mappers.relator)
|
77
77
|
acc = record.fields(CONTAINS_FIELDS).filter_map do |field|
|
78
78
|
next unless field.indicator2 == '2'
|
79
79
|
|
@@ -1,116 +1,202 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module PennMARC
|
4
|
-
# Do Series-
|
4
|
+
# Do Series and series-related field processing. Many of these fields are added entries that are justified by
|
5
|
+
# corresponding series statements (usually 490). These fields provide information about the published series in which
|
6
|
+
# a book, encoded finding aid, or other published work has appeared
|
7
|
+
# @todo We may want to include 410 in the display tags, since it is included in references below.
|
5
8
|
class Series < Helper
|
6
9
|
class << self
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
if %w[e w v n t].member?(sf.code)
|
18
|
-
[' ', sf.value]
|
19
|
-
elsif sf.code == '4'
|
20
|
-
[', ', relator_codes[sf.value]]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
series_append = pairs.flatten.join.strip
|
24
|
-
acc << { value: series, value_append: series_append, link_type: 'author_search' }
|
25
|
-
end
|
26
|
-
elsif %w[830 440 490].member?(tags_present.first)
|
27
|
-
record.fields(tags_present.first).each do |field|
|
28
|
-
# added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
29
|
-
series = join_subfields(field, &subfield_not_in(%w[0 5 6 8 c e w v n]))
|
30
|
-
series_append = join_subfields(field, &subfield_in(%w[c e w v n]))
|
31
|
-
acc << { value: series, value_append: series_append, link_type: 'title_search' }
|
32
|
-
end
|
33
|
-
end
|
10
|
+
# 800 - Series Added Entry-Personal Name - https://www.loc.gov/marc/bibliographic/bd800.html
|
11
|
+
# 810 - Series Added Entry-Corporate Name - https://www.loc.gov/marc/bibliographic/bd810.html
|
12
|
+
# 410 - Series Statement/Added Entry-Corporate Name - https://www.loc.gov/marc/bibliographic/bd410.html
|
13
|
+
# 811 - Series Added Entry-Meeting Name - https://www.loc.gov/marc/bibliographic/bd811.html
|
14
|
+
# 830 - Series Added Entry-Uniform Title - https://www.loc.gov/marc/bibliographic/bd830.html
|
15
|
+
# 400 - Series Statement/Added Entry-Personal Name - https://www.loc.gov/marc/bibliographic/bd400.html
|
16
|
+
# 411 - Series Statement/Added Entry Meeting Name - https://www.loc.gov/marc/bibliographic/bd411.html
|
17
|
+
# 440 - Series Statement/Added Entry-Title - https://www.loc.gov/marc/bibliographic/bd440.html
|
18
|
+
# 490 - Series Statement - https://www.loc.gov/marc/bibliographic/bd490.html
|
19
|
+
DISPLAY_TAGS = %w[800 810 811 830 400 411 440 490].freeze
|
34
20
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
21
|
+
# Fields for display that pertain to series information.
|
22
|
+
# @param [MARC::Record] record
|
23
|
+
# @param [Hash] relator_map
|
24
|
+
# @return [Array<String>] array of series information
|
25
|
+
def show(record, relator_map: Mappers.relator)
|
26
|
+
tags_present = DISPLAY_TAGS.select { |tag| record[tag].present? }
|
40
27
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
28
|
+
values = if %w[800 810 811 400 410 411].member?(tags_present.first)
|
29
|
+
author_show_entries(record, tags_present.first, relator_map)
|
30
|
+
elsif %w[830 440 490].member?(tags_present.first)
|
31
|
+
title_show_entries(record, tags_present.first)
|
32
|
+
end || []
|
47
33
|
|
48
|
-
|
34
|
+
values += remaining_show_entries(record, tags_present)
|
35
|
+
values + series_880_fields(record)
|
49
36
|
end
|
50
37
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
end
|
63
|
-
acc
|
38
|
+
# Values from series fields for display.
|
39
|
+
# @param [MARC::Record] record
|
40
|
+
# @param [Hash] relator_map
|
41
|
+
# @return [Array<String>] array of series values
|
42
|
+
def values(record, relator_map: Mappers.relator)
|
43
|
+
series_8x = record.fields(%w[800 810 811 830]).first
|
44
|
+
return Array.wrap(series_field(series_8x, relator_map)) if series_8x
|
45
|
+
|
46
|
+
series_4x = record.fields(%w[400 410 411 440 490]).first
|
47
|
+
Array.wrap(series_field(series_4x, relator_map)) if series_4x
|
64
48
|
end
|
65
49
|
|
50
|
+
# Series fields for search.
|
51
|
+
# @param [MARC::Record] record
|
52
|
+
# @return [Array<String>] array of series values
|
66
53
|
def search(record)
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
54
|
+
values = record.fields(%w[400 410 411]).filter_map do |field|
|
55
|
+
subfields = if field.indicator2 != '0'
|
56
|
+
%w[4 6 8]
|
57
|
+
elsif field.indicator2 != '1'
|
58
|
+
%w[4 6 8 a]
|
59
|
+
else
|
60
|
+
next
|
61
|
+
end
|
62
|
+
join_subfields(field, &subfield_not_in?(subfields))
|
71
63
|
end
|
72
|
-
|
73
|
-
|
74
|
-
.map do |field|
|
75
|
-
join_subfields(field, &subfield_not_in(%w[4 6 8 a]))
|
64
|
+
values += record.fields(%w[440]).filter_map do |field|
|
65
|
+
join_subfields(field, &subfield_not_in?(%w[0 5 6 8 w]))
|
76
66
|
end
|
77
|
-
|
78
|
-
|
79
|
-
join_subfields(field, &subfield_not_in(%w[0 5 6 8 w]))
|
67
|
+
values += record.fields(%w[800 810 811]).filter_map do |field|
|
68
|
+
join_subfields(field, &subfield_not_in?(%w[0 4 5 6 7 8 w]))
|
80
69
|
end
|
81
|
-
|
82
|
-
|
83
|
-
join_subfields(field, &subfield_not_in(%w[0 4 5 6 7 8 w]))
|
70
|
+
values += record.fields(%w[830]).filter_map do |field|
|
71
|
+
join_subfields(field, &subfield_not_in?(%w[0 5 6 7 8 w]))
|
84
72
|
end
|
85
|
-
|
86
|
-
|
73
|
+
values += record.fields(%w[533]).filter_map do |field|
|
74
|
+
filtered_values = field.filter_map { |sf| sf.value if sf.code == 'f' }
|
75
|
+
next if filtered_values.empty?
|
76
|
+
|
77
|
+
filtered_values.map { |v| v.gsub(/\(|\)/, '') }.join(' ')
|
87
78
|
end
|
88
|
-
|
89
|
-
.map do |field|
|
90
|
-
field.find_all { |sf| sf.code == 'f' }
|
91
|
-
.map(&:value)
|
92
|
-
.map { |v| v.gsub(/\(|\)/, '') }
|
93
|
-
.join(' ')
|
94
|
-
end
|
79
|
+
values
|
95
80
|
end
|
96
81
|
|
82
|
+
# Information concerning the immediate predecessor of the target item (chronological relationship). When a note
|
83
|
+
# is generated from this field, the introductory term or phrase may be generated based on the value in the second
|
84
|
+
# indicator position for display.
|
85
|
+
# https://www.loc.gov/marc/bibliographic/bd780.html
|
86
|
+
# @param [MARC::Record] record
|
87
|
+
# @return [String] continues fields string
|
97
88
|
def get_continues_display(record)
|
98
|
-
|
89
|
+
continues(record, '780')
|
99
90
|
end
|
100
91
|
|
92
|
+
# Information concerning the immediate successor to the target item (chronological relationship). When a note is
|
93
|
+
# generated from this field, the introductory phrase may be generated based on the value in the second indicator
|
94
|
+
# position for display.
|
95
|
+
# https://www.loc.gov/marc/bibliographic/bd785.html
|
96
|
+
# @param [MARC::Record] record
|
97
|
+
# @return [String] continued by fields string
|
101
98
|
def get_continued_by_display(record)
|
102
|
-
|
99
|
+
continues(record, '785')
|
103
100
|
end
|
104
101
|
|
105
102
|
private
|
106
103
|
|
107
|
-
#
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
104
|
+
# If any of these values: 800 810 811 400 410 411 are present, return a string with series information and
|
105
|
+
# appended values.
|
106
|
+
# @note added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
107
|
+
# @param [MARC::Record] record
|
108
|
+
# @param [String] first_tag
|
109
|
+
# @param [Hash] relator_mapping
|
110
|
+
# @return [Array<Hash>] array of author show entry hashes
|
111
|
+
def author_show_entries(record, first_tag, relator_mapping)
|
112
|
+
record.fields(first_tag).map do |field|
|
113
|
+
series = join_subfields(field, &subfield_not_in?(%w[0 5 6 8 e t w v n]))
|
114
|
+
author_show_subfields = %w[e w v n t]
|
115
|
+
pairs = field.map do |sf|
|
116
|
+
if author_show_subfields.member?(sf.code)
|
117
|
+
[' ', sf.value]
|
118
|
+
elsif sf.code == '4'
|
119
|
+
[', ', translate_relator(sf.value, relator_mapping)]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
series_append = pairs.flatten.join.strip
|
123
|
+
"#{series} #{series_append}".squish
|
124
|
+
end || []
|
125
|
+
end
|
126
|
+
|
127
|
+
# If any of these values: 830 440 490 are present, return a string with series information and appended values.
|
128
|
+
# @note added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
129
|
+
# @param [MARC::Record] record
|
130
|
+
# @param [String] first_tag
|
131
|
+
# @return [Array<Hash>] array of author show entry hashes
|
132
|
+
def title_show_entries(record, first_tag)
|
133
|
+
record.fields(first_tag).map do |field|
|
134
|
+
series = join_subfields(field, &subfield_not_in?(%w[0 5 6 8 c e w v n]))
|
135
|
+
series_append = join_subfields(field, &subfield_in?(%w[c e w v n]))
|
136
|
+
"#{series} #{series_append}".squish
|
137
|
+
end || []
|
138
|
+
end
|
139
|
+
|
140
|
+
# Assemble an array of hashes that includes the remaining show entries.
|
141
|
+
# @note added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
142
|
+
# @param [MARC::Record] record
|
143
|
+
# @param [Array<String>] tags_present
|
144
|
+
# @return [Array<Hash>] array of remaining show entry hashes
|
145
|
+
def remaining_show_entries(record, tags_present)
|
146
|
+
record.fields(tags_present.drop(1)).map do |field|
|
147
|
+
join_subfields(field, &subfield_not_in?(%w[0 5 6 8]))
|
148
|
+
end || []
|
149
|
+
end
|
150
|
+
|
151
|
+
# TODO: use linked alternate in place of this function
|
152
|
+
# @note There are multiple locations in these helpers where we should be able to use the linked_alternate util.
|
153
|
+
# @note This requires a more comprehensive evaluation and refactor of the linked_alternate utility.
|
154
|
+
#
|
155
|
+
# Fully content-designated representation, in a different script, of another field in the same record. Field 880
|
156
|
+
# is linked to the associated regular field by subfield $6 (Linkage). A subfield $6 in the associated field also
|
157
|
+
# links that field to the 880 field. The data in field 880 may be in more than one script. This function exists
|
158
|
+
# because it differs than the tradition use of linked_alternate.
|
159
|
+
# @param [MARC::Record] record
|
160
|
+
def series_880_fields(record)
|
161
|
+
record.fields('880').filter_map do |field|
|
162
|
+
next unless subfield_value?(field, '6', /^(800|810|811|830|400|410|411|440|490)/)
|
163
|
+
|
164
|
+
join_subfields(field, &subfield_not_in?(%w[5 6 8]))
|
165
|
+
end || []
|
166
|
+
end
|
167
|
+
|
168
|
+
# Assemble a formatted string of a given field.
|
169
|
+
# @note added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
170
|
+
# @param [MARC::Field] field
|
171
|
+
# @param [Hash] relator_mapping
|
172
|
+
# @return [String] series 4xx field
|
173
|
+
def series_field(field, relator_mapping)
|
174
|
+
subfields = if field.tag.start_with? '4'
|
175
|
+
%w[0 4 6 8]
|
176
|
+
else
|
177
|
+
%w[0 4 5 6 8]
|
178
|
+
end
|
179
|
+
s = field.filter_map { |sf|
|
180
|
+
if subfields.exclude?(sf.code)
|
181
|
+
" #{sf.value}"
|
182
|
+
elsif sf.code == '4'
|
183
|
+
", #{translate_relator(sf.value, relator_mapping)}"
|
184
|
+
end
|
185
|
+
}.join
|
186
|
+
s2 = s + (%w[. -].exclude?(s[-1]) ? '.' : '')
|
187
|
+
s2.squish
|
188
|
+
end
|
189
|
+
|
190
|
+
# Get subfields from a given field (continues or continued_by).
|
191
|
+
# @param [MARC::Record] record
|
192
|
+
# @param [String] tag
|
193
|
+
# @return [String] joined subfields
|
194
|
+
def continues(record, tag)
|
195
|
+
record.fields.filter_map do |field|
|
196
|
+
next unless field.tag == tag || (field.tag == '880' && subfield_value?(field, '6', /^#{tag}/))
|
197
|
+
next unless field.any?(&subfield_in?(%w[i a s t n d]))
|
198
|
+
|
199
|
+
join_subfields(field, &subfield_in?(%w[i a s t n d]))
|
114
200
|
end
|
115
201
|
end
|
116
202
|
end
|