@natlibfi/marc-record-validators-melinda 10.2.2 → 10.2.3
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/removeDuplicateDataFields.js +40 -6
- package/dist/removeDuplicateDataFields.js.map +1 -1
- package/dist/subfield6Utils.js +9 -1
- package/dist/subfield6Utils.js.map +1 -1
- package/package.json +1 -1
- package/src/removeDuplicateDataFields.js +44 -7
- package/src/subfield6Utils.js +11 -1
- package/test-fixtures/remove-duplicate-datafields/f09/expectedResult.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f09/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f09/record.json +9 -0
- package/test-fixtures/remove-duplicate-datafields/f10/expectedResult.json +15 -0
- package/test-fixtures/remove-duplicate-datafields/f10/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f10/record.json +24 -0
- package/test-fixtures/remove-duplicate-datafields/v02/expectedResult.json +2 -1
- package/test-fixtures/remove-duplicate-datafields/v03/expectedResult.json +1 -1
|
@@ -162,11 +162,14 @@ function removeIndividualDuplicateDatafields(record, fix = true) {
|
|
|
162
162
|
(0, _utils.nvdebug)(`DUPLICATE SINGLETON DETECTED: ${fieldAsString}`);
|
|
163
163
|
return true;
|
|
164
164
|
}
|
|
165
|
+
if (is7XX(field.tag) && convert7XXto1XX(fieldAsString) in seen) {
|
|
166
|
+
(0, _utils.nvdebug)(`DUPLICATE (1XX-7XX) SINGLETON DETECTED: ${fieldAsString}`);
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
165
169
|
(0, _utils.nvdebug)(`MARK SINGLETON AS SEEN: ${fieldAsString}`, debug);
|
|
166
170
|
seen[fieldAsString] = 1;
|
|
167
171
|
return;
|
|
168
172
|
}
|
|
169
|
-
|
|
170
173
|
/* eslint-enable */
|
|
171
174
|
}
|
|
172
175
|
|
|
@@ -179,7 +182,27 @@ function recordRemoveFieldOrSubfield8(record, field, currLinkingNumber) {
|
|
|
179
182
|
const subfields = field.subfields.filter(sf => (0, _subfield8Utils.getSubfield8LinkingNumber)(sf) === currLinkingNumber);
|
|
180
183
|
subfields.forEach(sf => record.removeSubfield(sf, field));
|
|
181
184
|
}
|
|
185
|
+
function is7XX(tag) {
|
|
186
|
+
return ['700', '710', '711', '730'].includes(tag);
|
|
187
|
+
}
|
|
188
|
+
function convert7XXto1XX(fieldString) {
|
|
189
|
+
/* eslint-disable prefer-named-capture-group, no-param-reassign */
|
|
190
|
+
fieldString = fieldString.replace(/^7(00|10|11|30)/u, '1$1');
|
|
191
|
+
fieldString = fieldString.replace(/‡6 [17](00|10|11|30)/gu, '‡6 X$1');
|
|
192
|
+
|
|
193
|
+
/* eslint-enable */
|
|
194
|
+
|
|
195
|
+
return fieldString;
|
|
196
|
+
}
|
|
182
197
|
function removeDuplicateSubfield8Chains(record, fix = true) {
|
|
198
|
+
// Seen $8 subsfields in various fields:
|
|
199
|
+
// 161 700
|
|
200
|
+
// 17 710
|
|
201
|
+
// 11 110
|
|
202
|
+
// 8 730
|
|
203
|
+
// 1 100
|
|
204
|
+
// Given these stats, there's no need to check for 1XX-vs-7XX removals
|
|
205
|
+
|
|
183
206
|
/* eslint-disable */
|
|
184
207
|
let seen = {};
|
|
185
208
|
let removables = []; // for validation
|
|
@@ -231,22 +254,33 @@ function removeDuplicateSubfield6Chains(record, fix = true) {
|
|
|
231
254
|
return;
|
|
232
255
|
}
|
|
233
256
|
const fieldsAsString = (0, _subfield6Utils.fieldsToNormalizedString)(fields);
|
|
257
|
+
// Frequencly list for $6 subfields in 1XX/7XX fields:
|
|
258
|
+
// 231115 100
|
|
259
|
+
// 183832 700
|
|
260
|
+
// 28773 710
|
|
261
|
+
// 2047 711
|
|
262
|
+
// 661 110
|
|
263
|
+
// 341 111
|
|
264
|
+
// 284 130
|
|
265
|
+
// 63 730
|
|
266
|
+
// Thus there's a real risk of ending up with, say, identical 100 vs 700 chains.
|
|
267
|
+
// Semi-hackily support 1XX/7XX-version: 7XX can be deleted if corresponding 1XX exists:
|
|
268
|
+
const altFieldsAsString = fieldsAsString.substring(0, 1) === '7' ? `1${fieldsAsString.substring(1)}` : fieldsAsString;
|
|
234
269
|
(0, _utils.nvdebug)(` step 2 ${fieldsAsString}`);
|
|
235
|
-
if (fieldsAsString in seen) {
|
|
270
|
+
if (fieldsAsString in seen || altFieldsAsString in seen) {
|
|
236
271
|
(0, _utils.nvdebug)(` step 3 ${fieldsAsString}`);
|
|
237
272
|
removables.push(fieldsAsString);
|
|
238
273
|
if (fix) {
|
|
239
|
-
(0, _utils.nvdebug)(
|
|
274
|
+
(0, _utils.nvdebug)(`$6 DOUBLE REMOVAL: REMOVE ${fieldsAsString}`, debug);
|
|
240
275
|
fields.forEach(currField => record.removeField(currField));
|
|
241
276
|
return;
|
|
242
277
|
}
|
|
243
|
-
(0, _utils.nvdebug)(
|
|
278
|
+
(0, _utils.nvdebug)(`$6 VALIDATION: DUPLICATE DETECTED ${fieldsAsString}`, debug);
|
|
244
279
|
}
|
|
245
|
-
(0, _utils.nvdebug)(
|
|
280
|
+
(0, _utils.nvdebug)(`$6 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${fieldsAsString}`, debug);
|
|
246
281
|
seen[fieldsAsString] = 1;
|
|
247
282
|
return;
|
|
248
283
|
}
|
|
249
|
-
|
|
250
284
|
/* eslint-enable */
|
|
251
285
|
return removables;
|
|
252
286
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"removeDuplicateDataFields.js","names":["debug","createDebugLogger","description","validate","fix","record","nvdebug","res","message","valid","removeDuplicateDatafields","duplicates","length","add6s","field","sixes","subfields","filter","sf","isValidSubfield6","occurrenceNumbers","map","subfield6GetOccurrenceNumber","value","undefined","join","relevantFields","fields","f","some","o","fieldHasOccurrenceNumber","forEach","fieldToString","add8s","fieldHasSubfield","numberOfLinkageSubfields","code","getAllLinkedSubfield6Fields","moreFields","getFirstField","fieldsAsStrings","i","findIndex","includes","isFirstLinkedSubfield6Field","chain","firstField","removeIndividualDuplicateDatafields","seen","removableFields","removableIndividualDuplicateDatafield","removableFieldsAsStrings","removeField","fieldAsString","recordRemoveFieldOrSubfield8","currLinkingNumber","eights","getSubfield8LinkingNumber","removeSubfield","removeDuplicateSubfield8Chains","removables","seenLinkingNumbers","recordGetAllSubfield8LinkingNumbers","linkedFields","recordGetFieldsWithSubfield8LinkingNumber","linkedFieldsAsString","fieldsToNormalizedString","push","fieldsToString","removeDuplicateSubfield6Chains","removeDuplicateDatafield","fieldsAsString","currField","removables8","removables6","removablesAll","concat"],"sources":["../src/removeDuplicateDataFields.js"],"sourcesContent":["import createDebugLogger from 'debug';\nimport {fieldHasSubfield, fieldsToString, fieldToString, nvdebug} from './utils';\nimport {fieldHasOccurrenceNumber, fieldsToNormalizedString, isValidSubfield6, subfield6GetOccurrenceNumber} from './subfield6Utils';\nimport {getSubfield8LinkingNumber, recordGetAllSubfield8LinkingNumbers, recordGetFieldsWithSubfield8LinkingNumber} from './subfield8Utils';\n\n// Relocated from melinda-marc-record-merge-reducers (and renamed)\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:removeDuplicateDataFields');\n\nexport default function () {\n return {\n description: 'Remove duplicate data fields. Certain exceptions apply, mainly too complited chained fields',\n validate, fix\n };\n\n function fix(record) {\n nvdebug('Remove duplicate data fields');\n const res = {message: [], fix: [], valid: true};\n removeDuplicateDatafields(record, true);\n // This can not really fail...\n return res;\n }\n\n function validate(record) {\n // Check max, and check number of different indexes\n nvdebug('Validate record: duplicate data fields cause (t)error', debug);\n\n const duplicates = removeDuplicateDatafields(record, false);\n\n //const orphanedFields = getOrphanedFields(fieldsContainingSubfield6);\n\n const res = {message: duplicates};\n\n /*\n if (orphanedFields.length > 0) { // eslint-disable-line functional/no-conditional-statement\n res.message = [`${orphanedFields.length} orphaned occurrence number field(s) detected`]; // eslint-disable-line functional/immutable-data\n }\n */\n res.valid = res.message.length < 1; // eslint-disable-line functional/immutable-data\n return res;\n }\n}\n\nfunction add6s(field, record) {\n\n /*\n // Can't rely on nice pairs...\n if (fieldHasSubfield(field, '6')) {\n\n const pairs = fieldGetOccurrenceNumberPairs(field, record.fields);\n if (pairs) {\n return [field].concat(pairs);\n }\n\n }\n */\n\n // Get all fields with given occurence number\n const sixes = field.subfields.filter(sf => isValidSubfield6(sf));\n\n if (sixes.length === 0) {\n return [field];\n }\n nvdebug(`SIXES: ${sixes.length}`);\n const occurrenceNumbers = sixes.map(sf => subfield6GetOccurrenceNumber(sf)).filter(value => value !== undefined && value !== '00');\n nvdebug(occurrenceNumbers.join(' -- '));\n\n const relevantFields = record.fields.filter(f => occurrenceNumbers.some(o => fieldHasOccurrenceNumber(f, o)));\n nvdebug(`RELFIELDS FOUND: ${relevantFields.length}...`);\n relevantFields.forEach(f => nvdebug(fieldToString(f)));\n return relevantFields;\n}\n\nfunction add8s(fields, record) {\n // Not implemented yet:\n if (fields && fields.some(f => fieldHasSubfield(f, '8'))) {\n return [];\n }\n return record ? fields : fields;\n}\n\nfunction numberOfLinkageSubfields(field) {\n const subfields = field.subfields.filter(sf => sf.code === '6' || sf.code === '8');\n return subfields.length;\n}\n\n\nfunction getAllLinkedSubfield6Fields(field, record) {\n const fields = add6s(field, record);\n const moreFields = add8s(fields, record);\n\n // Currently we don't handle fields with more than one $6 and/or $8 subfield.\n if (moreFields.length === 0 || moreFields.some(f => numberOfLinkageSubfields(f) > 1)) {\n return []; // Don't fix!\n }\n return moreFields;\n}\n\nfunction getFirstField(record, fields) {\n const fieldsAsStrings = fields.map(field => fieldToString(field));\n record.fields.forEach((field, i) => nvdebug(`${i}:\\t${fieldToString(field)}`));\n nvdebug(`INCOMING: ${fieldsAsStrings.join('\\t')}`);\n const i = record.fields.findIndex(field => fieldsAsStrings.includes(fieldToString(field)));\n if (i > -1) {\n const field = record.fields[i];\n nvdebug(`1st F: ${i + 1}/${record.fields.length} ${fieldToString(field)}`);\n return field;\n }\n return undefined;\n}\n\n\nfunction isFirstLinkedSubfield6Field(field, record) {\n if (!field.subfields) { // Is not a datafield\n return false;\n }\n const chain = getAllLinkedSubfield6Fields(field, record);\n if (chain.length < 2) {\n return false;\n }\n\n // Interpretation of first: position of field in record (however, we might have a duplicate field. See tests...)\n const firstField = getFirstField(record, chain);\n if (firstField) {\n return fieldToString(field) === fieldToString(firstField);\n }\n return false;\n\n // Fallback:\n //return fieldToString(field) === fieldToString(chain[0]);\n}\n\nexport function removeIndividualDuplicateDatafields(record, fix = true) { // No $6 nor $8 in field\n /* eslint-disable */\n let seen = {};\n\n record.fields.forEach(field => nvdebug(`DUPL-1 CHECK SINGLE ${fieldToString(field)}, mode=${fix ? 'FIX' : 'VALIDATE'}`));\n \n const removableFields = record.fields.filter(field => removableIndividualDuplicateDatafield(field));\n const removableFieldsAsStrings = removableFields.map(field => fieldToString(field));\n\n if (fix) {\n removableFields.forEach(field => record.removeField(field));\n }\n\n return removableFieldsAsStrings;\n\n function removableIndividualDuplicateDatafield(field) {\n if (!field.subfields) { // Not a datafield\n //nvdebug(`SKIP subfieldless ${fieldToString(field)}`);\n return false;\n }\n // There's actually no reason to check whether individual fields contain a $6 or an $8...\n // If everything incl. occurence/xxxx numbers match it's still deletable, regardless of chains.\n\n //nvdebug(`removeIndividualDuplicateDatafield? ${fieldToString(field)}`);\n\n // We are in trouble if $9 ^ and $9 ^^ style chains appear here...\n const fieldAsString = fieldToString(field); // Never normalize!\n\n //nvdebug(` step 2 ${fieldAsString}`);\n if (fieldAsString in seen) {\n nvdebug(`DUPLICATE SINGLETON DETECTED: ${fieldAsString}`);\n return true;\n }\n nvdebug(`MARK SINGLETON AS SEEN: ${fieldAsString}`, debug);\n seen[fieldAsString] = 1;\n return;\n }\n\n /* eslint-enable */\n\n}\n\n\nfunction recordRemoveFieldOrSubfield8(record, field, currLinkingNumber) {\n const eights = field.subfields.filter(sf => sf.code === '8');\n if (eights.length < 2) {\n record.removeField(field);\n return;\n }\n const subfields = field.subfields.filter(sf => getSubfield8LinkingNumber(sf) === currLinkingNumber);\n subfields.forEach(sf => record.removeSubfield(sf, field));\n}\n\n\nexport function removeDuplicateSubfield8Chains(record, fix = true) {\n /* eslint-disable */\n let seen = {};\n\n let removables = []; // for validation\n\n nvdebug(\"CHAIN-8\");\n const seenLinkingNumbers = recordGetAllSubfield8LinkingNumbers(record);\n if (seenLinkingNumbers.length === 0) {\n return removables;\n }\n\n nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(', ')}`, debug);\n\n seenLinkingNumbers.forEach(currLinkingNumber => {\n const linkedFields = recordGetFieldsWithSubfield8LinkingNumber(record, currLinkingNumber) //getFieldsWithSubfield8Index(base, baseIndex);\n const linkedFieldsAsString = fieldsToNormalizedString(linkedFields, currLinkingNumber);\n nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debug);\n nvdebug(`${linkedFieldsAsString}`, debug);\n\n if (linkedFieldsAsString in seen) {\n if (!removables.includes(linkedFieldsAsString)) {\n removables.push(linkedFieldsAsString);\n }\n\n if (fix) {\n nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debug);\n linkedFields.forEach(field => recordRemoveFieldOrSubfield8(record, field, currLinkingNumber));\n return;\n }\n\n nvdebug(`$8 VALIDATION: DUPLICATE DETECTED ${linkedFieldsAsString}`, debug);\n return;\n }\n nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debug);\n seen[linkedFieldsAsString] = 1;\n return;\n });\n\n /* eslint-enable */\n return removables;\n}\n\nexport function removeDuplicateSubfield6Chains(record, fix = true) {\n /* eslint-disable */\n let seen = {};\n\n let removables = []; // for validation\n\n record.fields.forEach(field => nvdebug(`DUPL-CHECK $CHAIN ${fieldToString(field)}, mode=${fix ? 'FIX' : 'VALIDATE'}`));\n \n const fields = record.fields.filter(field => isFirstLinkedSubfield6Field(field, record)); // Well a\n \n fields.forEach(field => removeDuplicateDatafield(field));\n\n function removeDuplicateDatafield(field) {\n nvdebug(`removeDuplicateDatafield? $6 ${fieldToString(field)} (and friends)`);\n const fields = getAllLinkedSubfield6Fields(field, record);\n if(fields.length === 0) {\n return;\n }\n\n const fieldsAsString = fieldsToNormalizedString(fields);\n nvdebug(` step 2 ${fieldsAsString}`);\n if (fieldsAsString in seen) {\n nvdebug(` step 3 ${fieldsAsString}`);\n\n removables.push(fieldsAsString);\n\n if (fix) {\n nvdebug(`DOUBLE REMOVAL: REMOVE ${fieldsAsString}`, debug);\n fields.forEach(currField => record.removeField(currField));\n return;\n }\n nvdebug(`VALIDATION: DUPLICATE DETECTED ${fieldsAsString}`, debug);\n \n }\n nvdebug(`DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${fieldsAsString}`, debug);\n seen[fieldsAsString] = 1;\n return;\n }\n\n\n /* eslint-enable */\n return removables;\n}\n\nexport function removeDuplicateDatafields(record, fix = true) {\n const removables = removeIndividualDuplicateDatafields(record, fix); // Lone fields\n const removables8 = removeDuplicateSubfield8Chains(record, fix); // Lone subfield $8 chains\n const removables6 = removeDuplicateSubfield6Chains(record, fix); // Lone subfield $6 chains\n // HOW TO HANDLE $6+$8 combos?\n\n const removablesAll = removables.concat(removables8).concat(removables6);\n\n return removablesAll;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"removeDuplicateDataFields.js","names":["debug","createDebugLogger","description","validate","fix","record","nvdebug","res","message","valid","removeDuplicateDatafields","duplicates","length","add6s","field","sixes","subfields","filter","sf","isValidSubfield6","occurrenceNumbers","map","subfield6GetOccurrenceNumber","value","undefined","join","relevantFields","fields","f","some","o","fieldHasOccurrenceNumber","forEach","fieldToString","add8s","fieldHasSubfield","numberOfLinkageSubfields","code","getAllLinkedSubfield6Fields","moreFields","getFirstField","fieldsAsStrings","i","findIndex","includes","isFirstLinkedSubfield6Field","chain","firstField","removeIndividualDuplicateDatafields","seen","removableFields","removableIndividualDuplicateDatafield","removableFieldsAsStrings","removeField","fieldAsString","is7XX","tag","convert7XXto1XX","recordRemoveFieldOrSubfield8","currLinkingNumber","eights","getSubfield8LinkingNumber","removeSubfield","fieldString","replace","removeDuplicateSubfield8Chains","removables","seenLinkingNumbers","recordGetAllSubfield8LinkingNumbers","linkedFields","recordGetFieldsWithSubfield8LinkingNumber","linkedFieldsAsString","fieldsToNormalizedString","push","fieldsToString","removeDuplicateSubfield6Chains","removeDuplicateDatafield","fieldsAsString","altFieldsAsString","substring","currField","removables8","removables6","removablesAll","concat"],"sources":["../src/removeDuplicateDataFields.js"],"sourcesContent":["import createDebugLogger from 'debug';\nimport {fieldHasSubfield, fieldsToString, fieldToString, nvdebug} from './utils';\nimport {fieldHasOccurrenceNumber, fieldsToNormalizedString, isValidSubfield6, subfield6GetOccurrenceNumber} from './subfield6Utils';\nimport {getSubfield8LinkingNumber, recordGetAllSubfield8LinkingNumbers, recordGetFieldsWithSubfield8LinkingNumber} from './subfield8Utils';\n\n// Relocated from melinda-marc-record-merge-reducers (and renamed)\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:removeDuplicateDataFields');\n\nexport default function () {\n return {\n description: 'Remove duplicate data fields. Certain exceptions apply, mainly too complited chained fields',\n validate, fix\n };\n\n function fix(record) {\n nvdebug('Remove duplicate data fields');\n const res = {message: [], fix: [], valid: true};\n removeDuplicateDatafields(record, true);\n // This can not really fail...\n return res;\n }\n\n function validate(record) {\n // Check max, and check number of different indexes\n nvdebug('Validate record: duplicate data fields cause (t)error', debug);\n\n const duplicates = removeDuplicateDatafields(record, false);\n\n //const orphanedFields = getOrphanedFields(fieldsContainingSubfield6);\n\n const res = {message: duplicates};\n\n /*\n if (orphanedFields.length > 0) { // eslint-disable-line functional/no-conditional-statement\n res.message = [`${orphanedFields.length} orphaned occurrence number field(s) detected`]; // eslint-disable-line functional/immutable-data\n }\n */\n res.valid = res.message.length < 1; // eslint-disable-line functional/immutable-data\n return res;\n }\n}\n\nfunction add6s(field, record) {\n\n /*\n // Can't rely on nice pairs...\n if (fieldHasSubfield(field, '6')) {\n\n const pairs = fieldGetOccurrenceNumberPairs(field, record.fields);\n if (pairs) {\n return [field].concat(pairs);\n }\n\n }\n */\n\n // Get all fields with given occurence number\n const sixes = field.subfields.filter(sf => isValidSubfield6(sf));\n\n if (sixes.length === 0) {\n return [field];\n }\n nvdebug(`SIXES: ${sixes.length}`);\n const occurrenceNumbers = sixes.map(sf => subfield6GetOccurrenceNumber(sf)).filter(value => value !== undefined && value !== '00');\n nvdebug(occurrenceNumbers.join(' -- '));\n\n const relevantFields = record.fields.filter(f => occurrenceNumbers.some(o => fieldHasOccurrenceNumber(f, o)));\n nvdebug(`RELFIELDS FOUND: ${relevantFields.length}...`);\n relevantFields.forEach(f => nvdebug(fieldToString(f)));\n return relevantFields;\n}\n\nfunction add8s(fields, record) {\n // Not implemented yet:\n if (fields && fields.some(f => fieldHasSubfield(f, '8'))) {\n return [];\n }\n return record ? fields : fields;\n}\n\nfunction numberOfLinkageSubfields(field) {\n const subfields = field.subfields.filter(sf => sf.code === '6' || sf.code === '8');\n return subfields.length;\n}\n\n\nfunction getAllLinkedSubfield6Fields(field, record) {\n const fields = add6s(field, record);\n const moreFields = add8s(fields, record);\n\n // Currently we don't handle fields with more than one $6 and/or $8 subfield.\n if (moreFields.length === 0 || moreFields.some(f => numberOfLinkageSubfields(f) > 1)) {\n return []; // Don't fix!\n }\n return moreFields;\n}\n\nfunction getFirstField(record, fields) {\n const fieldsAsStrings = fields.map(field => fieldToString(field));\n record.fields.forEach((field, i) => nvdebug(`${i}:\\t${fieldToString(field)}`));\n nvdebug(`INCOMING: ${fieldsAsStrings.join('\\t')}`);\n const i = record.fields.findIndex(field => fieldsAsStrings.includes(fieldToString(field)));\n if (i > -1) {\n const field = record.fields[i];\n nvdebug(`1st F: ${i + 1}/${record.fields.length} ${fieldToString(field)}`);\n return field;\n }\n return undefined;\n}\n\n\nfunction isFirstLinkedSubfield6Field(field, record) {\n if (!field.subfields) { // Is not a datafield\n return false;\n }\n const chain = getAllLinkedSubfield6Fields(field, record);\n if (chain.length < 2) {\n return false;\n }\n\n // Interpretation of first: position of field in record (however, we might have a duplicate field. See tests...)\n const firstField = getFirstField(record, chain);\n if (firstField) {\n return fieldToString(field) === fieldToString(firstField);\n }\n return false;\n\n // Fallback:\n //return fieldToString(field) === fieldToString(chain[0]);\n}\n\nexport function removeIndividualDuplicateDatafields(record, fix = true) { // No $6 nor $8 in field\n /* eslint-disable */\n let seen = {};\n\n record.fields.forEach(field => nvdebug(`DUPL-1 CHECK SINGLE ${fieldToString(field)}, mode=${fix ? 'FIX' : 'VALIDATE'}`));\n \n const removableFields = record.fields.filter(field => removableIndividualDuplicateDatafield(field));\n const removableFieldsAsStrings = removableFields.map(field => fieldToString(field));\n\n if (fix) {\n removableFields.forEach(field => record.removeField(field));\n }\n\n return removableFieldsAsStrings;\n\n function removableIndividualDuplicateDatafield(field) {\n if (!field.subfields) { // Not a datafield\n //nvdebug(`SKIP subfieldless ${fieldToString(field)}`);\n return false;\n }\n // There's actually no reason to check whether individual fields contain a $6 or an $8...\n // If everything incl. occurence/xxxx numbers match it's still deletable, regardless of chains.\n\n //nvdebug(`removeIndividualDuplicateDatafield? ${fieldToString(field)}`);\n\n // We are in trouble if $9 ^ and $9 ^^ style chains appear here...\n const fieldAsString = fieldToString(field); // Never normalize!\n\n //nvdebug(` step 2 ${fieldAsString}`);\n if (fieldAsString in seen) {\n nvdebug(`DUPLICATE SINGLETON DETECTED: ${fieldAsString}`);\n return true;\n }\n if (is7XX(field.tag) && convert7XXto1XX(fieldAsString) in seen) {\n nvdebug(`DUPLICATE (1XX-7XX) SINGLETON DETECTED: ${fieldAsString}`);\n return true;\n }\n\n nvdebug(`MARK SINGLETON AS SEEN: ${fieldAsString}`, debug);\n seen[fieldAsString] = 1;\n return;\n }\n /* eslint-enable */\n\n}\n\n\nfunction recordRemoveFieldOrSubfield8(record, field, currLinkingNumber) {\n const eights = field.subfields.filter(sf => sf.code === '8');\n if (eights.length < 2) {\n record.removeField(field);\n return;\n }\n const subfields = field.subfields.filter(sf => getSubfield8LinkingNumber(sf) === currLinkingNumber);\n subfields.forEach(sf => record.removeSubfield(sf, field));\n}\n\nfunction is7XX(tag) {\n return ['700', '710', '711', '730'].includes(tag);\n}\n\nfunction convert7XXto1XX(fieldString) {\n /* eslint-disable prefer-named-capture-group, no-param-reassign */\n fieldString = fieldString.replace(/^7(00|10|11|30)/u, '1$1');\n fieldString = fieldString.replace(/‡6 [17](00|10|11|30)/gu, '‡6 X$1');\n\n /* eslint-enable */\n\n return fieldString;\n}\n\nexport function removeDuplicateSubfield8Chains(record, fix = true) {\n\n // Seen $8 subsfields in various fields:\n // 161 700\n // 17 710\n // 11 110\n // 8 730\n // 1 100\n // Given these stats, there's no need to check for 1XX-vs-7XX removals\n\n /* eslint-disable */\n let seen = {};\n\n let removables = []; // for validation\n\n nvdebug(\"CHAIN-8\");\n const seenLinkingNumbers = recordGetAllSubfield8LinkingNumbers(record);\n if (seenLinkingNumbers.length === 0) {\n return removables;\n }\n\n nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(', ')}`, debug);\n\n seenLinkingNumbers.forEach(currLinkingNumber => {\n const linkedFields = recordGetFieldsWithSubfield8LinkingNumber(record, currLinkingNumber) //getFieldsWithSubfield8Index(base, baseIndex);\n const linkedFieldsAsString = fieldsToNormalizedString(linkedFields, currLinkingNumber);\n nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debug);\n nvdebug(`${linkedFieldsAsString}`, debug);\n\n if (linkedFieldsAsString in seen) {\n if (!removables.includes(linkedFieldsAsString)) {\n removables.push(linkedFieldsAsString);\n }\n\n if (fix) {\n nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debug);\n linkedFields.forEach(field => recordRemoveFieldOrSubfield8(record, field, currLinkingNumber));\n return;\n }\n\n nvdebug(`$8 VALIDATION: DUPLICATE DETECTED ${linkedFieldsAsString}`, debug);\n return;\n }\n nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debug);\n seen[linkedFieldsAsString] = 1;\n return;\n });\n\n /* eslint-enable */\n return removables;\n}\n\nexport function removeDuplicateSubfield6Chains(record, fix = true) {\n /* eslint-disable */\n let seen = {};\n\n let removables = []; // for validation\n\n record.fields.forEach(field => nvdebug(`DUPL-CHECK $CHAIN ${fieldToString(field)}, mode=${fix ? 'FIX' : 'VALIDATE'}`));\n \n const fields = record.fields.filter(field => isFirstLinkedSubfield6Field(field, record)); // Well a\n \n fields.forEach(field => removeDuplicateDatafield(field));\n\n function removeDuplicateDatafield(field) {\n nvdebug(`removeDuplicateDatafield? $6 ${fieldToString(field)} (and friends)`);\n const fields = getAllLinkedSubfield6Fields(field, record);\n if(fields.length === 0) {\n return;\n }\n\n const fieldsAsString = fieldsToNormalizedString(fields);\n // Frequencly list for $6 subfields in 1XX/7XX fields:\n // 231115 100\n // 183832 700\n // 28773 710\n // 2047 711\n // 661 110\n // 341 111\n // 284 130\n // 63 730\n // Thus there's a real risk of ending up with, say, identical 100 vs 700 chains.\n // Semi-hackily support 1XX/7XX-version: 7XX can be deleted if corresponding 1XX exists:\n const altFieldsAsString = fieldsAsString.substring(0, 1) === '7' ? `1${fieldsAsString.substring(1)}` : fieldsAsString;\n nvdebug(` step 2 ${fieldsAsString}`);\n if (fieldsAsString in seen || altFieldsAsString in seen) {\n nvdebug(` step 3 ${fieldsAsString}`);\n\n removables.push(fieldsAsString);\n\n if (fix) {\n nvdebug(`$6 DOUBLE REMOVAL: REMOVE ${fieldsAsString}`, debug);\n fields.forEach(currField => record.removeField(currField));\n return;\n }\n\n nvdebug(`$6 VALIDATION: DUPLICATE DETECTED ${fieldsAsString}`, debug);\n \n }\n nvdebug(`$6 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${fieldsAsString}`, debug);\n seen[fieldsAsString] = 1;\n return;\n }\n /* eslint-enable */\n return removables;\n}\n\nexport function removeDuplicateDatafields(record, fix = true) {\n const removables = removeIndividualDuplicateDatafields(record, fix); // Lone fields\n const removables8 = removeDuplicateSubfield8Chains(record, fix); // Lone subfield $8 chains\n const removables6 = removeDuplicateSubfield6Chains(record, fix); // Lone subfield $6 chains\n // HOW TO HANDLE $6+$8 combos?\n\n const removablesAll = removables.concat(removables8).concat(removables6);\n\n return removablesAll;\n}\n"],"mappings":"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"}
|
package/dist/subfield6Utils.js
CHANGED
|
@@ -12,6 +12,7 @@ exports.fieldToNormalizedString = fieldToNormalizedString;
|
|
|
12
12
|
exports.fieldsToNormalizedString = fieldsToNormalizedString;
|
|
13
13
|
exports.hasWantedTagAndOccurrenceNumber = hasWantedTagAndOccurrenceNumber;
|
|
14
14
|
exports.intToOccurrenceNumberString = intToOccurrenceNumberString;
|
|
15
|
+
exports.is7XX = is7XX;
|
|
15
16
|
exports.isValidSubfield6 = isValidSubfield6;
|
|
16
17
|
exports.recordGetMaxSubfield6OccurrenceNumberAsInteger = recordGetMaxSubfield6OccurrenceNumberAsInteger;
|
|
17
18
|
exports.resetFieldOccurrenceNumber = resetFieldOccurrenceNumber;
|
|
@@ -299,11 +300,18 @@ export function pairAndStringify6(field, record) {
|
|
|
299
300
|
}
|
|
300
301
|
*/
|
|
301
302
|
|
|
303
|
+
function is7XX(tag) {
|
|
304
|
+
return ['700', '710', '711', '730'].includes(tag);
|
|
305
|
+
}
|
|
302
306
|
function subfieldToNormalizedString(sf, targetLinkingNumber = 0) {
|
|
303
307
|
if (isValidSubfield6(sf) && targetLinkingNumber === 0) {
|
|
308
|
+
const tag = sf.value.substring(0, 3);
|
|
309
|
+
// 100/700 normalization:
|
|
310
|
+
const tag2 = tag.match(/^[17](?:00|10|11|30)$/u) ? `X${tag.substring(1)}` : tag;
|
|
311
|
+
|
|
304
312
|
// If we are normalizing $8 stuff, don't normalize $6 occurrence number!
|
|
305
313
|
// Replace $6 occurrence number with XX:
|
|
306
|
-
return ` ‡${sf.code} ${
|
|
314
|
+
return ` ‡${sf.code} ${tag2}-XX${subfield6GetTail(sf)}`;
|
|
307
315
|
}
|
|
308
316
|
if ((0, _subfield8Utils.isValidSubfield8)(sf)) {
|
|
309
317
|
const currLinkingNumber = (0, _subfield8Utils.getSubfield8LinkingNumber)(sf); //getSubfield8Index(sf);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subfield6Utils.js","names":["sf6Regexp","isValidSubfield6","subfield","code","value","match","subfield6GetTag","substring","undefined","subfield6GetOccurrenceNumber","replace","subfield6GetOccurrenceNumberAsInteger","index","result","parseInt","resetSubfield6OccurrenceNumber","occurrenceNumber","occurrenceNumberAsString","intToOccurrenceNumberString","newValue","subfield6GetTail","fieldGetUnambiguousTag","field","tags","subfields","filter","sf","length","nvdebug","subfieldToString","fieldGetUnambiguousOccurrenceNumber","occurrenceNumbers","fieldHasOccurrenceNumber","some","resetFieldOccurrenceNumber","newOccurrenceNumber","oldOccurrenceNumber","forEach","innerReset","currOccurrenceNumber","i","fieldGetMaxSubfield6OccurrenceNumberAsInteger","sf6s","vals","map","Math","max","recordGetMaxSubfield6OccurrenceNumberAsInteger","record","fields","hasWantedTagAndOccurrenceNumber","tagAndOccurrenceNumber","key","fieldHasWantedTagAndOccurrenceNumber","fieldHasValidSubfield6","isSubfield6Pair","otherField","tagsArePairable6","tag","fieldIndex","otherFieldIndex","tag1","tag2","fieldGetOccurrenceNumberPairs","candFields","pairs","fieldToString","pairedField","subfieldToNormalizedString","targetLinkingNumber","isValidSubfield8","currLinkingNumber","getSubfield8LinkingNumber","normVal","fieldToNormalizedString","ind1","ind2","formatAndNormalizeSubfields","join","fieldsToNormalizedString","strings","sort"],"sources":["../src/subfield6Utils.js"],"sourcesContent":["// import createDebugLogger from 'debug';\n// const debug = createDebugLogger('@natlibfi/marc-record-validator-melinda/subfield6Utils');\n\nimport {getSubfield8LinkingNumber, isValidSubfield8} from './subfield8Utils';\nimport {fieldToString, nvdebug, subfieldToString} from './utils';\n\n// NB! Subfield 6 is non-repeatable and it should always comes first!\n// NB! Index size should always be 2 (preceding 0 required for 01..09) However, support for 100+ was added on 2023-02-27.\n// NB! Index value '00' are left as they are (is not paired/indexed/whatever.\nconst sf6Regexp = /^[0-9][0-9][0-9]-(?:[0-9][0-9]|[1-9][0-9]+)(?:[^0-9].*)?$/u;\n\nexport function isValidSubfield6(subfield) {\n if (subfield.code !== '6') {\n return false;\n }\n return subfield.value.match(sf6Regexp);\n}\n\nfunction subfield6GetTag(subfield) {\n if (isValidSubfield6(subfield)) {\n return subfield.value.substring(0, 3);\n }\n return undefined;\n}\n\nexport function subfield6GetOccurrenceNumber(subfield) {\n if (isValidSubfield6(subfield)) {\n // Skip \"TAG-\" prefix. 2023-02-20: removed 2-digit requirement from here...\n return subfield.value.substring(4).replace(/\\D.*$/u, '');\n }\n return undefined;\n}\n\nexport function subfield6GetOccurrenceNumberAsInteger(subfield) {\n const index = subfield6GetOccurrenceNumber(subfield);\n if (index === undefined || index === '00') {\n return 0;\n }\n const result = parseInt(index, 10);\n //nvdebug(`SF6: ${subfield.value} => ${index} => ${result}`, debug);\n return result;\n}\n\nexport function resetSubfield6OccurrenceNumber(subfield, occurrenceNumber) {\n if (!isValidSubfield6(subfield)) {\n return;\n }\n const occurrenceNumberAsString = typeof occurrenceNumber === 'number' ? intToOccurrenceNumberString(occurrenceNumber) : occurrenceNumber;\n\n const newValue = subfield.value.substring(0, 4) + occurrenceNumberAsString + subfield6GetTail(subfield); // eslint-disable-line functional/immutable-data\n //nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`);\n subfield.value = newValue; // eslint-disable-line functional/immutable-data\n}\n\n\nfunction subfield6GetTail(subfield) {\n if (isValidSubfield6(subfield)) {\n // Skip \"TAG-\" prefix. 2023-02-20: removed 2-digit requirement from here...\n return subfield.value.replace(/^\\d+-\\d+/u, '');\n }\n return '';\n}\n\n// <= SUBFIELD, FIELD =>\n\n/*\nexport function fieldHasValidSubfield6AndIsNotAnAlternateGraphicRepresentation(field) {\n // AlternateGraphicRepresentation is same as \"field.tag === '880'\"\"\n if (!field.subfields || field.tag === '880') {\n return false;\n }\n const sf6s = field.subfields.filter(sf => sf.code === '6' && sf.value.match(sf6Regexp));\n return sf6s.length === 1;\n}\n*/\n\nexport function fieldGetUnambiguousTag(field) {\n const tags = field.subfields.filter(sf => subfield6GetTag(sf));\n if (tags.length === 1) {\n nvdebug(` GOT ${tags.length} tag(s): ${subfieldToString(tags[0])}`);\n return subfield6GetTag(tags[0]);\n }\n return undefined;\n}\n\nexport function fieldGetUnambiguousOccurrenceNumber(field) {\n const occurrenceNumbers = field.subfields.filter(sf => subfield6GetOccurrenceNumber(sf));\n if (occurrenceNumbers.length === 1) {\n return subfield6GetOccurrenceNumber(occurrenceNumbers[0]);\n }\n return undefined;\n}\n\nexport function fieldHasOccurrenceNumber(field, occurrenceNumber) {\n //nvdebug(`${occurrenceNumber} vs ${fieldToString(field)}`);\n return field.subfields && field.subfields.some(sf => subfield6GetOccurrenceNumber(sf) === occurrenceNumber);\n}\n\nexport function resetFieldOccurrenceNumber(field, newOccurrenceNumber, oldOccurrenceNumber = undefined) {\n field.subfields.forEach(subfield => innerReset(subfield));\n\n function innerReset(subfield) {\n // (Optional) Check that this is really the occurrence number we wan't to reseot\n if (oldOccurrenceNumber !== undefined) {\n const currOccurrenceNumber = subfield6GetOccurrenceNumber(subfield);\n if (currOccurrenceNumber !== oldOccurrenceNumber) {\n return;\n }\n }\n resetSubfield6OccurrenceNumber(subfield, newOccurrenceNumber);\n }\n}\n\nexport function intToOccurrenceNumberString(i) {\n return i < 10 ? `0${i}` : `${i}`;\n}\n\nfunction fieldGetMaxSubfield6OccurrenceNumberAsInteger(field) {\n //nvdebug(`Checking subfields $6 from ${JSON.stringify(field)}`);\n const sf6s = field.subfields ? field.subfields.filter(subfield => isValidSubfield6(subfield)) : [];\n if (sf6s.length === 0) {\n return 0;\n }\n // There should always be one, but here we check every subfield.\n //nvdebug(`Got ${field.subfields} $6-subfield(s) from ${JSON.stringify(field)}`, debug);\n const vals = sf6s.map(sf => subfield6GetOccurrenceNumberAsInteger(sf));\n return Math.max(...vals);\n}\n\n\nexport function recordGetMaxSubfield6OccurrenceNumberAsInteger(record) {\n // Should we cache the value here?\n const vals = record.fields.map((field) => fieldGetMaxSubfield6OccurrenceNumberAsInteger(field));\n return Math.max(...vals);\n}\n\nexport function hasWantedTagAndOccurrenceNumber(subfield, tagAndOccurrenceNumber) {\n if (subfield.code !== '6') {\n return false;\n }\n // We could also use generic code and go getTag()+'-'+getIndex() instead of regexp...\n const key = subfield.value.replace(/^([0-9][0-9][0-9]-[0-9][0-9]+).*$/u, '$1'); // eslint-disable-line prefer-named-capture-group\n nvdebug(` Compare '${key}' vs '${tagAndOccurrenceNumber}'`);\n return key === tagAndOccurrenceNumber;\n}\n\n\nexport function fieldHasWantedTagAndOccurrenceNumber(field, tagAndOccurrenceNumber) {\n return field.subfields && field.subfields.some(sf => hasWantedTagAndOccurrenceNumber(sf, tagAndOccurrenceNumber));\n}\n\n\n/*\nexport function getFieldsWithGivenOccurrenceNumberSubfield6(record, occurrenceNumberAsString) {\n const record.fields.filter(field => field\n\n function fieldHasIndex(field, index) {\n if (!field.subfields) {\n return false;\n }\n return field.subfields.find(sf => isValidSubfield6(sf) && subfieldGetOccurrenceNumber6(sf) === index);\n }\n}\n*/\n\n\nfunction fieldHasValidSubfield6(field) {\n return field.subfields && field.subfields.some(sf => isValidSubfield6(sf));\n}\n\n\n/*\n\nexport function subfieldGetOccurrenceNumber6(subfield) {\n if (isValidSubfield6(subfield)) {\n // Skip \"TAG-\" prefix. 2023-02-20: removed 2-digit requirement from here...\n return subfield.value.substring(4).replace(/\\D.*$/u, '');\n }\n return undefined;\n}\n\nfunction subfieldGetTag6(subfield) {\n if (isValidSubfield6(subfield)) {\n return subfield.value.substring(0, 3);\n }\n return undefined;\n}\n\n\nexport function resetSubfield6Tag(subfield, tag) {\n if (!isValidSubfield6(subfield)) {\n return;\n }\n // NB! mainly for 1XX<->7XX transfers\n const newValue = `${tag}-${subfield.value.substring(4)}`;\n nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`);\n subfield.value = newValue; // eslint-disable-line functional/immutable-data\n}\n\n\n*/\n\n\n/*\nexport function fieldGetOccurrenceNumber6(field) {\n if (!field.subfields) {\n return undefined;\n }\n // Subfield $6 should always be the 1st subfield... (not implemented)\n // There should be only one $6, so find is ok.\n const sf6 = field.subfields.find(subfield => isValidSubfield6(subfield));\n if (sf6 === undefined) {\n return undefined;\n }\n return subfieldGetOccurrenceNumber6(sf6);\n}\n\nfunction fieldGetTag6(field) {\n if (!field.subfields) {\n return undefined;\n }\n // Subfield $6 should always be the 1st subfield... (not implemented)\n // There should be only one $6, so find is ok.\n const sf6 = field.subfields.find(subfield => isValidSubfield6(subfield));\n if (sf6 === undefined) {\n return undefined;\n }\n return subfieldGetTag6(sf6);\n}\n\n*/\n\nfunction isSubfield6Pair(field, otherField) {\n // No need to log this:\n //nvdebug(`LOOK for $6-pair:\\n ${fieldToString(field)}\\n ${fieldToString(otherField)}`);\n if (!fieldHasValidSubfield6(field) || !fieldHasValidSubfield6(otherField)) {\n return false;\n }\n\n if (!tagsArePairable6(field.tag, otherField.tag)) {\n //nvdebug(` FAILED. REASON: TAGS NOT PAIRABLE!`);\n return false;\n }\n\n\n const fieldIndex = fieldGetUnambiguousOccurrenceNumber(field);\n if (fieldIndex === undefined || fieldIndex === '00') {\n //nvdebug(` FAILED. REASON: NO INDEX FOUND`);\n return false;\n }\n\n const otherFieldIndex = fieldGetUnambiguousOccurrenceNumber(otherField);\n\n\n if (fieldIndex !== otherFieldIndex) {\n //nvdebug(` FAILURE: INDEXES: ${fieldIndex} vs ${otherFieldIndex}`);\n return false;\n }\n\n if (fieldGetUnambiguousTag(field) !== otherField.tag || field.tag !== fieldGetUnambiguousTag(otherField)) {\n //nvdebug(` FAILURE: TAG vs $6 TAG`);\n return false;\n }\n return true;\n\n function tagsArePairable6(tag1, tag2) {\n // How to do XOR operation in one line? Well, this is probably more readable...\n if (tag1 === '880' && tag2 === '880') {\n return false;\n }\n if (tag1 !== '880' && tag2 !== '880') {\n return false;\n }\n return true;\n }\n}\n\nexport function fieldGetOccurrenceNumberPairs(field, candFields) {\n // NB! TAG!=880 returns 880 fields, TAG==880 returns non-880 field\n //nvdebug(` Trying to finds pair for ${fieldToString(field)} in ${candFields.length} fields`);\n const pairs = candFields.filter(otherField => isSubfield6Pair(field, otherField));\n if (pairs.length === 0) {\n nvdebug(`NO PAIRS FOUND FOR '${fieldToString(field)}'`);\n return pairs;\n }\n nvdebug(`${pairs.length} PAIR(S) FOUND FOR '${fieldToString(field)}'`);\n pairs.forEach(pairedField => nvdebug(` '${fieldToString(pairedField)}'`));\n return pairs;\n}\n\n/*\nexport function fieldGetSubfield6Pair(field, record) {\n const pairedFields = record.fields.filter(otherField => isSubfield6Pair(field, otherField));\n if (pairedFields.length !== 1) {\n return undefined;\n }\n // NB! It is theoretically possible to have multiple pairable 880 fields (one for each encoding)\n nvdebug(`fieldGetSubfield6Pair(): ${fieldToString(field)} => ${fieldToString(pairedFields[0])}`);\n return pairedFields[0];\n}\n*/\n\n/*\nexport function pairAndStringify6(field, record) {\n const pair6 = fieldGetSubfield6Pair(field, record);\n if (!pair6) {\n return fieldToNormalizedString(field);\n }\n return fieldsToNormalizedString([field, pair6]);\n}\n*/\n\nexport function subfieldToNormalizedString(sf, targetLinkingNumber = 0) {\n if (isValidSubfield6(sf) && targetLinkingNumber === 0) {\n // If we are normalizing $8 stuff, don't normalize $6 occurrence number!\n // Replace $6 occurrence number with XX:\n return ` ‡${sf.code} ${sf.value.substring(0, 3)}-XX${subfield6GetTail(sf)}`;\n }\n if (isValidSubfield8(sf)) {\n const currLinkingNumber = getSubfield8LinkingNumber(sf); //getSubfield8Index(sf);\n if (targetLinkingNumber > 0 && currLinkingNumber === targetLinkingNumber) {\n // For $8 we should only XX the index we are looking at...\n const normVal = sf.value.replace(/^[0-9]+/u, 'XX');\n return ` ‡${sf.code} ${normVal}`;\n }\n return ''; // Other $8 subfields are meaningless in this context\n }\n return ` ${subfieldToString(sf)}`; // `‡${sf.code} ${sf.value}`;\n}\n\nexport function fieldToNormalizedString(field, targetLinkingNumber = 0) {\n if ('subfields' in field) {\n return `${field.tag} ${field.ind1}${field.ind2}${formatAndNormalizeSubfields(field)}`;\n }\n return `${field.tag} ${field.value}`;\n\n function formatAndNormalizeSubfields(field) {\n return field.subfields.map(sf => subfieldToNormalizedString(sf, targetLinkingNumber)).join('');\n }\n}\n\nexport function fieldsToNormalizedString(fields, index = 0) {\n const strings = fields.map(field => fieldToNormalizedString(field, index));\n strings.sort(); // eslint-disable-line functional/immutable-data\n return strings.join('\\t__SEPARATOR__\\t');\n}\n\n/*\n\nexport function removeField6IfNeeded(field, record, fieldsAsString) {\n const pairField = fieldGetSubfield6Pair(field, record);\n const asString = pairField ? fieldsToNormalizedString([field, pairField]) : fieldToNormalizedString(field);\n nvdebug(`SOURCE: ${asString} -- REALITY: ${fieldToString(field)}`);\n const tmp = pairField ? fieldToString(pairField) : 'HUTI';\n nvdebug(`PAIR: ${tmp}`);\n nvdebug(`BASE:\\n ${fieldsAsString.join('\\n ')}`);\n if (!fieldsAsString.includes(asString)) {\n return;\n }\n nvdebug(`Duplicate $6 removal: ${fieldToString(field)}`);\n record.removeField(field);\n\n if (pairField === undefined) {\n return;\n }\n nvdebug(`Duplicate $6 removal (pair): ${fieldToString(pairField)}`);\n record.removeField(pairField);\n}\n*/\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"subfield6Utils.js","names":["sf6Regexp","isValidSubfield6","subfield","code","value","match","subfield6GetTag","substring","undefined","subfield6GetOccurrenceNumber","replace","subfield6GetOccurrenceNumberAsInteger","index","result","parseInt","resetSubfield6OccurrenceNumber","occurrenceNumber","occurrenceNumberAsString","intToOccurrenceNumberString","newValue","subfield6GetTail","fieldGetUnambiguousTag","field","tags","subfields","filter","sf","length","nvdebug","subfieldToString","fieldGetUnambiguousOccurrenceNumber","occurrenceNumbers","fieldHasOccurrenceNumber","some","resetFieldOccurrenceNumber","newOccurrenceNumber","oldOccurrenceNumber","forEach","innerReset","currOccurrenceNumber","i","fieldGetMaxSubfield6OccurrenceNumberAsInteger","sf6s","vals","map","Math","max","recordGetMaxSubfield6OccurrenceNumberAsInteger","record","fields","hasWantedTagAndOccurrenceNumber","tagAndOccurrenceNumber","key","fieldHasWantedTagAndOccurrenceNumber","fieldHasValidSubfield6","isSubfield6Pair","otherField","tagsArePairable6","tag","fieldIndex","otherFieldIndex","tag1","tag2","fieldGetOccurrenceNumberPairs","candFields","pairs","fieldToString","pairedField","is7XX","includes","subfieldToNormalizedString","targetLinkingNumber","isValidSubfield8","currLinkingNumber","getSubfield8LinkingNumber","normVal","fieldToNormalizedString","ind1","ind2","formatAndNormalizeSubfields","join","fieldsToNormalizedString","strings","sort"],"sources":["../src/subfield6Utils.js"],"sourcesContent":["// import createDebugLogger from 'debug';\n// const debug = createDebugLogger('@natlibfi/marc-record-validator-melinda/subfield6Utils');\n\nimport {getSubfield8LinkingNumber, isValidSubfield8} from './subfield8Utils';\nimport {fieldToString, nvdebug, subfieldToString} from './utils';\n\n// NB! Subfield 6 is non-repeatable and it should always comes first!\n// NB! Index size should always be 2 (preceding 0 required for 01..09) However, support for 100+ was added on 2023-02-27.\n// NB! Index value '00' are left as they are (is not paired/indexed/whatever.\nconst sf6Regexp = /^[0-9][0-9][0-9]-(?:[0-9][0-9]|[1-9][0-9]+)(?:[^0-9].*)?$/u;\n\nexport function isValidSubfield6(subfield) {\n if (subfield.code !== '6') {\n return false;\n }\n return subfield.value.match(sf6Regexp);\n}\n\nfunction subfield6GetTag(subfield) {\n if (isValidSubfield6(subfield)) {\n return subfield.value.substring(0, 3);\n }\n return undefined;\n}\n\nexport function subfield6GetOccurrenceNumber(subfield) {\n if (isValidSubfield6(subfield)) {\n // Skip \"TAG-\" prefix. 2023-02-20: removed 2-digit requirement from here...\n return subfield.value.substring(4).replace(/\\D.*$/u, '');\n }\n return undefined;\n}\n\nexport function subfield6GetOccurrenceNumberAsInteger(subfield) {\n const index = subfield6GetOccurrenceNumber(subfield);\n if (index === undefined || index === '00') {\n return 0;\n }\n const result = parseInt(index, 10);\n //nvdebug(`SF6: ${subfield.value} => ${index} => ${result}`, debug);\n return result;\n}\n\nexport function resetSubfield6OccurrenceNumber(subfield, occurrenceNumber) {\n if (!isValidSubfield6(subfield)) {\n return;\n }\n const occurrenceNumberAsString = typeof occurrenceNumber === 'number' ? intToOccurrenceNumberString(occurrenceNumber) : occurrenceNumber;\n\n const newValue = subfield.value.substring(0, 4) + occurrenceNumberAsString + subfield6GetTail(subfield); // eslint-disable-line functional/immutable-data\n //nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`);\n subfield.value = newValue; // eslint-disable-line functional/immutable-data\n}\n\n\nfunction subfield6GetTail(subfield) {\n if (isValidSubfield6(subfield)) {\n // Skip \"TAG-\" prefix. 2023-02-20: removed 2-digit requirement from here...\n return subfield.value.replace(/^\\d+-\\d+/u, '');\n }\n return '';\n}\n\n// <= SUBFIELD, FIELD =>\n\n/*\nexport function fieldHasValidSubfield6AndIsNotAnAlternateGraphicRepresentation(field) {\n // AlternateGraphicRepresentation is same as \"field.tag === '880'\"\"\n if (!field.subfields || field.tag === '880') {\n return false;\n }\n const sf6s = field.subfields.filter(sf => sf.code === '6' && sf.value.match(sf6Regexp));\n return sf6s.length === 1;\n}\n*/\n\nexport function fieldGetUnambiguousTag(field) {\n const tags = field.subfields.filter(sf => subfield6GetTag(sf));\n if (tags.length === 1) {\n nvdebug(` GOT ${tags.length} tag(s): ${subfieldToString(tags[0])}`);\n return subfield6GetTag(tags[0]);\n }\n return undefined;\n}\n\nexport function fieldGetUnambiguousOccurrenceNumber(field) {\n const occurrenceNumbers = field.subfields.filter(sf => subfield6GetOccurrenceNumber(sf));\n if (occurrenceNumbers.length === 1) {\n return subfield6GetOccurrenceNumber(occurrenceNumbers[0]);\n }\n return undefined;\n}\n\nexport function fieldHasOccurrenceNumber(field, occurrenceNumber) {\n //nvdebug(`${occurrenceNumber} vs ${fieldToString(field)}`);\n return field.subfields && field.subfields.some(sf => subfield6GetOccurrenceNumber(sf) === occurrenceNumber);\n}\n\nexport function resetFieldOccurrenceNumber(field, newOccurrenceNumber, oldOccurrenceNumber = undefined) {\n field.subfields.forEach(subfield => innerReset(subfield));\n\n function innerReset(subfield) {\n // (Optional) Check that this is really the occurrence number we wan't to reseot\n if (oldOccurrenceNumber !== undefined) {\n const currOccurrenceNumber = subfield6GetOccurrenceNumber(subfield);\n if (currOccurrenceNumber !== oldOccurrenceNumber) {\n return;\n }\n }\n resetSubfield6OccurrenceNumber(subfield, newOccurrenceNumber);\n }\n}\n\nexport function intToOccurrenceNumberString(i) {\n return i < 10 ? `0${i}` : `${i}`;\n}\n\nfunction fieldGetMaxSubfield6OccurrenceNumberAsInteger(field) {\n //nvdebug(`Checking subfields $6 from ${JSON.stringify(field)}`);\n const sf6s = field.subfields ? field.subfields.filter(subfield => isValidSubfield6(subfield)) : [];\n if (sf6s.length === 0) {\n return 0;\n }\n // There should always be one, but here we check every subfield.\n //nvdebug(`Got ${field.subfields} $6-subfield(s) from ${JSON.stringify(field)}`, debug);\n const vals = sf6s.map(sf => subfield6GetOccurrenceNumberAsInteger(sf));\n return Math.max(...vals);\n}\n\n\nexport function recordGetMaxSubfield6OccurrenceNumberAsInteger(record) {\n // Should we cache the value here?\n const vals = record.fields.map((field) => fieldGetMaxSubfield6OccurrenceNumberAsInteger(field));\n return Math.max(...vals);\n}\n\nexport function hasWantedTagAndOccurrenceNumber(subfield, tagAndOccurrenceNumber) {\n if (subfield.code !== '6') {\n return false;\n }\n // We could also use generic code and go getTag()+'-'+getIndex() instead of regexp...\n const key = subfield.value.replace(/^([0-9][0-9][0-9]-[0-9][0-9]+).*$/u, '$1'); // eslint-disable-line prefer-named-capture-group\n nvdebug(` Compare '${key}' vs '${tagAndOccurrenceNumber}'`);\n return key === tagAndOccurrenceNumber;\n}\n\n\nexport function fieldHasWantedTagAndOccurrenceNumber(field, tagAndOccurrenceNumber) {\n return field.subfields && field.subfields.some(sf => hasWantedTagAndOccurrenceNumber(sf, tagAndOccurrenceNumber));\n}\n\n\n/*\nexport function getFieldsWithGivenOccurrenceNumberSubfield6(record, occurrenceNumberAsString) {\n const record.fields.filter(field => field\n\n function fieldHasIndex(field, index) {\n if (!field.subfields) {\n return false;\n }\n return field.subfields.find(sf => isValidSubfield6(sf) && subfieldGetOccurrenceNumber6(sf) === index);\n }\n}\n*/\n\n\nfunction fieldHasValidSubfield6(field) {\n return field.subfields && field.subfields.some(sf => isValidSubfield6(sf));\n}\n\n\n/*\n\nexport function subfieldGetOccurrenceNumber6(subfield) {\n if (isValidSubfield6(subfield)) {\n // Skip \"TAG-\" prefix. 2023-02-20: removed 2-digit requirement from here...\n return subfield.value.substring(4).replace(/\\D.*$/u, '');\n }\n return undefined;\n}\n\nfunction subfieldGetTag6(subfield) {\n if (isValidSubfield6(subfield)) {\n return subfield.value.substring(0, 3);\n }\n return undefined;\n}\n\n\nexport function resetSubfield6Tag(subfield, tag) {\n if (!isValidSubfield6(subfield)) {\n return;\n }\n // NB! mainly for 1XX<->7XX transfers\n const newValue = `${tag}-${subfield.value.substring(4)}`;\n nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`);\n subfield.value = newValue; // eslint-disable-line functional/immutable-data\n}\n\n\n*/\n\n\n/*\nexport function fieldGetOccurrenceNumber6(field) {\n if (!field.subfields) {\n return undefined;\n }\n // Subfield $6 should always be the 1st subfield... (not implemented)\n // There should be only one $6, so find is ok.\n const sf6 = field.subfields.find(subfield => isValidSubfield6(subfield));\n if (sf6 === undefined) {\n return undefined;\n }\n return subfieldGetOccurrenceNumber6(sf6);\n}\n\nfunction fieldGetTag6(field) {\n if (!field.subfields) {\n return undefined;\n }\n // Subfield $6 should always be the 1st subfield... (not implemented)\n // There should be only one $6, so find is ok.\n const sf6 = field.subfields.find(subfield => isValidSubfield6(subfield));\n if (sf6 === undefined) {\n return undefined;\n }\n return subfieldGetTag6(sf6);\n}\n\n*/\n\nfunction isSubfield6Pair(field, otherField) {\n // No need to log this:\n //nvdebug(`LOOK for $6-pair:\\n ${fieldToString(field)}\\n ${fieldToString(otherField)}`);\n if (!fieldHasValidSubfield6(field) || !fieldHasValidSubfield6(otherField)) {\n return false;\n }\n\n if (!tagsArePairable6(field.tag, otherField.tag)) {\n //nvdebug(` FAILED. REASON: TAGS NOT PAIRABLE!`);\n return false;\n }\n\n\n const fieldIndex = fieldGetUnambiguousOccurrenceNumber(field);\n if (fieldIndex === undefined || fieldIndex === '00') {\n //nvdebug(` FAILED. REASON: NO INDEX FOUND`);\n return false;\n }\n\n const otherFieldIndex = fieldGetUnambiguousOccurrenceNumber(otherField);\n\n\n if (fieldIndex !== otherFieldIndex) {\n //nvdebug(` FAILURE: INDEXES: ${fieldIndex} vs ${otherFieldIndex}`);\n return false;\n }\n\n if (fieldGetUnambiguousTag(field) !== otherField.tag || field.tag !== fieldGetUnambiguousTag(otherField)) {\n //nvdebug(` FAILURE: TAG vs $6 TAG`);\n return false;\n }\n return true;\n\n function tagsArePairable6(tag1, tag2) {\n // How to do XOR operation in one line? Well, this is probably more readable...\n if (tag1 === '880' && tag2 === '880') {\n return false;\n }\n if (tag1 !== '880' && tag2 !== '880') {\n return false;\n }\n return true;\n }\n}\n\nexport function fieldGetOccurrenceNumberPairs(field, candFields) {\n // NB! TAG!=880 returns 880 fields, TAG==880 returns non-880 field\n //nvdebug(` Trying to finds pair for ${fieldToString(field)} in ${candFields.length} fields`);\n const pairs = candFields.filter(otherField => isSubfield6Pair(field, otherField));\n if (pairs.length === 0) {\n nvdebug(`NO PAIRS FOUND FOR '${fieldToString(field)}'`);\n return pairs;\n }\n nvdebug(`${pairs.length} PAIR(S) FOUND FOR '${fieldToString(field)}'`);\n pairs.forEach(pairedField => nvdebug(` '${fieldToString(pairedField)}'`));\n return pairs;\n}\n\n/*\nexport function fieldGetSubfield6Pair(field, record) {\n const pairedFields = record.fields.filter(otherField => isSubfield6Pair(field, otherField));\n if (pairedFields.length !== 1) {\n return undefined;\n }\n // NB! It is theoretically possible to have multiple pairable 880 fields (one for each encoding)\n nvdebug(`fieldGetSubfield6Pair(): ${fieldToString(field)} => ${fieldToString(pairedFields[0])}`);\n return pairedFields[0];\n}\n*/\n\n/*\nexport function pairAndStringify6(field, record) {\n const pair6 = fieldGetSubfield6Pair(field, record);\n if (!pair6) {\n return fieldToNormalizedString(field);\n }\n return fieldsToNormalizedString([field, pair6]);\n}\n*/\n\nexport function is7XX(tag) {\n return ['700', '710', '711', '730'].includes(tag);\n}\n\nexport function subfieldToNormalizedString(sf, targetLinkingNumber = 0) {\n if (isValidSubfield6(sf) && targetLinkingNumber === 0) {\n const tag = sf.value.substring(0, 3);\n // 100/700 normalization:\n const tag2 = tag.match(/^[17](?:00|10|11|30)$/u) ? `X${tag.substring(1)}` : tag;\n\n // If we are normalizing $8 stuff, don't normalize $6 occurrence number!\n // Replace $6 occurrence number with XX:\n return ` ‡${sf.code} ${tag2}-XX${subfield6GetTail(sf)}`;\n }\n\n if (isValidSubfield8(sf)) {\n const currLinkingNumber = getSubfield8LinkingNumber(sf); //getSubfield8Index(sf);\n if (targetLinkingNumber > 0 && currLinkingNumber === targetLinkingNumber) {\n // For $8 we should only XX the index we are looking at...\n const normVal = sf.value.replace(/^[0-9]+/u, 'XX');\n return ` ‡${sf.code} ${normVal}`;\n }\n return ''; // Other $8 subfields are meaningless in this context\n }\n return ` ${subfieldToString(sf)}`; // `‡${sf.code} ${sf.value}`;\n}\n\nexport function fieldToNormalizedString(field, targetLinkingNumber = 0) {\n if ('subfields' in field) {\n return `${field.tag} ${field.ind1}${field.ind2}${formatAndNormalizeSubfields(field)}`;\n }\n return `${field.tag} ${field.value}`;\n\n function formatAndNormalizeSubfields(field) {\n return field.subfields.map(sf => subfieldToNormalizedString(sf, targetLinkingNumber)).join('');\n }\n\n}\n\nexport function fieldsToNormalizedString(fields, index = 0) {\n const strings = fields.map(field => fieldToNormalizedString(field, index));\n strings.sort(); // eslint-disable-line functional/immutable-data\n return strings.join('\\t__SEPARATOR__\\t');\n}\n\n/*\n\nexport function removeField6IfNeeded(field, record, fieldsAsString) {\n const pairField = fieldGetSubfield6Pair(field, record);\n const asString = pairField ? fieldsToNormalizedString([field, pairField]) : fieldToNormalizedString(field);\n nvdebug(`SOURCE: ${asString} -- REALITY: ${fieldToString(field)}`);\n const tmp = pairField ? fieldToString(pairField) : 'HUTI';\n nvdebug(`PAIR: ${tmp}`);\n nvdebug(`BASE:\\n ${fieldsAsString.join('\\n ')}`);\n if (!fieldsAsString.includes(asString)) {\n return;\n }\n nvdebug(`Duplicate $6 removal: ${fieldToString(field)}`);\n record.removeField(field);\n\n if (pairField === undefined) {\n return;\n }\n nvdebug(`Duplicate $6 removal (pair): ${fieldToString(pairField)}`);\n record.removeField(pairField);\n}\n*/\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -163,11 +163,15 @@ export function removeIndividualDuplicateDatafields(record, fix = true) { // No
|
|
|
163
163
|
nvdebug(`DUPLICATE SINGLETON DETECTED: ${fieldAsString}`);
|
|
164
164
|
return true;
|
|
165
165
|
}
|
|
166
|
+
if (is7XX(field.tag) && convert7XXto1XX(fieldAsString) in seen) {
|
|
167
|
+
nvdebug(`DUPLICATE (1XX-7XX) SINGLETON DETECTED: ${fieldAsString}`);
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
|
|
166
171
|
nvdebug(`MARK SINGLETON AS SEEN: ${fieldAsString}`, debug);
|
|
167
172
|
seen[fieldAsString] = 1;
|
|
168
173
|
return;
|
|
169
174
|
}
|
|
170
|
-
|
|
171
175
|
/* eslint-enable */
|
|
172
176
|
|
|
173
177
|
}
|
|
@@ -183,8 +187,30 @@ function recordRemoveFieldOrSubfield8(record, field, currLinkingNumber) {
|
|
|
183
187
|
subfields.forEach(sf => record.removeSubfield(sf, field));
|
|
184
188
|
}
|
|
185
189
|
|
|
190
|
+
function is7XX(tag) {
|
|
191
|
+
return ['700', '710', '711', '730'].includes(tag);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function convert7XXto1XX(fieldString) {
|
|
195
|
+
/* eslint-disable prefer-named-capture-group, no-param-reassign */
|
|
196
|
+
fieldString = fieldString.replace(/^7(00|10|11|30)/u, '1$1');
|
|
197
|
+
fieldString = fieldString.replace(/‡6 [17](00|10|11|30)/gu, '‡6 X$1');
|
|
198
|
+
|
|
199
|
+
/* eslint-enable */
|
|
200
|
+
|
|
201
|
+
return fieldString;
|
|
202
|
+
}
|
|
186
203
|
|
|
187
204
|
export function removeDuplicateSubfield8Chains(record, fix = true) {
|
|
205
|
+
|
|
206
|
+
// Seen $8 subsfields in various fields:
|
|
207
|
+
// 161 700
|
|
208
|
+
// 17 710
|
|
209
|
+
// 11 110
|
|
210
|
+
// 8 730
|
|
211
|
+
// 1 100
|
|
212
|
+
// Given these stats, there's no need to check for 1XX-vs-7XX removals
|
|
213
|
+
|
|
188
214
|
/* eslint-disable */
|
|
189
215
|
let seen = {};
|
|
190
216
|
|
|
@@ -247,26 +273,37 @@ export function removeDuplicateSubfield6Chains(record, fix = true) {
|
|
|
247
273
|
}
|
|
248
274
|
|
|
249
275
|
const fieldsAsString = fieldsToNormalizedString(fields);
|
|
276
|
+
// Frequencly list for $6 subfields in 1XX/7XX fields:
|
|
277
|
+
// 231115 100
|
|
278
|
+
// 183832 700
|
|
279
|
+
// 28773 710
|
|
280
|
+
// 2047 711
|
|
281
|
+
// 661 110
|
|
282
|
+
// 341 111
|
|
283
|
+
// 284 130
|
|
284
|
+
// 63 730
|
|
285
|
+
// Thus there's a real risk of ending up with, say, identical 100 vs 700 chains.
|
|
286
|
+
// Semi-hackily support 1XX/7XX-version: 7XX can be deleted if corresponding 1XX exists:
|
|
287
|
+
const altFieldsAsString = fieldsAsString.substring(0, 1) === '7' ? `1${fieldsAsString.substring(1)}` : fieldsAsString;
|
|
250
288
|
nvdebug(` step 2 ${fieldsAsString}`);
|
|
251
|
-
if (fieldsAsString in seen)
|
|
289
|
+
if (fieldsAsString in seen || altFieldsAsString in seen) {
|
|
252
290
|
nvdebug(` step 3 ${fieldsAsString}`);
|
|
253
291
|
|
|
254
292
|
removables.push(fieldsAsString);
|
|
255
293
|
|
|
256
294
|
if (fix) {
|
|
257
|
-
nvdebug(
|
|
295
|
+
nvdebug(`$6 DOUBLE REMOVAL: REMOVE ${fieldsAsString}`, debug);
|
|
258
296
|
fields.forEach(currField => record.removeField(currField));
|
|
259
297
|
return;
|
|
260
298
|
}
|
|
261
|
-
|
|
299
|
+
|
|
300
|
+
nvdebug(`$6 VALIDATION: DUPLICATE DETECTED ${fieldsAsString}`, debug);
|
|
262
301
|
|
|
263
302
|
}
|
|
264
|
-
nvdebug(
|
|
303
|
+
nvdebug(`$6 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${fieldsAsString}`, debug);
|
|
265
304
|
seen[fieldsAsString] = 1;
|
|
266
305
|
return;
|
|
267
306
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
307
|
/* eslint-enable */
|
|
271
308
|
return removables;
|
|
272
309
|
}
|
package/src/subfield6Utils.js
CHANGED
|
@@ -310,12 +310,21 @@ export function pairAndStringify6(field, record) {
|
|
|
310
310
|
}
|
|
311
311
|
*/
|
|
312
312
|
|
|
313
|
+
export function is7XX(tag) {
|
|
314
|
+
return ['700', '710', '711', '730'].includes(tag);
|
|
315
|
+
}
|
|
316
|
+
|
|
313
317
|
export function subfieldToNormalizedString(sf, targetLinkingNumber = 0) {
|
|
314
318
|
if (isValidSubfield6(sf) && targetLinkingNumber === 0) {
|
|
319
|
+
const tag = sf.value.substring(0, 3);
|
|
320
|
+
// 100/700 normalization:
|
|
321
|
+
const tag2 = tag.match(/^[17](?:00|10|11|30)$/u) ? `X${tag.substring(1)}` : tag;
|
|
322
|
+
|
|
315
323
|
// If we are normalizing $8 stuff, don't normalize $6 occurrence number!
|
|
316
324
|
// Replace $6 occurrence number with XX:
|
|
317
|
-
return ` ‡${sf.code} ${
|
|
325
|
+
return ` ‡${sf.code} ${tag2}-XX${subfield6GetTail(sf)}`;
|
|
318
326
|
}
|
|
327
|
+
|
|
319
328
|
if (isValidSubfield8(sf)) {
|
|
320
329
|
const currLinkingNumber = getSubfield8LinkingNumber(sf); //getSubfield8Index(sf);
|
|
321
330
|
if (targetLinkingNumber > 0 && currLinkingNumber === targetLinkingNumber) {
|
|
@@ -337,6 +346,7 @@ export function fieldToNormalizedString(field, targetLinkingNumber = 0) {
|
|
|
337
346
|
function formatAndNormalizeSubfields(field) {
|
|
338
347
|
return field.subfields.map(sf => subfieldToNormalizedString(sf, targetLinkingNumber)).join('');
|
|
339
348
|
}
|
|
349
|
+
|
|
340
350
|
}
|
|
341
351
|
|
|
342
352
|
export function fieldsToNormalizedString(fields, index = 0) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{ "_validationOptions": {},
|
|
2
|
+
"leader": "01331cam a22003494i 4500",
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "100", "ind1": " ", "ind2": " ", "subfields": [ { "code": "a", "value": "Nimi"} ]},
|
|
5
|
+
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [ { "code": "a", "value": "Nimi"} ]}
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
]
|
|
9
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{ "_validationOptions": {},
|
|
2
|
+
"leader": "01331cam a22003494i 4500",
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "100", "ind1": " ", "ind2": " ", "subfields": [
|
|
5
|
+
{ "code": "6", "value": "880-01" },
|
|
6
|
+
{ "code": "a", "value": "Nimi2"}
|
|
7
|
+
]},
|
|
8
|
+
{ "tag": "880", "ind1": " ", "ind2": " ", "subfields": [
|
|
9
|
+
{ "code": "6", "value": "100-01" },
|
|
10
|
+
{ "code": "a", "value": "Inim2"}
|
|
11
|
+
]}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{ "_validationOptions": {},
|
|
2
|
+
"leader": "01331cam a22003494i 4500",
|
|
3
|
+
"fields": [
|
|
4
|
+
|
|
5
|
+
{ "tag": "100", "ind1": " ", "ind2": " ", "subfields": [
|
|
6
|
+
{ "code": "6", "value": "880-01" },
|
|
7
|
+
{ "code": "a", "value": "Nimi2"}
|
|
8
|
+
]},
|
|
9
|
+
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [
|
|
10
|
+
{ "code": "6", "value": "880-02" },
|
|
11
|
+
{ "code": "a", "value": "Nimi2"}
|
|
12
|
+
]},
|
|
13
|
+
|
|
14
|
+
{ "tag": "880", "ind1": " ", "ind2": " ", "subfields": [
|
|
15
|
+
{ "code": "6", "value": "100-01" },
|
|
16
|
+
{ "code": "a", "value": "Inim2"}
|
|
17
|
+
]},
|
|
18
|
+
{ "tag": "880", "ind1": " ", "ind2": " ", "subfields": [
|
|
19
|
+
{ "code": "6", "value": "700-02" },
|
|
20
|
+
{ "code": "a", "value": "Inim2"}
|
|
21
|
+
]}
|
|
22
|
+
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"message": [
|
|
3
3
|
"500 ‡a Whatever.",
|
|
4
|
+
"700 1 ‡a A., A., ‡e kirjoittaja, ‡e taiteilija.",
|
|
4
5
|
"700 1 ‡a B., B., ‡e kirjoittaja.",
|
|
5
6
|
"700 1 ‡6 880-01 ‡a C., C., ‡e kirjoittaja.",
|
|
6
7
|
"880 1 ‡6 700-02 ‡a D., D., ‡e kirjoittaja.",
|
|
7
8
|
"700 1 ‡6 880-XX ‡a C., C., ‡e kirjoittaja.\t__SEPARATOR__\t700 1 ‡6 880-XX ‡a C., C., ‡e kirjoittaja.",
|
|
8
|
-
"880 1 ‡6
|
|
9
|
+
"880 1 ‡6 X00-XX ‡a D., D., ‡e kirjoittaja.\t__SEPARATOR__\t880 1 ‡6 X00-XX ‡a D., D., ‡e kirjoittaja."
|
|
9
10
|
],
|
|
10
11
|
"valid": false
|
|
11
12
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"message": [
|
|
3
3
|
"100 1 ‡6 880-01 ‡a Zabara, Olena, ‡e kirjoittaja, ‡e taiteilija.",
|
|
4
|
-
"100 1 ‡6 880-XX ‡a Zabara, Olena, ‡e kirjoittaja, ‡e taiteilija.\t__SEPARATOR__\t100 1 ‡6 880-XX ‡a Zabara, Olena, ‡e kirjoittaja, ‡e taiteilija.\t__SEPARATOR__\t880 1 ‡6
|
|
4
|
+
"100 1 ‡6 880-XX ‡a Zabara, Olena, ‡e kirjoittaja, ‡e taiteilija.\t__SEPARATOR__\t100 1 ‡6 880-XX ‡a Zabara, Olena, ‡e kirjoittaja, ‡e taiteilija.\t__SEPARATOR__\t880 1 ‡6 X00-XX/(N ‡a Забара, Олена, ‡e kirjoittaja, ‡e taiteilija."
|
|
5
5
|
],
|
|
6
6
|
"valid": false
|
|
7
7
|
}
|