berkeley_library-tind 0.5.1 → 0.6.0
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/.github/workflows/build.yml +15 -3
- data/.gitignore +3 -0
- data/.idea/inspectionProfiles/Project_Default.xml +10 -0
- data/.idea/tind.iml +4 -3
- data/CHANGES.md +6 -0
- data/README.md +121 -2
- data/berkeley_library-tind.gemspec +1 -0
- 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/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 +101 -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 +146 -0
- data/lib/berkeley_library/tind/mapping/field_catalog_util.rb +59 -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 +143 -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 +170 -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_subfield_util.rb +154 -0
- data/lib/berkeley_library/tind/mapping/util.rb +117 -0
- data/lib/berkeley_library/tind/mapping.rb +1 -0
- data/lib/berkeley_library/tind/module_info.rb +1 -1
- data/lib/berkeley_library/util/files.rb +1 -2
- 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 +57 -0
- data/spec/berkeley_library/tind/mapping/match_tind_field_spec.rb +25 -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 +150 -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_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/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 +263 -0
- data/spec/data/mapping/record_not_qualified.xml +36 -0
- metadata +105 -2
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'marc'
|
2
|
+
|
3
|
+
module BerkeleyLibrary
|
4
|
+
module TIND
|
5
|
+
module Mapping
|
6
|
+
class Alma
|
7
|
+
include Util
|
8
|
+
|
9
|
+
attr_reader :record
|
10
|
+
|
11
|
+
def initialize(xml_file)
|
12
|
+
@record = alma_record(xml_file)
|
13
|
+
end
|
14
|
+
|
15
|
+
def control_field
|
16
|
+
@record.fields.each { |f| return f if f.tag.to_s == '008' }
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def field_880(subfield6_value)
|
21
|
+
@record.fields.each { |f| return f if f.tag.to_s == '880' && f['6'] == subfield6_value }
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def field(tag)
|
26
|
+
@record.fields.each { |f| return f if f.tag.to_s == tag }
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def alma_record(xml_file)
|
33
|
+
file = File.open(xml_file)
|
34
|
+
content = file.readlines.map(&:chomp)
|
35
|
+
xml = content.join(' ')
|
36
|
+
Util.from_xml(xml)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# 902__$d derived from current date is added in this module
|
2
|
+
|
3
|
+
module BerkeleyLibrary
|
4
|
+
module TIND
|
5
|
+
module Mapping
|
6
|
+
module AlmaBase
|
7
|
+
include BerkeleyLibrary::Logging
|
8
|
+
|
9
|
+
@collection_parameter_hash = {}
|
10
|
+
@is_barcode = false
|
11
|
+
@is_035_from_mms_id = false
|
12
|
+
|
13
|
+
class << self
|
14
|
+
attr_accessor :collection_parameter_hash
|
15
|
+
attr_accessor :is_barcode
|
16
|
+
attr_accessor :is_035_from_mms_id
|
17
|
+
end
|
18
|
+
|
19
|
+
# id can be:
|
20
|
+
# 1) Alma mms id
|
21
|
+
# 2) Oskicat No
|
22
|
+
# 3) BarCode No
|
23
|
+
# When alma record is nil or un-qualified, raise error
|
24
|
+
# Input datafields - an array of record specific datafields: for example, fft datafields, datafield 035 etc.
|
25
|
+
|
26
|
+
def base_tind_record(id, datafields, alma_record = nil)
|
27
|
+
marc_record = alma_record || alma_record_from(id)
|
28
|
+
|
29
|
+
raise ArgumentError, "#{id} has no Alma record." unless marc_record
|
30
|
+
|
31
|
+
unless Util.qualified_alma_record?(marc_record)
|
32
|
+
raise ArgumentError,
|
33
|
+
"#{id} belong to a host bibliographic record which should not be uploaded to TIND."
|
34
|
+
end
|
35
|
+
|
36
|
+
tind_record(id, marc_record, datafields)
|
37
|
+
end
|
38
|
+
|
39
|
+
# This is mainly for testing purpose, each collection can have a function to save it's record
|
40
|
+
def base_save(id, tind_record, file)
|
41
|
+
raise ArgumentError, "#{id} has no TIND record or not a qualified TIND record." unless tind_record
|
42
|
+
|
43
|
+
BerkeleyLibrary::TIND::MARC::XMLWriter.open(file) do |writer|
|
44
|
+
writer.write(tind_record)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def alma_record_from(id)
|
51
|
+
record_id = get_record_id(id)
|
52
|
+
raise ArgumentError, "#{id} gets no BarCode or RecordId from Alma module." unless record_id
|
53
|
+
|
54
|
+
record_id.get_marc_record
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_record_id(id)
|
58
|
+
AlmaBase.is_barcode ? BerkeleyLibrary::Alma::BarCode.new(id) : BerkeleyLibrary::Alma::RecordId.parse(id)
|
59
|
+
end
|
60
|
+
|
61
|
+
def derived_tind_fields(mms_id)
|
62
|
+
tind_fields = []
|
63
|
+
tind_fields << TindField.f_902_d
|
64
|
+
|
65
|
+
hash = AlmaBase.collection_parameter_hash
|
66
|
+
tind_fields.concat ExternalTindField.tind_fields_from_collection_information(hash)
|
67
|
+
|
68
|
+
tind_fields.concat ExternalTindField.tind_mms_id_fields(mms_id)
|
69
|
+
|
70
|
+
f_035 = add_f_035(mms_id, hash)
|
71
|
+
tind_fields << f_035 if f_035
|
72
|
+
|
73
|
+
tind_fields
|
74
|
+
end
|
75
|
+
|
76
|
+
def tind_record(id, marc_record, datafields)
|
77
|
+
tindmarc = TindMarc.new(marc_record)
|
78
|
+
# get all derived tind_fields: 1) from collection information; 2) from id
|
79
|
+
mms_id = tindmarc.field_catalog.mms_id
|
80
|
+
logger.warn("#{id} has no Control Field 001") unless mms_id
|
81
|
+
|
82
|
+
tind_fields = derived_tind_fields(mms_id)
|
83
|
+
# add inputted record specific datafields
|
84
|
+
tind_fields.concat datafields
|
85
|
+
tindmarc.tind_external_datafields = tind_fields
|
86
|
+
|
87
|
+
# creete a tind marc record
|
88
|
+
tindmarc.tind_record
|
89
|
+
end
|
90
|
+
|
91
|
+
def add_f_035(mms_id, hash)
|
92
|
+
return nil unless mms_id && AlmaBase.is_035_from_mms_id
|
93
|
+
|
94
|
+
val_980 = hash['980'][0].strip
|
95
|
+
TindField.f_035_from_alma_id(mms_id, val_980)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'marc'
|
2
|
+
require 'berkeley_library/tind'
|
3
|
+
require 'berkeley_library/alma'
|
4
|
+
module BerkeleyLibrary
|
5
|
+
module TIND
|
6
|
+
module Mapping
|
7
|
+
|
8
|
+
class AlmaMultipleTIND
|
9
|
+
include Util
|
10
|
+
include AlmaBase
|
11
|
+
include BerkeleyLibrary::Logging
|
12
|
+
|
13
|
+
# id can be
|
14
|
+
# 1) Alma mms id
|
15
|
+
# 2) Oskicat No
|
16
|
+
# 3) BarCode No
|
17
|
+
def initialize(id)
|
18
|
+
@id = id
|
19
|
+
@marc_record = alma_record_from(id)
|
20
|
+
end
|
21
|
+
|
22
|
+
# If alma record is nil or un-qualified, it returns nil
|
23
|
+
# Input datafields - an array of record specific datafields: for example, fft datafields, datafield 035 etc.
|
24
|
+
def record(datafields)
|
25
|
+
base_tind_record(@id, datafields, @marc_record)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'marc'
|
2
|
+
require 'berkeley_library/tind'
|
3
|
+
require 'berkeley_library/alma'
|
4
|
+
|
5
|
+
module BerkeleyLibrary
|
6
|
+
module TIND
|
7
|
+
module Mapping
|
8
|
+
class AlmaSingleTIND
|
9
|
+
include Util
|
10
|
+
include AlmaBase
|
11
|
+
include BerkeleyLibrary::Logging
|
12
|
+
|
13
|
+
def initialize; end
|
14
|
+
|
15
|
+
# id can be
|
16
|
+
# 1) Alma mms id
|
17
|
+
# 2) Oskicat No
|
18
|
+
# 3) BarCode No
|
19
|
+
# If alma record is nil or un-qualified, it returns nil
|
20
|
+
# Input datafields - an array of record specific datafields: for example, fft datafields, datafield 035 etc.
|
21
|
+
def record(id, datafields)
|
22
|
+
base_tind_record(id, datafields)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'marc'
|
2
|
+
|
3
|
+
module BerkeleyLibrary
|
4
|
+
module TIND
|
5
|
+
module Mapping
|
6
|
+
class Config
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def one_to_one_map_file
|
11
|
+
ENV.fetch('ONE_TO_ONE_MAP_FILE', File.expand_path('data/one_to_one_mapping.csv', __dir__))
|
12
|
+
end
|
13
|
+
|
14
|
+
def one_to_multiple_map_file
|
15
|
+
ENV.fetch('ONE_TO_ONE_MAP_FILE', File.expand_path('data/one_to_multiple_mapping.csv', __dir__))
|
16
|
+
end
|
17
|
+
|
18
|
+
def no_duplicated_tags
|
19
|
+
%w[245 260 852 901 902 980].freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
def punctuations
|
23
|
+
%w[, : ; / =].freeze
|
24
|
+
end
|
25
|
+
|
26
|
+
def clean_tags
|
27
|
+
%w[245 260 300].freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
def collection_subfield_names
|
31
|
+
{
|
32
|
+
'336' => ['a'],
|
33
|
+
'852' => ['c'],
|
34
|
+
'980' => ['a'],
|
35
|
+
'982' => ['a', 'b'],
|
36
|
+
'991' => ['a']
|
37
|
+
}.freeze
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'csv'
|
2
|
+
require 'berkeley_library/tind/mapping/util'
|
3
|
+
|
4
|
+
module BerkeleyLibrary
|
5
|
+
module TIND
|
6
|
+
module Mapping
|
7
|
+
module CsvMapper
|
8
|
+
@rows = []
|
9
|
+
class << self
|
10
|
+
attr_accessor :rows
|
11
|
+
end
|
12
|
+
|
13
|
+
CsvMapper.rows = Util.csv_rows(Config.one_to_one_map_file)
|
14
|
+
|
15
|
+
def from_tags
|
16
|
+
CsvMapper.rows.map { |row| row[:tag_origin] }.compact
|
17
|
+
end
|
18
|
+
|
19
|
+
def rules
|
20
|
+
CsvMapper.rows.to_h { |row| ["tag_#{row[:tag_origin]}".to_sym, SingleRule.new(row)] }
|
21
|
+
end
|
22
|
+
|
23
|
+
# tags allow to keep the first datafield from original marc record
|
24
|
+
def one_occurrence_tags
|
25
|
+
tags = []
|
26
|
+
CsvMapper.rows.each do |row|
|
27
|
+
tags << row[:tag_origin] if row[:keep_one_if_multiple_available]
|
28
|
+
end
|
29
|
+
tags.compact
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module BerkeleyLibrary
|
4
|
+
module TIND
|
5
|
+
module Mapping
|
6
|
+
module CsvMultipleMapper
|
7
|
+
@rows = []
|
8
|
+
class << self
|
9
|
+
attr_accessor :rows
|
10
|
+
end
|
11
|
+
|
12
|
+
CsvMultipleMapper.rows = Util.csv_rows(Config.one_to_multiple_map_file)
|
13
|
+
def from_tags
|
14
|
+
tags = []
|
15
|
+
CsvMultipleMapper.rows.each do |row|
|
16
|
+
tag = row[:tag_origin]
|
17
|
+
tags << tag unless tags.include?(tag)
|
18
|
+
end
|
19
|
+
tags
|
20
|
+
end
|
21
|
+
|
22
|
+
def rules
|
23
|
+
from_tags.to_h { |tag| [Util.tag_symbol(tag), rules_on_tag(tag)] }
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def rules_on_tag(tag)
|
29
|
+
rules = []
|
30
|
+
CsvMultipleMapper.rows.each do |row|
|
31
|
+
origin_tag = row[:tag_origin]
|
32
|
+
rules << MultipleRule.new(row) if origin_tag == tag
|
33
|
+
end
|
34
|
+
|
35
|
+
rules
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
tag_origin,tag_destination,subfield_single_from,subfield_single_to,subfield_combined_from_1,subfield_combined_to_1,symbol_1 ,subfield_combined_from_2,subfield_combined_to_2,symbol_2,subfield_combined_from_3,subfield_combined_to_3,symbol_3,New_indecator,Position_from,Position_to,Map_if_no_this_tag_existed,Map_if_no_this_tag_subfield_existed, Keep_one_if_multiple_available
|
2
|
+
100,700,"6,e","6,e","a,b,c,d,q",a,,,,,,,,"1,_",,,,,
|
3
|
+
110,710,"6,e","6,e","a,b",a,,,,,,,,"2,_",,,,,
|
4
|
+
111,711,6,6,"a,c,d,e,f,n,p,t",a,,,,,,,,"_,_",,,,,
|
5
|
+
242,246,6,6,"a,b,p,n",a,,,,,,,,,,,,,
|
6
|
+
245,245,"6,a","6,a","n,p",p,,,,,"b,f,k",b,,"_,_",,,,,
|
7
|
+
246,246,6,6,"a,b,p,n",a,,,,,,,,"_,_",,,,,
|
8
|
+
250,250,"6,a","6,a",,,,,,,,,,"_,_",,,,,
|
9
|
+
255,255,"6,a,b,c","6,a,b,c",,,,,,,,,,"_,_",,,,,
|
10
|
+
260,260,"6,a,b,c","6,a,b,c",,,,,,,,,,"_,_",,,,,
|
11
|
+
264,260,"6,a,b,c","6,a,b,c",,,,,,,,,,"_,_",,,260,,1
|
12
|
+
300,300,"6,b,c","6,b,c","3,a",a,,,,,,,,"_,_",,,,,
|
13
|
+
351,505,6,6,"a,b",a,,,,,,,,"_,_",,,,,
|
14
|
+
490,490,6,6,"a,v",a,,,,,,,,"_,_",,,,,
|
15
|
+
500,500,"6,a","6,a",,,,,,,,,,"_,_",,,,,
|
16
|
+
502,502,6,6,"a,b,c,d,g,o",a,,,,,,,,"_,_",,,,,
|
17
|
+
505,505,6,6,"a,g,r,t",a,,,,,,,,"_,_",,,,,
|
18
|
+
507,255,"6,a","6,a",,,,,,,,,,"_,_",,,,255__a,
|
19
|
+
520,520,"6,a","6,a",,,,,,,,,,"_,_",,,,,
|
20
|
+
522,522,"6,a","6,a",,,,,,,,,,"_,_",,,,,
|
21
|
+
524,524,"6,a","6,a",,,,,,,,,,"_,_",,,,,
|
22
|
+
536,536,"6,a","6,a",,,,,,,,,,"_,_",,,,,
|
23
|
+
541,541,6,6,"c,a,d",a,,,,,,,,"_,_",,,,,
|
24
|
+
545,545,"6,a","6,a",,,,,,,,,,"_,_",,,,,
|
25
|
+
546,546,"6,a","6,a",,,,,,,,,,"_,_",,,,,
|
26
|
+
600,600,6,6,"a,b,c,d,f,j,k,l,m,n,o,p,q,r,s,t",a,,"x,y,z,v",a,a--a,,,,"_,_",,,,,
|
27
|
+
610,610,6,6,"a,b,c,d,f,j,k,l,m,n,o,p,q,r,s,t",a,,"x,y,z,v",a,a--a,,,,"_,_",,,,,
|
28
|
+
611,611,6,6,"a,b,c,d,f,j,k,l,m,n,o,p,q,r,s,t",a,,"x,y,z,v",a,a--a,,,,"_,_",,,,,
|
29
|
+
630,630,6,6,"a,b,c,d,f,j,k,l,m,n,o,p,q,r,s,t",a,,"x,y,z,v",a,a--a,,,,"_,_",,,,,
|
30
|
+
650,650,6,6,"a,b,c",a,,"x,y,z,v",a,a--a,,,,"_,_",,,,,
|
31
|
+
651,651,6,6,a,a,,"x,y,z,v",a,a--a,,,,"_,_",,,,,
|
32
|
+
655,655,"6,2","6,2",a,a,,"x,y,z,v",a,a--a,,,,"_,_",,,,,
|
33
|
+
700,700,"6,e","6,e","a,b,c,d,q",a,,,,,,,,"1,_",,,,,
|
34
|
+
710,710,"6,e","6,e","a,b",a,,,,,,,,"2,_",,,,,
|
35
|
+
711,711,6,6,"a,c,d,e,f,n,p,t",a,,,,,,,,"_,_",,,,,
|
36
|
+
720,700,"6,a,e","6,a,e",,,,,,,,,,"1,_",,,,,
|
37
|
+
752,651,6,6,,,,"a,b,c,d,f,g",a,a--a,,,,"_,_",,,,,
|
38
|
+
773,773,"6,t,j,k,o","6,t,j,k,o",,,,,,,,,,"_,_",,,,,
|
39
|
+
907,901,"6,a","6,m",,,,,,,,,,"_,_",,,,,
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'marc'
|
2
|
+
|
3
|
+
# Derived fields from this module
|
4
|
+
# 1) From collection information:
|
5
|
+
# 336__$a
|
6
|
+
# 852__$c
|
7
|
+
# 982__$a,b
|
8
|
+
# 991__$a
|
9
|
+
# 2) From mms_id
|
10
|
+
# 901__$m
|
11
|
+
# 85641$u,y
|
12
|
+
|
13
|
+
module BerkeleyLibrary
|
14
|
+
module TIND
|
15
|
+
module Mapping
|
16
|
+
module ExternalTindField
|
17
|
+
class << self
|
18
|
+
include BerkeleyLibrary::Logging
|
19
|
+
|
20
|
+
def tind_fields_from_collection_information(hash)
|
21
|
+
raise ArgumentError, 'Collection parameters are incorrect.' unless valid_collection_hash?(hash)
|
22
|
+
|
23
|
+
collection_fields(hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
def tind_mms_id_fields(mms_id)
|
27
|
+
raise ArgumentError, 'mms_id is nil' unless mms_id
|
28
|
+
|
29
|
+
mms_id_fields(mms_id)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def collection_fields(hash)
|
35
|
+
fields = []
|
36
|
+
hash.each_key do |tag|
|
37
|
+
tindfield = tindfield_on_tag(tag, hash)
|
38
|
+
fields << tindfield if tindfield
|
39
|
+
end
|
40
|
+
|
41
|
+
fields
|
42
|
+
end
|
43
|
+
|
44
|
+
def mms_id_fields(mms_id)
|
45
|
+
fields = []
|
46
|
+
fields << tind_field_901_m(mms_id)
|
47
|
+
fields << tind_field_856_4_1(mms_id)
|
48
|
+
end
|
49
|
+
|
50
|
+
def tind_field_901_m(alma_id)
|
51
|
+
::MARC::DataField.new('901', ' ', ' ', ['m', alma_id])
|
52
|
+
end
|
53
|
+
|
54
|
+
def tind_field_856_4_1(alma_id)
|
55
|
+
u = "https://search.library.berkeley.edu/discovery/fulldisplay?context=L&vid=01UCS_BER:UCB&docid=alma#{alma_id}"
|
56
|
+
y = 'View library catalog record.'
|
57
|
+
subfield1 = Util.subfield('u', u)
|
58
|
+
subfield2 = Util.subfield('y', y)
|
59
|
+
|
60
|
+
::MARC::DataField.new('856', '4', '1', subfield1, subfield2)
|
61
|
+
end
|
62
|
+
|
63
|
+
def tindfield_on_tag(tag, hash)
|
64
|
+
subfield_names = Config.collection_subfield_names[tag]
|
65
|
+
subfield_values = hash[tag]
|
66
|
+
return nil if subfield_values.empty?
|
67
|
+
|
68
|
+
subfields = tind_subfields(subfield_values, subfield_names)
|
69
|
+
Util.datafield(tag, [' ', ' '], subfields)
|
70
|
+
end
|
71
|
+
|
72
|
+
def tind_subfields(subfield_values, subfield_names)
|
73
|
+
subfields = []
|
74
|
+
subfield_values.each_with_index do |value, i|
|
75
|
+
name = subfield_names[i]
|
76
|
+
subfield = Util.subfield(name, value.strip)
|
77
|
+
subfields << subfield
|
78
|
+
end
|
79
|
+
subfields
|
80
|
+
end
|
81
|
+
|
82
|
+
def valid_collection_hash?(hash)
|
83
|
+
return false unless valid_item?(hash, '336', 1) &&
|
84
|
+
valid_item?(hash, '852', 1) && valid_item?(hash, '980', 1) && valid_item?(hash, '982', 2) && valid_991(hash)
|
85
|
+
|
86
|
+
true
|
87
|
+
end
|
88
|
+
|
89
|
+
def valid_item?(hash, key, num)
|
90
|
+
(hash.key? key) && (hash[key].length == num)
|
91
|
+
end
|
92
|
+
|
93
|
+
def valid_991(hash)
|
94
|
+
cout = hash['991'].length
|
95
|
+
[0, 1].include?(cout)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'berkeley_library/tind/mapping/tind_subfield_util'
|
2
|
+
require 'berkeley_library/tind/mapping/misc'
|
3
|
+
require 'berkeley_library/tind/mapping/field_catalog_util'
|
4
|
+
require 'berkeley_library/tind/mapping/match_tind_field'
|
5
|
+
|
6
|
+
module BerkeleyLibrary
|
7
|
+
module TIND
|
8
|
+
module Mapping
|
9
|
+
|
10
|
+
class DataFieldsCatalog
|
11
|
+
include Misc
|
12
|
+
include TindSubfieldUtil
|
13
|
+
include CsvMapper
|
14
|
+
include Util
|
15
|
+
include AdditionalDatafieldProcess
|
16
|
+
include FieldCatalogUtil
|
17
|
+
include MatchTindField
|
18
|
+
include BerkeleyLibrary::Logging
|
19
|
+
|
20
|
+
attr_reader :control_fields
|
21
|
+
attr_reader :data_fields_group
|
22
|
+
attr_reader :data_fields_880_group
|
23
|
+
attr_reader :data_fields_880_00
|
24
|
+
attr_reader :mms_id
|
25
|
+
|
26
|
+
def initialize(record)
|
27
|
+
@control_fields = []
|
28
|
+
@data_fields_group = []
|
29
|
+
@data_fields_880_group = []
|
30
|
+
@data_fields_880_00 = []
|
31
|
+
@mms_id = ''
|
32
|
+
|
33
|
+
@data_fields = []
|
34
|
+
@data_fields_880 = []
|
35
|
+
@alma_field_tags = []
|
36
|
+
|
37
|
+
init(record)
|
38
|
+
end
|
39
|
+
|
40
|
+
def init(record)
|
41
|
+
prepare_catalog(record)
|
42
|
+
@data_fields_group = prepare_group(@data_fields)
|
43
|
+
@data_fields_880_group = prepare_group(@data_fields_880)
|
44
|
+
@mms_id = alma_mms_id
|
45
|
+
end
|
46
|
+
|
47
|
+
def prepare_catalog(record)
|
48
|
+
clean_fields = clean_subfields(record.fields)
|
49
|
+
check_abnormal_formated_subfield6(clean_fields)
|
50
|
+
allocate_fields(clean_fields)
|
51
|
+
remove_fields_with_subject_fast
|
52
|
+
end
|
53
|
+
|
54
|
+
def remove_fields_with_subject_fast
|
55
|
+
@data_fields = exluding_fields_with_fast_subject(@data_fields)
|
56
|
+
@data_fields_880 = exluding_fields_with_fast_subject(@data_fields_880)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def allocate_fields(fields)
|
62
|
+
fields.each do |f|
|
63
|
+
next if added_control_field?(f)
|
64
|
+
next if added_880_field?(f)
|
65
|
+
|
66
|
+
tag = f.tag
|
67
|
+
next unless (found_in_mapper? tag) && (no_pre_existed_field? tag)
|
68
|
+
|
69
|
+
@data_fields << f
|
70
|
+
@alma_field_tags << f.tag
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# 880 field with a subfield6 including a tag belong to origin tags defined in csv file
|
75
|
+
def qualified_880_field?(f)
|
76
|
+
return false unless referred_tag(f)
|
77
|
+
|
78
|
+
found_in_mapper?(referred_tag(f))
|
79
|
+
end
|
80
|
+
|
81
|
+
def added_control_field?(f)
|
82
|
+
return false unless ::MARC::ControlField.control_tag?(f.tag)
|
83
|
+
|
84
|
+
@control_fields << f
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
88
|
+
def added_880_field?(f)
|
89
|
+
return false unless f.tag == '880'
|
90
|
+
|
91
|
+
# adding 880 datafield with "non-subfield6" to "00" group for keeping this record in TIND
|
92
|
+
# with log information, to let users correcting or removing this datafield from TIND record
|
93
|
+
@data_fields_880_00 << f unless valid_subfield6?(f)
|
94
|
+
|
95
|
+
if qualified_880_field?(f)
|
96
|
+
subfield6_endwith_00?(f) ? @data_fields_880_00 << f : @data_fields_880 << f
|
97
|
+
end
|
98
|
+
|
99
|
+
true
|
100
|
+
end
|
101
|
+
|
102
|
+
def valid_subfield6?(f)
|
103
|
+
return true if subfield6?(f)
|
104
|
+
|
105
|
+
logger.warn("880 field has no subfield 6 #{f.inspect}")
|
106
|
+
|
107
|
+
false
|
108
|
+
end
|
109
|
+
|
110
|
+
# Is the origin_tag of a field has related from_tag in csv file?
|
111
|
+
def found_in_mapper?(tag)
|
112
|
+
from_tags.include? tag
|
113
|
+
end
|
114
|
+
|
115
|
+
# If tag is listed in csv_mapper.one_occurrence_tags
|
116
|
+
# Check pre_existed field of this tag
|
117
|
+
# make sure to keep the first datafield for an one_occurrence_tag defined in csv mapping file
|
118
|
+
# def no_pre_existed_field?(tag)
|
119
|
+
# # no one-occurrence defined in csv
|
120
|
+
# return true unless one_occurrence_tags.include? tag
|
121
|
+
|
122
|
+
# # Checking the exsisting regular fields include the one-occurrence field defined in the csv
|
123
|
+
# return false if @alma_field_tags.compact.include? tag
|
124
|
+
|
125
|
+
# true
|
126
|
+
# end
|
127
|
+
|
128
|
+
def no_pre_existed_field?(tag)
|
129
|
+
# no one-occurrence defined in csv
|
130
|
+
return true unless one_occurrence_tags.include? tag
|
131
|
+
|
132
|
+
# Checking the exsisting regular fields include the one-occurrence field defined in the csv
|
133
|
+
!(@alma_field_tags.compact.include? tag)
|
134
|
+
end
|
135
|
+
|
136
|
+
def alma_mms_id
|
137
|
+
f_001 = @control_fields.find { |f| f if f.tag == '001' }
|
138
|
+
return nil unless f_001
|
139
|
+
|
140
|
+
f_001.value
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module BerkeleyLibrary
|
2
|
+
module TIND
|
3
|
+
module Mapping
|
4
|
+
module FieldCatalogUtil
|
5
|
+
|
6
|
+
# Excluding fields: subfield2 = 'fast' and tag or refered tag(880 fields) started with '6':
|
7
|
+
def exluding_fields_with_fast_subject(fields)
|
8
|
+
fields.reject { |f| excluding_field?(f) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def prepare_group(from_fields)
|
12
|
+
datafields_hash = { normal: [], pre_tag: [], pre_tag_subfield: [] }
|
13
|
+
from_fields.each do |f|
|
14
|
+
# a regular field tag, or a tag value from 880 field captured from subfield6
|
15
|
+
tag = origin_mapping_tag(f)
|
16
|
+
next unless tag
|
17
|
+
|
18
|
+
rule = rules[Util.tag_symbol(tag)]
|
19
|
+
|
20
|
+
assing_field(rule, f, datafields_hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
datafields_hash
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def excluding_field?(f)
|
29
|
+
return false unless field_6xx?(f)
|
30
|
+
return false unless subfield2_fast(f)
|
31
|
+
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
# Both regular and 880 field: tag or refered tag started with '6'
|
36
|
+
def field_6xx?(f)
|
37
|
+
tag = origin_mapping_tag(f)
|
38
|
+
tag =~ /^6\d{2}$/
|
39
|
+
end
|
40
|
+
|
41
|
+
def subfield2_fast(f)
|
42
|
+
subject = f['2']
|
43
|
+
return false unless subject
|
44
|
+
|
45
|
+
subject.downcase == 'fast'
|
46
|
+
end
|
47
|
+
|
48
|
+
# f is either from field whose tag having a match in csv mapping file - 'from tag' column
|
49
|
+
def assing_field(rule, f, datafields_hash)
|
50
|
+
if rule.pre_existed_tag then datafields_hash[:pre_tag] << f
|
51
|
+
elsif rule.pre_existed_tag_subfield then datafields_hash[:pre_tag_subfield] << f
|
52
|
+
else datafields_hash[:normal] << f
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|