UNPKG

jspurefix

Version:
169 lines (148 loc) 4.82 kB
import * as fs from 'fs' import * as path from 'path' import { SAXParser } from 'sax' import { promisify } from 'util' import { IDictDoneCb, ISaxNode, SAXStream } from '../../dict-primitive' import { FixDefinitions } from '../../definition' import { AbbreviationsParser } from './abbreviations-parser' import { BaseParser } from './base-parser' import { ComponentsParser } from './components-parser' import { EnumsParser } from './enums-parser' import { FieldsParser } from './fields-parser' import { MessagesParser } from './messages-parser' import { MsgContentsParser } from './msg-contents-parser' import { Repository } from './repository' import { FixParser } from '../../fix-parser' import { VersionUtil } from '../../fix-versions' import { GetJsFixLogger, IJsFixLogger } from '../../../config' export class RepositoryXmlParser extends FixParser { public readonly repository: Repository private readonly singlePass = promisify(RepositoryXmlParser.subscribe) private readonly logger: IJsFixLogger constructor (public readonly rootPath: string, public readonly getLogger: GetJsFixLogger) { super() this.logger = getLogger('RepositoryXmlParser') this.repository = new Repository(VersionUtil.resolve(this.rootPath), getLogger) } private static subscribe (instance: RepositoryXmlParser, saxStream: SAXStream, done: IDictDoneCb): void { let parser: BaseParser let pending: string const saxParser: SAXParser = saxStream._parser saxStream.on('error', (e: Error) => { done(e, null) }) saxStream.on('closetag', (name) => { switch (name) { case 'Abbreviations': case 'Messages': case 'MsgContents': case 'Components': case 'Fields': case 'Enums': { if (parser != null) { parser.close(saxParser.line, name) instance.repository.assign(name, parser.data) parser = null } break } case 'Abbreviation': case 'MsgContent': case 'Field': case 'Enum': case 'Component': case 'Message': { if (parser != null) { parser.close(saxParser.line, name) } break } default: { pending = null break } } }) saxStream.on('text', (t: string) => { t = t.trim() if (pending) { parser.value(saxParser.line, pending, t) } }) saxStream.on('opentag', (node) => { const saxNode: ISaxNode = node as ISaxNode switch (saxNode.name) { case 'Fields': { parser = new FieldsParser(instance) break } case 'Enums': { parser = new EnumsParser(instance) break } case 'Components': { parser = new ComponentsParser(instance) break } case 'Messages': { parser = new MessagesParser(instance) break } case 'MsgContents': { parser = new MsgContentsParser(instance) break } case 'Abbreviations': { parser = new AbbreviationsParser(instance) break } case 'Abbreviation': case 'Field': case 'Message': case 'MsgContent': case 'Enum': case 'Component': { if (parser != null) { parser.open(saxParser.line, saxNode) } break } default: { pending = saxNode.name } } }) saxStream.on('ready', () => { if (done) { parser = null done(null, instance.repository.definitions) } }) } public parse (): Promise<FixDefinitions> { return new Promise<FixDefinitions>(async (accept, reject) => { try { await this.onePass('Fields.xml') await this.onePass('Enums.xml') await this.onePass('Components.xml') await this.onePass('Messages.xml') await this.onePass('MsgContents.xml') if (this.repository.includesAbbreviations) { await this.onePass('Abbreviations.xml') } accept(this.repository.definitions) } catch (e) { reject(e) } }) } private async onePass (fileName: string): Promise<any> { const logger = this.logger const fullFileName = path.join(this.rootPath, fileName) const pass: fs.ReadStream = fs.createReadStream(fullFileName) logger.info(`reading ${fullFileName}`) const saxStream: SAXStream = require('sax').createStream(true, {}) pass.pipe(saxStream) await this.singlePass(this, saxStream) } }