@natlibfi/marc-record-validators-melinda 11.3.1 → 11.3.2-alpha.2
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.
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/melindaCustomMergeFields.json +5120 -0
- package/dist/merge-fields/config.json +83 -0
- package/dist/merge-fields/controlSubfields.js +278 -0
- package/dist/merge-fields/controlSubfields.js.map +1 -0
- package/dist/merge-fields/counterpartField.js +674 -0
- package/dist/merge-fields/counterpartField.js.map +1 -0
- package/dist/merge-fields/index.js +76 -0
- package/dist/merge-fields/index.js.map +1 -0
- package/dist/merge-fields/mergableIndicator.js +95 -0
- package/dist/merge-fields/mergableIndicator.js.map +1 -0
- package/dist/merge-fields/mergableTag.js +33 -0
- package/dist/merge-fields/mergableTag.js.map +1 -0
- package/dist/merge-fields/mergeConstraints.js +1225 -0
- package/dist/merge-fields/mergeConstraints.js.map +1 -0
- package/dist/merge-fields/mergeField.js +190 -0
- package/dist/merge-fields/mergeField.js.map +1 -0
- package/dist/merge-fields/mergeIndicator.js +171 -0
- package/dist/merge-fields/mergeIndicator.js.map +1 -0
- package/dist/merge-fields/mergeOrAddPostprocess.js +57 -0
- package/dist/merge-fields/mergeOrAddPostprocess.js.map +1 -0
- package/dist/merge-fields/mergeOrAddSubfield.js +203 -0
- package/dist/merge-fields/mergeOrAddSubfield.js.map +1 -0
- package/dist/merge-fields/mergeSubfield.js +277 -0
- package/dist/merge-fields/mergeSubfield.js.map +1 -0
- package/dist/merge-fields/removeDuplicateSubfields.js +48 -0
- package/dist/merge-fields/removeDuplicateSubfields.js.map +1 -0
- package/dist/merge-fields/worldKnowledge.js +98 -0
- package/dist/merge-fields/worldKnowledge.js.map +1 -0
- package/dist/merge-fields.spec.js +51 -0
- package/dist/merge-fields.spec.js.map +1 -0
- package/dist/subfield6Utils.js +16 -1
- package/dist/subfield6Utils.js.map +1 -1
- package/dist/utils.js +108 -0
- package/dist/utils.js.map +1 -1
- package/package.json +6 -6
- package/src/index.js +3 -1
- package/src/melindaCustomMergeFields.json +5120 -0
- package/src/merge-fields/config.json +83 -0
- package/src/merge-fields/controlSubfields.js +307 -0
- package/src/merge-fields/counterpartField.js +736 -0
- package/src/merge-fields/index.js +69 -0
- package/src/merge-fields/mergableIndicator.js +90 -0
- package/src/merge-fields/mergableTag.js +89 -0
- package/src/merge-fields/mergeConstraints.js +309 -0
- package/src/merge-fields/mergeField.js +187 -0
- package/src/merge-fields/mergeIndicator.js +185 -0
- package/src/merge-fields/mergeOrAddPostprocess.js +56 -0
- package/src/merge-fields/mergeOrAddSubfield.js +218 -0
- package/src/merge-fields/mergeSubfield.js +306 -0
- package/src/merge-fields/removeDuplicateSubfields.js +50 -0
- package/src/merge-fields/worldKnowledge.js +104 -0
- package/src/merge-fields.spec.js +52 -0
- package/src/subfield6Utils.js +14 -1
- package/src/utils.js +119 -0
- package/test-fixtures/merge-fields/f01/expectedResult.json +11 -0
- package/test-fixtures/merge-fields/f01/metadata.json +5 -0
- package/test-fixtures/merge-fields/f01/record.json +13 -0
- package/test-fixtures/merge-fields/f02/expectedResult.json +14 -0
- package/test-fixtures/merge-fields/f02/metadata.json +6 -0
- package/test-fixtures/merge-fields/f02/record.json +16 -0
- package/test-fixtures/merge-fields/f03/expectedResult.json +17 -0
- package/test-fixtures/merge-fields/f03/metadata.json +7 -0
- package/test-fixtures/merge-fields/f03/record.json +23 -0
- package/test-fixtures/merge-fields/f04/expectedResult.json +14 -0
- package/test-fixtures/merge-fields/f04/metadata.json +5 -0
- package/test-fixtures/merge-fields/f04/record.json +19 -0
- package/test-fixtures/merge-fields/v01/expectedResult.json +6 -0
- package/test-fixtures/merge-fields/v01/metadata.json +5 -0
- package/test-fixtures/merge-fields/v01/record.json +13 -0
- package/test-fixtures/merge-fields/v02/expectedResult.json +4 -0
- package/test-fixtures/merge-fields/v02/metadata.json +5 -0
- package/test-fixtures/merge-fields/v02/record.json +13 -0
- package/test-fixtures/merge-fields/v03/expectedResult.json +6 -0
- package/test-fixtures/merge-fields/v03/metadata.json +6 -0
- package/test-fixtures/merge-fields/v03/record.json +16 -0
- package/test-fixtures/merge-fields/v04/expectedResult.json +4 -0
- package/test-fixtures/merge-fields/v04/metadata.json +6 -0
- package/test-fixtures/merge-fields/v04/record.json +16 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// NB! This validator is build on code that merged two different records originally in marc-record-merge-reducers.
|
|
2
|
+
// The idea was to write a validator that can merge fields in one record. (This is a good idea at least for field tags /^[1678](00|10|11|30)$/.)
|
|
3
|
+
// As we don't want copypaste coding everything was moved here, and marc-record-merge-reducers exports mergeField() function.
|
|
4
|
+
// That function uses a lot of stuff that is meant for the two-record-merge case only. Thus the tests for this validator are pretty limited here,
|
|
5
|
+
// and the test coverage is low. The extensive set of tests in in marc-record-merge-reducers for this code.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
//import createDebugLogger from 'debug';
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import {mergeField} from './mergeField';
|
|
12
|
+
import {MarcRecord} from '@natlibfi/marc-record';
|
|
13
|
+
import {postprocessRecords} from './mergeOrAddPostprocess.js';
|
|
14
|
+
|
|
15
|
+
const description = 'Merge fields within record';
|
|
16
|
+
|
|
17
|
+
const defaultConfig = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'src', 'merge-fields', 'config.json'), 'utf8'));
|
|
18
|
+
|
|
19
|
+
export default function () {
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
description, validate, fix
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
function mergeFieldsWithinRecord(record, config) {
|
|
27
|
+
//const candFields = record.fields.toReversed(); // Node 20+ only! Filter via config?
|
|
28
|
+
const fields = config && config.tagPattern ? record.get(config.tagPattern) : record.get(/^[1678](?:00|10|11|30)$/u);
|
|
29
|
+
|
|
30
|
+
fields.reverse(); // eslint-disable-line functional/immutable-data
|
|
31
|
+
const mergedField = fields.find(f => mergeField(record, record, f, config));
|
|
32
|
+
if (!mergedField) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
record.removeField(mergedField);
|
|
36
|
+
mergeFieldsWithinRecord(record, config);
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function fix(record, config = undefined) {
|
|
41
|
+
const config2 = config || defaultConfig;
|
|
42
|
+
record.internalMerge = true; // eslint-disable-line functional/immutable-data
|
|
43
|
+
mergeFieldsWithinRecord(record, config2);
|
|
44
|
+
delete record.internalMerge; // eslint-disable-line functional/immutable-data
|
|
45
|
+
// Remove deleted fields and field.merged marks:
|
|
46
|
+
postprocessRecords(record, record);
|
|
47
|
+
|
|
48
|
+
const res = {message: [], fix: [], valid: true};
|
|
49
|
+
return res;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function validate(record, config) {
|
|
53
|
+
//nvdebug(`VALIDATE ${description}...`);
|
|
54
|
+
|
|
55
|
+
const nFields = record.fields.length;
|
|
56
|
+
const clonedRecord = new MarcRecord(record, {subfieldValues: false});
|
|
57
|
+
fix(clonedRecord, config);
|
|
58
|
+
|
|
59
|
+
const nFields2 = clonedRecord.fields.length;
|
|
60
|
+
if (nFields === nFields2) {
|
|
61
|
+
return {message: [], valid: true};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const msg = `${description}: number of fields changes from ${nFields} to ${nFields2}`;
|
|
65
|
+
return {message: [msg], valid: false};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import createDebugLogger from 'debug';
|
|
2
|
+
import {marc21GetTagsLegalInd1Value, marc21GetTagsLegalInd2Value, nvdebug} from '../utils';
|
|
3
|
+
|
|
4
|
+
// Specs: https://workgroups.helsinki.fi/x/K1ohCw (though we occasionally differ from them)...
|
|
5
|
+
|
|
6
|
+
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:merge-fields:mergableIndicator');
|
|
7
|
+
//const debugData = debug.extend('data');
|
|
8
|
+
const debugDev = debug.extend('dev');
|
|
9
|
+
|
|
10
|
+
const ind1NonFilingChars = ['130', '630', '730', '740'];
|
|
11
|
+
const ind2NonFilingChars = ['222', '240', '242', '243', '245', '830'];
|
|
12
|
+
|
|
13
|
+
function marc21NoNeedToCheckInd1(tag) {
|
|
14
|
+
const cands = marc21GetTagsLegalInd1Value(tag);
|
|
15
|
+
if (typeof cands === 'string') { // single cand
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function marc21NoNeedToCheckInd2(tag) {
|
|
22
|
+
const cands = marc21GetTagsLegalInd2Value(tag);
|
|
23
|
+
nvdebug(`CHECK IND2 ${typeof cands} FOR ${tag}`, debugDev);
|
|
24
|
+
if (typeof cands === 'string') { // single cand
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
export function mergableIndicator1(field1, field2, config) {
|
|
32
|
+
// Indicators are identical:
|
|
33
|
+
if (field1.ind1 === field2.ind1) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
const {tag} = field1; // means "tag = field1.tag"
|
|
37
|
+
// Indicator has but one legal value or is a non-filing indicator (NB: can not be overridden via config...):
|
|
38
|
+
if (marc21NoNeedToCheckInd1(tag) || ind1NonFilingChars.includes(tag)) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
// Override via config:
|
|
42
|
+
if (config.ignoreIndicator1 && config.ignoreIndicator1.includes(tag)) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
// Tolerate value '#' (reason: not spefified etc, the other value is supposedly a good one)
|
|
46
|
+
if (field1.ind1 === ' ' || field2.ind1 === ' ') {
|
|
47
|
+
return config.tolerateBlankIndicator1 && config.tolerateBlankIndicator1.includes(tag);
|
|
48
|
+
}
|
|
49
|
+
// Fail:
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function mergableIndicator2(field1, field2, config) {
|
|
54
|
+
// Indicators are identical:
|
|
55
|
+
if (field1.ind2 === field2.ind2) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// nvdebug(`mergableIndicator2\n '${fieldToString(field1)}' vs\n '${fieldToString(field2)}'`, debugDev);
|
|
60
|
+
|
|
61
|
+
// NB! Our 260 vs 264 hacks...NB #2: We do this split check only for ind2, not for ind1.
|
|
62
|
+
// Maybe reasons to this for ind1 will rise later on. None known yetr though.
|
|
63
|
+
const tag1 = field1.tag;
|
|
64
|
+
const tag2 = field2.tag;
|
|
65
|
+
|
|
66
|
+
// Indicator has but one legal value or is a non-filing indicator (NB: can not be overridden via config...):
|
|
67
|
+
if (marc21NoNeedToCheckInd2(tag1) || marc21NoNeedToCheckInd2(tag2) || ind2NonFilingChars.includes(tag1)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Override via config:
|
|
72
|
+
if (config.ignoreIndicator2) {
|
|
73
|
+
if (config.ignoreIndicator2.includes(tag1) || config.ignoreIndicator2.includes(tag2)) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Tolerate value '#' (reason: not spefified etc, the other value is supposedly a good one)
|
|
79
|
+
if (config.tolerateBlankIndicator2) {
|
|
80
|
+
if (field1.ind2 === ' ' && config.tolerateBlankIndicator2.includes(tag1)) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
if (field2.ind2 === ' ' && config.tolerateBlankIndicator2.includes(tag2)) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
// Fail:
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
//import createDebugLogger from 'debug';
|
|
2
|
+
//import {nvdebug} from './utils';
|
|
3
|
+
//const debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers');
|
|
4
|
+
|
|
5
|
+
// Actually I hope that 066. 842-845, 852-855. 863-868, 876-878 and HLI are already removed
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const defaultNonMergableFields = [
|
|
9
|
+
'066', // 066 - Character sets present (NR)
|
|
10
|
+
'382', // 382: merging would be madness due to $n position etc...
|
|
11
|
+
// However, this will miss cases, where only $5 or $9 differs... Such is!
|
|
12
|
+
// 59X: always copy, never merge. NB! No specs exist!
|
|
13
|
+
'590',
|
|
14
|
+
'591',
|
|
15
|
+
'592',
|
|
16
|
+
'593',
|
|
17
|
+
'594',
|
|
18
|
+
'595',
|
|
19
|
+
'596',
|
|
20
|
+
'597',
|
|
21
|
+
'598',
|
|
22
|
+
'599',
|
|
23
|
+
'654',
|
|
24
|
+
'657',
|
|
25
|
+
'658',
|
|
26
|
+
'662',
|
|
27
|
+
'668',
|
|
28
|
+
'752',
|
|
29
|
+
// '753', // NV: Commented because of MRA-465 (2023-08-20)
|
|
30
|
+
'754',
|
|
31
|
+
'758',
|
|
32
|
+
'760',
|
|
33
|
+
'762',
|
|
34
|
+
'765',
|
|
35
|
+
'767',
|
|
36
|
+
'770',
|
|
37
|
+
'772',
|
|
38
|
+
'775',
|
|
39
|
+
'777',
|
|
40
|
+
'780',
|
|
41
|
+
'785',
|
|
42
|
+
'786',
|
|
43
|
+
'787',
|
|
44
|
+
// Them 8XX fields are holdings related fields:
|
|
45
|
+
'841',
|
|
46
|
+
'842',
|
|
47
|
+
'843',
|
|
48
|
+
'844',
|
|
49
|
+
'845',
|
|
50
|
+
'852',
|
|
51
|
+
'853',
|
|
52
|
+
'854',
|
|
53
|
+
'855',
|
|
54
|
+
// '856' is mergable, but a pain in the ass
|
|
55
|
+
'863',
|
|
56
|
+
'864',
|
|
57
|
+
'865',
|
|
58
|
+
'866',
|
|
59
|
+
'867',
|
|
60
|
+
'868',
|
|
61
|
+
'876',
|
|
62
|
+
'877',
|
|
63
|
+
'878',
|
|
64
|
+
'881',
|
|
65
|
+
'882',
|
|
66
|
+
'883',
|
|
67
|
+
// '884',
|
|
68
|
+
'885',
|
|
69
|
+
'886',
|
|
70
|
+
'887',
|
|
71
|
+
'900',
|
|
72
|
+
'901',
|
|
73
|
+
'910',
|
|
74
|
+
'940',
|
|
75
|
+
'960',
|
|
76
|
+
'995',
|
|
77
|
+
'CAT',
|
|
78
|
+
'HLI',
|
|
79
|
+
'LOW',
|
|
80
|
+
'SID'
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
export function mergableTag(tag, config) {
|
|
85
|
+
// Use either configured non-mergable tags or default non-mergable tags
|
|
86
|
+
const nonMergableFields = config.skipMergeTags && Array.isArray(config.skipMergeTags) ? config.skipMergeTags : defaultNonMergableFields;
|
|
87
|
+
|
|
88
|
+
return !nonMergableFields.includes(tag);
|
|
89
|
+
}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import createDebugLogger from 'debug';
|
|
2
|
+
const debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:mergeConstraints');
|
|
3
|
+
//const debugData = debug.extend('data');
|
|
4
|
+
const debugDev = debug.extend('dev');
|
|
5
|
+
|
|
6
|
+
// Specs: https://workgroups.helsinki.fi/x/K1ohCw (though we occasionally differ from them)...
|
|
7
|
+
|
|
8
|
+
// "key" is an unique key that must match (be absent or exist+be identical) in both.
|
|
9
|
+
// "paired" refers to a field that must either exist in both or be absent in both (negative XOR). Typically it's not defined.
|
|
10
|
+
// NB: key+paired with identical values is an attempt to prevent copy for (ET) fields, and to force separate fields on (T) fields.
|
|
11
|
+
// NB! If base has eg. no 264, two+ 264 fields can be copied from the source.
|
|
12
|
+
|
|
13
|
+
// NB! not all X00 fields have, say, $x subfield. However, we can still share them...
|
|
14
|
+
// $h is non-1XX?, $i is 7XX only, $w is 8XX only...
|
|
15
|
+
const keyX00 = 'abcjloqrtuwx'; // Shared: $abcdefg...
|
|
16
|
+
const keyX10 = 'abcdfghlnoprstuwx';
|
|
17
|
+
const keyX11 = 'acdefghlnpqstuwx';
|
|
18
|
+
const keyX30 = 'adfghklmnoprstvwxyz';
|
|
19
|
+
|
|
20
|
+
const mergeConstraints = [
|
|
21
|
+
{'tag': '010', 'required': 'a', 'key': 'a'},
|
|
22
|
+
{'tag': '013', 'required': 'a', 'key': 'a'}, // We have 2 instances in Melinda...
|
|
23
|
+
{'tag': '015', 'required': 'a', 'key': 'a'},
|
|
24
|
+
{'tag': '016', 'required': 'a', 'key': 'a2'},
|
|
25
|
+
{'tag': '017', 'required': 'a', 'key': 'a'},
|
|
26
|
+
{'tag': '018', 'required': 'a', 'key': 'a'},
|
|
27
|
+
{'tag': '020', 'required': '', 'paired': 'a', 'key': 'a'}, // NB! how to handle $z-only cases? 'required-fallback'='z'?
|
|
28
|
+
{'tag': '022', 'required': '', 'paired': 'a', 'key': 'alz'},
|
|
29
|
+
{'tag': '024', 'required': '', 'paired': 'a', 'key': 'ad'},
|
|
30
|
+
{'tag': '025', 'required': 'a', 'key': 'a'},
|
|
31
|
+
{'tag': '026', 'required': 'a', 'key': 'a'},
|
|
32
|
+
{'tag': '027', 'required': 'a', 'key': 'a'}, // on tuolla pari $z:ää
|
|
33
|
+
{'tag': '028', 'required': 'a', 'key': 'ab'},
|
|
34
|
+
{'tag': '030', 'required': 'a', 'key': 'a'},
|
|
35
|
+
{'tag': '031', 'required': '', 'key': 'abcegmnopr2'}, // mites tämmöisen käytännössä avaimettoman klaarais? TODO: tests
|
|
36
|
+
{'tag': '032', 'required': 'a', 'key': 'ab'},
|
|
37
|
+
{'tag': '033', 'required': 'a', 'key': 'abcp0123'}, // 0,1% are without $a. Ignore them for now.
|
|
38
|
+
{'tag': '034', 'required': 'ab', 'key': 'abcdefghjkmnprstxyz0123'},
|
|
39
|
+
{'tag': '035', 'required': '', 'key': 'az'},
|
|
40
|
+
{'tag': '036', 'required': 'a', 'key': 'a'},
|
|
41
|
+
{'tag': '037', 'required': 'b', 'key': 'ab'},
|
|
42
|
+
{'tag': '039', 'required': 'a'},
|
|
43
|
+
{'tag': '040', 'required': '', 'key': ''},
|
|
44
|
+
{'tag': '041', 'required': '', 'paired': '2', 'key': ''}, // Don't put $2 in 'key'! hasCommonNominator() would get into trouble with it...
|
|
45
|
+
{'tag': '042', 'required': 'a', 'key': ''}, // NB: preprocessor hacks applied
|
|
46
|
+
{'tag': '043', 'required': 'a', 'key': 'abc'},
|
|
47
|
+
{'tag': '044', 'required': '', 'key': 'abc', 'paired': 'abc'},
|
|
48
|
+
{'tag': '045', 'required': '', 'key': 'abc', 'paired': 'abc'}, // (ET) // 045 is problematic either-$a or $b or $c...
|
|
49
|
+
{'tag': '046', 'required': 'a', 'key': 'abcdejklmnop', 'paired': 'abcdejklmnop'},
|
|
50
|
+
{'tag': '047', 'required': 'a', 'key': 'a2'},
|
|
51
|
+
{'tag': '048', 'required': '', 'paired': 'ab', 'key': 'ba'},
|
|
52
|
+
{'tag': '049', 'required': '', 'key': 'abcd'},
|
|
53
|
+
{'tag': '050', 'required': 'a', 'key': 'ab13'},
|
|
54
|
+
{'tag': '051', 'required': 'a', 'key': 'abc'}, // 2021-08-27: only one field in the whole Melinda
|
|
55
|
+
{'tag': '052', 'required': 'a', 'key': 'abd'},
|
|
56
|
+
{'tag': '055', 'required': 'a', 'key': 'ab'},
|
|
57
|
+
{'tag': '060', 'required': 'a', 'key': 'ab'},
|
|
58
|
+
{'tag': '061', 'required': 'a', 'paired': 'b', 'key': 'abc'},
|
|
59
|
+
{'tag': '066', 'required': 'c'},
|
|
60
|
+
{'tag': '070', 'required': 'a', 'key': 'ab'},
|
|
61
|
+
{'tag': '071', 'required': 'a', 'paired': 'abc', 'key': 'abc'}, // N=3
|
|
62
|
+
{'tag': '072', 'required': 'a', 'key': 'ax'},
|
|
63
|
+
{'tag': '074', 'required': '', 'paired': 'a', 'key': 'az'},
|
|
64
|
+
{'tag': '080', 'required': 'a', 'paired': 'bx', 'key': 'abx'},
|
|
65
|
+
{'tag': '082', 'required': 'a', 'paired': 'b', 'key': 'abmq2'},
|
|
66
|
+
{'tag': '083', 'required': 'a', 'paired': 'b', 'key': 'abmqy'},
|
|
67
|
+
{'tag': '084', 'required': 'a', 'paired': 'b2', 'key': 'abq2'},
|
|
68
|
+
{'tag': '085', 'required': '', 'paired': 'abcfrstuvwyz', 'key': 'abcfrstuvwxyz'},
|
|
69
|
+
{'tag': '086', 'required': '', 'paired': 'a', 'key': 'a'},
|
|
70
|
+
{'tag': '088', 'required': '', 'paired': 'a', 'key': 'a'},
|
|
71
|
+
// NB! 100, 110 and 111 may have title parts that are handled elsewhere
|
|
72
|
+
{'tag': '100', 'required': 'a', 'paired': 't', 'key': keyX00},
|
|
73
|
+
{'tag': '110', 'required': 'a', 'paired': 'bt', 'key': keyX10},
|
|
74
|
+
{'tag': '111', 'required': 'a', 'paired': 't', 'key': keyX11},
|
|
75
|
+
// NB! 130 has no name part, key is used for title part
|
|
76
|
+
{'tag': '130', 'required': 'a', 'key': keyX30},
|
|
77
|
+
{'tag': '210', 'required': 'a', 'key': 'ab'},
|
|
78
|
+
{'tag': '222', 'required': 'a', 'key': 'ab'},
|
|
79
|
+
{'tag': '240', 'required': 'a', 'key': 'adfghklmnoprs'},
|
|
80
|
+
{'tag': '242', 'required': 'a', 'key': 'abchnpy'},
|
|
81
|
+
{'tag': '243', 'required': 'a', 'key': 'adfghklmnoprs'},
|
|
82
|
+
{'tag': '245', 'required': 'a', 'key': 'abcghnps', 'paired': 'abnps'},
|
|
83
|
+
{'tag': '246', 'required': 'a', 'key': 'abfnp'},
|
|
84
|
+
{'tag': '247', 'required': 'a', 'key': 'abfnpx'},
|
|
85
|
+
{'tag': '250', 'required': 'a', 'key': 'ab'},
|
|
86
|
+
{'tag': '251', 'required': 'a', 'key': 'a'},
|
|
87
|
+
{'tag': '254', 'required': 'a', 'key': 'a'},
|
|
88
|
+
{'tag': '255', 'required': 'a', 'key': 'abcdefg', 'paired': 'abcdefg'},
|
|
89
|
+
{'tag': '256', 'required': 'a', 'key': 'a'},
|
|
90
|
+
{'tag': '257', 'required': 'a', 'key': 'a'},
|
|
91
|
+
{'tag': '258', 'required': 'a', 'key': 'a'}, // Melinda: N=1
|
|
92
|
+
//{'tag': '260', 'required': '', 'paired': 'abcefg', 'key': 'abcefg'},
|
|
93
|
+
{'tag': '260', 'required': '', 'key': 'abcefg'},
|
|
94
|
+
{'tag': '263', 'required': 'a', 'key': 'a'},
|
|
95
|
+
//{'tag': '264', 'required': '', 'paired': 'abc', 'key': 'abc'}, // NB "S.l." normalizations?" not implemented
|
|
96
|
+
{'tag': '264', 'required': '', 'key': 'abc'}, // NB "S.l." normalizations?" not implemented
|
|
97
|
+
// SKIP TAG 270 ON PURPOSE! Melinda's N=43.
|
|
98
|
+
{'tag': '300', 'required': 'a', 'key': 'abcefg'},
|
|
99
|
+
{'tag': '306', 'required': 'a', 'key': 'a'},
|
|
100
|
+
// SKIP TAG 307 ON PURPOSE! N=0
|
|
101
|
+
{'tag': '310', 'required': 'a', 'key': 'ab'},
|
|
102
|
+
{'tag': '321', 'required': 'a', 'key': 'ab'},
|
|
103
|
+
{'tag': '335', 'required': 'a', 'key': 'ab'}, // Melinda N=1 (a test field). M might increase?
|
|
104
|
+
{'tag': '336', 'required': 'b2', 'key': 'ab2'}, // MET-88: don't merge different $a subfields
|
|
105
|
+
{'tag': '337', 'required': 'b2', 'key': 'ab2'}, // MET-88: don't merge different $a subfields
|
|
106
|
+
{'tag': '338', 'required': 'b2', 'key': 'ab2'}, // / MET-88: don't merge different $a subfields
|
|
107
|
+
{'tag': '340', 'required': '', 'paired': 'abcdefghijkmnop', 'key': 'abcdefghijkmnop'},
|
|
108
|
+
{'tag': '341', 'required': '', 'paired': 'abcde', 'key': 'abcde'}, // NEW! Starting to appear!
|
|
109
|
+
{'tag': '342', 'required': '', 'paired': 'abcdefghijklmnopqrstuvw', 'key': 'abcdefghijklmnopqrstuvw'}, // SKIP 342. NOT SEEN!
|
|
110
|
+
{'tag': '343', 'required': '', 'paired': 'abcdefghi', 'key': 'abcdefghi'}, // SKIP 343.
|
|
111
|
+
{'tag': '344', 'required': '', 'paired': 'abcdefgh', 'key': 'abcdefgh'},
|
|
112
|
+
{'tag': '345', 'required': '', 'paired': 'abcd', 'key': 'abcd'},
|
|
113
|
+
{'tag': '346', 'required': '', 'paired': 'ab', 'key': 'ab'},
|
|
114
|
+
{'tag': '347', 'required': '', 'paired': 'abcdef', 'key': 'abcdef'},
|
|
115
|
+
{'tag': '348', 'required': '', 'paired': 'ab', 'key': 'ab'},
|
|
116
|
+
{'tag': '348', 'required': '', 'paired': 'abc', 'key': 'abc'},
|
|
117
|
+
{'tag': '351', 'required': '', 'paired': 'abc', 'key': 'abc'},
|
|
118
|
+
{'tag': '352', 'required': '', 'paired': 'abcdefgiq', 'key': 'abcdefgiq'},
|
|
119
|
+
{'tag': '355', 'required': '', 'paired': 'abcdefghj', 'key': 'abcdefghj'},
|
|
120
|
+
{'tag': '357', 'required': 'a', 'key': 'abcg'},
|
|
121
|
+
{'tag': '362', 'required': 'a', 'key': 'az'},
|
|
122
|
+
{'tag': '363', 'required': '', 'paired': 'abcdefghijklmuv', 'key': 'abcdefghijklmuv'},
|
|
123
|
+
{'tag': '365', 'required': 'b', 'paired': 'abcdefghijkm', 'key': 'abcdefghijkm'}, // N=0
|
|
124
|
+
{'tag': '366', 'required': '', 'paired': 'abcdefgjkm', 'key': 'abcdefgjkm'},
|
|
125
|
+
{'tag': '370', 'required': '', 'paired': 'cfgistuv', 'key': 'cfgistuv'},
|
|
126
|
+
{'tag': '377', 'required': '', 'paired': 'al', 'key': 'al'},
|
|
127
|
+
{'tag': '380', 'required': 'a', 'key': 'a'},
|
|
128
|
+
{'tag': '381', 'required': 'auv', 'key': 'auv'},
|
|
129
|
+
{'tag': '382', 'required': ''},
|
|
130
|
+
{'tag': '383', 'required': 'abcde', 'key': 'abcde'},
|
|
131
|
+
{'tag': '384', 'required': 'a', 'key': 'a'},
|
|
132
|
+
{'tag': '385', 'required': 'a', 'paired': 'abmn', 'key': 'abmn'},
|
|
133
|
+
{'tag': '386', 'required': 'a', 'paired': 'abmn', 'key': 'abmn'},
|
|
134
|
+
{'tag': '388', 'required': 'a', 'key': 'a'},
|
|
135
|
+
{'tag': '490', 'required': 'a', 'key': 'axvl'},
|
|
136
|
+
{'tag': '500', 'required': 'a', 'key': 'a'},
|
|
137
|
+
{'tag': '501', 'required': 'a', 'key': 'a'},
|
|
138
|
+
{'tag': '502', 'required': 'a', 'key': 'abcdgo'},
|
|
139
|
+
{'tag': '504', 'required': 'a', 'paired': 'ab', 'key': 'ab'},
|
|
140
|
+
{'tag': '505', 'required': '', 'paired': 'agrtu', 'key': 'agrtu'},
|
|
141
|
+
{'tag': '506', 'required': 'a', 'paired': '', 'key': 'abcdefgqu'},
|
|
142
|
+
{'tag': '507', 'required': 'a', 'paired': 'ab', 'key': 'ab'},
|
|
143
|
+
{'tag': '508', 'required': 'a', 'key': 'a'},
|
|
144
|
+
{'tag': '509', 'required': 'a', 'key': 'acd'},
|
|
145
|
+
{'tag': '510', 'required': 'a', 'key': 'abcx'},
|
|
146
|
+
{'tag': '511', 'required': 'a', 'key': 'a'},
|
|
147
|
+
{'tag': '513', 'required': '', 'paired': 'ab', 'key': 'ab'},
|
|
148
|
+
{'tag': '514', 'required': '', 'paired': 'abcdefghijkmuz', 'key': 'abcdefghijkmuz'},
|
|
149
|
+
{'tag': '515', 'required': 'a', 'key': 'a'},
|
|
150
|
+
{'tag': '518', 'required': '', 'paired': 'adop', 'key': 'adop'},
|
|
151
|
+
{'tag': '520', 'required': 'a', 'paired': 'abc', 'key': 'abc'},
|
|
152
|
+
{'tag': '521', 'required': 'a', 'paired': 'ab', 'key': 'ab'},
|
|
153
|
+
{'tag': '522', 'required': 'a', 'key': 'a'},
|
|
154
|
+
{'tag': '524', 'required': 'a', 'key': 'a'},
|
|
155
|
+
{'tag': '525', 'required': 'a', 'key': 'a'},
|
|
156
|
+
{'tag': '526', 'required': 'a', 'paired': 'abcdi', 'key': 'abcdi'},
|
|
157
|
+
{'tag': '530', 'required': 'a', 'paired': 'abcd', 'key': 'abcd'},
|
|
158
|
+
{'tag': '532', 'required': 'a', 'key': 'a'},
|
|
159
|
+
{'tag': '533', 'required': 'a', 'paired': 'abcdefmn7', 'key': 'abcdefmn7'},
|
|
160
|
+
{'tag': '534', 'required': '', 'paired': 'abcempt', 'key': 'abcempt'},
|
|
161
|
+
{'tag': '535', 'required': '', 'paired': 'abcdg', 'key': 'abcdg'},
|
|
162
|
+
{'tag': '536', 'required': '', 'paired': 'abcdefgh', 'key': 'abcdefgh'},
|
|
163
|
+
{'tag': '538', 'required': 'a', 'paired': 'aiu', 'key': 'aiu'},
|
|
164
|
+
{'tag': '540', 'required': '', 'paired': 'abcdfgqu', 'key': 'abcdfgqu'},
|
|
165
|
+
{'tag': '541', 'required': '', 'paired': 'abcdefhno', 'key': 'abcdefhno'},
|
|
166
|
+
{'tag': '542', 'required': '', 'paired': 'abcdfghijklmopqrsu', 'key': 'abcdfghijklmopqrsu'},
|
|
167
|
+
{'tag': '544', 'required': '', 'paired': 'abcden', 'key': 'abcden'},
|
|
168
|
+
{'tag': '545', 'required': '', 'paired': 'abu', 'key': 'abu'},
|
|
169
|
+
{'tag': '546', 'required': '', 'paired': 'ab', 'key': 'ab'},
|
|
170
|
+
{'tag': '547', 'required': 'a', 'key': 'a'},
|
|
171
|
+
{'tag': '550', 'required': 'a', 'key': 'a'},
|
|
172
|
+
{'tag': '552', 'required': '', 'paired': 'abcdefghijklmnopuz', 'key': 'abcdefghijklmnopuz'},
|
|
173
|
+
{'tag': '555', 'required': 'a', 'paired': 'abcdu', 'key': 'abcdu'},
|
|
174
|
+
{'tag': '556', 'required': 'a', 'key': 'az'},
|
|
175
|
+
{'tag': '561', 'required': 'a', 'key': 'au'},
|
|
176
|
+
{'tag': '562', 'required': '', 'paired': 'abcde', 'key': 'abcde'},
|
|
177
|
+
{'tag': '563', 'required': 'a', 'key': 'au'},
|
|
178
|
+
{'tag': '565', 'required': '', 'paired': 'abc', 'key': 'abc'},
|
|
179
|
+
{'tag': '567', 'required': '', 'paired': 'ab', 'key': 'ab'},
|
|
180
|
+
{'tag': '580', 'required': 'a', 'key': 'a'},
|
|
181
|
+
{'tag': '581', 'required': 'a', 'key': 'a'},
|
|
182
|
+
{'tag': '583', 'required': '', 'paired': 'abcdefhijklnou', 'key': 'abcdefhijklnou'},
|
|
183
|
+
{'tag': '584', 'required': '', 'paired': 'ab', 'key': 'ab'},
|
|
184
|
+
{'tag': '585', 'required': 'a', 'key': 'a'},
|
|
185
|
+
{'tag': '586', 'required': 'a', 'key': 'a'},
|
|
186
|
+
{'tag': '588', 'required': 'a', 'key': 'a'},
|
|
187
|
+
{'tag': '590', 'required': ''},
|
|
188
|
+
{'tag': '591', 'required': ''},
|
|
189
|
+
{'tag': '592', 'required': ''},
|
|
190
|
+
{'tag': '593', 'required': ''},
|
|
191
|
+
{'tag': '594', 'required': ''},
|
|
192
|
+
{'tag': '595', 'required': ''},
|
|
193
|
+
{'tag': '596', 'required': ''},
|
|
194
|
+
{'tag': '597', 'required': ''},
|
|
195
|
+
{'tag': '598', 'required': ''},
|
|
196
|
+
{'tag': '599', 'required': ''},
|
|
197
|
+
{'tag': '600', 'required': 'a', 'paired': 'tvxyz', 'key': keyX00},
|
|
198
|
+
{'tag': '610', 'required': 'a', 'paired': 'btvxyz', 'key': keyX10},
|
|
199
|
+
{'tag': '611', 'required': 'a', 'paired': 'tvxyz', 'key': keyX11},
|
|
200
|
+
{'tag': '630', 'required': 'a', 'paired': 'atvxyz', 'key': keyX30},
|
|
201
|
+
// NB! 700, 710 and 711 may have title parts that are handled elsewhere
|
|
202
|
+
{'tag': '647', 'required': 'a', 'paired': 'avxyz', 'key': 'acdgvxyz02'},
|
|
203
|
+
{'tag': '648', 'required': 'a', 'paired': 'avxyz', 'key': 'avxyz02'},
|
|
204
|
+
{'tag': '650', 'required': 'a', 'paired': 'abcdegvxyz', 'key': 'abcdegvxyz20'},
|
|
205
|
+
{'tag': '651', 'required': 'a', 'paired': 'aegvxyz', 'key': 'aegvxyz20'},
|
|
206
|
+
{'tag': '653', 'required': 'a', 'paired': 'a', 'key': 'a'}, // this is interesting as a can be repeated
|
|
207
|
+
{'tag': '654', 'required': '', 'paired': 'abcevxyz'},
|
|
208
|
+
{'tag': '655', 'required': 'a', 'paired': 'abcvxyz', 'key': 'avxyz20'},
|
|
209
|
+
{'tag': '656', 'required': 'a', 'paired': 'akvxyz'}, // N=0
|
|
210
|
+
{'tag': '657', 'required': 'a', 'paired': 'avxyz'}, // N=0
|
|
211
|
+
{'tag': '658', 'required': 'a', 'paired': 'abcd'}, // N=0
|
|
212
|
+
{'tag': '662', 'required': '', 'paired': 'abcdefgh'}, // N=0
|
|
213
|
+
{'tag': '688', 'required': 'a'}, // N=0
|
|
214
|
+
{'tag': '700', 'required': 'a', 'paired': 't', 'key': keyX00}, // h/i/m/o/r/s/x are missing from 100
|
|
215
|
+
{'tag': '710', 'required': 'a', 'paired': 'bt', 'key': keyX10}, // h/j/m/o/r/s/x are missing from 110
|
|
216
|
+
{'tag': '711', 'required': 'a', 'paired': 'cdeflns', 'key': keyX11}, // h/i/s/x are missing from 711
|
|
217
|
+
{'tag': '720', 'required': 'a', 'key': 'a'},
|
|
218
|
+
// NB! 730 has no name part, key is used for title part
|
|
219
|
+
{'tag': '730', 'required': 'a', 'key': keyX30}, // NB: 130->730 magic subfields might not agree...
|
|
220
|
+
{'tag': '740', 'required': 'a', 'key': 'ahnp'},
|
|
221
|
+
{'tag': '751', 'required': 'a', 'key': 'a'}, // N=11, kaikissa pelkkä $a
|
|
222
|
+
{'tag': '752', 'required': '', 'key': 'abcdefgh'}, // N=12234
|
|
223
|
+
{'tag': '753', 'required': '', 'key': 'abc'},
|
|
224
|
+
{'tag': '754', 'required': '', 'key': 'acdxz'}, // N=3
|
|
225
|
+
{'tag': '758', 'required': 'a', 'key': 'ai'}, // N=1
|
|
226
|
+
|
|
227
|
+
{'tag': '760', 'required': 'tw', key: 'twxy'},
|
|
228
|
+
{'tag': '762', 'required': 't', key: 'abcdhmstxy'},
|
|
229
|
+
{'tag': '765', 'required': 't', key: 'abcdhmrstuwxyz'},
|
|
230
|
+
{'tag': '767', 'required': 't', key: 'abcdhmrstuwxyz'},
|
|
231
|
+
{'tag': '770', 'required': 't', 'paired': 'ruxyz', key: 'abcdhmrstuwxyz'},
|
|
232
|
+
{'tag': '772', 'required': 't', key: 'abcdhmrstuwxyz'},
|
|
233
|
+
{'tag': '773', 'required': 'w', key: 'wgq'}, // Kirjavälitys should not have any component parts. However, this need to be re-thought...
|
|
234
|
+
// Currently we (appently) drop fields that don't contain 773$w...
|
|
235
|
+
{'tag': '774', 'required': '', 'paired': 'nruxyz', 'key': 'npqrstrxyz'},
|
|
236
|
+
{'tag': '775', 'required': '', 'paired': 'ruxyz', 'key': 'abcdefhmstuxyz'},
|
|
237
|
+
{'tag': '776', 'required': '', 'paired': 'ruxyz', 'key': 'abcdhmsuwxyz'},
|
|
238
|
+
{'tag': '777', 'required': '', 'paired': 'ruxyz', 'key': 'abcdhmstuxyz'},
|
|
239
|
+
{'tag': '780', 'required': '', 'paired': 'ruxyz', 'key': 'abcdhmstuxyz'},
|
|
240
|
+
{'tag': '785', 'required': '', 'paired': 'uxyz', 'key': 'abcdhmstuxyz'},
|
|
241
|
+
{'tag': '786', 'required': '', 'paired': 'abcrstuxyz', 'key': 'abcdhijmprstuxyz4'},
|
|
242
|
+
{'tag': '787', 'required': '', 'paired': 'abcdhmstuxyz4'},
|
|
243
|
+
{'tag': '788', 'required': '', 'paired': 'stx', 'key': 'abdestx'},
|
|
244
|
+
{'tag': '800', 'required': 'a', 'paired': 't', 'key': keyX00},
|
|
245
|
+
{'tag': '810', 'required': 'a', 'paired': 'bt', 'key': keyX10},
|
|
246
|
+
{'tag': '811', 'required': 'a', 'paired': 't', 'key': keyX11},
|
|
247
|
+
{'tag': '830', 'required': 'a', 'key': keyX30},
|
|
248
|
+
{'tag': '840', 'required': 'a'},
|
|
249
|
+
{'tag': '841', 'required': 'a'},
|
|
250
|
+
{'tag': '842', 'required': 'a'},
|
|
251
|
+
{'tag': '843', 'required': 'a'},
|
|
252
|
+
{'tag': '844', 'required': 'a'},
|
|
253
|
+
{'tag': '845', 'required': 'a'},
|
|
254
|
+
{'tag': '850', 'required': 'a', 'key': 'a'},
|
|
255
|
+
{'tag': '852', 'required': 'a'}, // HMM... we might want to reconsider this...
|
|
256
|
+
{'tag': '853', 'required': 'a'},
|
|
257
|
+
{'tag': '854', 'required': 'a'},
|
|
258
|
+
{'tag': '855', 'required': 'a'},
|
|
259
|
+
{'tag': '856', 'required': 'u', 'paired': 'u', 'key': 'opuw23'}, // 856 is built around $u...
|
|
260
|
+
{'tag': '863', 'required': 'a'},
|
|
261
|
+
{'tag': '864', 'required': 'a'},
|
|
262
|
+
{'tag': '865', 'required': 'a'},
|
|
263
|
+
{'tag': '866', 'required': 'a'},
|
|
264
|
+
{'tag': '867', 'required': 'a'},
|
|
265
|
+
{'tag': '868', 'required': 'a'},
|
|
266
|
+
{'tag': '876', 'required': 'a'},
|
|
267
|
+
{'tag': '877', 'required': 'a'},
|
|
268
|
+
{'tag': '878', 'required': 'a'},
|
|
269
|
+
{'tag': '880', 'required': '', 'paired': 'a', 'key': 'abcdefghijklmnopqrstuvwxyz'},
|
|
270
|
+
{'tag': '881', 'required': ''},
|
|
271
|
+
{'tag': '882', 'required': ''},
|
|
272
|
+
{'tag': '883', 'required': ''},
|
|
273
|
+
{'tag': '884', 'required': '', 'paired': 'agkq'},
|
|
274
|
+
{'tag': '885', 'required': ''},
|
|
275
|
+
{'tag': '886', 'required': ''},
|
|
276
|
+
{'tag': '887', 'required': ''},
|
|
277
|
+
{'tag': '900', 'required': ''},
|
|
278
|
+
{'tag': '901', 'required': ''},
|
|
279
|
+
{'tag': '910', 'required': ''},
|
|
280
|
+
{'tag': '935', 'required': 'a', 'key': 'az'}, // Fono information at least
|
|
281
|
+
{'tag': '940', 'required': ''},
|
|
282
|
+
{'tag': '946', 'required': 'a', 'key': 'abfnp'}, // Copied from 246. However, final version might contain some elements from field 245 as well
|
|
283
|
+
{'tag': '960', 'required': ''},
|
|
284
|
+
{'tag': '973', 'required': 'w', 'key': 'w'}, // Viola multi-hosts
|
|
285
|
+
{'tag': '995', 'required': ''},
|
|
286
|
+
{'tag': 'CAT', 'required': ''},
|
|
287
|
+
{'tag': 'LOW', 'required': ''},
|
|
288
|
+
{'tag': 'SID', 'required': ''}
|
|
289
|
+
];
|
|
290
|
+
|
|
291
|
+
function constraintToValue(tagsConstraints, constraintName) {
|
|
292
|
+
if (constraintName in tagsConstraints) {
|
|
293
|
+
return tagsConstraints[constraintName];
|
|
294
|
+
}
|
|
295
|
+
return null; // NB! "" might mean "apply to everything" (eg. 040.key) while null means that it is not applied.
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export function getMergeConstraintsForTag(tag, constraintName) {
|
|
299
|
+
const tagsConstraintsArray = mergeConstraints.filter(entry => tag === entry.tag);
|
|
300
|
+
if (tagsConstraintsArray.length === 0) {
|
|
301
|
+
debugDev(`WARNING\tNo key found for ${tag}. Returning NULL!`);
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
// NB! should we support multiple contains for a field? Eg. 505$a vs 505($tg)+
|
|
305
|
+
if (tagsConstraintsArray.length > 1) { // eslint-disable-line functional/no-conditional-statements
|
|
306
|
+
debugDev(`WARNING\tMultiple values for '${constraintName}' (N=${tagsConstraintsArray.length}) found in ${tag}. Using first values.`);
|
|
307
|
+
}
|
|
308
|
+
return constraintToValue(tagsConstraintsArray[0], constraintName);
|
|
309
|
+
}
|