Skip to content

Commit

Permalink
Refactor sidecar validator to only validate a single sidecar file
Browse files Browse the repository at this point in the history
  • Loading branch information
happy5214 committed Jun 28, 2024
1 parent 7cfe86b commit 7fb593a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 56 deletions.
20 changes: 5 additions & 15 deletions bids/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ class BidsHedValidator {
* @returns {Promise<BidsIssue[]>} Any issues found.
*/
async validateFullDataset() {
const sidecarValidator = new BidsHedSidecarValidator(this.dataset.sidecarData, this.hedSchemas)
const sidecarErrorsFound = this._pushIssues(sidecarValidator.validateSidecars())
if (sidecarErrorsFound) {
for (const sidecar of this.dataset.sidecarData) {
const sidecarValidator = new BidsHedSidecarValidator(sidecar, this.hedSchemas)
this.issues.push(...sidecarValidator.validate())
}
if (BidsIssue.anyAreErrors(this.issues)) {
return this.issues
}
for (const eventFileData of this.dataset.eventData) {
Expand All @@ -75,16 +77,4 @@ class BidsHedValidator {
}
return this.issues
}

/**
* Push a list of issues to the validator's issue list.
*
* @param {BidsIssue[]} issues A list of issues generated by a file type-specific validator.
* @returns {boolean} Whether any of the issues generated/added were errors as opposed to warnings.
* @private
*/
_pushIssues(issues) {
this.issues.push(...issues)
return BidsIssue.anyAreErrors(issues)
}
}
68 changes: 28 additions & 40 deletions bids/validator/bidsHedSidecarValidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import { generateIssue } from '../../common/issues/issues'
*/
export class BidsHedSidecarValidator {
/**
* The BIDS sidecar data being validated.
* @type {BidsSidecar[]}
* The BIDS sidecar being validated.
* @type {BidsSidecar}
*/
sidecarData
sidecar
/**
* The HED schema collection being validated against.
* @type {Schemas}
Expand All @@ -27,50 +27,40 @@ export class BidsHedSidecarValidator {
/**
* Constructor.
*
* @param {BidsSidecar[]} sidecarData The BIDS sidecar data being validated.
* @param {BidsSidecar} sidecar The BIDS sidecar being validated.
* @param {Schemas} hedSchemas The HED schema collection being validated against.
*/
constructor(sidecarData, hedSchemas) {
this.sidecarData = sidecarData
constructor(sidecar, hedSchemas) {
this.sidecar = sidecar
this.hedSchemas = hedSchemas
this.issues = []
}

/**
* Validate a collection of BIDS sidecars. This method returns the complete issue list for convenience.
* Validate a BIDS JSON sidecar file. This method returns the complete issue list for convenience.
*
* @returns {BidsIssue[]} Any issues found during validation of the sidecars.
* @returns {BidsIssue[]} Any issues found during validation of this sidecar file.
*/
validateSidecars() {
for (const sidecar of this.sidecarData) {
const sidecarParsingIssues = BidsHedIssue.fromHedIssues(sidecar.parseHedStrings(this.hedSchemas), sidecar.file)
this.issues.push(...sidecarParsingIssues)
if (sidecarParsingIssues.length > 0) {
break
}
const sidecarIssues = this.validateSidecar(sidecar)
this.issues.push(...sidecarIssues)
validate() {
const sidecarParsingIssues = BidsHedIssue.fromHedIssues(
this.sidecar.parseHedStrings(this.hedSchemas),
this.sidecar.file,
)
this.issues.push(...sidecarParsingIssues)
if (sidecarParsingIssues.length > 0) {
return this.issues
}
const sidecarIssues = [...this._validateStrings(), ...this.validateCurlyBraces()]
this.issues.push(...sidecarIssues)
return this.issues
}

/**
* Validate an individual BIDS sidecar.
*
* @param {BidsSidecar} sidecar A BIDS sidecar.
* @returns {BidsIssue[]} All issues found.
*/
validateSidecar(sidecar) {
return [...this._validateSidecarStrings(sidecar), ...BidsHedSidecarValidator.validateSidecarCurlyBraces(sidecar)]
}

/**
* Validate an individual BIDS sidecar's HED strings.
*
* @param {BidsSidecar} sidecar A BIDS sidecar.
* @returns {BidsIssue[]} All issues found.
*/
_validateSidecarStrings(sidecar) {
_validateStrings() {
const issues = []

const categoricalOptions = {
Expand All @@ -84,12 +74,12 @@ export class BidsHedSidecarValidator {
definitionsAllowed: 'no',
}

for (const [sidecarKey, hedData] of sidecar.parsedHedData) {
for (const [sidecarKey, hedData] of this.sidecar.parsedHedData) {
if (hedData instanceof ParsedHedString) {
issues.push(...this._validateSidecarString(sidecarKey, hedData, sidecar, valueOptions))
issues.push(...this._validateString(sidecarKey, hedData, valueOptions))
} else if (hedData instanceof Map) {
for (const valueString of hedData.values()) {
issues.push(...this._validateSidecarString(sidecarKey, valueString, sidecar, categoricalOptions))
issues.push(...this._validateString(sidecarKey, valueString, categoricalOptions))
}
} else {
throw new Error('Unexpected type found in sidecar parsedHedData map.')
Expand All @@ -104,38 +94,36 @@ export class BidsHedSidecarValidator {
*
* @param {string} sidecarKey The sidecar key this string belongs to.
* @param {ParsedHedString} sidecarString The parsed sidecar HED string.
* @param {BidsSidecar} sidecar The BIDS sidecar.
* @param {Object} options Options specific to this validation run to pass to {@link validateHedString}.
* @returns {BidsIssue[]} All issues found.
* @private
*/
_validateSidecarString(sidecarKey, sidecarString, sidecar, options) {
_validateString(sidecarKey, sidecarString, options) {
// Parsing issues already pushed in validateSidecars()
if (sidecarString === null) {
return []
}

const [, hedIssues] = validateHedString(sidecarString, this.hedSchemas, options)
return BidsHedIssue.fromHedIssues(hedIssues, sidecar.file, { sidecarKey })
return BidsHedIssue.fromHedIssues(hedIssues, this.sidecar.file, { sidecarKey })
}

/**
* Validate an individual BIDS sidecar's curly braces.
* Validate this sidecar's curly braces.
*
* @param {BidsSidecar} sidecar A BIDS sidecar.
* @returns {BidsIssue[]} All issues found.
*/
static validateSidecarCurlyBraces(sidecar) {
validateCurlyBraces() {
const issues = []
const references = sidecar.columnSpliceMapping
const references = this.sidecar.columnSpliceMapping

for (const [key, referredKeys] of references) {
for (const referredKey of referredKeys) {
if (references.has(referredKey)) {
issues.push(
BidsHedIssue.fromHedIssue(
generateIssue('recursiveCurlyBracesWithKey', { column: referredKey, referrer: key }),
sidecar.file,
this.sidecar.file,
),
)
}
Expand Down
5 changes: 4 additions & 1 deletion bids/validator/bidsHedTsvValidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ export class BidsHedTsvValidator {
this.tsvFile.mergedSidecar.parseHedStrings(this.hedSchemas),
this.tsvFile.file,
)
const curlyBraceIssues = BidsHedSidecarValidator.validateSidecarCurlyBraces(this.tsvFile.mergedSidecar)
const curlyBraceIssues = new BidsHedSidecarValidator(
this.tsvFile.mergedSidecar,
this.hedSchemas,
).validateCurlyBraces()
const hedColumnIssues = this._validateHedColumn()
this.issues.push(...parsingIssues, ...curlyBraceIssues, ...hedColumnIssues)
if (BidsIssue.anyAreErrors(this.issues)) {
Expand Down

0 comments on commit 7fb593a

Please sign in to comment.