Skip to content

Commit

Permalink
Extend error objects
Browse files Browse the repository at this point in the history
  • Loading branch information
nichtich committed Jan 24, 2024
1 parent 5832524 commit ccf4f5c
Show file tree
Hide file tree
Showing 12 changed files with 59 additions and 50 deletions.
49 changes: 27 additions & 22 deletions lib/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,15 @@ export class Validator {
const { fields, types } = record

for (let field of fields) {
var id = schedule.identifier(field)
const id = schedule.identifier(field)
const { tag, occurrence, subfields } = field

// count
if (id in schedule) {
fieldCount.visit(id)
if (subfieldCount && field.subfields && schedule[id].subfields) {
for (let i=0; i<field.subfields.length; i+=2) {
const code = field.subfields[i]
if (subfieldCount && subfields && schedule[id].subfields) {
for (let i=0; i<subfields.length; i+=2) {
const code = subfields[i]
if (code in schedule[id].subfields) {
subfieldCount.visit(`${id}$${code}`)
}
Expand All @@ -124,7 +125,7 @@ export class Validator {
errors.push({
error: "deprecatedField",
message: `field ${id} is deprecated`,
id,
tag, id,
})
} else {
errors.push(
Expand All @@ -133,11 +134,10 @@ export class Validator {
)
if (!fieldVisitor.visit(id) && options.nonrepeatableField) {
const message = `Field '${id}' must not be repeated.`
errors.push({ message, identifier: id, error: "nonrepeatableField" })
errors.push({ message, tag, id, error: "nonrepeatableField" })
}
}
} else if (options.undefinedField) {
const { tag, occurrence } = field
const error = occurrence
? {message: `Unknown field '${tag}/${occurrence}'.`, tag, occurrence}
: {message: `Unknown field '${tag}'.`, tag}
Expand Down Expand Up @@ -186,10 +186,12 @@ export class Validator {

// See https://format.gbv.de/schema/avram/specification#field-validation
const validateFieldContent = (field, definition, options, types, id) => {
const path = { id, tag: field.tag }
if (field.occurrence) path.occurrence = field.occurrence
if (Array.isArray(field.subfields)) { // variable field
return validateSubfields(field.subfields, definition.subfields, options, id)
return validateSubfields(field, definition.subfields, options, id)
} else if (options.invalidFieldValue) { // fixed field
return validateValue(field.value, definition, options, types, { id })
return validateValue(field.value, definition, options, types, path)
} else {
return []
}
Expand All @@ -209,11 +211,11 @@ const validateIndicators = (field, definition, options, id) => {
if (!options.invalidIndicator) return []
const errors = []
for (let indicator of ["indicator1", "indicator2"]) {
const path = { id, indicator }
const path = { tag: field.tag, id, indicator }
if (indicator in field !== indicator in definition) {
errors.push({
message: `Existence mismatch of ${loc(path)}.`,
error: "invalidIndicator",
message: `Existence mismatch of ${loc(path)}`,
error: "invalidIndicator", ...path,
})
} else if (indicator in field) {
const { codes, pattern } = definition[indicator] ?? { codes: { " ": {} } }
Expand All @@ -225,7 +227,7 @@ const validateIndicators = (field, definition, options, id) => {
}

// See https://format.gbv.de/schema/avram/specification#field-validation
export const validateSubfields = (subfields, schedule, options, id) => {
const validateSubfields = ({ tag, subfields }, schedule, options, id) => {
if (!options.invalidSubfield) return []

const errors = []
Expand All @@ -234,7 +236,7 @@ export const validateSubfields = (subfields, schedule, options, id) => {
for (let i=0; i<subfields.length; i+=2) {
const code = subfields[i]
const definition = schedule[code]
const path = { id, subfield: code }
const path = { id, tag, subfield: code }

if (code in schedule) {
if (options.deprecatedSubfield && definition.deprecated) {
Expand Down Expand Up @@ -266,11 +268,14 @@ export const validateSubfields = (subfields, schedule, options, id) => {
}

if (options.missingSubfield) {
errors.push(...visitor.missing().map(subfield => ({
error: "missingSubfield",
message: `missing ${loc({id, subfield})}`,
id, subfield,
})))
errors.push(...visitor.missing().map(subfield => {
const path = { id, tag, subfield }
return {
error: "missingSubfield",
message: `missing ${loc(path)}`,
...path,
}
}))
}

return errors
Expand All @@ -295,7 +300,7 @@ export const validateValue = (value, definition, options, recordTypes, path) =>
}

// See https://format.gbv.de/schema/avram/specification#value-validation
export const validatePattern = (value, pattern, path) => {
const validatePattern = (value, pattern, path) => {
if (pattern) {
const regexp = new RegExp(pattern, "u")
if (!regexp.test(value)) {
Expand All @@ -310,7 +315,7 @@ export const validatePattern = (value, pattern, path) => {
}

// See https://format.gbv.de/schema/avram/specification#validation-with-codelist
export const validateCode = (value, codes, options = {}, path = {}, len=null) => {
const validateCode = (value, codes, options = {}, path = {}, len=null) => {
const { undefinedCode, undefinedCodelist, codelists } = options
const isIndicator = "indicator" in path

Expand Down Expand Up @@ -355,7 +360,7 @@ export const validateCode = (value, codes, options = {}, path = {}, len=null) =>
} : {
error: "undefinedCode",
message: `value '${value}' is not defined in codelist in ${loc(path)}`,
value, ...path,
...path, value,
}

return [ error ]
Expand Down
2 changes: 1 addition & 1 deletion test/suite/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Each test is an object with keys:
* `code` subfield code an error was found in
* `tag` tag of the field an error was found in
* `occurrence` occurrence of the field an error was found in
* `identifier` field identifier from the field schedule for the field an error was found in
* `id` field identifier from the field schedule for the field an error was found in
* `pattern` regular expression that was violated
* `value` malformed or disallowed value that caused an error

Expand Down
6 changes: 3 additions & 3 deletions test/suite/codes.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@
{
"error": "undefinedCode",
"message": "value 'deu' is not defined in codelist in field lang",
"id": "lang",
"id": "lang", "tag": "lang",
"value": "deu"
},
{
"error": "undefinedCode",
"message": "value 'y' is not defined in codelist in field bool",
"id": "bool",
"id": "bool", "tag": "bool",
"value": "y"
},
{
Expand Down Expand Up @@ -69,7 +69,7 @@
{
"error": "undefinedCode",
"message": "value 'y' is not defined in codelist in field bool",
"id": "bool",
"id": "bool", "tag": "bool",
"value": "y"
}
]
Expand Down
4 changes: 2 additions & 2 deletions test/suite/deprecated.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
{
"record": [ { "tag": "old", "value": "1" } ],
"errors": [ {
"error": "deprecatedField", "id": "old",
"error": "deprecatedField", "tag": "old", "id": "old",
"message": "field old is deprecated"
} ]
},
Expand All @@ -36,7 +36,7 @@
"errors": [ {
"error": "deprecatedSubfield",
"message": "field sub subfield o is deprecated",
"id": "sub",
"id": "sub", "tag": "sub",
"subfield": "o"
} ]
}
Expand Down
4 changes: 2 additions & 2 deletions test/suite/flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
{
"error": "invalidFlag",
"message": "value 'x' is not defined in flags in field a position 0-1",
"id": "a",
"id": "a", "tag": "a",
"position": "0-1",
"value": "x"
},
{
"error": "invalidFlag",
"message": "value 'y' is not defined in flags in field a position 2-7",
"id": "a",
"id": "a", "tag": "a",
"position": "2-7",
"value": "y"
}
Expand Down
2 changes: 1 addition & 1 deletion test/suite/ignore_unknown.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
{
"error": "undefinedSubfield",
"message": "unknown field known subfield a",
"id": "known",
"id": "known", "tag": "known",
"subfield": "a"
},
{
Expand Down
6 changes: 5 additions & 1 deletion test/suite/indicators.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
{
"error": "patternMismatch",
"message": "value '0' does not match regex pattern '[^0-9]' in field 210 indicator2",
"tag": "210",
"id": "210",
"indicator": "indicator2",
"pattern": "[^0-9]",
Expand All @@ -57,12 +58,15 @@
"errors": [
{
"error": "invalidIndicator",
"message": "Existence mismatch of field 010 indicator1."
"message": "Existence mismatch of field 010 indicator1",
"tag": "010", "id": "010",
"indicator": "indicator1"
},
{
"error": "invalidIndicator",
"message": "value 'x' in field 010 indicator2 is not defined in codelist",
"id": "010",
"tag": "010",
"indicator": "indicator2",
"value": "x"
}
Expand Down
2 changes: 1 addition & 1 deletion test/suite/positions.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"errors": [{
"error": "invalidPosition",
"message": "field x position 01-2 does not exist",
"id": "x",
"id": "x", "tag": "x",
"position": "01-2",
"value": "a"
}]
Expand Down
8 changes: 4 additions & 4 deletions test/suite/subfields.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
{
"error": "missingSubfield",
"message": "missing field _ subfield 0",
"id": "_",
"id": "_", "tag": "_",
"subfield": "0"
}
]
Expand All @@ -37,7 +37,7 @@
{
"error": "nonrepeatableSubfield",
"message": "field _ subfield 0 must not be repeated",
"id": "_",
"id": "_", "tag": "_",
"subfield": "0"
}
]
Expand All @@ -50,13 +50,13 @@
{
"error": "undefinedSubfield",
"message": "unknown field _ subfield x",
"id": "_",
"id": "_", "tag": "_",
"subfield": "x"
},
{
"error": "missingSubfield",
"message": "missing field _ subfield 0",
"id": "_",
"id": "_", "tag": "_",
"subfield": "0"
}
]
Expand Down
8 changes: 4 additions & 4 deletions test/suite/types.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
{
"error": "patternMismatch",
"message": "value '9' does not match regex pattern '[a-z]' in field A",
"id": "A",
"id": "A", "tag": "A",
"pattern": "[a-z]",
"value": "9"
},
{
"error": "undefinedCode",
"message": "value '9' is not defined in codelist in field A",
"id": "A",
"id": "A", "tag": "A",
"value": "9"
}
]
Expand All @@ -51,15 +51,15 @@
{
"error": "patternMismatch",
"message": "value 'x' does not match regex pattern '0' in field A position 0",
"id": "A",
"id": "A", "tag": "A",
"pattern": "0",
"value": "x",
"position": "0"
},
{
"error": "patternMismatch",
"message": "value 'x' does not match regex pattern '[0-9]' in field A",
"id": "A",
"id": "A", "tag": "A",
"pattern": "[0-9]",
"value": "x"
}
Expand Down
8 changes: 4 additions & 4 deletions test/suite/validate-values.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
{
"error": "patternMismatch",
"message": "value 'x' does not match regex pattern '[0-9]' in field _",
"id": "_",
"id": "_", "tag": "_",
"pattern": "[0-9]",
"value": "x"
}
Expand All @@ -37,7 +37,7 @@
{
"error": "undefinedCode",
"message": "value 'x' is not defined in codelist in field _",
"id": "_",
"id": "_", "tag": "_",
"value": "x"
}
]
Expand Down Expand Up @@ -75,15 +75,15 @@
{
"error": "patternMismatch",
"message": "value '9' does not match regex pattern '[a-z]' in field _ position 00",
"id": "_",
"id": "_", "tag": "_",
"position": "00",
"pattern": "[a-z]",
"value": "9"
},
{
"error": "invalidPosition",
"message": "field _ position 01-02 does not exist",
"id": "_",
"id": "_", "tag": "_",
"position": "01-02",
"value": "9a"
}
Expand Down
10 changes: 5 additions & 5 deletions test/suite/validator.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@
{
"error": "missingSubfield",
"message": "missing field A subfield x",
"id": "A",
"id": "A", "tag": "A",
"subfield": "x"
},
{
"message": "value '1' does not match regex pattern '^[a-z]$' in field A subfield x",
"error": "patternMismatch",
"id": "A",
"id": "A", "tag": "A",
"subfield": "x",
"pattern": "^[a-z]$",
"value": "1"
},
{ "identifier": "A", "message": "Field 'A' must not be repeated.", "error": "nonrepeatableField" },
{ "tag": "A", "id": "A", "message": "Field 'A' must not be repeated.", "error": "nonrepeatableField" },
{ "tag": "Y", "occurrence": "1", "message": "Unknown field 'Y/1'.", "error": "undefinedField" }
]
},{
Expand All @@ -60,12 +60,12 @@
{
"error": "undefinedCode",
"message": "value 'z' is not defined in codelist in field B",
"id": "B",
"id": "B", "tag": "B",
"value": "z"
},{
"error": "undefinedCode",
"message": "value ' ' is not defined in codelist in field C subfield z",
"id": "C",
"id": "C", "tag": "C",
"subfield": "z",
"value": " "
},
Expand Down

0 comments on commit ccf4f5c

Please sign in to comment.