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.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +15 -3
- data/.gitignore +3 -0
- data/.idea/inspectionProfiles/Project_Default.xml +10 -0
- data/.idea/tind.iml +10 -9
- data/.rubocop.yml +1 -1
- data/CHANGES.md +15 -1
- data/README.md +165 -2
- data/berkeley_library-tind.gemspec +2 -2
- data/bin/alma-multiple-tind +50 -0
- data/bin/alma-single-tind +48 -0
- data/bin/save_tind_records +80 -0
- data/bin/tind-marc +73 -0
- data/lib/berkeley_library/tind/export/ods_exporter.rb +4 -6
- data/lib/berkeley_library/tind/mapping/additional_datafield_process.rb +128 -0
- data/lib/berkeley_library/tind/mapping/alma.rb +42 -0
- data/lib/berkeley_library/tind/mapping/alma_base.rb +108 -0
- data/lib/berkeley_library/tind/mapping/alma_multiple_tind.rb +31 -0
- data/lib/berkeley_library/tind/mapping/alma_single_tind.rb +28 -0
- data/lib/berkeley_library/tind/mapping/config.rb +44 -0
- data/lib/berkeley_library/tind/mapping/csv_mapper.rb +35 -0
- data/lib/berkeley_library/tind/mapping/csv_multiple_mapper.rb +41 -0
- data/lib/berkeley_library/tind/mapping/data/one_to_multiple_mapping.csv +4 -0
- data/lib/berkeley_library/tind/mapping/data/one_to_one_mapping.csv +39 -0
- data/lib/berkeley_library/tind/mapping/external_tind_field.rb +103 -0
- data/lib/berkeley_library/tind/mapping/field_catalog.rb +137 -0
- data/lib/berkeley_library/tind/mapping/field_catalog_util.rb +105 -0
- data/lib/berkeley_library/tind/mapping/match_tind_field.rb +77 -0
- data/lib/berkeley_library/tind/mapping/misc.rb +69 -0
- data/lib/berkeley_library/tind/mapping/multiple_rule.rb +36 -0
- data/lib/berkeley_library/tind/mapping/single_rule.rb +149 -0
- data/lib/berkeley_library/tind/mapping/tind_control_subfield.rb +59 -0
- data/lib/berkeley_library/tind/mapping/tind_field.rb +49 -0
- data/lib/berkeley_library/tind/mapping/tind_field_from_leader.rb +27 -0
- data/lib/berkeley_library/tind/mapping/tind_field_from_multiple_map.rb +59 -0
- data/lib/berkeley_library/tind/mapping/tind_field_from_single_map.rb +182 -0
- data/lib/berkeley_library/tind/mapping/tind_field_util.rb +112 -0
- data/lib/berkeley_library/tind/mapping/tind_marc.rb +134 -0
- data/lib/berkeley_library/tind/mapping/tind_record_util.rb +135 -0
- data/lib/berkeley_library/tind/mapping/tind_subfield_util.rb +154 -0
- data/lib/berkeley_library/tind/mapping/util.rb +136 -0
- data/lib/berkeley_library/tind/mapping.rb +1 -0
- data/lib/berkeley_library/tind/module_info.rb +1 -1
- data/spec/berkeley_library/tind/mapping/additional_datafield_process_spec.rb +35 -0
- data/spec/berkeley_library/tind/mapping/alma_base_spec.rb +115 -0
- data/spec/berkeley_library/tind/mapping/alma_multiple_tind_spec.rb +20 -0
- data/spec/berkeley_library/tind/mapping/alma_single_tind_spec.rb +87 -0
- data/spec/berkeley_library/tind/mapping/alma_spec.rb +28 -0
- data/spec/berkeley_library/tind/mapping/config_spec.rb +19 -0
- data/spec/berkeley_library/tind/mapping/csv_mapper_spec.rb +27 -0
- data/spec/berkeley_library/tind/mapping/csv_multiple_mapper_spec.rb +27 -0
- data/spec/berkeley_library/tind/mapping/external_tind_field_spec.rb +45 -0
- data/spec/berkeley_library/tind/mapping/field_catalog_spec.rb +78 -0
- data/spec/berkeley_library/tind/mapping/field_catalog_util_spec.rb +105 -0
- data/spec/berkeley_library/tind/mapping/match_tind_field_spec.rb +24 -0
- data/spec/berkeley_library/tind/mapping/misc_spec.rb +51 -0
- data/spec/berkeley_library/tind/mapping/multiple_rule_spec.rb +44 -0
- data/spec/berkeley_library/tind/mapping/single_rule_spec.rb +52 -0
- data/spec/berkeley_library/tind/mapping/tind_control_subfield_spec.rb +96 -0
- data/spec/berkeley_library/tind/mapping/tind_field_from_leader_spec.rb +21 -0
- data/spec/berkeley_library/tind/mapping/tind_field_from_multiple_map_spec.rb +31 -0
- data/spec/berkeley_library/tind/mapping/tind_field_from_single_map_spec.rb +167 -0
- data/spec/berkeley_library/tind/mapping/tind_field_spec.rb +60 -0
- data/spec/berkeley_library/tind/mapping/tind_field_util_spec.rb +68 -0
- data/spec/berkeley_library/tind/mapping/tind_marc_spec.rb +88 -0
- data/spec/berkeley_library/tind/mapping/tind_record_util_spec.rb +30 -0
- data/spec/berkeley_library/tind/mapping/tind_subfield_util_spec.rb +48 -0
- data/spec/berkeley_library/tind/mapping/util_spec.rb +56 -0
- data/spec/berkeley_library/tind/marc/xml_writer_spec.rb +24 -0
- data/spec/data/api/pre_assigned_response.json +15 -0
- data/spec/data/api/result_file.csv +3 -0
- data/spec/data/api/upload_file.json +1 -0
- data/spec/data/api/upload_response.json +13 -0
- data/spec/data/mapping/991032333019706532-sru.xml +216 -0
- data/spec/data/mapping/one_to_multiple_mapping.csv +4 -0
- data/spec/data/mapping/one_to_one_mapping.csv +39 -0
- data/spec/data/mapping/record.xml +266 -0
- data/spec/data/mapping/record_not_qualified.xml +36 -0
- metadata +89 -54
- 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.
|
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
|