185 lines
8.2 KiB
JavaScript
185 lines
8.2 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Parser = void 0;
|
|
const configuration_1 = require("./configuration");
|
|
const tokenizer_1 = require("./tokenizer");
|
|
const events_1 = require("events");
|
|
const separators_1 = require("./edi/separators");
|
|
var States;
|
|
(function (States) {
|
|
States[States["EMPTY"] = 0] = "EMPTY";
|
|
States[States["SEGMENT"] = 1] = "SEGMENT";
|
|
States[States["ELEMENT"] = 2] = "ELEMENT";
|
|
States[States["COMPONENT"] = 3] = "COMPONENT";
|
|
States[States["MODESET"] = 4] = "MODESET";
|
|
States[States["DATA"] = 5] = "DATA";
|
|
States[States["CONTINUED"] = 6] = "CONTINUED";
|
|
})(States || (States = {}));
|
|
class Parser extends events_1.EventEmitter {
|
|
constructor(configuration) {
|
|
super();
|
|
this.errors = {
|
|
incompleteMessage: function () {
|
|
return new Error("Cannot close an incomplete message");
|
|
},
|
|
invalidCharacter: function (character, index) {
|
|
let message = "";
|
|
message += "Invalid character " + character;
|
|
message += ` at position ${index}`;
|
|
return new Error(message);
|
|
},
|
|
invalidControlAfterSegment: function (segment, character) {
|
|
let message = "";
|
|
message += "Invalid character '" + character;
|
|
message += "' after reading segment name " + segment;
|
|
return new Error(message);
|
|
}
|
|
};
|
|
events_1.EventEmitter.apply(this);
|
|
if (configuration) {
|
|
this.configuration = configuration;
|
|
}
|
|
else {
|
|
this.configuration = new configuration_1.Configuration();
|
|
}
|
|
this.validator = this.configuration.validator;
|
|
this.tokenizer = new tokenizer_1.Tokenizer(this.configuration);
|
|
this.state = States.EMPTY;
|
|
}
|
|
separators() {
|
|
const builder = new separators_1.EdifactSeparatorsBuilder();
|
|
builder.elementSeparator(String.fromCharCode(this.configuration.config.dataElementSeparator));
|
|
builder.componentSeparator(String.fromCharCode(this.configuration.config.componentDataSeparator));
|
|
builder.decimalSeparator(String.fromCharCode(this.configuration.config.decimalMark));
|
|
builder.releaseIndicator(String.fromCharCode(this.configuration.config.releaseCharacter));
|
|
builder.segmentTerminator(String.fromCharCode(this.configuration.config.segmentTerminator));
|
|
return builder.build();
|
|
}
|
|
onOpenSegment(segment) {
|
|
this.emit("openSegment", segment);
|
|
}
|
|
onCloseSegment() {
|
|
this.emit("closeSegment");
|
|
}
|
|
onElement() {
|
|
this.emit("element");
|
|
}
|
|
onComponent(data) {
|
|
this.emit("component", data);
|
|
}
|
|
updateCharset(charset) {
|
|
const previous = this.configuration.charset;
|
|
this.configuration.updateCharset(charset);
|
|
if (this.configuration.charset !== previous) {
|
|
this.tokenizer.setCharsetBasedOnConfig(this.configuration);
|
|
}
|
|
}
|
|
end() {
|
|
if (this.state !== States.SEGMENT || this.tokenizer.buffer !== "") {
|
|
throw this.errors.incompleteMessage();
|
|
}
|
|
else {
|
|
this.state = States.EMPTY;
|
|
}
|
|
}
|
|
una(chunk) {
|
|
if (/^UNA.... ./g.test(chunk)) {
|
|
this.configuration.config.componentDataSeparator = chunk.charCodeAt(3);
|
|
this.configuration.config.dataElementSeparator = chunk.charCodeAt(4);
|
|
this.configuration.config.decimalMark = chunk.charCodeAt(5);
|
|
this.configuration.config.releaseCharacter = chunk.charCodeAt(6);
|
|
this.configuration.config.segmentTerminator = chunk.charCodeAt(8);
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
write(chunk) {
|
|
let index = 0;
|
|
if (this.state === States.CONTINUED) {
|
|
this.state = States.MODESET;
|
|
}
|
|
while (index < chunk.length) {
|
|
switch (this.state) {
|
|
case States.EMPTY:
|
|
index = this.una(chunk) ? 9 : 0;
|
|
this.state = States.SEGMENT;
|
|
case States.SEGMENT:
|
|
index = this.tokenizer.segment(chunk, index);
|
|
switch (chunk.charCodeAt(index) || this.configuration.config.endOfTag) {
|
|
case this.configuration.config.dataElementSeparator:
|
|
this.validator.onOpenSegment(this.tokenizer.buffer);
|
|
this.onOpenSegment(this.tokenizer.buffer);
|
|
this.state = States.ELEMENT;
|
|
this.tokenizer.buffer = "";
|
|
break;
|
|
case this.configuration.config.segmentTerminator:
|
|
this.validator.onOpenSegment(this.tokenizer.buffer);
|
|
this.onOpenSegment(this.tokenizer.buffer);
|
|
this.validator.onCloseSegment("");
|
|
this.onCloseSegment();
|
|
this.state = States.SEGMENT;
|
|
this.tokenizer.buffer = "";
|
|
break;
|
|
case this.configuration.config.endOfTag:
|
|
case this.configuration.config.carriageReturn:
|
|
case this.configuration.config.lineFeed:
|
|
break;
|
|
default:
|
|
throw this.errors.invalidControlAfterSegment(this.tokenizer.buffer, chunk.charAt(index));
|
|
}
|
|
break;
|
|
case States.ELEMENT:
|
|
this.validator.onElement();
|
|
this.onElement();
|
|
case States.COMPONENT:
|
|
this.validator.onOpenComponent(this.tokenizer);
|
|
case States.MODESET:
|
|
case States.DATA:
|
|
index = this.tokenizer.data(chunk, index);
|
|
switch (chunk.charCodeAt(index) || this.configuration.config.endOfTag) {
|
|
case this.configuration.config.componentDataSeparator:
|
|
this.validator.onCloseComponent(this.tokenizer);
|
|
this.onComponent(this.tokenizer.buffer);
|
|
this.state = States.COMPONENT;
|
|
this.tokenizer.buffer = "";
|
|
break;
|
|
case this.configuration.config.dataElementSeparator:
|
|
this.validator.onCloseComponent(this.tokenizer);
|
|
this.onComponent(this.tokenizer.buffer);
|
|
this.state = States.ELEMENT;
|
|
this.tokenizer.buffer = "";
|
|
break;
|
|
case this.configuration.config.segmentTerminator:
|
|
this.validator.onCloseComponent(this.tokenizer);
|
|
this.onComponent(this.tokenizer.buffer);
|
|
this.validator.onCloseSegment("");
|
|
this.onCloseSegment();
|
|
this.state = States.SEGMENT;
|
|
this.tokenizer.buffer = "";
|
|
break;
|
|
case this.configuration.config.decimalMark:
|
|
this.tokenizer.decimal(chunk, index);
|
|
this.state = States.DATA;
|
|
break;
|
|
case this.configuration.config.releaseCharacter:
|
|
index++;
|
|
this.tokenizer.release(chunk, index);
|
|
this.state = States.DATA;
|
|
break;
|
|
case this.configuration.config.endOfTag:
|
|
case this.configuration.config.carriageReturn:
|
|
case this.configuration.config.lineFeed:
|
|
this.state = States.DATA;
|
|
break;
|
|
default:
|
|
throw this.errors.invalidCharacter(chunk.charAt(index), index);
|
|
}
|
|
}
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
exports.Parser = Parser;
|
|
//# sourceMappingURL=parser.js.map
|