From 6dc19e60ac86244d14e1ff915fd5afbbbcb519d4 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:58:27 -0500 Subject: [PATCH] Started the implementation of special tag handling --- .gitignore | 1 + common/issues/data.js | 5 ++ spec_tests/jsonTests.spec.js | 4 +- validator/event/special.js | 57 +++++++++++++++ validator/event/specialTags.json | 121 +++++++++++++++++++++++++++++++ validator/event/validator.js | 2 +- validator/specialTags.json | 92 ----------------------- 7 files changed, 187 insertions(+), 95 deletions(-) create mode 100644 validator/event/special.js create mode 100644 validator/event/specialTags.json delete mode 100644 validator/specialTags.json diff --git a/.gitignore b/.gitignore index fa59cf1e..55d6a413 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ dist/ /venv/ spec_tests/*.txt spec_tests/temp*.json +spec_tests/temp.spec.js # Unit test / coverage reports htmlcov/ diff --git a/common/issues/data.js b/common/issues/data.js index fedae346..a7877d1e 100644 --- a/common/issues/data.js +++ b/common/issues/data.js @@ -58,6 +58,11 @@ export default { level: 'error', message: stringTemplate`Descendant tag required - "${'tag'}".`, }, + childForbidden: { + hedCode: 'TAG_INVALID', + level: 'error', + message: stringTemplate`Child tag or value not allowed - "${'tag'}".`, + }, requiredPrefixMissing: { hedCode: 'REQUIRED_TAG_MISSING', level: 'warning', diff --git a/spec_tests/jsonTests.spec.js b/spec_tests/jsonTests.spec.js index ed7cd5c7..78f5257f 100644 --- a/spec_tests/jsonTests.spec.js +++ b/spec_tests/jsonTests.spec.js @@ -3,7 +3,7 @@ const assert = chai.assert import { beforeAll, describe, afterAll } from '@jest/globals' import * as hed from '../validator/event' -import { BidsIssue } from '../bids/types/issues' +import { BidsHedIssue } from '../bids/types/issues' import { buildSchemas } from '../validator/schema/init' import { SchemaSpec, SchemasSpec } from '../common/schema/types' import path from 'path' @@ -128,7 +128,7 @@ describe('HED validation using JSON tests', () => { const log = [header] totalTests += 1 for (const issue of issues) { - if (issue instanceof BidsIssue) { + if (issue instanceof BidsHedIssue) { errors.push(`${issue.hedIssue.hedCode}`) } else { errors.push(`${issue.hedCode}`) diff --git a/validator/event/special.js b/validator/event/special.js new file mode 100644 index 00000000..97734d66 --- /dev/null +++ b/validator/event/special.js @@ -0,0 +1,57 @@ +import specialTags from './specialTags.json' +import { ParsedHedGroup } from '../../parser/parsedHedGroup' +import { ParsedHedTag } from '../../parser/parsedHedTag' + +export class SpecialTagValidator { + /** + * Map of properties for special tags. + * @type {Object} + */ + specialTags + + constructor() { + this.specialTags = specialTags + } + + // Example method to check if a tag exists in specialTags + isSpecialTag(tag) { + return tag._schemaTag.name in this.specialTags + } + + /** Check a list of tags for whether they can have children **/ + checkTags(tagList) { + const issueList = [] + for (const tag of tagList) { + if (!this.isSpecialTag(tag)) { + continue + } + const specReq = this.specialTags[tag._schemaTag.name] + if (!specReq['child'] && tag._remainder.length > 0) { + issueList.push({ internalCode: 'childForbidden', parameters: { tag: tag } }) + } else if (specReq['child'] && tag._remainder.length === 0) { + issueList.push({ internalCode: 'childRequired', parameters: { tag: tag } }) + } + } + return issueList + } + + checkTagGroup(tagGroup) { + const issueList = [] + const topTags = tagGroup.tag.filter((tag) => tag instanceof ParsedHedTag) + const topSubgroups = tagGroup.tag.filter((tag) => tag instanceof ParsedHedGroup) + } + + checktopTags(tag, topSubgroups) { + const issueList = [] + if (this.isSpecialTag(tag)) { + return issueList + } + const specReq = this.specialTags[tag._schemaTag.name] + for (const tag of tagList) { + } + } + + // Add more methods as needed... +} + +export default SpecialTagValidator diff --git a/validator/event/specialTags.json b/validator/event/specialTags.json new file mode 100644 index 00000000..7424b1a9 --- /dev/null +++ b/validator/event/specialTags.json @@ -0,0 +1,121 @@ +{ + "Definition": { + "child": true, + "requireChild": true, + "tagGroup": true, + "topLevelTagGroup": true, + "maxNumberSubgroups": 1, + "minNumberSubgroups": 0, + "ERROR_CODE": "DEFINITION_INVALID", + "subgroupTagsNotAllowed": [ + "Def", + "Def-expand", + "Event-context", + "Definition", + "Onset", + "Inset", + "Offset", + "Delay", + "Duration" + ], + "defTagRequired": false, + "otherAllowedTags": [] + }, + "Def": { + "child": true, + "tagGroup": false, + "topLevelTagGroup": false, + "maxNumberSubgroups": null, + "minNumberSubgroups": null, + "ERROR_CODE": "DEF_INVALID", + "subgroupTagsNotAllowed": [], + "defTagRequired": false, + "otherAllowedTags": [] + }, + "Def-expand": { + "child": true, + "tagGroup": true, + "topLevelTagGroup": false, + "maxNumberSubgroups": 1, + "minNumberSubgroups": 0, + "ERROR_CODE": "DEF_EXPAND_INVALID", + "subgroupTagsNotAllowed": [ + "Def", + "Def-expand", + "Event-context", + "Definition", + "Onset", + "Inset", + "Offset", + "Delay", + "Duration" + ], + "defTagRequired": false, + "otherAllowedTags": [] + }, + "Onset": { + "child": false, + "tagGroup": true, + "topLevelTagGroup": true, + "maxNumberSubgroups": 1, + "minNumberSubgroups": 0, + "ERROR_CODE": "TEMPORAL_TAG_ERROR", + "subgroupTagsNotAllowed": ["Event-context", "Definition", "Onset", "Inset", "Offset", "Delay", "Duration"], + "defTagRequired": true, + "otherAllowedTags": [] + }, + "Inset": { + "child": false, + "tagGroup": true, + "topLevelTagGroup": true, + "maxNumberSubgroups": 1, + "minNumberSubgroups": 0, + "ERROR_CODE": "TEMPORAL_TAG_ERROR", + "subgroupTagsNotAllowed": ["Event-context", "Definition", "Onset", "Inset", "Offset", "Delay", "Duration"], + "defTagRequired": true, + "otherAllowedTags": [] + }, + "Offset": { + "child": false, + "tagGroup": true, + "topLevelTagGroup": true, + "maxNumberSubgroups": 0, + "minNumberSubgroups": 0, + "ERROR_CODE": "TEMPORAL_TAG_ERROR", + "subgroupTagsNotAllowed": [], + "defTagRequired": true, + "otherAllowedTags": [] + }, + "Delay": { + "child": true, + "tagGroup": true, + "topLevelTagGroup": true, + "maxNumberSubgroups": 1, + "minNumberSubgroups": 1, + "ERROR_CODE": "TEMPORAL_TAG_ERROR", + "subgroupTagsNotAllowed": ["Event-context", "Definition", "Onset", "Inset", "Offset", "Delay", "Duration"], + "defTagRequired": false, + "otherAllowedTags": ["Duration"] + }, + "Duration": { + "child": true, + "topLevelTagGroup": true, + "maxNumberSubgroups": 1, + "minNumberSubgroups": 1, + "ERROR_CODE": "TEMPORAL_TAG_ERROR", + "subgroupTagsNotAllowed": ["Event-context", "Definition", "Onset", "Inset", "Offset", "Delay", "Duration"], + "defTagRequired": false, + "otherAllowedTags": ["Delay"] + }, + "Event-context": { + "child": false, + "tagGroup": true, + "topLevelTagGroup": true, + "maxNumberSubgroups": null, + "minNumberSubgroups": 0, + "ERROR_CODE": "TAG_GROUP_ERROR", + "subgroupTagsNotAllowed": ["Event-context", "Definition", "Onset", "Inset", "Offset", "Delay", "Duration"], + "defTagRequired": false, + "otherAllowedTags": [] + } +} diff --git a/validator/event/validator.js b/validator/event/validator.js index b140f16e..3ed23161 100644 --- a/validator/event/validator.js +++ b/validator/event/validator.js @@ -6,7 +6,7 @@ const NAME_CLASS_REGEX = /^[\w\-\u0080-\uFFFF]+$/ const uniqueType = 'unique' const requiredType = 'required' const requireChildType = 'requireChild' -const specialTags = require('../specialTags.json') +const specialTags = require('./specialTags.json') // Validation tests /** diff --git a/validator/specialTags.json b/validator/specialTags.json deleted file mode 100644 index 5dba4ef1..00000000 --- a/validator/specialTags.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "Definition": { - "requireChild": true, - "tagGroup": true, - "topLevelTagGroup": true, - "maxNumberSubgroups": 1, - "minNumberSubgroups": 0, - "ERROR_CODE": "DEFINITION_INVALID", - "requiredGroupTags": [], - "otherTags": [] - }, - "Def": { - "requireChild": true, - "tagGroup": false, - "topLevelTagGroup": false, - "maxNumberSubgroups": null, - "minNumberSubgroups": null, - "ERROR_CODE": "DEF_INVALID", - "requiredGroupTags": [], - "otherTags": [] - }, - "Def-expand": { - "requireChild": true, - "tagGroup": true, - "topLevelTagGroup": false, - "maxNumberSubgroups": 1, - "minNumberSubgroups": 0, - "ERROR_CODE": "DEF_EXPAND_INVALID", - "requiredGroupTags": [], - "otherTags": [] - }, - "Onset": { - "requireChild": true, - "tagGroup": true, - "topLevelTagGroup": true, - "maxNumberSubgroups": 1, - "minNumberSubgroups": 0, - "ERROR_CODE": "TEMPORAL_TAG_ERROR", - "requiredGroupTags": ["Def"], - "otherTags": [] - }, - "Inset": { - "requireChild": true, - "tagGroup": true, - "topLevelTagGroup": true, - "maxNumberSubgroups": 1, - "minNumberSubgroups": 0, - "ERROR_CODE": "TEMPORAL_TAG_ERROR", - "requiredGroupTags": ["Def"], - "otherTags": [] - }, - "Offset": { - "requireChild": true, - "tagGroup": true, - "topLevelTagGroup": true, - "maxNumberSubgroups": 0, - "minNumberSubgroups": 0, - "ERROR_CODE": "TEMPORAL_TAG_ERROR", - "requiredGroupTags": ["Def"], - "otherTags": [] - }, - "Delay": { - "requireChild": true, - "tagGroup": true, - "topLevelTagGroup": true, - "maxNumberSubgroups": 1, - "minNumberSubgroups": 1, - "ERROR_CODE": "TEMPORAL_TAG_ERROR", - "requiredGroupTags": [], - "otherTags": ["Duration"] - }, - "Duration": { - "requireChild": true, - "tagGroup": true, - "topLevelTagGroup": true, - "maxNumberSubgroups": 1, - "minNumberSubgroups": 1, - "ERROR_CODE": "TEMPORAL_TAG_ERROR", - "requiredGroupTags": [], - "otherTags": ["Delay"] - }, - "Event-context": { - "requireChild": false, - "tagGroup": true, - "topLevelTagGroup": true, - "maxNumberSubgroups": null, - "minNumberSubgroups": 0, - "ERROR_CODE": "TAG_GROUP_ERROR", - "requiredGroupTags": [], - "otherTags": [] - } -}