diff --git a/bids/index.js b/bids/index.js index 729bb851..af24e5ff 100644 --- a/bids/index.js +++ b/bids/index.js @@ -1,7 +1,7 @@ -import buildBidsSchemas from './schema' +import { buildBidsSchemas } from './schema' import validateBidsDataset from './validate' import { BidsJsonFile, BidsSidecar } from './types/json' -import { BidsTabularFile, BidsTsvFile } from './types/tsv' +import { BidsTsvFile } from './types/tsv' import BidsDataset from './types/dataset' import { BidsHedIssue, BidsIssue } from './types/issues' import BidsHedSidecarValidator from './validator/sidecarValidator' @@ -10,7 +10,6 @@ import BidsHedTsvValidator from './validator/tsvValidator' export { BidsDataset, BidsTsvFile, - BidsTabularFile, BidsJsonFile, BidsSidecar, BidsIssue, @@ -24,7 +23,6 @@ export { export default { BidsDataset, BidsTsvFile, - BidsTabularFile, BidsJsonFile, BidsSidecar, BidsIssue, diff --git a/bids/types/dataset.js b/bids/types/dataset.js index 0a007144..ede11909 100644 --- a/bids/types/dataset.js +++ b/bids/types/dataset.js @@ -1,7 +1,7 @@ export class BidsDataset { /** * The dataset's event file data. - * @type {BidsEventFile[]} + * @type {BidsTsvFile[]} */ eventData /** diff --git a/bids/types/tsv.js b/bids/types/tsv.js index ad0f919e..c2b116d6 100644 --- a/bids/types/tsv.js +++ b/bids/types/tsv.js @@ -98,17 +98,29 @@ export class BidsTsvElement { */ hedString + /** + * The ParsedHedString representation of this row + * @type {ParsedHedString} + */ parsedHedString /** - * The file this row belongs to. + * The file this row belongs to (usually just the path). * @type {Object} */ file + /** + * The onset represented by this row or a NaN. + * @type {Number} + */ onset + /** + * The line number(s) (including the header) represented by this row. + */ tsvLine + /** * Constructor. * @@ -141,7 +153,12 @@ export class BidsTsvElement { * A row in a BIDS TSV file. */ export class BidsTsvRow extends BidsTsvElement { + /** + * The map of column name to value for this row. + * @type {Map} + */ rowCells + /** * Constructor. * @@ -156,23 +173,3 @@ export class BidsTsvRow extends BidsTsvElement { this.rowCells = rowCells } } - -/** - * A BIDS events.tsv file. - * - * @deprecated Use {@link BidsTsvFile}. Will be removed in version 4.0.0. - */ -export class BidsEventFile extends BidsTsvFile { - /** - * Constructor. - * - * @param {string} name The name of the event TSV file. - * @param {string[]} potentialSidecars The list of potential JSON sidecars. - * @param {object} mergedDictionary The merged sidecar data. - * @param {{headers: string[], rows: string[][]}|string} tsvData This file's TSV data. - * @param {object} file The file object representing this file. - */ - constructor(name, potentialSidecars, mergedDictionary, tsvData, file) { - super(name, tsvData, file, potentialSidecars, mergedDictionary) - } -} diff --git a/tests/utils/map.spec.js b/tests/utils/map.spec.js deleted file mode 100644 index 028cf2f8..00000000 --- a/tests/utils/map.spec.js +++ /dev/null @@ -1,35 +0,0 @@ -import chai from 'chai' -const assert = chai.assert -import { describe, it } from '@jest/globals' - -import isEqual from 'lodash/isEqual' - -import * as mapUtils from '../../utils/map' - -describe('Map utility functions', () => { - describe('Non-equal duplicate filtering', () => { - it('must filter non-equal duplicates', () => { - const keyValueList = [ - ['first', 21], - ['second', 42], - ['duplicate', 63], - ['duplicate', 64], - ['third', 75], - ['fourth', 100], - ] - const expectedMap = new Map([ - ['first', 21], - ['second', 42], - ['third', 75], - ['fourth', 100], - ]) - const expectedDuplicates = [ - ['duplicate', 63], - ['duplicate', 64], - ] - const [actualMap, actualDuplicates] = mapUtils.filterNonEqualDuplicates(keyValueList, isEqual) - assert.deepStrictEqual(actualMap, expectedMap, 'Filtered map') - assert.sameDeepMembers(actualDuplicates, expectedDuplicates, 'Duplicate map') - }) - }) -}) diff --git a/utils/array.js b/utils/array.js index 546e7cba..cc5cfd5e 100644 --- a/utils/array.js +++ b/utils/array.js @@ -30,20 +30,3 @@ export function recursiveMap(fn, array) { return fn(array) } } - -/** - * Apply a function recursively to an array. - * - * @template T,U - * @param {function(T, U[]): U} fn The function to apply. - * @param {T[]} array The array to map. - * @param {U[]} [issues] An optional array to collect issues. - * @returns {U[]} The mapped array. - */ -export function recursiveMapNew(fn, array, issues = []) { - if (Array.isArray(array)) { - return array.map((element) => recursiveMap(fn, element, issues)) - } else { - return fn(array, issues) - } -} diff --git a/utils/hedData.js b/utils/hedData.js index 8e7c2814..5e75e83a 100644 --- a/utils/hedData.js +++ b/utils/hedData.js @@ -1,8 +1,5 @@ import lt from 'semver/functions/lt' -import ParsedHedTag from '../parser/parsedHedTag' -import { TagSpec } from '../parser/tokenizer' - /** * Determine the HED generation for a base schema version number. * @@ -18,32 +15,3 @@ export const getGenerationForSchemaVersion = function (version) { return 3 } } - -export const mergeParsingIssues = function (previousIssues, currentIssues) { - for (const [key, currentIssue] of Object.entries(currentIssues)) { - previousIssues[key] = previousIssues[key] !== undefined ? previousIssues[key].concat(currentIssue) : currentIssue - } -} - -/** - * Get the parent tag objects for a given short tag. - * - * @param {Schemas} hedSchemas The HED schema collection. - * @param {string} shortTag A short-form HED 3 tag. - * @returns {Map} A Map mapping a {@link Schema} to a {@link ParsedHedTag} object representing the full tag. - */ -export const getParsedParentTags = function (hedSchemas, shortTag) { - const parentTags = new Map() - for (const [schemaNickname, schema] of hedSchemas.schemas) { - try { - const parentTag = new ParsedHedTag( - new TagSpec(shortTag, 0, shortTag.length - 1, schemaNickname), - hedSchemas, - shortTag, - ) - parentTags.set(schema, parentTag) - // eslint-disable-next-line no-empty - } catch (e) {} - } - return parentTags -} diff --git a/utils/hedStrings.js b/utils/hedStrings.js index ed926c4c..9f6c7875 100644 --- a/utils/hedStrings.js +++ b/utils/hedStrings.js @@ -25,17 +25,6 @@ export const getTagSlashIndices = function (tag) { return indices } -/** - * Get the levels of a tag. - * - * @param {string} tag A HED tag string. - * @returns {string[]} The levels of this tag. - */ -export const getTagLevels = function (tag) { - const tagSlashIndices = getTagSlashIndices(tag) - return tagSlashIndices.map((tagSlashIndex) => tag.slice(0, tagSlashIndex)) -} - /** * Get the last part of a HED tag. * diff --git a/utils/map.js b/utils/map.js deleted file mode 100644 index fb45f915..00000000 --- a/utils/map.js +++ /dev/null @@ -1,51 +0,0 @@ -import identity from 'lodash/identity' -import isEqual from 'lodash/isEqual' - -/** - * Filter non-equal duplicates from a key-value list, - * - * @template K,V - * @param {[K,V][]} list A list of key-value pairs. - * @param {function(V, V): boolean} equalityFunction An equality function for the value data. - * @returns {[Map, [K,V][]]} A map and any non-equal duplicate keys found. - */ -export const filterNonEqualDuplicates = function (list, equalityFunction = isEqual) { - const map = new Map() - const duplicateKeySet = new Set() - const duplicates = [] - for (const [key, value] of list) { - if (!map.has(key)) { - map.set(key, value) - } else if (!equalityFunction(map.get(key), value)) { - duplicates.push([key, value]) - duplicateKeySet.add(key) - } - } - for (const key of duplicateKeySet) { - const value = map.get(key) - map.delete(key) - duplicates.push([key, value]) - } - return [map, duplicates] -} - -/** - * Group a list by a given grouping function. - * - * @template T, U - * @param {T[]} list The list to group. - * @param {function (T): U} groupingFunction A function mapping a list value to the key it is to be grouped under. - * @returns {Map} The grouped map. - */ -export const groupBy = function (list, groupingFunction = identity) { - const groupingMap = new Map() - for (const listEntry of list) { - const groupingValue = groupingFunction(listEntry) - if (groupingMap.has(groupingValue)) { - groupingMap.get(groupingValue).push(listEntry) - } else { - groupingMap.set(groupingValue, [listEntry]) - } - } - return groupingMap -} diff --git a/validator/dataset.js b/validator/dataset.js deleted file mode 100644 index 014f5adb..00000000 --- a/validator/dataset.js +++ /dev/null @@ -1,204 +0,0 @@ -import zip from 'lodash/zip' - -import { generateIssue, Issue } from '../common/issues/issues' -import { validateHedEventWithDefinitions } from './event' -import { parseHedStrings } from '../parser/parser' -import { filterNonEqualDuplicates } from '../utils/map' - -/** - * Parse the dataset's definitions and evaluate labels in the dataset. - * - * @param {ParsedHedString[]} parsedHedStrings The dataset's parsed HED strings. - * @returns {[Map, Issue[]]} The definition map and any issues found. - */ -export const parseDefinitions = function (parsedHedStrings) { - const issues = [] - const parsedHedStringDefinitions = parsedHedStrings.flatMap((parsedHedString) => - parsedHedString ? parsedHedString.definitions : [], - ) - const [definitionMap, definitionDuplicates] = filterNonEqualDuplicates( - parsedHedStringDefinitions, - (definition, other) => definition.definitionGroup.equivalent(other.definitionGroup), - ) - for (const [duplicateKey, duplicateValue] of definitionDuplicates) { - issues.push( - generateIssue('duplicateDefinition', { - definition: duplicateKey, - tagGroup: duplicateValue.originalTag, - }), - ) - } - return [definitionMap, issues] -} - -/** - * Check a parsed HED group for its onset and offset ordering. - * - * @param {ParsedHedGroup} parsedGroup A parsed HED group. - * @param {Set} activeScopes The active duration scopes, represented by the groups' canonical Def tags. - * @returns {Issue[]} Any issues found. - */ -const checkGroupForTemporalOrder = (parsedGroup, activeScopes) => { - if (parsedGroup.isSpecialGroup('Onset')) { - activeScopes.add(parsedGroup.defNameAndValue) - } - if (parsedGroup.isSpecialGroup('Inset') && !activeScopes.has(parsedGroup.defNameAndValue)) { - return [ - generateIssue('inactiveOnset', { - definition: parsedGroup.defNameAndValue, - tag: 'Inset', - }), - ] - } - if (parsedGroup.isSpecialGroup('Offset') && !activeScopes.delete(parsedGroup.defNameAndValue)) { - return [ - generateIssue('inactiveOnset', { - definition: parsedGroup.defNameAndValue, - tag: 'Offset', - }), - ] - } - return [] -} - -/** - * Validate onset and offset ordering. - * - * @param {ParsedHedString[]} hedStrings The dataset's HED strings. - * @param {Schemas} hedSchemas The HED schema container object. - * @returns {Issue[]} Any issues found. - */ -export const validateTemporalOrder = function (hedStrings, hedSchemas) { - const issues = [] - const activeScopes = new Set() - for (const hedString of hedStrings) { - const temporalGroups = hedString.tagGroups.filter((tagGroup) => tagGroup.isTemporalGroup) - const defNames = temporalGroups.map((tagGroup) => tagGroup.defNameAndValue) - const [defToGroup, duplicates] = filterNonEqualDuplicates(zip(defNames, temporalGroups), (tagGroup, other) => - tagGroup.equivalent(other), - ) - const duplicateDefs = new Set(duplicates.map((duplicate) => duplicate[0])) - for (const duplicate of duplicateDefs) { - issues.push( - generateIssue('duplicateTemporal', { - string: hedString.hedString, - definition: duplicate, - }), - ) - } - for (const parsedGroup of defToGroup.values()) { - issues.push(...checkGroupForTemporalOrder(parsedGroup, activeScopes)) - } - } - return issues -} - -/** - * Perform dataset-level validation on a HED dataset. - * - * @param {Definitions} definitions The parsed dataset definitions. - * @param {ParsedHedString[]} hedStrings The dataset's HED strings. - * @param {Schemas} hedSchemas The HED schema container object. - * @returns {Issue[]} Whether the HED dataset is valid and any issues found. - */ -export const validateDataset = function (definitions, hedStrings, hedSchemas) { - // TODO: Implement - const temporalOrderIssues = validateTemporalOrder(hedStrings, hedSchemas) - return temporalOrderIssues -} - -/** - * Validate a group of HED strings. - * - * @param {(string[]|ParsedHedString[])} parsedHedStrings The dataset's parsed HED strings. - * @param {Schemas} hedSchemas The HED schema container object. - * @param {DefinitionManager} definitions The dataset's parsed definitions. - * @param {Object} settings The configuration settings for validation. - * @returns {[boolean, Issue[]]} Whether the HED strings are valid and any issues found. - */ -export const validateHedEvents = function (parsedHedStrings, hedSchemas, definitions, settings) { - let stringsValid = true - let stringIssues = [] - for (const hedString of parsedHedStrings) { - const [valid, issues] = validateHedEventWithDefinitions(hedString, hedSchemas, definitions, settings) - stringsValid = stringsValid && valid - stringIssues = stringIssues.concat(issues) - } - return [stringsValid, stringIssues] -} - -/** - * Validate a HED dataset. - * - * @param {string[]} hedStrings The dataset's HED strings. - * @param {Schemas} hedSchemas The HED schema container object. - * @param {boolean} checkForWarnings Whether to check for warnings or only errors. - * @returns {[boolean, Issue[]]} Whether the HED dataset is valid and any issues found. - */ -export const validateHedDataset = function (hedStrings, hedSchemas, ...args) { - let settings - if (args[0] === Object(args[0])) { - settings = { - checkForWarnings: args[0].checkForWarnings ?? false, - validateDatasetLevel: args[0].validateDatasetLevel ?? true, - } - } else { - settings = { - checkForWarnings: args[0] ?? false, - validateDatasetLevel: true, - } - } - if (hedStrings.length === 0) { - return [true, []] - } - const [parsedHedStrings, parsingIssues] = parseHedStrings(hedStrings, hedSchemas, false) - const [definitions, definitionIssues] = parseDefinitions(parsedHedStrings) - const [stringsValid, stringIssues] = validateHedEvents(parsedHedStrings, hedSchemas, definitions, settings) - let datasetIssues = [] - if (stringsValid && settings.validateDatasetLevel) { - datasetIssues = validateDataset(definitions, parsedHedStrings, hedSchemas) - } - const issues = [...parsingIssues, ...definitionIssues, ...stringIssues, ...datasetIssues] - - return Issue.issueListWithValidStatus(issues) -} - -/** - * Validate a HED dataset with additional context. - * - * @param {string[]|ParsedHedString[]} hedStrings The dataset's HED strings. - * @param {BidsSidecar} contextHedStrings The dataset's context HED strings. - * @param {Schemas} hedSchemas The HED schema container object. - * @param {boolean} checkForWarnings Whether to check for warnings or only errors. - * @returns {[boolean, Issue[]]} Whether the HED dataset is valid and any issues found. - */ -export const validateHedDatasetWithContext = function (hedStrings, context, hedSchemas, ...args) { - let settings - if (args[0] === Object(args[0])) { - settings = { - checkForWarnings: args[0].checkForWarnings ?? false, - validateDatasetLevel: args[0].validateDatasetLevel ?? true, - } - } else { - settings = { - checkForWarnings: args[0] ?? false, - validateDatasetLevel: true, - } - } - if (hedStrings.length + context.hedStrings.length === 0) { - return [true, []] - } - const [parsedHedStrings, issues] = parseHedStrings(hedStrings, hedSchemas, true, false, false) - //const [parsedContextHedStrings, contextParsingIssues] = parseHedStrings(contextHedStrings, hedSchemas, false) - //const combinedParsedHedStrings = parsedHedStrings.concat(parsedContextHedStrings) - //const [definitions, definitionIssues] = parseDefinitions(combinedParsedHedStrings) - const [stringsValid, stringIssues] = validateHedEvents(parsedHedStrings, hedSchemas, context.definitions, settings) - issues.push(...stringIssues) - let datasetIssues = [] - if (stringsValid && settings.validateDatasetLevel) { - datasetIssues = validateDataset(context.definitions, parsedHedStrings, hedSchemas) - } - issues.push(...datasetIssues) - - return Issue.issueListWithValidStatus(issues) -} diff --git a/validator/event/index.js b/validator/event/index.js deleted file mode 100644 index 772718e3..00000000 --- a/validator/event/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import { validateHedString, validateHedEvent, validateHedEventWithDefinitions } from './init' - -import HedValidator from './validator' - -export { validateHedString, validateHedEvent, validateHedEventWithDefinitions, HedValidator } - -export default { - validateHedString, - validateHedEvent, - validateHedEventWithDefinitions, - HedValidator, -} diff --git a/validator/event/init.js b/validator/event/init.js deleted file mode 100644 index d744d87c..00000000 --- a/validator/event/init.js +++ /dev/null @@ -1,130 +0,0 @@ -import { parseHedString } from '../../parser/parser' -import HedValidator from './validator' -import { Issue } from '../../common/issues/issues' - -// /** -// * Perform initial validation on a HED string and parse it so further validation can be performed. -// * -// * @param {string|ParsedHedString} hedString The HED string to validate. -// * @param {Schemas} hedSchemas The HED schemas to validate against. -// * @param {Object} options Any validation options passed in. -// * @param {Map?} definitions The definitions for this HED dataset. -// * @returns {[ParsedHedString, Issue[], HedValidator]} The parsed HED string, the actual HED schema collection to use, any issues found, and whether to perform semantic validation. -// */ -// const initiallyValidateHedString = function (hedString, hedSchemas, options, definitions = null) { -// const [parsedString, parsingIssues] = parseHedString(hedString, hedSchemas) -// if (parsedString === null) { -// return [null, [].concat(...Object.values(parsingIssues)), null] -// } -// const hedValidator = new HedValidator(parsedString, hedSchemas, definitions, options) -// const allParsingIssues = [].concat(...Object.values(parsingIssues)) -// return [parsedString, allParsingIssues, hedValidator] -// } - -/** - * Validate a HED string. - * - * @param {string|ParsedHedString} hedString The HED string to validate. - * @param {Schemas} hedSchemas The HED schemas to validate against. - * @param {boolean?} checkForWarnings Whether to check for warnings or only errors. - * @param {boolean?} expectValuePlaceholderString Whether this string is expected to have a '#' placeholder representing a value. - * @returns {[boolean, Issue[]]} Whether the HED string is valid and any issues found. - * @deprecated - */ - -export const validateHedString = function (hedString, hedSchemas, ...args) { - let settings - const settingsArg = args[0] - if (settingsArg === Object(settingsArg)) { - settings = { - checkForWarnings: settingsArg.checkForWarnings ?? false, - expectValuePlaceholderString: settingsArg.expectValuePlaceholderString ?? false, - definitionsAllowed: settingsArg.definitionsAllowed ?? true, - } - } else { - settings = { - checkForWarnings: args[0] ?? false, - expectValuePlaceholderString: args[1] ?? false, - definitionsAllowed: true, - } - } - const [parsedString, parsingIssues] = parseHedString(hedString, hedSchemas, false, settings.definitionsAllowed) - if (parsedString === null) { - return [false, [].concat(...Object.values(parsingIssues))] - } - // const [parsedString, parsedStringIssues, hedValidator] = initiallyValidateHedString(hedString, hedSchemas, settings) - // - // if (parsedString === null) { - // return [false, parsedStringIssues] - // } - const hedValidator = new HedValidator(parsedString, hedSchemas, null, settings) - hedValidator.validateStringLevel() - const issues = [].concat(...Object.values(parsingIssues), hedValidator.issues) - - return Issue.issueListWithValidStatus(issues) -} - -/** - * Validate a HED event string. - * - * @param {string|ParsedHedString} hedString The HED event string to validate. - * @param {Schemas} hedSchemas The HED schemas to validate against. - * @param {boolean} checkForWarnings Whether to check for warnings or only errors. - * @returns {[boolean, Issue[]]} Whether the HED string is valid and any issues found. - * @deprecated - */ -export const validateHedEvent = function (hedString, hedSchemas, ...args) { - let settings - if (args[0] === Object(args[0])) { - settings = { - checkForWarnings: args[0].checkForWarnings ?? false, - } - } else { - settings = { - checkForWarnings: args[0] ?? false, - } - } - //const [parsedString, parsedStringIssues, hedValidator] = initiallyValidateHedString(hedString, hedSchemas, settings) - const [parsedString, parsingIssues] = parseHedString(hedString, hedSchemas, true, false) - if (parsedString === null) { - return [false, [].concat(...Object.values(parsingIssues))] - } - const hedValidator = new HedValidator(parsedString, hedSchemas, null, settings) - hedValidator.validateEventLevel() - const issues = [].concat(...Object.values(parsingIssues), hedValidator.issues) - return Issue.issueListWithValidStatus(issues) -} - -/** - * Validate a HED event string. - * - * @param {string|ParsedHedString} hedString The HED event string to validate. - * @param {Schemas} hedSchemas The HED schemas to validate against. - * @param {DefinitionManager} definitions The dataset's parsed definitions. - * @param {boolean} checkForWarnings Whether to check for warnings or only errors. - * @returns {[boolean, Issue[]]} Whether the HED string is valid and any issues found. - */ -export const validateHedEventWithDefinitions = function (hedString, hedSchemas, definitions, ...args) { - let settings - if (args[0] === Object(args[0])) { - settings = { - checkForWarnings: args[0].checkForWarnings ?? false, - } - } else { - settings = { - checkForWarnings: args[0] ?? false, - } - } - //const [parsedString, parsedStringIssues, hedValidator] = initiallyValidateHedString( - // hedString, hedSchemas, settings, definitions,) - const [parsedString, parsingIssues] = parseHedString(hedString, hedSchemas, true, false) - if (parsedString === null) { - return [false, [].concat(...Object.values(parsingIssues))] - } - const hedValidator = new HedValidator(parsedString, hedSchemas, definitions, settings) - - hedValidator.validateEventLevel() - const issues = [].concat(...Object.values(parsingIssues), hedValidator.issues) - - return Issue.issueListWithValidStatus(issues) -} diff --git a/validator/event/validator.js b/validator/event/validator.js deleted file mode 100644 index ca9ad6f5..00000000 --- a/validator/event/validator.js +++ /dev/null @@ -1,448 +0,0 @@ -import differenceWith from 'lodash/differenceWith' -import isEqual from 'lodash/isEqual' - -import { IssueError, generateIssue } from '../../common/issues/issues' -import ParsedHedGroup from '../../parser/parsedHedGroup' -import ParsedHedTag from '../../parser/parsedHedTag' -import ParsedHedColumnSplice from '../../parser/parsedHedColumnSplice' -import { getParsedParentTags } from '../../utils/hedData' -import { hedStringIsAGroup, replaceTagNameWithPound } from '../../utils/hedStrings' -import { getCharacterCount } from '../../utils/string' - -const tagGroupType = 'tagGroup' -const topLevelTagGroupType = 'topLevelTagGroup' - -const uniqueType = 'unique' -const requiredType = 'required' -const specialTags = require('../../data/json/reservedTags.json') - -/** - * HED validator. - */ -export default class HedValidator { - /** - * The parsed HED string to be validated. - * @type {ParsedHedString} - */ - parsedString - /** - * The collection of HED schemas. - * @type {Schemas} - */ - hedSchemas - /** - * The validation options. - * @type {Object} - */ - options - /** - * The running issue list. - * @type {Issue[]} - */ - issues - /** - * The parsed definitions. - * - * @type {DefinitionManager} - */ - definitions - - /** - * Constructor. - * - * @param {ParsedHedString} parsedString The parsed HED string to be validated. - * @param {Schemas} hedSchemas The collection of HED schemas. - * @param {DefinitionManager} definitions The parsed definitions. - * @param {Object} options The validation options. - */ - constructor(parsedString, hedSchemas, definitions, options) { - this.parsedString = parsedString - this.hedSchemas = hedSchemas - this.options = options - this.issues = [] - this.definitions = definitions - } - - validateStringLevel() { - // this.options.isEventLevel = false - // this.validateIndividualHedTags() - // this.validateHedTagLevels() - // this.validateHedTagGroups() - // this.validateFullParsedHedString() - } - - validateEventLevel() { - // this.options.isEventLevel = true - // this.validateTopLevelTags() - // this.validateIndividualHedTags() - // this.validateHedTagLevels() - // this.validateHedTagGroups() - // this.validateTopLevelTagGroups() - } - - // Categories - - // /** - // * Validate the individual HED tags in a parsed HED string object. - // */ - // validateIndividualHedTags() { - // for (const tag of this.parsedString.tags) { - // this.validateIndividualHedTag(tag) - // } - // } - - // /** - // * Validate an individual HED tag. - // */ - // validateIndividualHedTag(tag) { - // //this.checkIfTagIsValid(tag, previousTag) - // //this.checkIfTagUnitClassUnitsAreValid(tag) - // if (!this.options.isEventLevel) { - // //this.checkValueTagSyntax(tag) - // } - // if (this.definitions !== null) { - // const [definition, missingIssues] = this.definitions.findDefinition(tag) - // this.issues.push(...missingIssues) - // } - // // if (this.options.expectValuePlaceholderString) { - // // this.checkPlaceholderTagSyntax(tag) - // // } - // } - // - // /** - // * Validate the HED tag levels in a parsed HED string object. - // */ - // validateHedTagLevels() { - // for (const tagGroup of this.parsedString.tagGroups) { - // for (const subGroup of tagGroup.subGroupArrayIterator()) { - // this.validateHedTagLevel(subGroup) - // } - // } - // this.validateHedTagLevel(this.parsedString.parseTree) - // } - // - // /** - // * Validate a HED tag level. - // */ - // validateHedTagLevel(tagList) { - // //this.checkForMultipleUniqueTags(tagList) - // //this.checkForDuplicateTags(tagList) - // } - - /** - * Validate the HED tag groups in a parsed HED string. - */ - validateHedTagGroups() { - for (const tagGroup of this.parsedString.tagGroups) { - for (const subGroup of tagGroup.subParsedGroupIterator()) { - this.validateHedTagGroup(subGroup) - } - } - } - - // /** - // * Validate a HED tag group. - // */ - // // eslint-disable-next-line no-unused-vars - // validateHedTagGroup(parsedTagGroup) { - // //this.checkDefinitionGroupSyntax(parsedTagGroup) - // //this.checkTemporalSyntax(parsedTagGroup) - // } - // - // /** - // * Validate the top-level HED tags in a parsed HED string. - // */ - // validateTopLevelTags() { - // for (const topLevelTag of this.parsedString.topLevelTags) { - // if ( - // !hedStringIsAGroup(topLevelTag.formattedTag) && - // (topLevelTag.hasAttribute(tagGroupType) || topLevelTag.parentHasAttribute(tagGroupType)) - // ) { - // this.pushIssue('invalidTopLevelTag', { - // tag: topLevelTag, - // }) - // } - // } - // } - // - // /** - // * Validate the top-level HED tag groups in a parsed HED string. - // */ - // validateTopLevelTagGroups() { - // for (const tag of this.parsedString.tags) { - // if (!tag.hasAttribute(topLevelTagGroupType) && !tag.parentHasAttribute(topLevelTagGroupType)) { - // continue - // } - // if (!this.parsedString.topLevelGroupTags.some((topLevelTagGroup) => topLevelTagGroup.includes(tag))) { - // this.pushIssue('invalidTopLevelTagGroupTag', { - // tag: tag, - // string: this.parsedString.hedString, - // }) - // } - // } - // } - - /** - * Validate the full parsed HED string. - */ - validateFullParsedHedString() { - this.checkPlaceholderStringSyntax() - //this.checkDefinitionStringSyntax() - } // Individual checks - - // /** - // * Check for duplicate tags at the top level or within a single group. - // */ - // checkForDuplicateTags(tagList) { - // const duplicateTags = new Set() - // - // const addIssue = (tag) => { - // if (duplicateTags.has(tag)) { - // return - // } - // this.pushIssue('duplicateTag', { - // tag: tag, - // }) - // duplicateTags.add(tag) - // } - // - // tagList.forEach((firstTag, firstIndex) => { - // tagList.forEach((secondTag, secondIndex) => { - // if (firstIndex !== secondIndex && firstTag.equivalent(secondTag)) { - // // firstIndex and secondIndex are not the same (i.e. comparing a tag with itself), - // // but they are equivalent tags or tag groups (i.e. have the same members up to order). - // addIssue(firstTag) - // addIssue(secondTag) - // } - // }) - // }) - //} - - /* /!** - * Validation check based on a tag attribute. - * - * @param {string} attribute The name of the attribute. - * @param {function (string): void} fn The actual validation code. - *!/ - _checkForTagAttribute(attribute, fn) { - const schemas = this.hedSchemas.schemas.values() - for (const schema of schemas) { - const tags = schema.entries.tags.getEntriesWithBooleanAttribute(attribute) - for (const tag of tags.values()) { - fn(tag.longName) - } - } - }*/ - - /** - * Check basic placeholder tag syntax. - * - * @param {ParsedHedTag} tag A HED tag. - */ - /* checkPlaceholderTagSyntax(tag) { - // TODO: Refactor or eliminate after column splicing completed - const placeholderCount = getCharacterCount(tag.formattedTag, '#') - if (placeholderCount === 1) { - const valueTag = replaceTagNameWithPound(tag.formattedTag) - if (getCharacterCount(valueTag, '#') !== 1) { - this.pushIssue('invalidPlaceholder', { - tag: tag, - }) - } - } else if (placeholderCount > 1) { - // More than one placeholder. - this.pushIssue('invalidPlaceholder', { - tag: tag, - }) - } - }*/ - - // /** - // * Check full-string placeholder syntax. - // */ - // checkPlaceholderStringSyntax() { - // const standalonePlaceholders = { - // // Count of placeholders not in Definition groups. - // placeholders: 0, - // // Whether an Issue has already been generated for an excess placeholder outside a Definition group. - // issueGenerated: false, - // } - // this._checkStandalonePlaceholderStringSyntaxInGroup(this.parsedString.topLevelTags, standalonePlaceholders) - // // Loop over the top-level tag groups. - // for (const tagGroup of this.parsedString.tagGroups) { - // if (tagGroup.isDefinitionGroup) { - // this._checkDefinitionPlaceholderStringSyntaxInGroup(tagGroup) - // } else if (!standalonePlaceholders.issueGenerated) { - // this._checkStandalonePlaceholderStringSyntaxInGroup(tagGroup.tagIterator(), standalonePlaceholders) - // } - // } - // if (this.options.expectValuePlaceholderString && standalonePlaceholders.placeholders === 0) { - // this.pushIssue('missingPlaceholder', { - // string: this.parsedString.hedString, - // }) - // } - // } - - // /** - // * Check Definition-related placeholder syntax in a tag group. - // * - // * @param {ParsedHedGroup} tagGroup A HED tag group. - // * @private - // */ - // _checkDefinitionPlaceholderStringSyntaxInGroup(tagGroup) { - // // Count of placeholders within this Definition group. - // let definitionPlaceholders = 0 - // const definitionValue = tagGroup.definitionValue - // const definitionHasPlaceholder = definitionValue === '#' - // const definitionName = tagGroup.definitionName - // for (const tag of tagGroup.tagIterator()) { - // if (!definitionHasPlaceholder || tag !== tagGroup.definitionTag) { - // definitionPlaceholders += getCharacterCount(tag.formattedTag, '#') - // } - // } - // const isValid = - // (definitionValue === '' && definitionPlaceholders === 0) || - // (definitionHasPlaceholder && definitionPlaceholders === 1) - // if (!isValid) { - // this.pushIssue('invalidPlaceholderInDefinition', { - // definition: definitionName, - // }) - // } - // } - - // /** - // * Check non-Definition-related placeholder syntax in a tag group. - // * - // * @param {ParsedHedTag[]|Generator} tags A HED tag iterator. - // * @param {{placeholders: number, issueGenerated: boolean}} standalonePlaceholders The validator's standalone placeholder context. - // * @private - // */ - // _checkStandalonePlaceholderStringSyntaxInGroup(tags, standalonePlaceholders) { - // let firstStandaloneTag - // for (const tag of tags) { - // const tagString = tag.formattedTag - // const tagPlaceholders = getCharacterCount(tagString, '#') - // standalonePlaceholders.placeholders += tagPlaceholders - // if (!firstStandaloneTag && tagPlaceholders > 0) { - // firstStandaloneTag = tag - // } - // if ( - // tagPlaceholders === 0 || - // (standalonePlaceholders.placeholders <= 1 && - // (this.options.expectValuePlaceholderString || standalonePlaceholders.placeholders === 0)) - // ) { - // continue - // } - // if (this.options.expectValuePlaceholderString && !standalonePlaceholders.issueGenerated) { - // this.pushIssue('invalidPlaceholder', { - // tag: firstStandaloneTag, - // }) - // } - // this.pushIssue('invalidPlaceholder', { - // tag: tag, - // }) - // standalonePlaceholders.issueGenerated = true - // } - // } - - /* /!** - * Check for missing HED 3 definitions. - * - * @param {ParsedHedTag} tag The HED tag. - * @param {string} defShortTag The short tag to check for. - *!/ - checkForMissingDefinitions(tag, defShortTag = 'Def') { - if (tag.schemaTag?.name !== defShortTag) { - return - } - const defName = ParsedHedGroup.findDefinitionName(tag.canonicalTag, defShortTag) - if (!this.definitions.has(defName)) { - const code = defShortTag === 'Def' ? 'missingDefinitionForDef' : 'missingDefinitionForDefExpand' - this.pushIssue(code, { definition: defName }) - } - } -*/ - - // /** - // * Check the syntax of HED 3 onsets and offsets. - // * - // * @param {ParsedHedGroup} tagGroup The tag group. - // */ - // checkTemporalSyntax(tagGroup) { - // if (!tagGroup.isTemporalGroup) { - // return - // } - // const definitionName = this._getTemporalDefinitionName(tagGroup) - // - // const defExpandChildren = tagGroup.defExpandChildren - // const defTags = tagGroup.getSpecial('Def') - // if (tagGroup.defCount === 0) { - // this.pushIssue('temporalWithoutDefinition', { - // tagGroup: tagGroup, - // tag: tagGroup.temporalGroupName, - // }) - // } - // /** - // * The Onset/Offset tag plus the definition tag/tag group. - // * @type {(ParsedHedTag|ParsedHedGroup)[]} - // */ - // const allowedTags = [ - // ...getParsedParentTags(this.hedSchemas, tagGroup.temporalGroupName).values(), - // ...defExpandChildren, - // ...defTags, - // ] - // const remainingTags = differenceWith(tagGroup.tags, allowedTags, (ours, theirs) => ours.equivalent(theirs)) - // const allowedTagGroups = tagGroup.isSpecialGroup('Onset') || tagGroup.isSpecialGroup('Inset') ? 1 : 0 - // if ( - // remainingTags.length > allowedTagGroups || - // remainingTags.filter((tag) => tag instanceof ParsedHedTag).length > 0 - // ) { - // this.pushIssue('extraTagsInTemporal', { - // definition: definitionName, - // tagGroup: tagGroup.originalTag, - // }) - // } - // } - - // /** - // * Determine the definition name for an Onset- or Offset-type tag group. - // * - // * Normally, this simply returns the tag group's {@link ParsedHedGroup.defNameAndValue} return value. However, - // * if this throws an {@link IssueError}, we add the embedded {@link Issue} to our issue list and return a string - // * stating that multiple definitions were found. - // * - // * @param {ParsedHedGroup} tagGroup The onset or offset group. - // * @returns {string} The group's definition name and (optional) value, if any, or a string noting that multiple definitions were found. - // * @throws {Error} If passed a {@link ParsedHedGroup} that is not an Onset- or Offset-type group. - // * @private - // */ - // _getTemporalDefinitionName(tagGroup) { - // if (!tagGroup.isTemporalGroup) { - // throw new Error( - // 'Internal validator function "Hed3Validator._getTemporalDefinitionName()" called outside of its intended context', - // ) - // } - // try { - // return tagGroup.defNameAndValue - // } catch (e) { - // if (e instanceof IssueError) { - // this.issues.push(e.issue) - // return 'Multiple definition tags found' - // } - // } - // } - - /** - * Generate a new issue object and push it to the end of the issues array. - * - * @param {string} internalCode The internal error code. - * @param {Object} parameters The error string parameters. - */ - pushIssue(internalCode, parameters) { - const tsvLine = this.parsedString.tsvLine ?? this.parsedString.tsvLines - if (tsvLine) { - parameters.tsvLine = tsvLine - } - this.issues.push(generateIssue(internalCode, parameters)) - } -} diff --git a/validator/index.js b/validator/index.js deleted file mode 100644 index 4b66a8c0..00000000 --- a/validator/index.js +++ /dev/null @@ -1,28 +0,0 @@ -// import { BidsDataset, BidsEventFile, BidsJsonFile, BidsSidecar, validateBidsDataset } from '../bids' -// import { validateHedDataset } from './dataset' -// import { validateHedEvent, validateHedString } from './event' -// import { buildSchemas } from '../schema/init' -// -// export { -// BidsDataset, -// BidsEventFile, -// BidsJsonFile, -// BidsSidecar, -// validateBidsDataset, -// validateHedDataset, -// validateHedEvent, -// validateHedString, -// buildSchemas, -// } -// -// export default { -// BidsDataset, -// BidsEventFile, -// BidsJsonFile, -// BidsSidecar, -// validateBidsDataset, -// validateHedDataset, -// validateHedEvent, -// validateHedString, -// buildSchemas, -// }