import ParsedHedTag from './parsedHedTag'
import ParsedHedGroup from './parsedHedGroup'
import ParsedHedColumnSplice from './parsedHedColumnSplice'
import { filterByClass, getDuplicates } from './parseUtils'
import { IssueError } from '../issues/issues'
/**
* A parsed HED string.
*/
export class ParsedHedString {
/**
* The original HED string.
* @type {string}
*/
hedString
/**
* The parsed substring data in unfiltered form.
* @type {ParsedHedSubstring[]}
*/
parseTree
/**
* The tag groups in the string (top-level).
* @type {ParsedHedGroup[]}
*/
tagGroups
/**
* All the top-level tags in the string.
* @type {ParsedHedTag[]}
*/
topLevelTags
/**
* All the tags in the string at all levels
* @type {ParsedHedTag[]}
*/
tags
/**
* All the column splices in the string at all levels.
* @type {ParsedHedColumnSplice[]}
*/
columnSplices
/**
* The tags in the top-level tag groups in the string, split into arrays.
* @type {ParsedHedTag[][]}
*/
topLevelGroupTags
/**
* The top-level definition tag groups in the string.
* @type {ParsedHedGroup[]}
*/
definitions
/**
* Constructor.
* @param {string} hedString The original HED string.
* @param {ParsedHedSubstring[]} parsedTags The nested list of parsed HED tags and groups.
*/
constructor(hedString, parsedTags) {
this.hedString = hedString
this.parseTree = parsedTags
this.tagGroups = filterByClass(parsedTags, ParsedHedGroup)
this.topLevelTags = filterByClass(parsedTags, ParsedHedTag)
const subgroupTags = this.tagGroups.flatMap((tagGroup) => Array.from(tagGroup.tagIterator()))
this.tags = this.topLevelTags.concat(subgroupTags)
const topLevelColumnSplices = filterByClass(parsedTags, ParsedHedColumnSplice)
const subgroupColumnSplices = this.tagGroups.flatMap((tagGroup) => Array.from(tagGroup.columnSpliceIterator()))
this.columnSplices = topLevelColumnSplices.concat(subgroupColumnSplices)
//this.topLevelGroupTags = this.tagGroups.map((tagGroup) => filterByClass(tagGroup.tags, ParsedHedTag))
this.topLevelGroupTags = this.tagGroups.flatMap((tagGroup) => filterByClass(tagGroup.tags, ParsedHedTag))
this.definitions = this.tagGroups.filter((group) => group.isDefinitionGroup)
this.normalized = this._getNormalized()
}
/**
* Nicely format this HED string. (Doesn't allow column splices).
*
* @param {boolean} long Whether the tags should be in long form.
* @returns {string}
*/
format(long = true) {
return this.parseTree.map((substring) => substring.format(long)).join(', ')
}
/**
* Return a normalized string representation
* @returns {string}
*/
_getNormalized() {
// This is an implicit recursion as the items have the same call.
const normalizedItems = this.parseTree.map((item) => item.normalized)
// Sort normalized items to ensure order independence
const sortedNormalizedItems = normalizedItems.sort()
const duplicates = getDuplicates(sortedNormalizedItems)
if (duplicates.length > 0) {
IssueError.generateAndThrow('duplicateTag', { tags: '[' + duplicates.join('],[') + ']', string: this.hedString })
}
// Return the normalized group as a string
return `${sortedNormalizedItems.join(',')}` // Using curly braces to indicate unordered group
}
/**
* Override of {@link Object.prototype.toString}.
*
* @returns {string}
*/
toString() {
return this.hedString
}
}
export default ParsedHedString