pennmarc 1.0.7 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11dd403cd5a0f964db340be6258d2cc510c99ccc0fc6d43a65b236853cb5b87c
4
- data.tar.gz: 85eed79f3e637121cce8be8b0f0509d26e3fa9b6283b7f5bc48b0b321259e3f3
3
+ metadata.gz: 652039b781e2ce7442f628ca722f4fda59207d1d8171bfd2fad84d2c67f3c06f
4
+ data.tar.gz: 166bbf8498f673b36373671db47031ef8a2f4d5496ed1fddeee89718bd23e09c
5
5
  SHA512:
6
- metadata.gz: 90a59eaf167d985b596663d6b8d1eab0c3263724da550babfb28fa253df326b07b72bbb5aac1cf1d4150efd2eaecce84686b2de9e99801ff178bbfabc982b765
7
- data.tar.gz: 5e0a4fdc1518af2b3a52bc137f76a30430d025f58f5cd46b9d0347a7a6a08f901e72e45917cc9a52d0352a6dbb0213725fd5a6e22650cfedb00d534fb72b44f2
6
+ metadata.gz: 68df667344adaff013da3eab5417bdd44748726a113190d20c44cc1cf4d061269619265e3de1edc9c7c767ffff5a4548a9fcb3ed2039b28a2608ec62a6e024d1
7
+ data.tar.gz: 8df6d32dbc84ff3851e4b35576e24c96c42b536330ded1f0f1678de3d1aa0729547a71b0c6ccea15e7c949ee15e068d1c0f19b18a6b414167cb736effa2b01dd
@@ -32,5 +32,16 @@ module PennMARC
32
32
  # a subfield code NOT used by the MARC 21 spec for 852 holdings records.
33
33
  # we add this subfield during preprocessing to store boundwith record IDs.
34
34
  SUB_BOUND_WITH_ID = 'y'
35
+
36
+ # MARC enrichment originating from Alma Api
37
+ # @see https://developers.exlibrisgroup.com/alma/apis/docs/bibs/R0VUIC9hbG1hd3MvdjEvYmlicy97bW1zX2lkfQ==/ Alma docs
38
+ module AlmaApi
39
+ TAG_PHYSICAL_INVENTORY = 'AVA'
40
+ TAG_DIGITAL_INVENTORY = 'AVA'
41
+ TAG_ELECTRONIC_INVENTORY = 'AVE'
42
+
43
+ SUB_PHYSICAL_CALL_NUMBER = 'd'
44
+ SUB_PHYSICAL_CALL_NUMBER_TYPE = 'k'
45
+ end
35
46
  end
36
47
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PennMARC
4
+ # Generates library of congress and dewey classifications using call number data.
5
+ class Classification < Helper
6
+ # Subfield value that identifies Library of Congress call number
7
+ LOC_CALL_NUMBER_TYPE = '0'
8
+
9
+ # Subfield value that identifies Dewey call number
10
+ DEWEY_CALL_NUMBER_TYPE = '1'
11
+
12
+ # Hash that maps call number type to the appropriate mapper
13
+ CLASSIFICATION_MAPS = {
14
+ LOC_CALL_NUMBER_TYPE => Mappers.loc_classification,
15
+ DEWEY_CALL_NUMBER_TYPE => Mappers.dewey_classification
16
+ }.freeze
17
+
18
+ # Enriched MARC tags that hold classification data
19
+ TAGS = [EnrichedMarc::TAG_ITEM, EnrichedMarc::AlmaApi::TAG_PHYSICAL_INVENTORY].freeze
20
+
21
+ class << self
22
+ # Parse classification values for faceting. We retrieve classification values from enriched MARC fields 'itm' or
23
+ # 'AVA' originating respectively from the Alma publishing process or from the Alma Api. We return the
24
+ # highest level LOC or Dewey classifications from each available call number, joining the class code with
25
+ # its title in a single string. See {PennMARC::EnrichedMarc} and {PennMARC::EnrichedMarc::AlmaApi} for more
26
+ # information on the enriched MARC fields.
27
+ # @see https://developers.exlibrisgroup.com/alma/apis/docs/bibs/R0VUIC9hbG1hd3MvdjEvYmlicy97bW1zX2lkfQ==/ AVA docs
28
+ # @param [MARC::Record] record
29
+ # @return [Array<String>] array of classifications
30
+ def facet(record)
31
+ record.fields(TAGS).flat_map do |field|
32
+ call_number_type = subfield_values(field, call_number_type_sf(field))&.first
33
+ call_numbers = subfield_values(field, call_number_sf(field))
34
+
35
+ call_numbers.filter_map do |call_number|
36
+ class_code = call_number[0]
37
+ title = translate_classification(class_code, call_number_type)
38
+ next if title.blank?
39
+
40
+ format_facet(class_code, call_number_type, title)
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ # Retrieve subfield code that stores the call number on enriched marc field
48
+ # @param [MARC::DataField] field
49
+ # @return [String]
50
+ def call_number_sf(field)
51
+ return EnrichedMarc::SUB_ITEM_CALL_NUMBER if field.tag == EnrichedMarc::TAG_ITEM
52
+
53
+ EnrichedMarc::AlmaApi::SUB_PHYSICAL_CALL_NUMBER
54
+ end
55
+
56
+ # Retrieve subfield code that stores call number type on enriched marc field
57
+ # @param [MARC::DataField] field
58
+ # @return [String]
59
+ def call_number_type_sf(field)
60
+ return EnrichedMarc::SUB_ITEM_CALL_NUMBER_TYPE if field.tag == EnrichedMarc::TAG_ITEM
61
+
62
+ EnrichedMarc::AlmaApi::SUB_PHYSICAL_CALL_NUMBER_TYPE
63
+ end
64
+
65
+ # retrieve title of classification based on single char classification code and call number type
66
+ # @param[String] class_code classification code
67
+ # @param[String] call_number_type value from call number type subfield
68
+ # @return [String, NilClass]
69
+ def translate_classification(class_code, call_number_type)
70
+ map = CLASSIFICATION_MAPS[call_number_type]
71
+
72
+ return if map.blank?
73
+
74
+ translate_relator(class_code, map)
75
+ end
76
+
77
+ # format classification facet by joining single character classification code with its corresponding title.
78
+ # Our Dewey mapping codes are single digit, so we must concatenate '00' to the class code to accurately reflect
79
+ # Dewey class codes.
80
+ # @return [String]
81
+ def format_facet(class_code, call_number_type, title)
82
+ return [class_code, title].join(' - ') if loc_call_number_type?(call_number_type)
83
+
84
+ ["#{class_code}00", title].join(' - ')
85
+ end
86
+
87
+ # Determine whether call number type is library of congress
88
+ # @param [String] call_number_type value from call number type subfield
89
+ # @return [Boolean]
90
+ def loc_call_number_type?(call_number_type)
91
+ call_number_type == '0'
92
+ end
93
+ end
94
+ end
95
+ end
@@ -13,7 +13,7 @@ module PennMARC
13
13
  # Full text links from MARC 856 fields.
14
14
  # @param [MARC::Record] record
15
15
  # @return [Array] array of hashes
16
- def full_text(record:)
16
+ def full_text(record)
17
17
  indicator2_options = %w[0 1]
18
18
  links_from_record(record, indicator2_options)
19
19
  end
@@ -21,7 +21,7 @@ module PennMARC
21
21
  # Web text links from MARC 856 fields.
22
22
  # @param [MARC::Record] record
23
23
  # @return [Array] array of hashes
24
- def web(record:)
24
+ def web(record)
25
25
  indicator2_options = ['2', ' ', '']
26
26
  links_from_record(record, indicator2_options)
27
27
  end
@@ -23,6 +23,16 @@ module PennMARC
23
23
  @relator ||= load_map('relator.yml')
24
24
  end
25
25
 
26
+ # @return [Hash]
27
+ def loc_classification
28
+ @loc_classification ||= load_map('loc_classification.yml')
29
+ end
30
+
31
+ # @return [Hash]
32
+ def dewey_classification
33
+ @dewey_classification ||= load_map('dewey_classification.yml')
34
+ end
35
+
26
36
  # @param [String] filename of mapping file in config directory, with file extension
27
37
  # @return [Hash] mapping as hash
28
38
  def load_map(filename)
@@ -0,0 +1,11 @@
1
+ ---
2
+ '0': Computer science, information & general works
3
+ '1': Philosophy & psychology
4
+ '2': Religion
5
+ '3': Social sciences
6
+ '4': Language
7
+ '5': Science
8
+ '6': Technology
9
+ '7': Arts & recreation
10
+ '8': Literature
11
+ '9': History & geography
@@ -0,0 +1,22 @@
1
+ ---
2
+ A: General Works
3
+ B: Philosophy, Psychology, Religion
4
+ C: 'History: Auxiliary Sciences'
5
+ D: 'History: General & European'
6
+ E: 'History: United States'
7
+ F: 'History: Western Hemisphere'
8
+ G: Geography, Anthropology, Recreation
9
+ H: Social Science, Economics, Sociology
10
+ J: Political Science
11
+ K: Law
12
+ L: Education
13
+ M: Music
14
+ N: Fine Arts
15
+ P: Literature & Languages
16
+ Q: Science
17
+ R: Medicine
18
+ S: Agriculture
19
+ T: Technology
20
+ U: Military Science
21
+ V: Naval Science
22
+ Z: Bibliography & Library Science
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PennMARC
4
- VERSION = '1.0.7'
4
+ VERSION = '1.0.9'
5
5
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'PennMARC::Classification' do
4
+ include MarcSpecHelpers
5
+
6
+ let(:helper) { PennMARC::Classification }
7
+ let(:record) do
8
+ marc_record fields: [marc_field(tag: tag,
9
+ subfields: { call_number_type_sf => '0', call_number_sf => 'TA683 .B3 1909b' }),
10
+ marc_field(tag: tag,
11
+ subfields: { call_number_type_sf => '0', call_number_sf => 'QL756 .S643' }),
12
+ marc_field(tag: tag,
13
+ subfields: { call_number_type_sf => '1', call_number_sf => '691.3 B2141' }),
14
+ marc_field(tag: tag,
15
+ subfields: { call_number_type_sf => '1', call_number_sf => '378.748 POS1952.29' })]
16
+ end
17
+
18
+ describe '.facet' do
19
+ context 'with enrichment via the Alma publishing process' do
20
+ let(:tag) { PennMARC::EnrichedMarc::TAG_ITEM }
21
+ let(:call_number_type_sf) { PennMARC::EnrichedMarc::SUB_ITEM_CALL_NUMBER_TYPE }
22
+ let(:call_number_sf) { PennMARC::EnrichedMarc::SUB_ITEM_CALL_NUMBER }
23
+
24
+ it 'returns expected values' do
25
+ expect(helper.facet(record)).to contain_exactly('T - Technology', '600 - Technology',
26
+ '300 - Social sciences', 'Q - Science')
27
+ end
28
+ end
29
+
30
+ context 'with enrichment with availability info via Alma Api' do
31
+ let(:tag) { PennMARC::EnrichedMarc::AlmaApi::TAG_PHYSICAL_INVENTORY }
32
+ let(:call_number_type_sf) { PennMARC::EnrichedMarc::AlmaApi::SUB_PHYSICAL_CALL_NUMBER_TYPE }
33
+ let(:call_number_sf) { PennMARC::EnrichedMarc::AlmaApi::SUB_PHYSICAL_CALL_NUMBER }
34
+
35
+ it 'returns expected values' do
36
+ expect(helper.facet(record)).to contain_exactly('T - Technology', '600 - Technology',
37
+ '300 - Social sciences', 'Q - Science')
38
+ end
39
+ end
40
+ end
41
+ end
@@ -15,8 +15,8 @@ describe 'PennMARC::Link' do
15
15
  end
16
16
 
17
17
  it 'returns full text link text and url' do
18
- expect(helper.full_text(record: record)).to contain_exactly({ link_text: 'Materials specified Public note',
19
- link_url: 'https://www.test-uri.com/' })
18
+ expect(helper.full_text(record)).to contain_exactly({ link_text: 'Materials specified Public note',
19
+ link_url: 'https://www.test-uri.com/' })
20
20
  end
21
21
  end
22
22
 
@@ -30,8 +30,8 @@ describe 'PennMARC::Link' do
30
30
  end
31
31
 
32
32
  it 'returns web link text and url' do
33
- expect(helper.web(record: record)).to contain_exactly({ link_text: 'Materials specified Public note',
34
- link_url: 'https://www.test-uri.com/' })
33
+ expect(helper.web(record)).to contain_exactly({ link_text: 'Materials specified Public note',
34
+ link_url: 'https://www.test-uri.com/' })
35
35
  end
36
36
  end
37
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pennmarc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Kanning
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-12-06 00:00:00.000000000 Z
13
+ date: 2023-12-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -91,6 +91,7 @@ files:
91
91
  - lib/pennmarc/heading_control.rb
92
92
  - lib/pennmarc/helpers/access.rb
93
93
  - lib/pennmarc/helpers/citation.rb
94
+ - lib/pennmarc/helpers/classification.rb
94
95
  - lib/pennmarc/helpers/creator.rb
95
96
  - lib/pennmarc/helpers/database.rb
96
97
  - lib/pennmarc/helpers/date.rb
@@ -109,8 +110,10 @@ files:
109
110
  - lib/pennmarc/helpers/subject.rb
110
111
  - lib/pennmarc/helpers/title.rb
111
112
  - lib/pennmarc/mappers.rb
113
+ - lib/pennmarc/mappings/dewey_classification.yml
112
114
  - lib/pennmarc/mappings/iso639-2-languages.yml
113
115
  - lib/pennmarc/mappings/iso639-3-languages.yml
116
+ - lib/pennmarc/mappings/loc_classification.yml
114
117
  - lib/pennmarc/mappings/locations.yml
115
118
  - lib/pennmarc/mappings/relator.yml
116
119
  - lib/pennmarc/parser.rb
@@ -120,6 +123,7 @@ files:
120
123
  - spec/fixtures/marcxml/test.xml
121
124
  - spec/lib/pennmarc/helpers/access_spec.rb
122
125
  - spec/lib/pennmarc/helpers/citation_spec.rb
126
+ - spec/lib/pennmarc/helpers/classification_spec.rb
123
127
  - spec/lib/pennmarc/helpers/creator_spec.rb
124
128
  - spec/lib/pennmarc/helpers/database_spec.rb
125
129
  - spec/lib/pennmarc/helpers/date_spec.rb