jspurefix 5.3.0 → 5.5.4
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/DEMO_PORT_PLAN.md +286 -0
- 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/transport/ascii/ascii-session.js +3 -0
- package/dist/transport/ascii/ascii-session.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/transport/ascii/ascii-session.ts +4 -0
- package/src/util/definition-factory.ts +2 -2
|
@@ -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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quick-fix-graph-parser.js","sourceRoot":"","sources":["../../../../src/dictionary/parser/quickfix/quick-fix-graph-parser.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Graph-based QuickFix XML dictionary parser.\n *\n * Verbatim port of C# QuickFixXmlFileParser. Uses XDocument tree (from SaxTreeBuilder)\n * for random-access XML traversal and a Node/Edge/work-queue pattern for forward\n * reference resolution. Replaces the iterative N-pass SAX-streaming approach.\n *\n * Pre-parse validation via DictionaryValidator catches missing fields, duplicates,\n * and undefined references with \"did you mean\" suggestions before parsing begins.\n */\nimport { XDocument, XNode } from './x-element'\nimport { SaxTreeBuilder } from './sax-tree-builder'\nimport { DictionaryValidator } from './dictionary-validator'\nimport { FixDefinitions } from '../../definition/fix-definitions'\nimport { SimpleFieldDefinition } from '../../definition/simple-field-definition'\nimport { ComponentFieldDefinition } from '../../definition/component-field-definition'\nimport { GroupFieldDefinition } from '../../definition/group-field-definition'\nimport { MessageDefinition } from '../../definition/message-definition'\nimport { ContainedFieldSet } from '../../contained/contained-field-set'\nimport { ContainedSimpleField } from '../../contained/contained-simple-field'\nimport { ContainedComponentField } from '../../contained/contained-component-field'\nimport { ContainedGroupField } from '../../contained/contained-group-field'\nimport { ContainedSetBuilder } from '../../contained/contained-set-builder'\nimport { FixDefinitionSource } from '../../fix-definition-source'\nimport { VersionUtil } from '../../version-util'\nimport { IndexVisitor } from './index-visitor'\n\nexport enum NodeElementType {\n MessageDefinition = 'MessageDefinition',\n SimpleFieldDefinition = 'SimpleFieldDefinition',\n SimpleFieldDeclaration = 'SimpleFieldDeclaration',\n InlineGroupDefinition = 'InlineGroupDefinition',\n GroupDefinition = 'GroupDefinition',\n GroupDeclaration = 'GroupDeclaration',\n ComponentDefinition = 'ComponentDefinition',\n ComponentDeclaration = 'ComponentDeclaration'\n}\n\nexport interface Edge {\n readonly head: number\n readonly tail: number\n}\n\nexport class GraphNode {\n private readonly _edges: Edge[] = []\n\n constructor (\n public readonly id: number,\n public readonly name: string,\n public readonly type: NodeElementType,\n public readonly element: XNode\n ) {}\n\n get edges (): ReadonlyArray<Edge> {\n return this._edges\n }\n\n makeEdge (tail: number): Edge {\n const edge: Edge = { head: this.id, tail }\n this._edges.push(edge)\n return edge\n }\n\n isRequired (): boolean {\n if (this.name === 'StandardHeader' || this.name === 'StandardTrailer') return true\n return this.element.attribute('required') === 'Y'\n }\n\n toString (): string {\n return `Node: id=${this.id}, name=${this.name}, type=${this.type}`\n }\n}\n\nexport interface QuickFixGraphParserOptions {\n validateBeforeParsing?: boolean\n}\n\nexport class QuickFixGraphParser {\n private readonly definitions: FixDefinitions\n private readonly nodes = new Map<number, GraphNode>()\n private readonly containedSets = new Map<number, ContainedFieldSet>()\n private readonly queue: GraphNode[] = []\n private nextId = 0\n private header: GraphNode | null = null\n private trailer: GraphNode | null = null\n\n public validator: DictionaryValidator | null = null\n public readonly validateBeforeParsing: boolean\n\n constructor (definitions: FixDefinitions, options: QuickFixGraphParserOptions = {}) {\n this.definitions = definitions\n this.validateBeforeParsing = options.validateBeforeParsing ?? true\n }\n\n /**\n * Parse XML text into the FixDefinitions provided at construction.\n * Throws DictionaryValidationException if validation is enabled and errors are found.\n */\n parseText (xml: string): FixDefinitions {\n const doc = SaxTreeBuilder.parse(xml)\n return this.parseDocument(doc)\n }\n\n /**\n * Parse a pre-built XDocument tree.\n */\n parseDocument (doc: XDocument): FixDefinitions {\n if (this.validateBeforeParsing) {\n this.validator = new DictionaryValidator()\n this.validator.validate(doc)\n this.validator.throwIfErrors()\n }\n\n this.parseVersion(doc)\n this.parseFields(doc)\n this.parseComponents(doc)\n this.parseHeader(doc)\n this.parseTrailer(doc)\n this.parseMessages(doc)\n\n while (this.queue.length > 0) {\n const node = this.queue.shift()!\n this.work(node)\n }\n\n /*\n * At this point all fields on all sets are placed, however the parent (e.g. an\n * Instrument component) is not aware of the tags contained in nested groups/components\n * that were resolved AFTER it. The IndexVisitor walks every message and re-indexes\n * its tree post-order so each set knows all tags below it — essential for the segment\n * parser to work.\n */\n new IndexVisitor().compute(this.definitions)\n\n return this.definitions\n }\n\n // ── Graph construction ──\n\n private makeNode (name: string, element: XNode, type: NodeElementType): GraphNode {\n const node = new GraphNode(this.nextId++, name, type, element)\n this.nodes.set(node.id, node)\n this.queue.push(node)\n return node\n }\n\n private constructTailNode (name: string, headNode: GraphNode, element: XNode, type: NodeElementType): void {\n const tailNode = this.makeNode(name, element, type)\n headNode.makeEdge(tailNode.id)\n tailNode.makeEdge(headNode.id)\n }\n\n // ── Parsing entry points ──\n\n private parseVersion (doc: XDocument): void {\n const version = doc.firstDescendant('fix')\n if (!version) throw new Error('no <fix> root element')\n const major = parseInt(version.attribute('major') ?? '0', 10)\n const minor = parseInt(version.attribute('minor') ?? '0', 10)\n const servicepack = parseInt(version.attribute('servicepack') ?? '0', 10)\n const description = (major !== 5 || servicepack === 0)\n ? `FIX.${major}.${minor}`\n : `FIX.${major}.${minor}SP${servicepack}`\n const resolved = VersionUtil.resolve(description)\n // FixDefinitions doesn't have a setVersion — version is set at construction\n if (resolved !== this.definitions.version) {\n throw new Error(`version mismatch: dictionary declares ${description} but FixDefinitions was constructed with ${this.definitions.version}`)\n }\n }\n\n private parseFields (doc: XDocument): void {\n const fieldsNode = doc.firstDescendant('fields')\n if (!fieldsNode) return\n for (const fieldElement of fieldsNode.elements('field')) {\n this.makeNode(QuickFixGraphParser.nameFrom(fieldElement), fieldElement, NodeElementType.SimpleFieldDefinition)\n }\n }\n\n private parseComponents (doc: XDocument): void {\n const componentsNode = doc.firstDescendant('components')\n if (!componentsNode) return\n for (const componentElement of componentsNode.elements('component')) {\n this.makeNode(QuickFixGraphParser.nameFrom(componentElement), componentElement, NodeElementType.ComponentDefinition)\n }\n }\n\n private parseHeader (doc: XDocument): void {\n const header = doc.firstDescendant('header')\n if (!header) throw new Error('no header declared in fix definitions')\n this.header = this.makeNode('StandardHeader', header, NodeElementType.ComponentDefinition)\n }\n\n private parseTrailer (doc: XDocument): void {\n const trailer = doc.firstDescendant('trailer')\n if (!trailer) throw new Error('no trailer declared in fix definitions')\n this.trailer = this.makeNode('StandardTrailer', trailer, NodeElementType.ComponentDefinition)\n }\n\n private parseMessages (doc: XDocument): void {\n const messagesNode = doc.firstDescendant('messages')\n if (!messagesNode) return\n for (const messageElement of messagesNode.elements('message')) {\n const msgType = messageElement.attribute('msgtype')\n if (!msgType) continue\n this.makeNode(msgType, messageElement, NodeElementType.MessageDefinition)\n }\n }\n\n // ── Work queue dispatch ──\n\n private work (node: GraphNode): void {\n switch (node.type) {\n case NodeElementType.SimpleFieldDefinition: {\n const sd = QuickFixGraphParser.getField(node.element)\n this.definitions.addSimpleFieldDef(sd)\n break\n }\n case NodeElementType.MessageDefinition: {\n this.messageDefinition(node)\n break\n }\n case NodeElementType.ComponentDefinition: {\n this.componentDefinition(node)\n break\n }\n case NodeElementType.SimpleFieldDeclaration: {\n this.simpleFieldDeclaration(node)\n break\n }\n case NodeElementType.InlineGroupDefinition: {\n this.inlineGroupDefinition(node)\n break\n }\n case NodeElementType.GroupDefinition: {\n this.groupDefinition(node)\n break\n }\n case NodeElementType.ComponentDeclaration: {\n this.componentDeclaration(node)\n break\n }\n case NodeElementType.GroupDeclaration: {\n // QuickFix XML never has standalone group declarations — groups are always inline\n break\n }\n }\n }\n\n // ── Definition handlers ──\n\n private getComponentDefinition (node: GraphNode): ComponentFieldDefinition {\n let definition = this.definitions.component.get(node.name)\n if (definition) return definition\n definition = new ComponentFieldDefinition(node.name, node.name, null, node.name)\n this.definitions.addComponentFieldDef(definition)\n return definition\n }\n\n private componentDeclaration (node: GraphNode): void {\n const definition = this.getComponentDefinition(node)\n const edge = node.edges[0]\n const parentSet = this.containedSets.get(edge.tail)\n if (!parentSet) {\n throw new Error(`edge tail ${edge.tail} has no contained set on which to place declared component '${node.name}'`)\n }\n const containedComponent = new ContainedComponentField(definition, parentSet.fields.length, node.isRequired())\n new ContainedSetBuilder(parentSet).add(containedComponent)\n this.containedSets.set(edge.head, definition)\n }\n\n private messageDefinition (node: GraphNode): void {\n if (!this.header) throw new Error('header not set')\n if (!this.trailer) throw new Error('trailer not set')\n\n const md = QuickFixGraphParser.getMessage(node.element)\n this.definitions.addMessage(md)\n this.containedSets.set(node.id, md)\n\n // wrap the message body in StandardHeader + content + StandardTrailer\n this.constructTailNode('StandardHeader', node, this.header.element, NodeElementType.ComponentDeclaration)\n this.expandSet(node)\n this.constructTailNode('StandardTrailer', node, this.trailer.element, NodeElementType.ComponentDeclaration)\n }\n\n private componentDefinition (node: GraphNode): void {\n const definition = this.getComponentDefinition(node)\n this.containedSets.set(node.id, definition)\n this.expandSet(node)\n }\n\n private groupDefinition (node: GraphNode): void {\n const tail = node.edges[0]?.tail\n if (tail == null) {\n throw new Error(`node ${node} has no edges to find tail for group definition`)\n }\n const definition = this.containedSets.get(tail)\n if (!definition) {\n throw new Error(`node ${node} has no contained set for group definition`)\n }\n this.containedSets.set(node.edges[0].head, definition)\n this.expandSet(node)\n }\n\n private inlineGroupDefinition (node: GraphNode): void {\n const edge = node.edges[0]\n if (!edge) {\n throw new Error(`node ${node} has no edges to find tail for inline group definition`)\n }\n const parentSet = this.containedSets.get(edge.tail)\n if (!parentSet) {\n throw new Error(`edge tail ${edge.tail} has no contained set for inline group '${node.name}'`)\n }\n const noOFieldDefinition = this.definitions.simple.get(node.name)\n if (!noOFieldDefinition) {\n throw new Error(`${node.name} does not exist in simple field definitions to construct inline group`)\n }\n const name = node.name\n const definition = new GroupFieldDefinition(name, name, null, noOFieldDefinition, name)\n const containedGroup = new ContainedGroupField(definition, parentSet.fields.length, node.isRequired())\n new ContainedSetBuilder(parentSet).add(containedGroup)\n this.containedSets.set(edge.head, definition)\n this.constructTailNode(name, node, node.element, NodeElementType.GroupDefinition)\n }\n\n private simpleFieldDeclaration (node: GraphNode): void {\n const edge = node.edges[0]\n if (!edge) {\n throw new Error(`node ${node} has no edges to find tail for simple field declaration`)\n }\n const parentSet = this.containedSets.get(edge.tail)\n if (!parentSet) {\n throw new Error(`edge tail ${edge.tail} has no contained set for declared field '${node.name}'`)\n }\n const sd = this.definitions.simple.get(node.name)\n if (!sd) {\n throw new Error(`element ${node} cannot be located as a simple field`)\n }\n const containedSimpleField = new ContainedSimpleField(sd, parentSet.fields.length, node.isRequired(), false)\n new ContainedSetBuilder(parentSet).add(containedSimpleField)\n }\n\n // ── Set expansion ──\n\n /**\n * Walks the children of a definition node and constructs tail nodes for each\n * field/group/component reference, queuing them for resolution.\n */\n private expandSet (node: GraphNode): void {\n for (const child of node.element.elements()) {\n switch (child.name) {\n case 'field': {\n this.expandField(node, child)\n break\n }\n case 'group': {\n this.expandGroup(node, child)\n break\n }\n case 'component': {\n this.expandComponent(node, child)\n break\n }\n }\n }\n }\n\n private expandField (node: GraphNode, element: XNode): void {\n this.constructTailNode(QuickFixGraphParser.nameFrom(element), node, element, NodeElementType.SimpleFieldDeclaration)\n }\n\n private expandGroup (node: GraphNode, element: XNode): void {\n this.expandSetChild(node, element, NodeElementType.InlineGroupDefinition, NodeElementType.GroupDeclaration)\n }\n\n private expandComponent (node: GraphNode, element: XNode): void {\n this.expandSetChild(node, element, NodeElementType.ComponentDefinition, NodeElementType.ComponentDeclaration)\n }\n\n private expandSetChild (\n node: GraphNode,\n element: XNode,\n defineElement: NodeElementType,\n declareElement: NodeElementType\n ): void {\n const name = QuickFixGraphParser.nameFrom(element)\n const hasInlinedFields = element.elements().length > 0\n const elementType = hasInlinedFields ? defineElement : declareElement\n this.constructTailNode(name, node, element, elementType)\n }\n\n // ── Static helpers ──\n\n /**\n * Extract a name from an element's attributes, with the same conventions as the C# parser:\n * strip spaces, prefix with 'F' if the name starts with a digit.\n */\n static nameFrom (element: XNode): string {\n let name = element.attribute('name') ?? ''\n name = name.replace(/ /g, '')\n if (name.length > 0 && name[0] >= '0' && name[0] <= '9') {\n name = `F${name}`\n }\n return name\n }\n\n static getField (element: XNode): SimpleFieldDefinition {\n const name = QuickFixGraphParser.nameFrom(element)\n const numberStr = element.attribute('number')\n const tag = numberStr != null ? parseInt(numberStr, 10) : -1\n if (tag < 0) throw new Error(`no tag/number for ${name}`)\n const type = element.attribute('type') ?? 'STRING'\n\n const sd = new SimpleFieldDefinition(String(tag), name, name, null, null, type, null)\n // Add enum values\n for (const value of element.elements('value')) {\n const enumKey = value.attribute('enum')\n const description = value.attribute('description') ?? ''\n if (enumKey != null) {\n sd.addEnum(enumKey, description, description)\n }\n }\n return sd\n }\n\n static getMessage (element: XNode): MessageDefinition {\n const name = QuickFixGraphParser.nameFrom(element)\n const msgCat = element.attribute('msgcat') ?? ''\n const msgType = element.attribute('msgtype') ?? ''\n return new MessageDefinition(name, name, msgType, msgCat, name)\n }\n\n /**\n * Convenience: parse XML text into a fresh FixDefinitions.\n */\n static parse (xml: string, options: QuickFixGraphParserOptions = {}): FixDefinitions {\n // Pre-parse the version so we can construct FixDefinitions correctly\n const doc = SaxTreeBuilder.parse(xml)\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 const definitions = new FixDefinitions(FixDefinitionSource.QuickFix, VersionUtil.resolve(description))\n const parser = new QuickFixGraphParser(definitions, options)\n return parser.parseDocument(doc)\n }\n}\n"]}
|
|
@@ -0,0 +1,103 @@
|
|
|
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.SaxTreeBuilder = void 0;
|
|
13
|
+
const x_element_1 = require("./x-element");
|
|
14
|
+
class SaxTreeBuilder {
|
|
15
|
+
static parse(xml) {
|
|
16
|
+
const sax = require('sax');
|
|
17
|
+
const parser = sax.parser(true, {});
|
|
18
|
+
const stack = [];
|
|
19
|
+
let root = null;
|
|
20
|
+
let lastWasSelfClosing = false;
|
|
21
|
+
parser.onopentag = (node) => {
|
|
22
|
+
const element = {
|
|
23
|
+
name: node.name,
|
|
24
|
+
attributes: Object.assign({}, node.attributes),
|
|
25
|
+
children: [],
|
|
26
|
+
line: parser.line + 1
|
|
27
|
+
};
|
|
28
|
+
if (stack.length > 0) {
|
|
29
|
+
stack[stack.length - 1].children.push(element);
|
|
30
|
+
}
|
|
31
|
+
lastWasSelfClosing = node.isSelfClosing;
|
|
32
|
+
if (!node.isSelfClosing) {
|
|
33
|
+
stack.push(element);
|
|
34
|
+
}
|
|
35
|
+
if (!root)
|
|
36
|
+
root = element;
|
|
37
|
+
};
|
|
38
|
+
parser.onclosetag = () => {
|
|
39
|
+
if (lastWasSelfClosing) {
|
|
40
|
+
lastWasSelfClosing = false;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
stack.pop();
|
|
44
|
+
};
|
|
45
|
+
parser.onerror = (err) => {
|
|
46
|
+
throw new Error(`XML parse error at line ${parser.line + 1}: ${err.message}`);
|
|
47
|
+
};
|
|
48
|
+
parser.write(xml).close();
|
|
49
|
+
if (!root) {
|
|
50
|
+
throw new Error('empty XML document');
|
|
51
|
+
}
|
|
52
|
+
return new x_element_1.XDocument(root);
|
|
53
|
+
}
|
|
54
|
+
static parseStream(readable) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
return yield new Promise((resolve, reject) => {
|
|
57
|
+
const sax = require('sax');
|
|
58
|
+
const saxStream = sax.createStream(true, {});
|
|
59
|
+
const stack = [];
|
|
60
|
+
let root = null;
|
|
61
|
+
let lastWasSelfClosing = false;
|
|
62
|
+
saxStream.on('opentag', (node) => {
|
|
63
|
+
const element = {
|
|
64
|
+
name: node.name,
|
|
65
|
+
attributes: Object.assign({}, node.attributes),
|
|
66
|
+
children: [],
|
|
67
|
+
line: saxStream._parser.line + 1
|
|
68
|
+
};
|
|
69
|
+
if (stack.length > 0) {
|
|
70
|
+
stack[stack.length - 1].children.push(element);
|
|
71
|
+
}
|
|
72
|
+
lastWasSelfClosing = node.isSelfClosing;
|
|
73
|
+
if (!node.isSelfClosing) {
|
|
74
|
+
stack.push(element);
|
|
75
|
+
}
|
|
76
|
+
if (!root)
|
|
77
|
+
root = element;
|
|
78
|
+
});
|
|
79
|
+
saxStream.on('closetag', () => {
|
|
80
|
+
if (lastWasSelfClosing) {
|
|
81
|
+
lastWasSelfClosing = false;
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
stack.pop();
|
|
85
|
+
});
|
|
86
|
+
saxStream.on('error', (err) => {
|
|
87
|
+
reject(new Error(`XML parse error: ${err.message}`));
|
|
88
|
+
});
|
|
89
|
+
saxStream.on('end', () => {
|
|
90
|
+
if (!root) {
|
|
91
|
+
reject(new Error('empty XML document'));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
resolve(new x_element_1.XDocument(root));
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
readable.pipe(saxStream);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.SaxTreeBuilder = SaxTreeBuilder;
|
|
103
|
+
//# sourceMappingURL=sax-tree-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sax-tree-builder.js","sourceRoot":"","sources":["../../../../src/dictionary/parser/quickfix/sax-tree-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import { XDocument, XElement } from './x-element'\n\n/**\n * Builds an in-memory XElement tree from XML using a single SAX pass.\n * After construction, the tree provides DOM-like random access for\n * graph-based parsing and validation.\n */\nexport class SaxTreeBuilder {\n /**\n * Parse XML text into an XDocument.\n */\n static parse (xml: string): XDocument {\n const sax = require('sax')\n const parser = sax.parser(true, {})\n const stack: XElement[] = []\n let root: XElement | null = null\n let lastWasSelfClosing = false\n\n parser.onopentag = (node: { name: string, attributes: Record<string, string>, isSelfClosing: boolean }) => {\n const element: XElement = {\n name: node.name,\n attributes: { ...node.attributes },\n children: [],\n line: parser.line + 1\n }\n\n if (stack.length > 0) {\n stack[stack.length - 1].children.push(element)\n }\n\n lastWasSelfClosing = node.isSelfClosing\n if (!node.isSelfClosing) {\n stack.push(element)\n }\n if (!root) root = element\n }\n\n parser.onclosetag = () => {\n if (lastWasSelfClosing) {\n lastWasSelfClosing = false\n return\n }\n stack.pop()\n }\n\n parser.onerror = (err: Error) => {\n throw new Error(`XML parse error at line ${parser.line + 1}: ${err.message}`)\n }\n\n parser.write(xml).close()\n\n if (!root) {\n throw new Error('empty XML document')\n }\n\n return new XDocument(root)\n }\n\n /**\n * Parse XML from a readable stream into an XDocument.\n */\n static async parseStream (readable: NodeJS.ReadableStream): Promise<XDocument> {\n return await new Promise<XDocument>((resolve, reject) => {\n const sax = require('sax')\n const saxStream = sax.createStream(true, {})\n const stack: XElement[] = []\n let root: XElement | null = null\n let lastWasSelfClosing = false\n\n saxStream.on('opentag', (node: { name: string, attributes: Record<string, string>, isSelfClosing: boolean }) => {\n const element: XElement = {\n name: node.name,\n attributes: { ...node.attributes },\n children: [],\n line: saxStream._parser.line + 1\n }\n\n if (stack.length > 0) {\n stack[stack.length - 1].children.push(element)\n }\n\n lastWasSelfClosing = node.isSelfClosing\n if (!node.isSelfClosing) {\n stack.push(element)\n }\n if (!root) root = element\n })\n\n saxStream.on('closetag', () => {\n if (lastWasSelfClosing) {\n lastWasSelfClosing = false\n return\n }\n stack.pop()\n })\n\n saxStream.on('error', (err: Error) => {\n reject(new Error(`XML parse error: ${err.message}`))\n })\n\n saxStream.on('end', () => {\n if (!root) {\n reject(new Error('empty XML document'))\n } else {\n resolve(new XDocument(root))\n }\n })\n\n readable.pipe(saxStream)\n })\n }\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare enum ValidationSeverity {
|
|
2
|
+
Warning = "Warning",
|
|
3
|
+
Error = "Error"
|
|
4
|
+
}
|
|
5
|
+
export interface ValidationError {
|
|
6
|
+
readonly severity: ValidationSeverity;
|
|
7
|
+
readonly code: string;
|
|
8
|
+
readonly message: string;
|
|
9
|
+
readonly elementName?: string;
|
|
10
|
+
readonly elementType?: string;
|
|
11
|
+
readonly lineNumber?: number;
|
|
12
|
+
readonly suggestion?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class DictionaryValidationException extends Error {
|
|
15
|
+
readonly errors: ReadonlyArray<ValidationError>;
|
|
16
|
+
constructor(errors: ReadonlyArray<ValidationError>);
|
|
17
|
+
}
|