Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove experimental schema loading code #152

Merged
merged 4 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 28 additions & 49 deletions bids/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,111 +2,90 @@ import castArray from 'lodash/castArray'
import semver from 'semver'

import { buildSchemas } from '../validator/schema/init'
import { generateIssue } from '../common/issues/issues'
import { generateIssue, IssueError } from '../common/issues/issues'
import { SchemaSpec, SchemasSpec } from '../common/schema/types'

const alphanumericRegExp = new RegExp('^[a-zA-Z0-9]+$')
const alphabeticRegExp = new RegExp('^[a-zA-Z]+$')

/**
* Build a HED schema collection based on the defined BIDS schemas.
*
* @param {BidsDataset} dataset The BIDS dataset being validated.
* @param {object} schemaDefinition The version spec for the schema to be loaded.
* @returns {Promise<[Schemas,Issue[]]>|Promise<never>} A Promise with the schema collection and any issues found, or an issue list upon failure.
* @param {SchemasSpec} schemaDefinition The version spec for the schema to be loaded.
* @returns {Promise<Schemas>} A Promise with the schema collection and any issues found, or an issue list upon failure.
* @throws {IssueError} If the schema specification is invalid or missing.
*/
export function buildBidsSchemas(dataset, schemaDefinition) {
export async function buildBidsSchemas(dataset, schemaDefinition) {
let schemasSpec
let issues
if (schemaDefinition) {
;[schemasSpec, issues] = validateSchemasSpec(schemaDefinition)
schemasSpec = validateSchemasSpec(schemaDefinition)
} else if (dataset.datasetDescription.jsonData?.HEDVersion) {
;[schemasSpec, issues] = parseSchemasSpec(dataset.datasetDescription.jsonData.HEDVersion)
schemasSpec = parseSchemasSpec(dataset.datasetDescription.jsonData.HEDVersion)
} else {
;[schemasSpec, issues] = [null, [generateIssue('invalidSchemaSpecification', { spec: 'no schema available' })]]
}
if (issues.length > 0) {
return Promise.reject(issues)
} else {
return buildSchemas(schemasSpec).then(([schemas]) => [schemas, issues])
throw new IssueError(generateIssue('invalidSchemaSpecification', { spec: 'no schema available' }))
}
return buildSchemas(schemasSpec)
}

export function validateSchemasSpec(schemasSpec) {
// TODO: implement
function validateSchemasSpec(schemasSpec) {
if (schemasSpec instanceof SchemasSpec) {
return [schemasSpec, []]
} else if (schemasSpec instanceof Map) {
const newSchemasSpec = new SchemasSpec()
newSchemasSpec.data = schemasSpec
return [newSchemasSpec, []]
return schemasSpec
} else {
return [null, [generateIssue('invalidSchemaSpecification', { spec: JSON.stringify(schemasSpec) })]]
throw new IssueError(generateIssue('invalidSchemaSpecification', { spec: JSON.stringify(schemasSpec) }))
}
}

export function parseSchemasSpec(hedVersion) {
const schemasSpec = new SchemasSpec()
const processVersion = castArray(hedVersion)
const issues = []
for (const schemaVersion of processVersion) {
const [schemaSpec, verIssues] = parseSchemaSpec(schemaVersion)
if (verIssues.length > 0) {
issues.push(...verIssues)
} else {
schemasSpec.addSchemaSpec(schemaSpec)
}
const schemaSpec = parseSchemaSpec(schemaVersion)
schemasSpec.addSchemaSpec(schemaSpec)
}
return [schemasSpec, issues]
return schemasSpec
}

export function parseSchemaSpec(schemaVersion) {
const [[nickname, schema], nicknameIssues] = splitNicknameAndSchema(schemaVersion)
if (nicknameIssues.length > 0) {
return [null, nicknameIssues]
}
const [[library, version], libraryIssues] = splitLibraryAndVersion(schema, schemaVersion)
if (libraryIssues.length > 0) {
return [null, libraryIssues]
}
const schemaSpec = new SchemaSpec(nickname, version, library)
return [schemaSpec, []]
const [nickname, schema] = splitNicknameAndSchema(schemaVersion)
const [library, version] = splitLibraryAndVersion(schema, schemaVersion)
return new SchemaSpec(nickname, version, library)
}

function splitNicknameAndSchema(schemaVersion) {
const nicknameSplit = schemaVersion.split(':')
let nickname = ''
let schema
if (nicknameSplit.length > 2) {
return [['', ''], [generateIssue('invalidSchemaSpecification', { spec: schemaVersion })]]
throw new IssueError(generateIssue('invalidSchemaSpecification', { spec: schemaVersion }))
}
if (nicknameSplit.length > 1) {
;[nickname, schema] = nicknameSplit
if (nickname === '' || !alphanumericRegExp.test(nickname)) {
return [['', ''], [generateIssue('invalidSchemaNickname', { nickname: nickname, spec: schemaVersion })]]
if (!alphabeticRegExp.test(nickname)) {
throw new IssueError(generateIssue('invalidSchemaNickname', { nickname: nickname, spec: schemaVersion }))
}
} else {
schema = nicknameSplit[0]
}
return [[nickname, schema], []]
return [nickname, schema]
}

function splitLibraryAndVersion(schemaVersion, originalVersion) {
const versionSplit = schemaVersion.split('_')
let library = ''
let version
if (versionSplit.length > 2) {
return [['', ''], [generateIssue('invalidSchemaSpecification', { spec: originalVersion })]]
throw new IssueError(generateIssue('invalidSchemaSpecification', { spec: originalVersion }))
}
if (versionSplit.length > 1) {
;[library, version] = versionSplit
if (library === '' || !alphanumericRegExp.test(library)) {
return [['', ''], [generateIssue('invalidSchemaSpecification', { spec: originalVersion })]]
if (!alphabeticRegExp.test(library)) {
throw new IssueError(generateIssue('invalidSchemaSpecification', { spec: originalVersion }))
}
} else {
version = versionSplit[0]
}
if (!semver.valid(version)) {
return [['', ''], [generateIssue('invalidSchemaSpecification', { spec: originalVersion })]]
throw new IssueError(generateIssue('invalidSchemaSpecification', { spec: originalVersion }))
}
return [[library, version], []]
return [library, version]
}
54 changes: 26 additions & 28 deletions bids/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@ import { BidsHedColumnValidator } from './validator/bidsHedColumnValidator'
* Validate a BIDS dataset.
*
* @param {BidsDataset} dataset The BIDS dataset.
* @param {object} schemaDefinition The version spec for the schema to be loaded.
* @param {SchemasSpec} schemaDefinition The version spec for the schema to be loaded.
* @returns {Promise<BidsIssue[]>} Any issues found.
*/
export function validateBidsDataset(dataset, schemaDefinition) {
return buildBidsSchemas(dataset, schemaDefinition).then(
([hedSchemas, schemaLoadIssues]) => {
return new BidsHedValidator(dataset, hedSchemas)
.validateFullDataset()
.catch(BidsIssue.generateInternalErrorPromise)
.then((issues) => issues.concat(BidsHedIssue.fromHedIssues(schemaLoadIssues, dataset.datasetDescription.file)))
},
(issues) => BidsHedIssue.fromHedIssues(issues, dataset.datasetDescription.file),
)
export async function validateBidsDataset(dataset, schemaDefinition) {
try {
const hedSchemas = await buildBidsSchemas(dataset, schemaDefinition)
const validator = new BidsHedValidator(dataset, hedSchemas)
try {
return validator.validateFullDataset()
} catch (internalError) {
return BidsIssue.generateInternalErrorPromise(internalError)
}
} catch (schemaIssues) {
return BidsHedIssue.fromHedIssues(schemaIssues, dataset.datasetDescription.file)
}
}

/**
Expand Down Expand Up @@ -58,25 +60,21 @@ class BidsHedValidator {
/**
* Validate a full BIDS dataset using a HED schema collection.
*
* @returns {Promise<BidsIssue[]>|Promise<never>} Any issues found.
* @returns {Promise<BidsIssue[]>} Any issues found.
*/
validateFullDataset() {
try {
const sidecarValidator = new BidsHedSidecarValidator(this.dataset, this.hedSchemas)
const hedColumnValidator = new BidsHedColumnValidator(this.dataset, this.hedSchemas)
const sidecarErrorsFound = this._pushIssues(sidecarValidator.validateSidecars())
const hedColumnErrorsFound = this._pushIssues(hedColumnValidator.validate())
if (sidecarErrorsFound || hedColumnErrorsFound) {
return Promise.resolve(this.issues)
}
for (const eventFileData of this.dataset.eventData) {
const tsvValidator = new BidsHedTsvValidator(eventFileData, this.hedSchemas)
this.issues.push(...tsvValidator.validate())
}
return Promise.resolve(this.issues)
} catch (e) {
return Promise.reject(e)
async validateFullDataset() {
const sidecarValidator = new BidsHedSidecarValidator(this.dataset, this.hedSchemas)
const hedColumnValidator = new BidsHedColumnValidator(this.dataset, this.hedSchemas)
const sidecarErrorsFound = this._pushIssues(sidecarValidator.validateSidecars())
const hedColumnErrorsFound = this._pushIssues(hedColumnValidator.validate())
if (sidecarErrorsFound || hedColumnErrorsFound) {
return this.issues
}
for (const eventFileData of this.dataset.eventData) {
const tsvValidator = new BidsHedTsvValidator(eventFileData, this.hedSchemas)
this.issues.push(...tsvValidator.validate())
}
return this.issues
}

/**
Expand Down
20 changes: 0 additions & 20 deletions common/issues/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,26 +252,6 @@ export default {
level: 'error',
message: stringTemplate`The supplied schema specification is invalid. Specification: ${'spec'}.`,
},
requestedSchemaLoadFailedFallbackUsed: {
hedCode: 'SCHEMA_LOAD_FAILED',
level: 'warning',
message: stringTemplate`The requested schema failed to load. The fallback schema bundled with this validator will be used instead. Specification: ${'spec'}.`,
},
requestedSchemaLoadFailedNoFallbackUsed: {
hedCode: 'SCHEMA_LOAD_FAILED',
level: 'error',
message: stringTemplate`The requested schema failed to load. The validator did not attempt to load a fallback schema. Specification: ${'spec'}.`,
},
fallbackSchemaLoadFailed: {
hedCode: 'SCHEMA_LOAD_FAILED',
level: 'error',
message: stringTemplate`The fallback schema bundled with this validator failed to load. No HED validation was performed.`,
},
noFallbackSchemaForLibrary: {
hedCode: 'SCHEMA_LOAD_FAILED',
level: 'error',
message: stringTemplate`No fallback schema was found for library "${'library'}". No HED validation was performed.`,
},
bundledSchemaLoadFailed: {
hedCode: 'SCHEMA_LOAD_FAILED',
level: 'error',
Expand Down
6 changes: 0 additions & 6 deletions common/schema/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,3 @@ export const localSchemaList = new Map([
['HED_testlib_1.0.2', require('../../data/HED_testlib_1.0.2.xml')],
['HED_testlib_2.0.0', require('../../data/HED_testlib_2.0.0.xml')],
])

export const fallbackFilePath = new Map([
['', 'data/HED8.2.0.xml'],
['score', 'data/HED_score_1.1.0.xml'],
['testlib', 'data/HED_testlib_2.0.0.xml'],
])
Loading
Loading