jspurefix 5.3.0 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BACKPORT_PLAN.md +120 -10
- package/dist/dictionary/parser/quickfix/dictionary-validator.d.ts +39 -0
- package/dist/dictionary/parser/quickfix/dictionary-validator.js +321 -0
- package/dist/dictionary/parser/quickfix/dictionary-validator.js.map +1 -0
- package/dist/dictionary/parser/quickfix/index-visitor.d.ts +10 -0
- package/dist/dictionary/parser/quickfix/index-visitor.js +68 -0
- package/dist/dictionary/parser/quickfix/index-visitor.js.map +1 -0
- package/dist/dictionary/parser/quickfix/index.d.ts +7 -0
- package/dist/dictionary/parser/quickfix/index.js +7 -0
- package/dist/dictionary/parser/quickfix/index.js.map +1 -1
- package/dist/dictionary/parser/quickfix/quick-fix-graph-file-parser.d.ts +13 -0
- package/dist/dictionary/parser/quickfix/quick-fix-graph-file-parser.js +65 -0
- package/dist/dictionary/parser/quickfix/quick-fix-graph-file-parser.js.map +1 -0
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.d.ts +73 -0
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.js +363 -0
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.js.map +1 -0
- package/dist/dictionary/parser/quickfix/sax-tree-builder.d.ts +5 -0
- package/dist/dictionary/parser/quickfix/sax-tree-builder.js +103 -0
- package/dist/dictionary/parser/quickfix/sax-tree-builder.js.map +1 -0
- package/dist/dictionary/parser/quickfix/validation-error.d.ts +17 -0
- package/dist/dictionary/parser/quickfix/validation-error.js +32 -0
- package/dist/dictionary/parser/quickfix/validation-error.js.map +1 -0
- package/dist/dictionary/parser/quickfix/x-element.d.ts +26 -0
- package/dist/dictionary/parser/quickfix/x-element.js +82 -0
- package/dist/dictionary/parser/quickfix/x-element.js.map +1 -0
- package/dist/store/fix-msg-ascii-store-resend.js +6 -0
- package/dist/store/fix-msg-ascii-store-resend.js.map +1 -1
- package/dist/store/store-config.d.ts +1 -0
- package/dist/store/store-config.js.map +1 -1
- package/dist/util/definition-factory.js +1 -1
- package/dist/util/definition-factory.js.map +1 -1
- package/jsfix.test_client.txt +67 -67
- package/jsfix.test_server.txt +64 -64
- package/package.json +6 -6
- package/src/dictionary/parser/quickfix/dictionary-validator.ts +473 -0
- package/src/dictionary/parser/quickfix/index-visitor.ts +100 -0
- package/src/dictionary/parser/quickfix/index.ts +7 -0
- package/src/dictionary/parser/quickfix/quick-fix-graph-file-parser.ts +63 -0
- package/src/dictionary/parser/quickfix/quick-fix-graph-parser.ts +450 -0
- package/src/dictionary/parser/quickfix/sax-tree-builder.ts +112 -0
- package/src/dictionary/parser/quickfix/validation-error.ts +34 -0
- package/src/dictionary/parser/quickfix/x-element.ts +115 -0
- package/src/store/fix-msg-ascii-store-resend.ts +8 -0
- package/src/store/store-config.ts +1 -0
- package/src/util/definition-factory.ts +2 -2
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IndexVisitor = void 0;
|
|
4
|
+
const contained_field_type_1 = require("../../contained/contained-field-type");
|
|
5
|
+
const contained_set_builder_1 = require("../../contained/contained-set-builder");
|
|
6
|
+
class IndexVisitor {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.visited = new Set();
|
|
9
|
+
}
|
|
10
|
+
compute(definitions) {
|
|
11
|
+
const messages = new Set(definitions.message.values());
|
|
12
|
+
for (const msg of messages) {
|
|
13
|
+
this.reindex(msg);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
reindex(set) {
|
|
17
|
+
if (this.visited.has(set))
|
|
18
|
+
return;
|
|
19
|
+
this.visited.add(set);
|
|
20
|
+
for (const field of set.fields) {
|
|
21
|
+
if (field.type === contained_field_type_1.ContainedFieldType.Group) {
|
|
22
|
+
const gf = field;
|
|
23
|
+
if (gf.definition)
|
|
24
|
+
this.reindex(gf.definition);
|
|
25
|
+
}
|
|
26
|
+
else if (field.type === contained_field_type_1.ContainedFieldType.Component) {
|
|
27
|
+
const cf = field;
|
|
28
|
+
if (cf.definition)
|
|
29
|
+
this.reindex(cf.definition);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const level0 = [...set.fields];
|
|
33
|
+
IndexVisitor.clearAggregated(set);
|
|
34
|
+
const builder = new contained_set_builder_1.ContainedSetBuilder(set);
|
|
35
|
+
for (const field of level0) {
|
|
36
|
+
builder.add(field);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
static clearAggregated(set) {
|
|
40
|
+
set.fields.length = 0;
|
|
41
|
+
set.simple.clear();
|
|
42
|
+
set.groups.clear();
|
|
43
|
+
set.components.clear();
|
|
44
|
+
set.localNameToField.clear();
|
|
45
|
+
set.flattenedTag.length = 0;
|
|
46
|
+
set.localAttribute.length = 0;
|
|
47
|
+
set.nameToLocalAttribute.clear();
|
|
48
|
+
set.firstSimple = null;
|
|
49
|
+
set.containsRaw = false;
|
|
50
|
+
IndexVisitor.clearObject(set.containedTag);
|
|
51
|
+
IndexVisitor.clearObject(set.localTag);
|
|
52
|
+
IndexVisitor.clearObject(set.localRequired);
|
|
53
|
+
IndexVisitor.clearObject(set.tagToSimple);
|
|
54
|
+
IndexVisitor.clearObject(set.tagToField);
|
|
55
|
+
IndexVisitor.clearObject(set.containedLength);
|
|
56
|
+
const def = set;
|
|
57
|
+
if (def.noOfField) {
|
|
58
|
+
set.containedTag[def.noOfField.tag] = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
static clearObject(obj) {
|
|
62
|
+
for (const k of Object.keys(obj)) {
|
|
63
|
+
delete obj[k];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.IndexVisitor = IndexVisitor;
|
|
68
|
+
//# sourceMappingURL=index-visitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-visitor.js","sourceRoot":"","sources":["../../../../src/dictionary/parser/quickfix/index-visitor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Post-processing reindexer for ContainedFieldSet.\n *\n * After the graph parser drains its work queue, parent sets may not yet\n * know about all tags in their nested groups/components — because those\n * children may have been resolved AFTER the parent. This visitor walks\n * every message/component/group definition in post-order (children first),\n * clears the aggregated tag indices, and re-adds direct fields via\n * ContainedSetBuilder, which propagates child tags upward correctly.\n *\n * Equivalent to the C# IndexVisitor + ContainedFieldSet.Index() pair.\n */\nimport { ContainedFieldSet } from '../../contained/contained-field-set'\nimport { ContainedField } from '../../contained/contained-field'\nimport { ContainedFieldType } from '../../contained/contained-field-type'\nimport { ContainedGroupField } from '../../contained/contained-group-field'\nimport { ContainedComponentField } from '../../contained/contained-component-field'\nimport { ContainedSetBuilder } from '../../contained/contained-set-builder'\nimport { FixDefinitions } from '../../definition/fix-definitions'\nimport { IContainedSet } from '../../contained/contained-set'\n\nexport class IndexVisitor {\n private readonly visited = new Set<IContainedSet>()\n\n /**\n * Reindex every message in the definitions. Components and groups are\n * reindexed transitively as they are encountered during message reindexing.\n */\n compute (definitions: FixDefinitions): void {\n // Use a Set to dedupe — definitions.message contains duplicate entries (by name + msgType + abbreviation)\n const messages = new Set(definitions.message.values())\n for (const msg of messages) {\n this.reindex(msg)\n }\n }\n\n /**\n * Reindex a single set: post-order traversal ensures every nested\n * group/component is fully indexed before its parent is rebuilt.\n */\n reindex (set: IContainedSet): void {\n if (this.visited.has(set)) return\n this.visited.add(set)\n\n // First, recurse into all child groups/components (post-order)\n for (const field of set.fields) {\n if (field.type === ContainedFieldType.Group) {\n const gf = field as ContainedGroupField\n if (gf.definition) this.reindex(gf.definition)\n } else if (field.type === ContainedFieldType.Component) {\n const cf = field as ContainedComponentField\n if (cf.definition) this.reindex(cf.definition)\n }\n }\n\n // Save direct fields, clear all aggregated state, re-add via builder\n const level0: ContainedField[] = [...set.fields]\n IndexVisitor.clearAggregated(set as ContainedFieldSet)\n\n const builder = new ContainedSetBuilder(set)\n for (const field of level0) {\n builder.add(field)\n }\n }\n\n /**\n * Reset every aggregated index on a set without touching its identity.\n * Direct fields are passed back via the return of clearAggregated for\n * the caller to re-add.\n */\n static clearAggregated (set: ContainedFieldSet): void {\n set.fields.length = 0\n set.simple.clear()\n set.groups.clear()\n set.components.clear()\n set.localNameToField.clear()\n set.flattenedTag.length = 0\n set.localAttribute.length = 0\n set.nameToLocalAttribute.clear()\n set.firstSimple = null\n set.containsRaw = false\n IndexVisitor.clearObject(set.containedTag)\n IndexVisitor.clearObject(set.localTag)\n IndexVisitor.clearObject(set.localRequired)\n IndexVisitor.clearObject(set.tagToSimple)\n IndexVisitor.clearObject(set.tagToField)\n IndexVisitor.clearObject(set.containedLength)\n // Re-add the noOfField tag for groups (otherwise the group counter is lost)\n const def = set as any\n if (def.noOfField) {\n set.containedTag[def.noOfField.tag] = true\n }\n }\n\n private static clearObject (obj: Record<string, unknown>): void {\n for (const k of Object.keys(obj)) {\n delete obj[k]\n }\n }\n}\n"]}
|
|
@@ -1 +1,8 @@
|
|
|
1
1
|
export * from './quick-fix-xml-file-parser';
|
|
2
|
+
export * from './quick-fix-graph-parser';
|
|
3
|
+
export * from './quick-fix-graph-file-parser';
|
|
4
|
+
export * from './x-element';
|
|
5
|
+
export * from './sax-tree-builder';
|
|
6
|
+
export * from './dictionary-validator';
|
|
7
|
+
export * from './validation-error';
|
|
8
|
+
export * from './index-visitor';
|
|
@@ -15,4 +15,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./quick-fix-xml-file-parser"), exports);
|
|
18
|
+
__exportStar(require("./quick-fix-graph-parser"), exports);
|
|
19
|
+
__exportStar(require("./quick-fix-graph-file-parser"), exports);
|
|
20
|
+
__exportStar(require("./x-element"), exports);
|
|
21
|
+
__exportStar(require("./sax-tree-builder"), exports);
|
|
22
|
+
__exportStar(require("./dictionary-validator"), exports);
|
|
23
|
+
__exportStar(require("./validation-error"), exports);
|
|
24
|
+
__exportStar(require("./index-visitor"), exports);
|
|
18
25
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/dictionary/parser/quickfix/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA2C","sourcesContent":["export * from './quick-fix-xml-file-parser'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/dictionary/parser/quickfix/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA2C;AAC3C,2DAAwC;AACxC,gEAA6C;AAC7C,8CAA2B;AAC3B,qDAAkC;AAClC,yDAAsC;AACtC,qDAAkC;AAClC,kDAA+B","sourcesContent":["export * from './quick-fix-xml-file-parser'\nexport * from './quick-fix-graph-parser'\nexport * from './quick-fix-graph-file-parser'\nexport * from './x-element'\nexport * from './sax-tree-builder'\nexport * from './dictionary-validator'\nexport * from './validation-error'\nexport * from './index-visitor'\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FixParser } from '../../fix-parser';
|
|
2
|
+
import { FixDefinitions } from '../../definition/fix-definitions';
|
|
3
|
+
import { GetJsFixLogger } from '../../../config';
|
|
4
|
+
import { MakeDuplex } from '../../../transport';
|
|
5
|
+
import { QuickFixGraphParserOptions } from './quick-fix-graph-parser';
|
|
6
|
+
export declare class QuickFixGraphFileParser extends FixParser {
|
|
7
|
+
readonly make: MakeDuplex;
|
|
8
|
+
readonly getLogger: GetJsFixLogger;
|
|
9
|
+
readonly options: QuickFixGraphParserOptions;
|
|
10
|
+
constructor(make: MakeDuplex, getLogger: GetJsFixLogger, options?: QuickFixGraphParserOptions);
|
|
11
|
+
parse(): Promise<FixDefinitions>;
|
|
12
|
+
private readAll;
|
|
13
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.QuickFixGraphFileParser = void 0;
|
|
13
|
+
const fix_parser_1 = require("../../fix-parser");
|
|
14
|
+
const fix_definitions_1 = require("../../definition/fix-definitions");
|
|
15
|
+
const sax_tree_builder_1 = require("./sax-tree-builder");
|
|
16
|
+
const quick_fix_graph_parser_1 = require("./quick-fix-graph-parser");
|
|
17
|
+
const fix_definition_source_1 = require("../../fix-definition-source");
|
|
18
|
+
const version_util_1 = require("../../version-util");
|
|
19
|
+
class QuickFixGraphFileParser extends fix_parser_1.FixParser {
|
|
20
|
+
constructor(make, getLogger, options = {}) {
|
|
21
|
+
super();
|
|
22
|
+
this.make = make;
|
|
23
|
+
this.getLogger = getLogger;
|
|
24
|
+
this.options = options;
|
|
25
|
+
}
|
|
26
|
+
parse() {
|
|
27
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
var _a, _b, _c;
|
|
29
|
+
const xml = yield this.readAll();
|
|
30
|
+
const doc = sax_tree_builder_1.SaxTreeBuilder.parse(xml);
|
|
31
|
+
const fixRoot = doc.firstDescendant('fix');
|
|
32
|
+
if (!fixRoot)
|
|
33
|
+
throw new Error('no <fix> root element');
|
|
34
|
+
const major = parseInt((_a = fixRoot.attribute('major')) !== null && _a !== void 0 ? _a : '0', 10);
|
|
35
|
+
const minor = parseInt((_b = fixRoot.attribute('minor')) !== null && _b !== void 0 ? _b : '0', 10);
|
|
36
|
+
const servicepack = parseInt((_c = fixRoot.attribute('servicepack')) !== null && _c !== void 0 ? _c : '0', 10);
|
|
37
|
+
const description = (major !== 5 || servicepack === 0)
|
|
38
|
+
? `FIX.${major}.${minor}`
|
|
39
|
+
: `FIX.${major}.${minor}SP${servicepack}`;
|
|
40
|
+
const definitions = new fix_definitions_1.FixDefinitions(fix_definition_source_1.FixDefinitionSource.QuickFix, version_util_1.VersionUtil.resolve(description));
|
|
41
|
+
const parser = new quick_fix_graph_parser_1.QuickFixGraphParser(definitions, this.options);
|
|
42
|
+
return parser.parseDocument(doc);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
readAll() {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
const duplex = this.make();
|
|
48
|
+
const readable = duplex.readable;
|
|
49
|
+
return yield new Promise((resolve, reject) => {
|
|
50
|
+
const chunks = [];
|
|
51
|
+
readable.on('data', (chunk) => {
|
|
52
|
+
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
|
|
53
|
+
});
|
|
54
|
+
readable.on('end', () => {
|
|
55
|
+
resolve(Buffer.concat(chunks).toString('utf-8'));
|
|
56
|
+
});
|
|
57
|
+
readable.on('error', (err) => {
|
|
58
|
+
reject(err);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.QuickFixGraphFileParser = QuickFixGraphFileParser;
|
|
65
|
+
//# sourceMappingURL=quick-fix-graph-file-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quick-fix-graph-file-parser.js","sourceRoot":"","sources":["../../../../src/dictionary/parser/quickfix/quick-fix-graph-file-parser.ts"],"names":[],"mappings":";;;;;;;;;;;;AAKA,iDAA4C;AAC5C,sEAAiE;AAGjE,yDAAmD;AACnD,qEAA0F;AAC1F,uEAAiE;AACjE,qDAAgD;AAEhD,MAAa,uBAAwB,SAAQ,sBAAS;IACpD,YACkB,IAAgB,EAChB,SAAyB,EACzB,UAAsC,EAAE;QAExD,KAAK,EAAE,CAAA;QAJS,SAAI,GAAJ,IAAI,CAAY;QAChB,cAAS,GAAT,SAAS,CAAgB;QACzB,YAAO,GAAP,OAAO,CAAiC;IAG1D,CAAC;IAEY,KAAK;;;YAChB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAA;YAChC,MAAM,GAAG,GAAG,iCAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAErC,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,CAAA;YAC1C,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;YACtD,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAA,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,mCAAI,GAAG,EAAE,EAAE,CAAC,CAAA;YAC7D,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAA,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,mCAAI,GAAG,EAAE,EAAE,CAAC,CAAA;YAC7D,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAA,OAAO,CAAC,SAAS,CAAC,aAAa,CAAC,mCAAI,GAAG,EAAE,EAAE,CAAC,CAAA;YACzE,MAAM,WAAW,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,CAAC;gBACpD,CAAC,CAAC,OAAO,KAAK,IAAI,KAAK,EAAE;gBACzB,CAAC,CAAC,OAAO,KAAK,IAAI,KAAK,KAAK,WAAW,EAAE,CAAA;YAE3C,MAAM,WAAW,GAAG,IAAI,gCAAc,CAAC,2CAAmB,CAAC,QAAQ,EAAE,0BAAW,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAA;YACtG,MAAM,MAAM,GAAG,IAAI,4CAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;YACjE,OAAO,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;QAClC,CAAC;KAAA;IAOa,OAAO;;YACnB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;YAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAA;YAChC,OAAO,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACnD,MAAM,MAAM,GAAa,EAAE,CAAA;gBAC3B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE;oBAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;gBACrE,CAAC,CAAC,CAAA;gBACF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;oBACtB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;gBAClD,CAAC,CAAC,CAAA;gBACF,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;oBAClC,MAAM,CAAC,GAAG,CAAC,CAAA;gBACb,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC;KAAA;CACF;AAhDD,0DAgDC","sourcesContent":["/**\n * Drop-in replacement for QuickFixXmlFileParser that uses the graph-based\n * parser internally. Maintains the same constructor signature so it can be\n * swapped in the DefinitionFactory without changes to call sites.\n */\nimport { FixParser } from '../../fix-parser'\nimport { FixDefinitions } from '../../definition/fix-definitions'\nimport { GetJsFixLogger } from '../../../config'\nimport { MakeDuplex } from '../../../transport'\nimport { SaxTreeBuilder } from './sax-tree-builder'\nimport { QuickFixGraphParser, QuickFixGraphParserOptions } from './quick-fix-graph-parser'\nimport { FixDefinitionSource } from '../../fix-definition-source'\nimport { VersionUtil } from '../../version-util'\n\nexport class QuickFixGraphFileParser extends FixParser {\n constructor (\n public readonly make: MakeDuplex,\n public readonly getLogger: GetJsFixLogger,\n public readonly options: QuickFixGraphParserOptions = {}\n ) {\n super()\n }\n\n public async parse (): Promise<FixDefinitions> {\n const xml = await this.readAll()\n const doc = SaxTreeBuilder.parse(xml)\n\n const fixRoot = doc.firstDescendant('fix')\n if (!fixRoot) throw new Error('no <fix> root element')\n const major = parseInt(fixRoot.attribute('major') ?? '0', 10)\n const minor = parseInt(fixRoot.attribute('minor') ?? '0', 10)\n const servicepack = parseInt(fixRoot.attribute('servicepack') ?? '0', 10)\n const description = (major !== 5 || servicepack === 0)\n ? `FIX.${major}.${minor}`\n : `FIX.${major}.${minor}SP${servicepack}`\n\n const definitions = new FixDefinitions(FixDefinitionSource.QuickFix, VersionUtil.resolve(description))\n const parser = new QuickFixGraphParser(definitions, this.options)\n return parser.parseDocument(doc)\n }\n\n /**\n * Read the entire duplex stream into a UTF-8 string. The graph parser\n * needs the full document in memory because it walks the XDocument tree\n * with random access — unlike the legacy SAX-streaming parser.\n */\n private async readAll (): Promise<string> {\n const duplex = this.make()\n const readable = duplex.readable\n return await new Promise<string>((resolve, reject) => {\n const chunks: Buffer[] = []\n readable.on('data', (chunk: Buffer | string) => {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk)\n })\n readable.on('end', () => {\n resolve(Buffer.concat(chunks).toString('utf-8'))\n })\n readable.on('error', (err: Error) => {\n reject(err)\n })\n })\n }\n}\n"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { XDocument, XNode } from './x-element';
|
|
2
|
+
import { DictionaryValidator } from './dictionary-validator';
|
|
3
|
+
import { FixDefinitions } from '../../definition/fix-definitions';
|
|
4
|
+
import { SimpleFieldDefinition } from '../../definition/simple-field-definition';
|
|
5
|
+
import { MessageDefinition } from '../../definition/message-definition';
|
|
6
|
+
export declare enum NodeElementType {
|
|
7
|
+
MessageDefinition = "MessageDefinition",
|
|
8
|
+
SimpleFieldDefinition = "SimpleFieldDefinition",
|
|
9
|
+
SimpleFieldDeclaration = "SimpleFieldDeclaration",
|
|
10
|
+
InlineGroupDefinition = "InlineGroupDefinition",
|
|
11
|
+
GroupDefinition = "GroupDefinition",
|
|
12
|
+
GroupDeclaration = "GroupDeclaration",
|
|
13
|
+
ComponentDefinition = "ComponentDefinition",
|
|
14
|
+
ComponentDeclaration = "ComponentDeclaration"
|
|
15
|
+
}
|
|
16
|
+
export interface Edge {
|
|
17
|
+
readonly head: number;
|
|
18
|
+
readonly tail: number;
|
|
19
|
+
}
|
|
20
|
+
export declare class GraphNode {
|
|
21
|
+
readonly id: number;
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly type: NodeElementType;
|
|
24
|
+
readonly element: XNode;
|
|
25
|
+
private readonly _edges;
|
|
26
|
+
constructor(id: number, name: string, type: NodeElementType, element: XNode);
|
|
27
|
+
get edges(): ReadonlyArray<Edge>;
|
|
28
|
+
makeEdge(tail: number): Edge;
|
|
29
|
+
isRequired(): boolean;
|
|
30
|
+
toString(): string;
|
|
31
|
+
}
|
|
32
|
+
export interface QuickFixGraphParserOptions {
|
|
33
|
+
validateBeforeParsing?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export declare class QuickFixGraphParser {
|
|
36
|
+
private readonly definitions;
|
|
37
|
+
private readonly nodes;
|
|
38
|
+
private readonly containedSets;
|
|
39
|
+
private readonly queue;
|
|
40
|
+
private nextId;
|
|
41
|
+
private header;
|
|
42
|
+
private trailer;
|
|
43
|
+
validator: DictionaryValidator | null;
|
|
44
|
+
readonly validateBeforeParsing: boolean;
|
|
45
|
+
constructor(definitions: FixDefinitions, options?: QuickFixGraphParserOptions);
|
|
46
|
+
parseText(xml: string): FixDefinitions;
|
|
47
|
+
parseDocument(doc: XDocument): FixDefinitions;
|
|
48
|
+
private makeNode;
|
|
49
|
+
private constructTailNode;
|
|
50
|
+
private parseVersion;
|
|
51
|
+
private parseFields;
|
|
52
|
+
private parseComponents;
|
|
53
|
+
private parseHeader;
|
|
54
|
+
private parseTrailer;
|
|
55
|
+
private parseMessages;
|
|
56
|
+
private work;
|
|
57
|
+
private getComponentDefinition;
|
|
58
|
+
private componentDeclaration;
|
|
59
|
+
private messageDefinition;
|
|
60
|
+
private componentDefinition;
|
|
61
|
+
private groupDefinition;
|
|
62
|
+
private inlineGroupDefinition;
|
|
63
|
+
private simpleFieldDeclaration;
|
|
64
|
+
private expandSet;
|
|
65
|
+
private expandField;
|
|
66
|
+
private expandGroup;
|
|
67
|
+
private expandComponent;
|
|
68
|
+
private expandSetChild;
|
|
69
|
+
static nameFrom(element: XNode): string;
|
|
70
|
+
static getField(element: XNode): SimpleFieldDefinition;
|
|
71
|
+
static getMessage(element: XNode): MessageDefinition;
|
|
72
|
+
static parse(xml: string, options?: QuickFixGraphParserOptions): FixDefinitions;
|
|
73
|
+
}
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QuickFixGraphParser = exports.GraphNode = exports.NodeElementType = void 0;
|
|
4
|
+
const sax_tree_builder_1 = require("./sax-tree-builder");
|
|
5
|
+
const dictionary_validator_1 = require("./dictionary-validator");
|
|
6
|
+
const fix_definitions_1 = require("../../definition/fix-definitions");
|
|
7
|
+
const simple_field_definition_1 = require("../../definition/simple-field-definition");
|
|
8
|
+
const component_field_definition_1 = require("../../definition/component-field-definition");
|
|
9
|
+
const group_field_definition_1 = require("../../definition/group-field-definition");
|
|
10
|
+
const message_definition_1 = require("../../definition/message-definition");
|
|
11
|
+
const contained_simple_field_1 = require("../../contained/contained-simple-field");
|
|
12
|
+
const contained_component_field_1 = require("../../contained/contained-component-field");
|
|
13
|
+
const contained_group_field_1 = require("../../contained/contained-group-field");
|
|
14
|
+
const contained_set_builder_1 = require("../../contained/contained-set-builder");
|
|
15
|
+
const fix_definition_source_1 = require("../../fix-definition-source");
|
|
16
|
+
const version_util_1 = require("../../version-util");
|
|
17
|
+
const index_visitor_1 = require("./index-visitor");
|
|
18
|
+
var NodeElementType;
|
|
19
|
+
(function (NodeElementType) {
|
|
20
|
+
NodeElementType["MessageDefinition"] = "MessageDefinition";
|
|
21
|
+
NodeElementType["SimpleFieldDefinition"] = "SimpleFieldDefinition";
|
|
22
|
+
NodeElementType["SimpleFieldDeclaration"] = "SimpleFieldDeclaration";
|
|
23
|
+
NodeElementType["InlineGroupDefinition"] = "InlineGroupDefinition";
|
|
24
|
+
NodeElementType["GroupDefinition"] = "GroupDefinition";
|
|
25
|
+
NodeElementType["GroupDeclaration"] = "GroupDeclaration";
|
|
26
|
+
NodeElementType["ComponentDefinition"] = "ComponentDefinition";
|
|
27
|
+
NodeElementType["ComponentDeclaration"] = "ComponentDeclaration";
|
|
28
|
+
})(NodeElementType || (exports.NodeElementType = NodeElementType = {}));
|
|
29
|
+
class GraphNode {
|
|
30
|
+
constructor(id, name, type, element) {
|
|
31
|
+
this.id = id;
|
|
32
|
+
this.name = name;
|
|
33
|
+
this.type = type;
|
|
34
|
+
this.element = element;
|
|
35
|
+
this._edges = [];
|
|
36
|
+
}
|
|
37
|
+
get edges() {
|
|
38
|
+
return this._edges;
|
|
39
|
+
}
|
|
40
|
+
makeEdge(tail) {
|
|
41
|
+
const edge = { head: this.id, tail };
|
|
42
|
+
this._edges.push(edge);
|
|
43
|
+
return edge;
|
|
44
|
+
}
|
|
45
|
+
isRequired() {
|
|
46
|
+
if (this.name === 'StandardHeader' || this.name === 'StandardTrailer')
|
|
47
|
+
return true;
|
|
48
|
+
return this.element.attribute('required') === 'Y';
|
|
49
|
+
}
|
|
50
|
+
toString() {
|
|
51
|
+
return `Node: id=${this.id}, name=${this.name}, type=${this.type}`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.GraphNode = GraphNode;
|
|
55
|
+
class QuickFixGraphParser {
|
|
56
|
+
constructor(definitions, options = {}) {
|
|
57
|
+
var _a;
|
|
58
|
+
this.nodes = new Map();
|
|
59
|
+
this.containedSets = new Map();
|
|
60
|
+
this.queue = [];
|
|
61
|
+
this.nextId = 0;
|
|
62
|
+
this.header = null;
|
|
63
|
+
this.trailer = null;
|
|
64
|
+
this.validator = null;
|
|
65
|
+
this.definitions = definitions;
|
|
66
|
+
this.validateBeforeParsing = (_a = options.validateBeforeParsing) !== null && _a !== void 0 ? _a : true;
|
|
67
|
+
}
|
|
68
|
+
parseText(xml) {
|
|
69
|
+
const doc = sax_tree_builder_1.SaxTreeBuilder.parse(xml);
|
|
70
|
+
return this.parseDocument(doc);
|
|
71
|
+
}
|
|
72
|
+
parseDocument(doc) {
|
|
73
|
+
if (this.validateBeforeParsing) {
|
|
74
|
+
this.validator = new dictionary_validator_1.DictionaryValidator();
|
|
75
|
+
this.validator.validate(doc);
|
|
76
|
+
this.validator.throwIfErrors();
|
|
77
|
+
}
|
|
78
|
+
this.parseVersion(doc);
|
|
79
|
+
this.parseFields(doc);
|
|
80
|
+
this.parseComponents(doc);
|
|
81
|
+
this.parseHeader(doc);
|
|
82
|
+
this.parseTrailer(doc);
|
|
83
|
+
this.parseMessages(doc);
|
|
84
|
+
while (this.queue.length > 0) {
|
|
85
|
+
const node = this.queue.shift();
|
|
86
|
+
this.work(node);
|
|
87
|
+
}
|
|
88
|
+
new index_visitor_1.IndexVisitor().compute(this.definitions);
|
|
89
|
+
return this.definitions;
|
|
90
|
+
}
|
|
91
|
+
makeNode(name, element, type) {
|
|
92
|
+
const node = new GraphNode(this.nextId++, name, type, element);
|
|
93
|
+
this.nodes.set(node.id, node);
|
|
94
|
+
this.queue.push(node);
|
|
95
|
+
return node;
|
|
96
|
+
}
|
|
97
|
+
constructTailNode(name, headNode, element, type) {
|
|
98
|
+
const tailNode = this.makeNode(name, element, type);
|
|
99
|
+
headNode.makeEdge(tailNode.id);
|
|
100
|
+
tailNode.makeEdge(headNode.id);
|
|
101
|
+
}
|
|
102
|
+
parseVersion(doc) {
|
|
103
|
+
var _a, _b, _c;
|
|
104
|
+
const version = doc.firstDescendant('fix');
|
|
105
|
+
if (!version)
|
|
106
|
+
throw new Error('no <fix> root element');
|
|
107
|
+
const major = parseInt((_a = version.attribute('major')) !== null && _a !== void 0 ? _a : '0', 10);
|
|
108
|
+
const minor = parseInt((_b = version.attribute('minor')) !== null && _b !== void 0 ? _b : '0', 10);
|
|
109
|
+
const servicepack = parseInt((_c = version.attribute('servicepack')) !== null && _c !== void 0 ? _c : '0', 10);
|
|
110
|
+
const description = (major !== 5 || servicepack === 0)
|
|
111
|
+
? `FIX.${major}.${minor}`
|
|
112
|
+
: `FIX.${major}.${minor}SP${servicepack}`;
|
|
113
|
+
const resolved = version_util_1.VersionUtil.resolve(description);
|
|
114
|
+
if (resolved !== this.definitions.version) {
|
|
115
|
+
throw new Error(`version mismatch: dictionary declares ${description} but FixDefinitions was constructed with ${this.definitions.version}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
parseFields(doc) {
|
|
119
|
+
const fieldsNode = doc.firstDescendant('fields');
|
|
120
|
+
if (!fieldsNode)
|
|
121
|
+
return;
|
|
122
|
+
for (const fieldElement of fieldsNode.elements('field')) {
|
|
123
|
+
this.makeNode(QuickFixGraphParser.nameFrom(fieldElement), fieldElement, NodeElementType.SimpleFieldDefinition);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
parseComponents(doc) {
|
|
127
|
+
const componentsNode = doc.firstDescendant('components');
|
|
128
|
+
if (!componentsNode)
|
|
129
|
+
return;
|
|
130
|
+
for (const componentElement of componentsNode.elements('component')) {
|
|
131
|
+
this.makeNode(QuickFixGraphParser.nameFrom(componentElement), componentElement, NodeElementType.ComponentDefinition);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
parseHeader(doc) {
|
|
135
|
+
const header = doc.firstDescendant('header');
|
|
136
|
+
if (!header)
|
|
137
|
+
throw new Error('no header declared in fix definitions');
|
|
138
|
+
this.header = this.makeNode('StandardHeader', header, NodeElementType.ComponentDefinition);
|
|
139
|
+
}
|
|
140
|
+
parseTrailer(doc) {
|
|
141
|
+
const trailer = doc.firstDescendant('trailer');
|
|
142
|
+
if (!trailer)
|
|
143
|
+
throw new Error('no trailer declared in fix definitions');
|
|
144
|
+
this.trailer = this.makeNode('StandardTrailer', trailer, NodeElementType.ComponentDefinition);
|
|
145
|
+
}
|
|
146
|
+
parseMessages(doc) {
|
|
147
|
+
const messagesNode = doc.firstDescendant('messages');
|
|
148
|
+
if (!messagesNode)
|
|
149
|
+
return;
|
|
150
|
+
for (const messageElement of messagesNode.elements('message')) {
|
|
151
|
+
const msgType = messageElement.attribute('msgtype');
|
|
152
|
+
if (!msgType)
|
|
153
|
+
continue;
|
|
154
|
+
this.makeNode(msgType, messageElement, NodeElementType.MessageDefinition);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
work(node) {
|
|
158
|
+
switch (node.type) {
|
|
159
|
+
case NodeElementType.SimpleFieldDefinition: {
|
|
160
|
+
const sd = QuickFixGraphParser.getField(node.element);
|
|
161
|
+
this.definitions.addSimpleFieldDef(sd);
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
case NodeElementType.MessageDefinition: {
|
|
165
|
+
this.messageDefinition(node);
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
case NodeElementType.ComponentDefinition: {
|
|
169
|
+
this.componentDefinition(node);
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
case NodeElementType.SimpleFieldDeclaration: {
|
|
173
|
+
this.simpleFieldDeclaration(node);
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
case NodeElementType.InlineGroupDefinition: {
|
|
177
|
+
this.inlineGroupDefinition(node);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
case NodeElementType.GroupDefinition: {
|
|
181
|
+
this.groupDefinition(node);
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
case NodeElementType.ComponentDeclaration: {
|
|
185
|
+
this.componentDeclaration(node);
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
case NodeElementType.GroupDeclaration: {
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
getComponentDefinition(node) {
|
|
194
|
+
let definition = this.definitions.component.get(node.name);
|
|
195
|
+
if (definition)
|
|
196
|
+
return definition;
|
|
197
|
+
definition = new component_field_definition_1.ComponentFieldDefinition(node.name, node.name, null, node.name);
|
|
198
|
+
this.definitions.addComponentFieldDef(definition);
|
|
199
|
+
return definition;
|
|
200
|
+
}
|
|
201
|
+
componentDeclaration(node) {
|
|
202
|
+
const definition = this.getComponentDefinition(node);
|
|
203
|
+
const edge = node.edges[0];
|
|
204
|
+
const parentSet = this.containedSets.get(edge.tail);
|
|
205
|
+
if (!parentSet) {
|
|
206
|
+
throw new Error(`edge tail ${edge.tail} has no contained set on which to place declared component '${node.name}'`);
|
|
207
|
+
}
|
|
208
|
+
const containedComponent = new contained_component_field_1.ContainedComponentField(definition, parentSet.fields.length, node.isRequired());
|
|
209
|
+
new contained_set_builder_1.ContainedSetBuilder(parentSet).add(containedComponent);
|
|
210
|
+
this.containedSets.set(edge.head, definition);
|
|
211
|
+
}
|
|
212
|
+
messageDefinition(node) {
|
|
213
|
+
if (!this.header)
|
|
214
|
+
throw new Error('header not set');
|
|
215
|
+
if (!this.trailer)
|
|
216
|
+
throw new Error('trailer not set');
|
|
217
|
+
const md = QuickFixGraphParser.getMessage(node.element);
|
|
218
|
+
this.definitions.addMessage(md);
|
|
219
|
+
this.containedSets.set(node.id, md);
|
|
220
|
+
this.constructTailNode('StandardHeader', node, this.header.element, NodeElementType.ComponentDeclaration);
|
|
221
|
+
this.expandSet(node);
|
|
222
|
+
this.constructTailNode('StandardTrailer', node, this.trailer.element, NodeElementType.ComponentDeclaration);
|
|
223
|
+
}
|
|
224
|
+
componentDefinition(node) {
|
|
225
|
+
const definition = this.getComponentDefinition(node);
|
|
226
|
+
this.containedSets.set(node.id, definition);
|
|
227
|
+
this.expandSet(node);
|
|
228
|
+
}
|
|
229
|
+
groupDefinition(node) {
|
|
230
|
+
var _a;
|
|
231
|
+
const tail = (_a = node.edges[0]) === null || _a === void 0 ? void 0 : _a.tail;
|
|
232
|
+
if (tail == null) {
|
|
233
|
+
throw new Error(`node ${node} has no edges to find tail for group definition`);
|
|
234
|
+
}
|
|
235
|
+
const definition = this.containedSets.get(tail);
|
|
236
|
+
if (!definition) {
|
|
237
|
+
throw new Error(`node ${node} has no contained set for group definition`);
|
|
238
|
+
}
|
|
239
|
+
this.containedSets.set(node.edges[0].head, definition);
|
|
240
|
+
this.expandSet(node);
|
|
241
|
+
}
|
|
242
|
+
inlineGroupDefinition(node) {
|
|
243
|
+
const edge = node.edges[0];
|
|
244
|
+
if (!edge) {
|
|
245
|
+
throw new Error(`node ${node} has no edges to find tail for inline group definition`);
|
|
246
|
+
}
|
|
247
|
+
const parentSet = this.containedSets.get(edge.tail);
|
|
248
|
+
if (!parentSet) {
|
|
249
|
+
throw new Error(`edge tail ${edge.tail} has no contained set for inline group '${node.name}'`);
|
|
250
|
+
}
|
|
251
|
+
const noOFieldDefinition = this.definitions.simple.get(node.name);
|
|
252
|
+
if (!noOFieldDefinition) {
|
|
253
|
+
throw new Error(`${node.name} does not exist in simple field definitions to construct inline group`);
|
|
254
|
+
}
|
|
255
|
+
const name = node.name;
|
|
256
|
+
const definition = new group_field_definition_1.GroupFieldDefinition(name, name, null, noOFieldDefinition, name);
|
|
257
|
+
const containedGroup = new contained_group_field_1.ContainedGroupField(definition, parentSet.fields.length, node.isRequired());
|
|
258
|
+
new contained_set_builder_1.ContainedSetBuilder(parentSet).add(containedGroup);
|
|
259
|
+
this.containedSets.set(edge.head, definition);
|
|
260
|
+
this.constructTailNode(name, node, node.element, NodeElementType.GroupDefinition);
|
|
261
|
+
}
|
|
262
|
+
simpleFieldDeclaration(node) {
|
|
263
|
+
const edge = node.edges[0];
|
|
264
|
+
if (!edge) {
|
|
265
|
+
throw new Error(`node ${node} has no edges to find tail for simple field declaration`);
|
|
266
|
+
}
|
|
267
|
+
const parentSet = this.containedSets.get(edge.tail);
|
|
268
|
+
if (!parentSet) {
|
|
269
|
+
throw new Error(`edge tail ${edge.tail} has no contained set for declared field '${node.name}'`);
|
|
270
|
+
}
|
|
271
|
+
const sd = this.definitions.simple.get(node.name);
|
|
272
|
+
if (!sd) {
|
|
273
|
+
throw new Error(`element ${node} cannot be located as a simple field`);
|
|
274
|
+
}
|
|
275
|
+
const containedSimpleField = new contained_simple_field_1.ContainedSimpleField(sd, parentSet.fields.length, node.isRequired(), false);
|
|
276
|
+
new contained_set_builder_1.ContainedSetBuilder(parentSet).add(containedSimpleField);
|
|
277
|
+
}
|
|
278
|
+
expandSet(node) {
|
|
279
|
+
for (const child of node.element.elements()) {
|
|
280
|
+
switch (child.name) {
|
|
281
|
+
case 'field': {
|
|
282
|
+
this.expandField(node, child);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
case 'group': {
|
|
286
|
+
this.expandGroup(node, child);
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
case 'component': {
|
|
290
|
+
this.expandComponent(node, child);
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
expandField(node, element) {
|
|
297
|
+
this.constructTailNode(QuickFixGraphParser.nameFrom(element), node, element, NodeElementType.SimpleFieldDeclaration);
|
|
298
|
+
}
|
|
299
|
+
expandGroup(node, element) {
|
|
300
|
+
this.expandSetChild(node, element, NodeElementType.InlineGroupDefinition, NodeElementType.GroupDeclaration);
|
|
301
|
+
}
|
|
302
|
+
expandComponent(node, element) {
|
|
303
|
+
this.expandSetChild(node, element, NodeElementType.ComponentDefinition, NodeElementType.ComponentDeclaration);
|
|
304
|
+
}
|
|
305
|
+
expandSetChild(node, element, defineElement, declareElement) {
|
|
306
|
+
const name = QuickFixGraphParser.nameFrom(element);
|
|
307
|
+
const hasInlinedFields = element.elements().length > 0;
|
|
308
|
+
const elementType = hasInlinedFields ? defineElement : declareElement;
|
|
309
|
+
this.constructTailNode(name, node, element, elementType);
|
|
310
|
+
}
|
|
311
|
+
static nameFrom(element) {
|
|
312
|
+
var _a;
|
|
313
|
+
let name = (_a = element.attribute('name')) !== null && _a !== void 0 ? _a : '';
|
|
314
|
+
name = name.replace(/ /g, '');
|
|
315
|
+
if (name.length > 0 && name[0] >= '0' && name[0] <= '9') {
|
|
316
|
+
name = `F${name}`;
|
|
317
|
+
}
|
|
318
|
+
return name;
|
|
319
|
+
}
|
|
320
|
+
static getField(element) {
|
|
321
|
+
var _a, _b;
|
|
322
|
+
const name = QuickFixGraphParser.nameFrom(element);
|
|
323
|
+
const numberStr = element.attribute('number');
|
|
324
|
+
const tag = numberStr != null ? parseInt(numberStr, 10) : -1;
|
|
325
|
+
if (tag < 0)
|
|
326
|
+
throw new Error(`no tag/number for ${name}`);
|
|
327
|
+
const type = (_a = element.attribute('type')) !== null && _a !== void 0 ? _a : 'STRING';
|
|
328
|
+
const sd = new simple_field_definition_1.SimpleFieldDefinition(String(tag), name, name, null, null, type, null);
|
|
329
|
+
for (const value of element.elements('value')) {
|
|
330
|
+
const enumKey = value.attribute('enum');
|
|
331
|
+
const description = (_b = value.attribute('description')) !== null && _b !== void 0 ? _b : '';
|
|
332
|
+
if (enumKey != null) {
|
|
333
|
+
sd.addEnum(enumKey, description, description);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return sd;
|
|
337
|
+
}
|
|
338
|
+
static getMessage(element) {
|
|
339
|
+
var _a, _b;
|
|
340
|
+
const name = QuickFixGraphParser.nameFrom(element);
|
|
341
|
+
const msgCat = (_a = element.attribute('msgcat')) !== null && _a !== void 0 ? _a : '';
|
|
342
|
+
const msgType = (_b = element.attribute('msgtype')) !== null && _b !== void 0 ? _b : '';
|
|
343
|
+
return new message_definition_1.MessageDefinition(name, name, msgType, msgCat, name);
|
|
344
|
+
}
|
|
345
|
+
static parse(xml, options = {}) {
|
|
346
|
+
var _a, _b, _c;
|
|
347
|
+
const doc = sax_tree_builder_1.SaxTreeBuilder.parse(xml);
|
|
348
|
+
const fixRoot = doc.firstDescendant('fix');
|
|
349
|
+
if (!fixRoot)
|
|
350
|
+
throw new Error('no <fix> root element');
|
|
351
|
+
const major = parseInt((_a = fixRoot.attribute('major')) !== null && _a !== void 0 ? _a : '0', 10);
|
|
352
|
+
const minor = parseInt((_b = fixRoot.attribute('minor')) !== null && _b !== void 0 ? _b : '0', 10);
|
|
353
|
+
const servicepack = parseInt((_c = fixRoot.attribute('servicepack')) !== null && _c !== void 0 ? _c : '0', 10);
|
|
354
|
+
const description = (major !== 5 || servicepack === 0)
|
|
355
|
+
? `FIX.${major}.${minor}`
|
|
356
|
+
: `FIX.${major}.${minor}SP${servicepack}`;
|
|
357
|
+
const definitions = new fix_definitions_1.FixDefinitions(fix_definition_source_1.FixDefinitionSource.QuickFix, version_util_1.VersionUtil.resolve(description));
|
|
358
|
+
const parser = new QuickFixGraphParser(definitions, options);
|
|
359
|
+
return parser.parseDocument(doc);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
exports.QuickFixGraphParser = QuickFixGraphParser;
|
|
363
|
+
//# sourceMappingURL=quick-fix-graph-parser.js.map
|