berkeley_library-tind 0.5.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +15 -3
  3. data/.gitignore +3 -0
  4. data/.idea/inspectionProfiles/Project_Default.xml +10 -0
  5. data/.idea/tind.iml +10 -9
  6. data/.rubocop.yml +1 -1
  7. data/CHANGES.md +15 -1
  8. data/README.md +165 -2
  9. data/berkeley_library-tind.gemspec +2 -2
  10. data/bin/alma-multiple-tind +50 -0
  11. data/bin/alma-single-tind +48 -0
  12. data/bin/save_tind_records +80 -0
  13. data/bin/tind-marc +73 -0
  14. data/lib/berkeley_library/tind/export/ods_exporter.rb +4 -6
  15. data/lib/berkeley_library/tind/mapping/additional_datafield_process.rb +128 -0
  16. data/lib/berkeley_library/tind/mapping/alma.rb +42 -0
  17. data/lib/berkeley_library/tind/mapping/alma_base.rb +108 -0
  18. data/lib/berkeley_library/tind/mapping/alma_multiple_tind.rb +31 -0
  19. data/lib/berkeley_library/tind/mapping/alma_single_tind.rb +28 -0
  20. data/lib/berkeley_library/tind/mapping/config.rb +44 -0
  21. data/lib/berkeley_library/tind/mapping/csv_mapper.rb +35 -0
  22. data/lib/berkeley_library/tind/mapping/csv_multiple_mapper.rb +41 -0
  23. data/lib/berkeley_library/tind/mapping/data/one_to_multiple_mapping.csv +4 -0
  24. data/lib/berkeley_library/tind/mapping/data/one_to_one_mapping.csv +39 -0
  25. data/lib/berkeley_library/tind/mapping/external_tind_field.rb +103 -0
  26. data/lib/berkeley_library/tind/mapping/field_catalog.rb +137 -0
  27. data/lib/berkeley_library/tind/mapping/field_catalog_util.rb +105 -0
  28. data/lib/berkeley_library/tind/mapping/match_tind_field.rb +77 -0
  29. data/lib/berkeley_library/tind/mapping/misc.rb +69 -0
  30. data/lib/berkeley_library/tind/mapping/multiple_rule.rb +36 -0
  31. data/lib/berkeley_library/tind/mapping/single_rule.rb +149 -0
  32. data/lib/berkeley_library/tind/mapping/tind_control_subfield.rb +59 -0
  33. data/lib/berkeley_library/tind/mapping/tind_field.rb +49 -0
  34. data/lib/berkeley_library/tind/mapping/tind_field_from_leader.rb +27 -0
  35. data/lib/berkeley_library/tind/mapping/tind_field_from_multiple_map.rb +59 -0
  36. data/lib/berkeley_library/tind/mapping/tind_field_from_single_map.rb +182 -0
  37. data/lib/berkeley_library/tind/mapping/tind_field_util.rb +112 -0
  38. data/lib/berkeley_library/tind/mapping/tind_marc.rb +134 -0
  39. data/lib/berkeley_library/tind/mapping/tind_record_util.rb +135 -0
  40. data/lib/berkeley_library/tind/mapping/tind_subfield_util.rb +154 -0
  41. data/lib/berkeley_library/tind/mapping/util.rb +136 -0
  42. data/lib/berkeley_library/tind/mapping.rb +1 -0
  43. data/lib/berkeley_library/tind/module_info.rb +1 -1
  44. data/spec/berkeley_library/tind/mapping/additional_datafield_process_spec.rb +35 -0
  45. data/spec/berkeley_library/tind/mapping/alma_base_spec.rb +115 -0
  46. data/spec/berkeley_library/tind/mapping/alma_multiple_tind_spec.rb +20 -0
  47. data/spec/berkeley_library/tind/mapping/alma_single_tind_spec.rb +87 -0
  48. data/spec/berkeley_library/tind/mapping/alma_spec.rb +28 -0
  49. data/spec/berkeley_library/tind/mapping/config_spec.rb +19 -0
  50. data/spec/berkeley_library/tind/mapping/csv_mapper_spec.rb +27 -0
  51. data/spec/berkeley_library/tind/mapping/csv_multiple_mapper_spec.rb +27 -0
  52. data/spec/berkeley_library/tind/mapping/external_tind_field_spec.rb +45 -0
  53. data/spec/berkeley_library/tind/mapping/field_catalog_spec.rb +78 -0
  54. data/spec/berkeley_library/tind/mapping/field_catalog_util_spec.rb +105 -0
  55. data/spec/berkeley_library/tind/mapping/match_tind_field_spec.rb +24 -0
  56. data/spec/berkeley_library/tind/mapping/misc_spec.rb +51 -0
  57. data/spec/berkeley_library/tind/mapping/multiple_rule_spec.rb +44 -0
  58. data/spec/berkeley_library/tind/mapping/single_rule_spec.rb +52 -0
  59. data/spec/berkeley_library/tind/mapping/tind_control_subfield_spec.rb +96 -0
  60. data/spec/berkeley_library/tind/mapping/tind_field_from_leader_spec.rb +21 -0
  61. data/spec/berkeley_library/tind/mapping/tind_field_from_multiple_map_spec.rb +31 -0
  62. data/spec/berkeley_library/tind/mapping/tind_field_from_single_map_spec.rb +167 -0
  63. data/spec/berkeley_library/tind/mapping/tind_field_spec.rb +60 -0
  64. data/spec/berkeley_library/tind/mapping/tind_field_util_spec.rb +68 -0
  65. data/spec/berkeley_library/tind/mapping/tind_marc_spec.rb +88 -0
  66. data/spec/berkeley_library/tind/mapping/tind_record_util_spec.rb +30 -0
  67. data/spec/berkeley_library/tind/mapping/tind_subfield_util_spec.rb +48 -0
  68. data/spec/berkeley_library/tind/mapping/util_spec.rb +56 -0
  69. data/spec/berkeley_library/tind/marc/xml_writer_spec.rb +24 -0
  70. data/spec/data/api/pre_assigned_response.json +15 -0
  71. data/spec/data/api/result_file.csv +3 -0
  72. data/spec/data/api/upload_file.json +1 -0
  73. data/spec/data/api/upload_response.json +13 -0
  74. data/spec/data/mapping/991032333019706532-sru.xml +216 -0
  75. data/spec/data/mapping/one_to_multiple_mapping.csv +4 -0
  76. data/spec/data/mapping/one_to_one_mapping.csv +39 -0
  77. data/spec/data/mapping/record.xml +266 -0
  78. data/spec/data/mapping/record_not_qualified.xml +36 -0
  79. metadata +89 -54
  80. data/lib/berkeley_library/util/files.rb +0 -39
@@ -0,0 +1,154 @@
1
+ require 'marc'
2
+
3
+ module BerkeleyLibrary
4
+ module TIND
5
+ module Mapping
6
+ module TindSubfieldUtil
7
+
8
+ def clean_subfield(subfield)
9
+ new_value = clr_value(subfield.value)
10
+ subfield.value = new_value
11
+ end
12
+
13
+ def fields_880_subfield6(datafields_880)
14
+ formated_subfield6_value_arr(fields_by(datafields_880) { |f| is_880_field?(f) })
15
+ end
16
+
17
+ # From all subfield 6 gotten for repeated fields - with the same tag
18
+ # return the first subfield 6
19
+ def the_first_subfield6(fields)
20
+ values = subfield_6_values(fields)
21
+ return nil if values.empty?
22
+
23
+ # keep it here, in case needed in future: this can make sure
24
+ # 880 and regular fields having matching sequence number
25
+ # subfield6_with_small_no(values)
26
+
27
+ # new implementation: keep the first subfield 6 value
28
+ logger.warn("#{f[0].tag} have multiple datafields with multiple subfield 6, the first subfield 6 is kept") if values.length > 1
29
+ Util.subfield('6', values[0])
30
+ end
31
+
32
+ private
33
+
34
+ def subfield6?(f)
35
+ !f['6'].nil?
36
+ end
37
+
38
+ # f.tag can be a string or integer
39
+ def is_880_field?(f)
40
+ f.tag.to_s == '880'
41
+ end
42
+
43
+ # return subfield6 value formated the same way for both 880 and regular datafields
44
+ def formated_subfield6_value(f)
45
+ is_880_field?(f) ? formated_subfield6_from_880(f) : formated_subfield6_from_regular_field(f)
46
+ end
47
+
48
+ def fields_by(fields, &block)
49
+ fields.select(&block)
50
+ end
51
+
52
+ # return array of formated subfield6 values on inputted datafields
53
+ def formated_subfield6_value_arr(fields_source)
54
+ # fields_source = is_880_field ? fields_880(datafields) : fields_regular(datafields)
55
+ ls = []
56
+ fields_source.map do |f|
57
+ next unless subfield6?(f)
58
+
59
+ ls << formated_subfield6_value(f)
60
+ end
61
+ ls.compact
62
+ end
63
+
64
+ # return formated field6 for a regular datafield
65
+ # tag:246, subfields: 880-02 => 880-246-02
66
+ def formated_subfield6_from_regular_field(f)
67
+ return nil unless f['6']
68
+
69
+ tag = f.tag
70
+ arr = f['6'].strip.split('-')
71
+ "#{arr[0]}-#{tag}-#{arr[1]}"
72
+ end
73
+
74
+ # return formated subfield6 for a 880 datafield
75
+ # tag: 880, subfield6: 245-01/$1 => 880-245-01
76
+ def formated_subfield6_from_880(f)
77
+ return nil unless f['6']
78
+
79
+ "#{f.tag}-#{f['6'].strip[0, 6].strip}"
80
+ end
81
+
82
+ # return subfields of specific code
83
+ # Datafield returned from Alma may have mutiple subfields with the same code
84
+ def subfields(field, code)
85
+ sf = []
86
+ field.each do |s|
87
+ next unless s.code == code
88
+
89
+ captilize_subfield(s) if code == '3'
90
+ sf << s
91
+ end
92
+ sf
93
+ end
94
+
95
+ def captilize_subfield(subfield)
96
+ new_value = subfield.value.capitalize
97
+ subfield.value = new_value
98
+ end
99
+
100
+ # Combine multiple subfield values based on definition from csv file
101
+ def combined_subfield_value(field, code, symbol)
102
+ sf_arr = subfields(field, code)
103
+ return '' if sf_arr.empty?
104
+
105
+ sf_arr.map(&:value).join(symbol) << symbol # symbol exmaple ' -- '
106
+ end
107
+
108
+ # Mutilpe subfields in one field may have the same name
109
+ # Get all subfields on 'from subfield name'
110
+ # Change subfield names with 'to subfield name'
111
+ def subfields_from_to(field, from, to)
112
+ subfield_arr = subfields(field, from)
113
+ subfield_arr.each { |sf| sf.code = to } if !subfield_arr.empty? && (from != to)
114
+ subfield_arr
115
+ end
116
+
117
+ def subfield6_endwith_00?(f)
118
+ return false unless is_880_field?(f)
119
+
120
+ two_digits = f['6'].strip.split('-')[1][0..1]
121
+ two_digits.to_s == '00'
122
+ end
123
+
124
+ def fields_with_subfield6(fields)
125
+ fields.select { |f| subfield6?(f) }
126
+ end
127
+
128
+ # return subfield 6 with the smallest sequence number
129
+ def subfield_6_values(fields)
130
+ fields_with_subfield6(fields).map(&:value)
131
+ end
132
+
133
+ def subfield6_value_with_lowest_seq_no(values)
134
+ seq = 9999
135
+ txt = nil
136
+ values.each do |val|
137
+ num = seq_no(val)
138
+ if (num > 0) && (num < seq)
139
+ seq = num
140
+ txt = val
141
+ end
142
+ end
143
+ txt
144
+ end
145
+
146
+ # return all subfields except subfield6
147
+ def subfields_without_subfield6(field)
148
+ field.subfields.reject { |sf| sf.code == '6' }
149
+ end
150
+
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,136 @@
1
+ require 'csv'
2
+ require 'marc'
3
+ require 'berkeley_library/tind/mapping/alma_base'
4
+
5
+ module BerkeleyLibrary
6
+ module TIND
7
+ module Mapping
8
+ module Util
9
+ include AlmaBase
10
+
11
+ class << self
12
+
13
+ def csv_rows(file)
14
+ rows = []
15
+ CSV.foreach(file, headers: true, header_converters: :symbol, encoding: 'bom|utf-8') do |row|
16
+ # puts row.headers
17
+ rows << clr_row(row)
18
+ end
19
+ rows
20
+ end
21
+
22
+ def concatenation_symbol(str)
23
+ str ? str.gsub('a', ' ') : ' '
24
+ end
25
+
26
+ def indicator(str)
27
+ return [] unless str
28
+
29
+ str.strip.gsub('_', ' ').split(',')
30
+ end
31
+
32
+ def tag_symbol(tag)
33
+ "tag_#{tag}".to_sym
34
+ end
35
+
36
+ def datafield(tag, indicator, subfields)
37
+ datafield = ::MARC::DataField.new(tag, indicator[0], indicator[1])
38
+ subfields.each { |sf| datafield.append(sf) }
39
+ datafield
40
+ end
41
+
42
+ def subfield(code, value)
43
+ ::MARC::Subfield.new(code, value)
44
+ end
45
+
46
+ def subfield_hash(field)
47
+ code_value_arr = field.to_hash[field.tag]['subfields']
48
+ {}.tap { |i| code_value_arr.each(&i.method(:update)) }
49
+ end
50
+
51
+ # input an array of rules, example: [["a,b,c,d", "b", "--"],["o,p,q", "b", ""]]
52
+ def symbols(rules)
53
+ rules.map { |rule| concatenation_symbol(rule[2]).strip }
54
+ end
55
+
56
+ def remove_extra_symbol(rules, val)
57
+ symbols = symbols(rules)
58
+ symbols.each { |s| val = val.strip.delete_suffix(s) }
59
+ val
60
+ end
61
+
62
+ def alma_datafield(tag, record)
63
+ record.fields.each { |f| return f if f.tag.to_s == tag }
64
+ nil
65
+ end
66
+
67
+ def qualified_alma_record?(alma_record)
68
+ f_245 = alma_datafield('245', alma_record)
69
+ f_245_a = f_245['a'].downcase
70
+
71
+ val = 'Host bibliographic record'.downcase
72
+ !f_245_a.start_with? val
73
+ end
74
+
75
+ # From DM - get testing MARC from xml file
76
+ # @param xml [String] the XML to parse
77
+ # @return [MARC::Record, nil] the MARC record from the specified XML
78
+ def from_xml(xml)
79
+ # noinspection RubyYardReturnMatch,RubyMismatchedReturnType
80
+ all_from_xml(xml).first
81
+ end
82
+
83
+ def collection_config_correct?
84
+ no_including = BerkeleyLibrary::TIND::Mapping::AlmaBase.including_origin_tags.empty?
85
+ no_excluding = BerkeleyLibrary::TIND::Mapping::AlmaBase.excluding_origin_tags.empty?
86
+ no_including || no_excluding
87
+ end
88
+
89
+ # subfield util
90
+ def order_subfields(subfields, codes)
91
+ found_subfields = []
92
+ codes.each do |code|
93
+ sfs = subfields.select { |subfield| subfield.code == code }
94
+ found_subfields.concat sfs
95
+ end
96
+ not_found_subfields = subfields - found_subfields
97
+ found_subfields.concat not_found_subfields
98
+ end
99
+
100
+ private
101
+
102
+ def clr_row(row)
103
+ row[:tag_origin] = format_tag(row[:tag_origin])
104
+ row[:tag_destination] = format_tag(row[:tag_destination])
105
+ row[:map_if_no_this_tag_existed] = format_tag(row[:map_if_no_this_tag_existed])
106
+ row
107
+ end
108
+
109
+ # To ensure tag from csv file in three digits
110
+ def format_tag(tag)
111
+ # LDR is not a numeric tag
112
+ return tag unless numeric? tag
113
+
114
+ format('%03d', tag)
115
+ end
116
+
117
+ def numeric?(str)
118
+ return false if str.nil?
119
+
120
+ str.scan(/\D/).empty?
121
+ end
122
+
123
+ # Parses MARCXML.
124
+ #
125
+ # @param xml [String] the XML to parse
126
+ # @return [MARC::XMLReader] the MARC records
127
+ def all_from_xml(xml)
128
+ input = StringIO.new(xml.scrub)
129
+ MARC::XMLReader.new(input)
130
+ end
131
+
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1 @@
1
+ Dir.glob(File.expand_path('mapping/*.rb', __dir__)).sort.each(&method(:require))
@@ -7,7 +7,7 @@ module BerkeleyLibrary
7
7
  SUMMARY = 'TIND DA utilities for the UC Berkeley Library'.freeze
8
8
  DESCRIPTION = 'UC Berkeley Library utility gem for working with the TIND DA digital archive.'.freeze
9
9
  LICENSE = 'MIT'.freeze
10
- VERSION = '0.5.1'.freeze
10
+ VERSION = '0.7.0'.freeze
11
11
  HOMEPAGE = 'https://github.com/BerkeleyLibrary/tind'.freeze
12
12
  end
13
13
  end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+ require 'marc'
3
+
4
+ module BerkeleyLibrary
5
+ module TIND
6
+ module Mapping
7
+ describe AdditionalDatafieldProcess do
8
+
9
+ let(:qualified_alma_obj) { Alma.new('spec/data/mapping/record.xml') }
10
+ let(:qualified_alm_record) { qualified_alma_obj.record }
11
+
12
+ let(:tind_marc) { TindMarc.new(qualified_alm_record) }
13
+ let(:tindfields) { tind_marc.tindfields }
14
+ let(:additona_245_field) { [Util.datafield('245', [' ', ' '], [Util.subfield('a', 'fake 245 a')])] }
15
+ let(:with_repeated_fields) { tindfields.concat additona_245_field }
16
+
17
+ context '# Process 1: Remove duplicated fields' do
18
+ # two 245 fields inputed, one is removed
19
+ it 'Input two 245 fields, return only one 245 field' do
20
+ expect(tind_marc.remove_repeats(with_repeated_fields).map(&:tag).count('245')).to eq 1
21
+ end
22
+
23
+ # one subfield 'a' is kept, subfield 'a' with a value of 'fake 245 a' is ignored
24
+ it 'Input two subfield $a, keeping the first one' do
25
+ without_repeated_fields = tind_marc.remove_repeats(with_repeated_fields)
26
+ single_field_245 = tind_marc.field_on_tag('245', without_repeated_fields)
27
+ expect(single_field_245['a']).to eq 'Cang jie pian'
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+ require 'tempfile'
3
+
4
+ module BerkeleyLibrary
5
+ module TIND
6
+ module Mapping
7
+ describe AlmaBase do
8
+ extend BerkeleyLibrary::Logging
9
+ let(:dummy_obj) { Class.new { extend AlmaBase } }
10
+ let(:alma_record) { ::MARC::Record.new }
11
+ let(:save_to_file) { Tempfile.new('xml') }
12
+ let(:record_id) { Class.new { extend BerkeleyLibrary::Alma::RecordId } }
13
+ let(:hash) { { '980' => ['pre_1912'] } }
14
+
15
+ let(:qualified_alma_obj) { Alma.new('spec/data/mapping/record.xml') }
16
+ let(:qualified_alm_record) { qualified_alma_obj.record }
17
+
18
+ let(:un_qualified_alma_obj) { Alma.new('spec/data/mapping/record_not_qualified.xml') }
19
+ let(:un_qualified_alm_record) { un_qualified_alma_obj.record }
20
+
21
+ describe '# base_tind_record' do
22
+ it 'input a qualified Alma record - return a tind record' do
23
+ allow(dummy_obj).to receive(:tind_record).with('C084093187', qualified_alm_record, []).and_return(::MARC::Record.new)
24
+ expect(dummy_obj.base_tind_record('C084093187', [], qualified_alm_record)).to be_a ::MARC::Record
25
+ end
26
+
27
+ it 'input an unqualified Alma record - return nil' do
28
+ expect { dummy_obj.base_tind_record('C084093187', [], un_qualified_alm_record) }.to raise_error(ArgumentError)
29
+ end
30
+
31
+ it 'no input Alma record with a nil (record) from id - return nil' do
32
+ allow(dummy_obj).to receive(:alma_record_from).with('C084093187').and_return(nil)
33
+ expect { dummy_obj.base_tind_record('C084093187', []) }.to raise_error(ArgumentError)
34
+ end
35
+ end
36
+
37
+ describe '# base_save' do
38
+ it 'save tind record' do
39
+ dummy_obj.base_save('C084093187', qualified_alm_record, save_to_file)
40
+ expect(File.open(save_to_file.path).readlines[0]).to eq "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
41
+ end
42
+ end
43
+
44
+ describe '# alma_record' do
45
+ it 'get Alma record' do
46
+ allow(record_id).to receive(:get_marc_record).and_return(::MARC::Record.new)
47
+ allow(dummy_obj).to receive(:get_record_id).with('C084093187').and_return(record_id)
48
+ expect(dummy_obj.send(:alma_record_from, 'C084093187')).to be_instance_of ::MARC::Record
49
+ end
50
+ end
51
+
52
+ describe '# get_record_id' do
53
+ it 'return BerkeleyLibrary::Alma::BarCode' do
54
+ BerkeleyLibrary::TIND::Mapping::AlmaBase.is_barcode = true
55
+ expect(dummy_obj.send(:get_record_id, 'C084093187')).to be_instance_of BerkeleyLibrary::Alma::BarCode
56
+ end
57
+
58
+ it 'return BerkeleyLibrary::Alma::MMSID' do
59
+ BerkeleyLibrary::TIND::Mapping::AlmaBase.is_barcode = false
60
+ expect(dummy_obj.send(:get_record_id, '991085821143406532')).to be_instance_of BerkeleyLibrary::Alma::MMSID
61
+
62
+ end
63
+
64
+ it 'return BerkeleyLibrary::Alma::BibNumber' do
65
+ BerkeleyLibrary::TIND::Mapping::AlmaBase.is_barcode = false
66
+ expect(dummy_obj.send(:get_record_id, 'b11082434')).to be_instance_of BerkeleyLibrary::Alma::BibNumber
67
+
68
+ end
69
+ end
70
+
71
+ describe '# add_f_035' do
72
+ it 'Add 035 from mms_id' do
73
+ BerkeleyLibrary::TIND::Mapping::AlmaBase.is_035_from_mms_id = true
74
+ expect(dummy_obj.send(:add_f_035, '991085821143406532', hash).tag).to eq '035'
75
+ end
76
+
77
+ it 'Not to add 035 from mms_id' do
78
+ BerkeleyLibrary::TIND::Mapping::AlmaBase.is_035_from_mms_id = false
79
+ expect(dummy_obj.send(:add_f_035, '991085821143406532', hash)).to eq nil
80
+ end
81
+ end
82
+
83
+ describe '# tind_record, # derived_tind_fields' do
84
+ BerkeleyLibrary::TIND::Mapping::AlmaBase.collection_parameter_hash = {
85
+ '336' => ['Image'],
86
+ '852' => ['East Asian Library'],
87
+ '980' => ['pre_1912'],
88
+ '982' => ['Pre 1912 Chinese Materials - short name', 'Pre 1912 Chinese Materials - long name'],
89
+ '991' => []
90
+ }
91
+ let(:id) { '991085821143406532' }
92
+ let(:tags) { %w[902 336 852 980 982 901 856] }
93
+ let(:tags_with_035) { %w[902 336 852 980 982 901 856 035] }
94
+
95
+ it ' get tind_record' do
96
+ datafields = []
97
+ marc_record = qualified_alm_record
98
+ expect(dummy_obj.send(:tind_record, id, marc_record, datafields)).to be_instance_of ::MARC::Record
99
+ end
100
+
101
+ it 'get derived fields without 035' do
102
+ expect(dummy_obj.send(:derived_tind_fields, id).map(&:tag)).to eq tags
103
+ end
104
+
105
+ it 'get derived fields with 035' do
106
+ BerkeleyLibrary::TIND::Mapping::AlmaBase.is_035_from_mms_id = true
107
+ expect(dummy_obj.send(:derived_tind_fields, id).map(&:tag)).to eq tags_with_035
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ module BerkeleyLibrary
4
+ module TIND
5
+ module Mapping
6
+ describe AlmaMultipleTIND do
7
+ let(:additona_245_field) { [Util.datafield('245', [' ', ' '], [Util.subfield('a', 'fake 245 a')])] }
8
+ let(:marc_obj) { ::MARC::Record.new.append(additona_245_field) }
9
+
10
+ it ' get tind record' do
11
+ allow_any_instance_of(BerkeleyLibrary::TIND::Mapping::AlmaMultipleTIND).to receive(:alma_record_from).with('991085821143406532').and_return(marc_obj)
12
+ alma_multiple_tind = BerkeleyLibrary::TIND::Mapping::AlmaMultipleTIND.new('991085821143406532')
13
+
14
+ allow(alma_multiple_tind).to receive(:base_tind_record).with('991085821143406532', additona_245_field, marc_obj).and_return(marc_obj)
15
+ expect(alma_multiple_tind.record(additona_245_field)).to be marc_obj
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ module BerkeleyLibrary
4
+ module TIND
5
+ module Mapping
6
+ describe AlmaSingleTIND do
7
+ let(:additona_245_field) { [Util.datafield('245', [' ', ' '], [Util.subfield('a', 'fake 245 a')])] }
8
+ let(:marc_obj) { ::MARC::Record.new.append(additona_245_field) }
9
+
10
+ before { BerkeleyLibrary::Alma::Config.default! }
11
+ after { BerkeleyLibrary::Alma::Config.send(:clear!) }
12
+
13
+ it ' get tind record' do
14
+ alma_single_tind = BerkeleyLibrary::TIND::Mapping::AlmaSingleTIND.new
15
+
16
+ allow(alma_single_tind).to receive(:base_tind_record).with('991085821143406532', additona_245_field).and_return(marc_obj)
17
+ expect(alma_single_tind.record('991085821143406532', additona_245_field)).to be marc_obj
18
+ end
19
+
20
+ describe 'TIND record mapping' do
21
+ let(:coll_param_hash) do
22
+ {
23
+ '336' => ['Image'],
24
+ '852' => ['East Asian Library'],
25
+ '980' => ['pre_1912'],
26
+ '982' => ['Pre 1912 Chinese Materials - short name', 'Pre 1912 Chinese Materials - long name'],
27
+ '991' => []
28
+ }
29
+ end
30
+
31
+ let(:id) { '991032333019706532' }
32
+ let(:marc_url) { BerkeleyLibrary::Alma::RecordId.parse(id).marc_uri.to_s }
33
+ let(:logger) { BerkeleyLibrary::Logging.logger }
34
+
35
+ before do
36
+ AlmaBase.collection_parameter_hash = coll_param_hash
37
+ AlmaBase.is_035_from_mms_id = true
38
+ end
39
+
40
+ after do
41
+ AlmaBase.collection_parameter_hash = nil
42
+ AlmaBase.is_035_from_mms_id = false
43
+ end
44
+
45
+ it 'transforms a record' do
46
+ marc_xml = File.read('spec/data/mapping/991032333019706532-sru.xml')
47
+ stub_request(:get, marc_url).to_return(body: marc_xml)
48
+
49
+ expect(logger).not_to receive(:warn)
50
+
51
+ mapper = BerkeleyLibrary::TIND::Mapping::AlmaSingleTIND.new
52
+ url = "https://digitalassets.lib.berkeley.edu/pre1912ChineseMaterials/ucb/ready/#{id}/#{id}_v001_0064.jpg"
53
+ fft = BerkeleyLibrary::TIND::Mapping::TindField.f_fft(url, 'v001_0064')
54
+ tind_record = mapper.record(id, [fft])
55
+
56
+ expect(tind_record).to be_a(::MARC::Record)
57
+ expect(tind_record['FFT']).to eq(fft)
58
+
59
+ expect(tind_record['901']['m']).to eq(id)
60
+ expect(tind_record['035']['a']).to eq("(pre_1912)#{id}")
61
+
62
+ alma_record = ::MARC::XMLReader.read(StringIO.new(marc_xml)).first
63
+ sf_245a_expected = alma_record.spec('245$a{$6=\880-02}').first
64
+ sf_245_value_expected = sf_245a_expected.value.sub(/[^[:alnum:]]+$/, '')
65
+
66
+ sf_245a_actual = tind_record.spec('245$a{$6=\880-02}').first
67
+ sf_245a_value_actual = sf_245a_actual.value
68
+ expect(sf_245a_value_actual).to eq(sf_245_value_expected)
69
+ end
70
+
71
+ it 'handles pathological records without an 001 control field' do
72
+ marc_xml = File.read('spec/data/mapping/991032333019706532-sru.xml')
73
+ .sub('<controlfield tag="001">991032333019706532</controlfield>', '')
74
+ stub_request(:get, marc_url).to_return(body: marc_xml)
75
+
76
+ expect(logger).to receive(:warn).with("#{id} has no Control Field 001")
77
+
78
+ mapper = BerkeleyLibrary::TIND::Mapping::AlmaSingleTIND.new
79
+ url = "https://digitalassets.lib.berkeley.edu/pre1912ChineseMaterials/ucb/ready/#{id}/#{id}_v001_0064.jpg"
80
+ fft = BerkeleyLibrary::TIND::Mapping::TindField.f_fft(url, 'v001_0064')
81
+ expect { mapper.record(id, [fft]) }.to raise_error(ArgumentError)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ module BerkeleyLibrary
4
+ module TIND
5
+ module Mapping
6
+ describe Alma do
7
+ let(:alma_obj) { Alma.new('spec/data/mapping/record.xml') }
8
+
9
+ it 'control field value' do
10
+ expect(alma_obj.control_field.tag).to eq '008'
11
+ end
12
+
13
+ it 'control field value' do
14
+ expect(alma_obj.control_field.tag).to eq '008'
15
+ end
16
+
17
+ it '880 field' do
18
+ expect(alma_obj.field_880('245-01/$1')['6']).to eq '245-01/$1'
19
+ end
20
+
21
+ it 'regular field' do
22
+ expect(alma_obj.field('245').tag).to eq '245'
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ module BerkeleyLibrary
4
+ module TIND
5
+ module Mapping
6
+ describe Config do
7
+
8
+ it 'get the one to one mapping file' do
9
+ expect(Config.one_to_one_map_file).to end_with('one_to_one_mapping.csv')
10
+ end
11
+
12
+ it 'get the one to multiple mapping file' do
13
+ expect(Config.one_to_multiple_map_file).to end_with('one_to_multiple_mapping.csv')
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+ require 'marc'
3
+
4
+ module BerkeleyLibrary
5
+ module TIND
6
+ module Mapping
7
+ describe CsvMapper do
8
+ let(:dummy_class) { Class.new { extend CsvMapper } }
9
+ let(:from_tag) { %w[100 110 111 242 245 246 250 255 260 264 300 351 490 500 502 505 507 520 522 524 536 541 545 546 600 610 611 630 650 651 655 700 710 711 720 752 773 907] }
10
+ let(:rules_keys) { %i[tag_100 tag_110 tag_111 tag_242 tag_245 tag_246 tag_250 tag_255 tag_260 tag_264 tag_300 tag_351 tag_490 tag_500 tag_502 tag_505 tag_507 tag_520 tag_522 tag_524 tag_536 tag_541 tag_545 tag_546 tag_600 tag_610 tag_611 tag_630 tag_650 tag_651 tag_655 tag_700 tag_710 tag_711 tag_720 tag_752 tag_773 tag_907] }
11
+
12
+ it 'get origin tags' do
13
+ expect(dummy_class.from_tags).to eq from_tag
14
+ end
15
+
16
+ it 'get keys of rules' do
17
+ expect(dummy_class.rules.keys).to eq rules_keys
18
+ end
19
+
20
+ it 'get tag required one occurrence in csv ' do
21
+ expect(dummy_class.one_occurrence_tags).to eq ['264']
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+ require 'marc'
3
+
4
+ module BerkeleyLibrary
5
+ module TIND
6
+ module Mapping
7
+ describe CsvMultipleMapper do
8
+ let(:dummy_class) { Class.new { extend CsvMultipleMapper } }
9
+ let(:from_tag) { ['008', 'LDR'] }
10
+ let(:rules_keys) { %i[tag_008 tag_LDR] }
11
+
12
+ it 'get origin tags' do
13
+ expect(dummy_class.from_tags).to eq from_tag
14
+ end
15
+
16
+ it 'get keys of rules' do
17
+ expect(dummy_class.rules.keys).to eq rules_keys
18
+ end
19
+
20
+ it 'get 2 rules on tag "008" ' do
21
+ expect(dummy_class.send(:rules_on_tag, '008').count).to eq 2
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end