@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.
@@ -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)(`DOUBLE REMOVAL: REMOVE ${fieldsAsString}`, debug);
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)(`VALIDATION: DUPLICATE DETECTED ${fieldsAsString}`, debug);
278
+ (0, _utils.nvdebug)(`$6 VALIDATION: DUPLICATE DETECTED ${fieldsAsString}`, debug);
244
279
  }
245
- (0, _utils.nvdebug)(`DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${fieldsAsString}`, debug);
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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"}
@@ -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} ${sf.value.substring(0, 3)}-XX${subfield6GetTail(sf)}`;
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
@@ -14,7 +14,7 @@
14
14
  "url": "git@github.com:natlibfi/marc-record-validators-melinda.git"
15
15
  },
16
16
  "license": "MIT",
17
- "version": "10.2.2",
17
+ "version": "10.2.3",
18
18
  "main": "./dist/index.js",
19
19
  "publishConfig": {
20
20
  "access": "public"
@@ -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(`DOUBLE REMOVAL: REMOVE ${fieldsAsString}`, debug);
295
+ nvdebug(`$6 DOUBLE REMOVAL: REMOVE ${fieldsAsString}`, debug);
258
296
  fields.forEach(currField => record.removeField(currField));
259
297
  return;
260
298
  }
261
- nvdebug(`VALIDATION: DUPLICATE DETECTED ${fieldsAsString}`, debug);
299
+
300
+ nvdebug(`$6 VALIDATION: DUPLICATE DETECTED ${fieldsAsString}`, debug);
262
301
 
263
302
  }
264
- nvdebug(`DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${fieldsAsString}`, debug);
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
  }
@@ -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} ${sf.value.substring(0, 3)}-XX${subfield6GetTail(sf)}`;
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,6 @@
1
+ { "_validationOptions": {},
2
+ "leader": "01331cam a22003494i 4500",
3
+ "fields": [
4
+ { "tag": "100", "ind1": " ", "ind2": " ", "subfields": [ { "code": "a", "value": "Nimi"} ]}
5
+ ]
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "Fix-09: remove duplicate 1XX-7XX (no chains)",
3
+ "enabled": true,
4
+ "fix": true,
5
+ "only": false
6
+ }
@@ -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,6 @@
1
+ {
2
+ "description": "Fix-10: remove duplicate 1XX-7XX $6-chains",
3
+ "enabled": true,
4
+ "fix": true,
5
+ "only": false
6
+ }
@@ -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 700-XX ‡a D., D., ‡e kirjoittaja.\t__SEPARATOR__\t880 1 ‡6 700-XX ‡a D., D., ‡e kirjoittaja."
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 100-XX/(N ‡a Забара, Олена, ‡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 X00-XX/(N ‡a Забара, Олена, ‡e kirjoittaja, ‡e taiteilija."
5
5
  ],
6
6
  "valid": false
7
7
  }