From dd9715672346e490be02fa22f6b9e89c2926f955 Mon Sep 17 00:00:00 2001 From: Alexander Jones Date: Mon, 4 Nov 2024 10:27:05 -0600 Subject: [PATCH 1/2] Reorganize non-code data files --- common/schema/config.js | 18 +++++++++--------- .../event => data/json}/specialTags.json | 0 data/{ => schemas}/HED8.0.0.xml | 0 data/{ => schemas}/HED8.1.0.xml | 0 data/{ => schemas}/HED8.2.0.xml | 0 data/{ => schemas}/HED8.3.0.xml | 0 data/{ => schemas}/HED_lang_1.0.0.xml | 0 data/{ => schemas}/HED_score_1.0.0.xml | 0 data/{ => schemas}/HED_score_1.1.0.xml | 0 data/{ => schemas}/HED_score_2.0.0.xml | 0 data/{ => schemas}/HED_testlib_1.0.2.xml | 0 data/{ => schemas}/HED_testlib_2.0.0.xml | 0 validator/event/special.js | 2 +- validator/event/validator.js | 2 +- 14 files changed, 11 insertions(+), 11 deletions(-) rename {validator/event => data/json}/specialTags.json (100%) rename data/{ => schemas}/HED8.0.0.xml (100%) rename data/{ => schemas}/HED8.1.0.xml (100%) rename data/{ => schemas}/HED8.2.0.xml (100%) rename data/{ => schemas}/HED8.3.0.xml (100%) rename data/{ => schemas}/HED_lang_1.0.0.xml (100%) rename data/{ => schemas}/HED_score_1.0.0.xml (100%) rename data/{ => schemas}/HED_score_1.1.0.xml (100%) rename data/{ => schemas}/HED_score_2.0.0.xml (100%) rename data/{ => schemas}/HED_testlib_1.0.2.xml (100%) rename data/{ => schemas}/HED_testlib_2.0.0.xml (100%) diff --git a/common/schema/config.js b/common/schema/config.js index 007e0fa8..40ae694f 100644 --- a/common/schema/config.js +++ b/common/schema/config.js @@ -1,13 +1,13 @@ /** Bundled HED schema configuration. */ export const localSchemaList = new Map([ - ['HED8.0.0', require('../../data/HED8.0.0.xml')], - ['HED8.1.0', require('../../data/HED8.1.0.xml')], - ['HED8.2.0', require('../../data/HED8.2.0.xml')], - ['HED8.3.0', require('../../data/HED8.3.0.xml')], - ['HED_score_1.0.0', require('../../data/HED_score_1.0.0.xml')], - ['HED_score_1.1.0', require('../../data/HED_score_1.1.0.xml')], - ['HED_score_2.0.0', require('../../data/HED_score_2.0.0.xml')], - ['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')], + ['HED8.0.0', require('../../data/schemas/HED8.0.0.xml')], + ['HED8.1.0', require('../../data/schemas/HED8.1.0.xml')], + ['HED8.2.0', require('../../data/schemas/HED8.2.0.xml')], + ['HED8.3.0', require('../../data/schemas/HED8.3.0.xml')], + ['HED_score_1.0.0', require('../../data/schemas/HED_score_1.0.0.xml')], + ['HED_score_1.1.0', require('../../data/schemas/HED_score_1.1.0.xml')], + ['HED_score_2.0.0', require('../../data/schemas/HED_score_2.0.0.xml')], + ['HED_testlib_1.0.2', require('../../data/schemas/HED_testlib_1.0.2.xml')], + ['HED_testlib_2.0.0', require('../../data/schemas/HED_testlib_2.0.0.xml')], ]) diff --git a/validator/event/specialTags.json b/data/json/specialTags.json similarity index 100% rename from validator/event/specialTags.json rename to data/json/specialTags.json diff --git a/data/HED8.0.0.xml b/data/schemas/HED8.0.0.xml similarity index 100% rename from data/HED8.0.0.xml rename to data/schemas/HED8.0.0.xml diff --git a/data/HED8.1.0.xml b/data/schemas/HED8.1.0.xml similarity index 100% rename from data/HED8.1.0.xml rename to data/schemas/HED8.1.0.xml diff --git a/data/HED8.2.0.xml b/data/schemas/HED8.2.0.xml similarity index 100% rename from data/HED8.2.0.xml rename to data/schemas/HED8.2.0.xml diff --git a/data/HED8.3.0.xml b/data/schemas/HED8.3.0.xml similarity index 100% rename from data/HED8.3.0.xml rename to data/schemas/HED8.3.0.xml diff --git a/data/HED_lang_1.0.0.xml b/data/schemas/HED_lang_1.0.0.xml similarity index 100% rename from data/HED_lang_1.0.0.xml rename to data/schemas/HED_lang_1.0.0.xml diff --git a/data/HED_score_1.0.0.xml b/data/schemas/HED_score_1.0.0.xml similarity index 100% rename from data/HED_score_1.0.0.xml rename to data/schemas/HED_score_1.0.0.xml diff --git a/data/HED_score_1.1.0.xml b/data/schemas/HED_score_1.1.0.xml similarity index 100% rename from data/HED_score_1.1.0.xml rename to data/schemas/HED_score_1.1.0.xml diff --git a/data/HED_score_2.0.0.xml b/data/schemas/HED_score_2.0.0.xml similarity index 100% rename from data/HED_score_2.0.0.xml rename to data/schemas/HED_score_2.0.0.xml diff --git a/data/HED_testlib_1.0.2.xml b/data/schemas/HED_testlib_1.0.2.xml similarity index 100% rename from data/HED_testlib_1.0.2.xml rename to data/schemas/HED_testlib_1.0.2.xml diff --git a/data/HED_testlib_2.0.0.xml b/data/schemas/HED_testlib_2.0.0.xml similarity index 100% rename from data/HED_testlib_2.0.0.xml rename to data/schemas/HED_testlib_2.0.0.xml diff --git a/validator/event/special.js b/validator/event/special.js index eb5228fc..69f9a5b6 100644 --- a/validator/event/special.js +++ b/validator/event/special.js @@ -1,4 +1,4 @@ -import specialTags from './specialTags.json' +import specialTags from '../../data/json/specialTags.json' import { ParsedHedGroup } from '../../parser/parsedHedGroup' import { ParsedHedTag } from '../../parser/parsedHedTag' diff --git a/validator/event/validator.js b/validator/event/validator.js index 49b71ac4..85f1df33 100644 --- a/validator/event/validator.js +++ b/validator/event/validator.js @@ -5,7 +5,7 @@ import { Schemas } from '../../common/schema/types' const NAME_CLASS_REGEX = /^[\w\-\u0080-\uFFFF]+$/ const uniqueType = 'unique' const requiredType = 'required' -const specialTags = require('./specialTags.json') +const specialTags = require('../../data/json/specialTags.json') // Validation tests /** From c75f0b58af33e3173a2a8985275d7c753ca74147 Mon Sep 17 00:00:00 2001 From: Alexander Jones Date: Mon, 4 Nov 2024 11:38:45 -0600 Subject: [PATCH 2/2] Refactor schema parsing code --- validator/schema/hed3.js | 139 +++++++++++++++++++++++++++++---------- 1 file changed, 106 insertions(+), 33 deletions(-) diff --git a/validator/schema/hed3.js b/validator/schema/hed3.js index 12e55026..60872261 100644 --- a/validator/schema/hed3.js +++ b/validator/schema/hed3.js @@ -24,6 +24,8 @@ import { } from './types' import { generateIssue, IssueError } from '../../common/issues/issues' +const specialTags = require('../../data/json/specialTags.json') + const lc = (str) => str.toLowerCase() export class Hed3SchemaParser extends SchemaParser { @@ -108,22 +110,19 @@ export class Hed3SchemaParser extends SchemaParser { this.properties = new Map() for (const definition of propertyDefinitions) { const propertyName = this.getElementTagName(definition) - if ( - this._versionDefinitions.categoryProperties && - this._versionDefinitions.categoryProperties.has(propertyName) - ) { + if (this._versionDefinitions.categoryProperties?.has(propertyName)) { this.properties.set( propertyName, // TODO: Switch back to class constant once upstream bug is fixed. new SchemaProperty(propertyName, 'categoryProperty'), ) - } else if (this._versionDefinitions.typeProperties && this._versionDefinitions.typeProperties.has(propertyName)) { + } else if (this._versionDefinitions.typeProperties?.has(propertyName)) { this.properties.set( propertyName, // TODO: Switch back to class constant once upstream bug is fixed. new SchemaProperty(propertyName, 'typeProperty'), ) - } else if (this._versionDefinitions.roleProperties && this._versionDefinitions.roleProperties.has(propertyName)) { + } else if (this._versionDefinitions.roleProperties?.has(propertyName)) { this.properties.set( propertyName, // TODO: Switch back to class constant once upstream bug is fixed. @@ -144,7 +143,7 @@ export class Hed3SchemaParser extends SchemaParser { if (propertyElements === undefined) { properties = [] } else { - properties = propertyElements.map((element) => this.properties.get(element.name[0]._)) + properties = propertyElements.map((element) => this.properties.get(this.getElementTagName(element))) } this.attributes.set(attributeName, new SchemaAttribute(attributeName, properties)) } @@ -206,8 +205,46 @@ export class Hed3SchemaParser extends SchemaParser { return unitClassUnits } + // Tag parsing + + /** + * Parse the schema's tags. + */ parseTags() { const tags = this.getAllTags() + const shortTags = this._getShortTags(tags) + const [booleanAttributeDefinitions, valueAttributeDefinitions] = this._parseAttributeElements( + tags.keys(), + (element) => shortTags.get(element), + ) + + const tagUnitClassDefinitions = this._processTagUnitClasses(shortTags, valueAttributeDefinitions) + this._processRecursiveAttributes(shortTags, booleanAttributeDefinitions) + + const tagEntries = this._createSchemaTags( + booleanAttributeDefinitions, + valueAttributeDefinitions, + tagUnitClassDefinitions, + ) + + this._injectTagFields(tags, shortTags, tagEntries) + + const longNameTagEntries = new Map() + for (const tag of tagEntries.values()) { + longNameTagEntries.set(lc(tag.longName), tag) + } + + this.tags = new SchemaTagManager(tagEntries, longNameTagEntries) + } + + /** + * Generate the map from tag elements to shortened tag names. + * + * @param {Map} tags The map from tag elements to tag strings. + * @returns {Map} The map from tag elements to shortened tag names. + * @private + */ + _getShortTags(tags) { const shortTags = new Map() for (const tagElement of tags.keys()) { const shortKey = @@ -216,18 +253,22 @@ export class Hed3SchemaParser extends SchemaParser { : this.getElementTagName(tagElement) shortTags.set(tagElement, shortKey) } - const [booleanAttributeDefinitions, valueAttributeDefinitions] = this._parseAttributeElements( - tags.keys(), - (element) => shortTags.get(element), - ) + return shortTags + } - const recursiveAttributes = this._getRecursiveAttributes() + /** + * Process unit classes in tags. + * + * @param {Map} shortTags The map from tag elements to shortened tag names. + * @param {Map>} valueAttributeDefinitions The map from shortened tag names to their value schema attributes. + * @returns {Map} The map from shortened tag names to their unit classes. + * @private + */ + _processTagUnitClasses(shortTags, valueAttributeDefinitions) { const tagUnitClassAttribute = this.attributes.get('unitClass') - const tagTakesValueAttribute = this.attributes.get('takesValue') - const tagUnitClassDefinitions = new Map() - const recursiveChildren = new Map() - for (const [tagElement, tagName] of shortTags) { + + for (const tagName of shortTags.values()) { const valueAttributes = valueAttributeDefinitions.get(tagName) if (valueAttributes.has(tagUnitClassAttribute)) { tagUnitClassDefinitions.set( @@ -238,29 +279,54 @@ export class Hed3SchemaParser extends SchemaParser { ) valueAttributes.delete(tagUnitClassAttribute) } + } + + return tagUnitClassDefinitions + } + + /** + * Process recursive schema attributes. + * + * @param {Map} shortTags The map from tag elements to shortened tag names. + * @param {Map>} booleanAttributeDefinitions The map from shortened tag names to their boolean schema attributes. Passed by reference. + * @private + */ + _processRecursiveAttributes(shortTags, booleanAttributeDefinitions) { + const recursiveAttributes = this._getRecursiveAttributes() + + for (const [tagElement, tagName] of shortTags) { for (const attribute of recursiveAttributes) { - const children = recursiveChildren.get(attribute) ?? [] if (booleanAttributeDefinitions.get(tagName).has(attribute)) { - children.push(...this.getAllChildTags(tagElement)) + for (const childTag of this.getAllChildTags(tagElement)) { + const childTagName = this.getElementTagName(childTag) + booleanAttributeDefinitions.get(childTagName).add(attribute) + } } - recursiveChildren.set(attribute, children) - } - } - - for (const [attribute, childTagElements] of recursiveChildren) { - for (const tagElement of childTagElements) { - const tagName = this.getElementTagName(tagElement) - booleanAttributeDefinitions.get(tagName).add(attribute) } } + } + /** + * Create the {@link SchemaTag} objects. + * + * @param {Map>} booleanAttributeDefinitions The map from shortened tag names to their boolean schema attributes. + * @param {Map>} valueAttributeDefinitions The map from shortened tag names to their value schema attributes. + * @param {Map} tagUnitClassDefinitions The map from shortened tag names to their unit classes. + * @returns {Map} The map from lowercase shortened tag names to their tag objects. + * @private + */ + _createSchemaTags(booleanAttributeDefinitions, valueAttributeDefinitions, tagUnitClassDefinitions) { + const tagTakesValueAttribute = this.attributes.get('takesValue') const tagEntries = new Map() + for (const [name, valueAttributes] of valueAttributeDefinitions) { if (tagEntries.has(name)) { IssueError.generateAndThrow('duplicateTagsInSchema') } + const booleanAttributes = booleanAttributeDefinitions.get(name) const unitClasses = tagUnitClassDefinitions.get(name) + if (booleanAttributes.has(tagTakesValueAttribute)) { tagEntries.set(lc(name), new SchemaValueTag(name, booleanAttributes, valueAttributes, unitClasses)) } else { @@ -268,23 +334,30 @@ export class Hed3SchemaParser extends SchemaParser { } } + return tagEntries + } + + /** + * Inject special tag fields into the {@link SchemaTag} objects. + * + * @param {Map} tags The map from tag elements to tag strings. + * @param {Map} shortTags The map from tag elements to shortened tag names. + * @param {Map} tagEntries The map from shortened tag names to tag objects. + * @private + */ + _injectTagFields(tags, shortTags, tagEntries) { for (const tagElement of tags.keys()) { const tagName = shortTags.get(tagElement) const parentTagName = shortTags.get(tagElement.$parent) + if (parentTagName) { tagEntries.get(lc(tagName))._parent = tagEntries.get(lc(parentTagName)) } + if (this.getElementTagName(tagElement) === '#') { tagEntries.get(lc(parentTagName))._valueTag = tagEntries.get(lc(tagName)) } } - - const longNameTagEntries = new Map() - for (const tag of tagEntries.values()) { - longNameTagEntries.set(lc(tag.longName), tag) - } - - this.tags = new SchemaTagManager(tagEntries, longNameTagEntries) } _parseDefinitions(category) {