363 lines
13 KiB
JavaScript
363 lines
13 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.ValidatorImpl = exports.NullValidator = exports.ValidatorStates = exports.Dictionary = void 0;
|
|
class Dictionary {
|
|
constructor(data) {
|
|
this.entries = {};
|
|
if (data) {
|
|
for (const key in data) {
|
|
if (key !== "") {
|
|
this.add(key, data[key]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
contains(key) {
|
|
if (Object.prototype.hasOwnProperty.call(this.entries, key)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
get(key) {
|
|
if (this.contains(key)) {
|
|
return this.entries[key];
|
|
}
|
|
return undefined;
|
|
}
|
|
keys() {
|
|
return Object.keys(this.entries);
|
|
}
|
|
add(key, value) {
|
|
this.entries[key] = value;
|
|
return value;
|
|
}
|
|
length() {
|
|
return this.keys().length;
|
|
}
|
|
}
|
|
exports.Dictionary = Dictionary;
|
|
var ValidatorStates;
|
|
(function (ValidatorStates) {
|
|
ValidatorStates[ValidatorStates["NONE"] = 0] = "NONE";
|
|
ValidatorStates[ValidatorStates["SEGMENTS"] = 1] = "SEGMENTS";
|
|
ValidatorStates[ValidatorStates["ELEMENTS"] = 2] = "ELEMENTS";
|
|
ValidatorStates[ValidatorStates["ALL"] = 3] = "ALL";
|
|
ValidatorStates[ValidatorStates["ENTER"] = 4] = "ENTER";
|
|
ValidatorStates[ValidatorStates["ENABLE"] = 5] = "ENABLE";
|
|
})(ValidatorStates = exports.ValidatorStates || (exports.ValidatorStates = {}));
|
|
class NullValidator {
|
|
onOpenSegment() { }
|
|
onElement() { }
|
|
onOpenComponent() { }
|
|
onCloseComponent() { }
|
|
onCloseSegment() { }
|
|
disable() { }
|
|
enable() { }
|
|
define() { }
|
|
format() { return undefined; }
|
|
}
|
|
exports.NullValidator = NullValidator;
|
|
class ValidatorImpl {
|
|
constructor(throwOnMissingDefinitions = false) {
|
|
this.segments = new Dictionary();
|
|
this.elements = new Dictionary();
|
|
this.formats = new Dictionary();
|
|
this.counts = {
|
|
segment: 0,
|
|
element: 0,
|
|
component: 0
|
|
};
|
|
this.segment = undefined;
|
|
this.element = undefined;
|
|
this.component = undefined;
|
|
this.required = 0;
|
|
this.minimum = 0;
|
|
this.maximum = 0;
|
|
this.errors = {
|
|
invalidData: function (element, msg) {
|
|
return new Error(`Could not accept data on element ${element}: ${msg}`);
|
|
},
|
|
invalidFormatString: function (formatString) {
|
|
return new Error("Invalid format string " + formatString);
|
|
},
|
|
countError: function (type, name, definition, count) {
|
|
let array;
|
|
let start = type + " " + name;
|
|
let end;
|
|
let length = 0;
|
|
if (type === "Segment") {
|
|
array = "elements";
|
|
const entry = definition;
|
|
length = entry.elements.length;
|
|
}
|
|
else {
|
|
array = "components";
|
|
const entry = definition;
|
|
length = entry.components.length;
|
|
}
|
|
if (count < definition.requires) {
|
|
start += " only";
|
|
end = ` but requires at least ${definition.requires}`;
|
|
}
|
|
else {
|
|
end = ` but accepts at most ${length}`;
|
|
}
|
|
return new Error(start + ` got ${count} ` + array + end);
|
|
},
|
|
missingElementStart: function (segment) {
|
|
const message = `Active open element expected on segment ${segment}`;
|
|
return new Error(message);
|
|
},
|
|
missingElementDefinition: function (element) {
|
|
const message = `No definition found for element ${element}`;
|
|
return new Error(message);
|
|
},
|
|
missingSegmentStart: function (segment, throwOnMissingDefinitions) {
|
|
if (!throwOnMissingDefinitions) {
|
|
return undefined;
|
|
}
|
|
let name;
|
|
if (segment) {
|
|
name = "'" + segment + "'";
|
|
}
|
|
else {
|
|
name = "''";
|
|
}
|
|
return new Error(`Active open segment ${name} expected. Found none`);
|
|
},
|
|
missingSegmentDefinition: function (segment, throwOnMissingDefinitions) {
|
|
if (throwOnMissingDefinitions) {
|
|
return new Error(`No segment definition found for segment name ${segment}`);
|
|
}
|
|
else {
|
|
console.warn(`No segment definition found for segment name ${segment}`);
|
|
return undefined;
|
|
}
|
|
}
|
|
};
|
|
this.state = ValidatorStates.ALL;
|
|
this.throwOnMissingDefinitions = throwOnMissingDefinitions;
|
|
}
|
|
disable() {
|
|
this.state = ValidatorStates.NONE;
|
|
}
|
|
enable() {
|
|
this.state = ValidatorStates.SEGMENTS;
|
|
}
|
|
define(definitions) {
|
|
for (const key of definitions.keys()) {
|
|
const entry = definitions.get(key);
|
|
if (entry && Object.prototype.hasOwnProperty.call(entry, "elements")) {
|
|
this.segments.add(key, entry);
|
|
}
|
|
if (entry && Object.prototype.hasOwnProperty.call(entry, "components")) {
|
|
this.elements.add(key, entry);
|
|
}
|
|
}
|
|
}
|
|
format(formatString) {
|
|
if (this.formats.contains(formatString)) {
|
|
return this.formats.get(formatString);
|
|
}
|
|
else {
|
|
let parts;
|
|
if ((parts = /^(a|an|n)(\.\.)?([1-9][0-9]*)?$/.exec(formatString))) {
|
|
const max = parseInt(parts[3]);
|
|
const min = parts[2] === ".." ? 0 : max;
|
|
let alpha = false;
|
|
let numeric = false;
|
|
switch (parts[1]) {
|
|
case "a":
|
|
alpha = true;
|
|
break;
|
|
case "n":
|
|
numeric = true;
|
|
break;
|
|
case "an":
|
|
alpha = true;
|
|
numeric = true;
|
|
break;
|
|
}
|
|
return this.formats.add(formatString, { alpha: alpha, numeric: numeric, minimum: min, maximum: max });
|
|
}
|
|
else {
|
|
throw this.errors.invalidFormatString(formatString);
|
|
}
|
|
}
|
|
}
|
|
onOpenSegment(segment) {
|
|
switch (this.state) {
|
|
case ValidatorStates.ALL:
|
|
case ValidatorStates.ELEMENTS:
|
|
case ValidatorStates.SEGMENTS:
|
|
case ValidatorStates.ENABLE:
|
|
if ((this.segment = this.segments.get(segment))) {
|
|
this.state = ValidatorStates.ELEMENTS;
|
|
}
|
|
else {
|
|
const error = this.errors.missingSegmentDefinition(segment, this.throwOnMissingDefinitions);
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
this.counts.segment += 1;
|
|
this.counts.element = 0;
|
|
}
|
|
onElement() {
|
|
let name;
|
|
switch (this.state) {
|
|
case ValidatorStates.ALL:
|
|
if (this.segment === undefined) {
|
|
const error = this.errors.missingSegmentStart(undefined, this.throwOnMissingDefinitions);
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
name = this.segment.elements[this.counts.element];
|
|
if (this.element === undefined) {
|
|
throw this.errors.missingElementStart(name);
|
|
}
|
|
if (this.counts.component < this.element.requires || this.counts.component > this.element.components.length) {
|
|
throw this.errors.countError("Element", name, this.element, this.counts.component);
|
|
}
|
|
case ValidatorStates.ENTER:
|
|
case ValidatorStates.ELEMENTS:
|
|
if (this.segment === undefined) {
|
|
const error = this.errors.missingSegmentStart(undefined, this.throwOnMissingDefinitions);
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
const key = this.segment.elements[this.counts.element];
|
|
if ((this.element = this.elements.get(key))) {
|
|
this.state = ValidatorStates.ALL;
|
|
}
|
|
else {
|
|
this.state = ValidatorStates.ELEMENTS;
|
|
if (this.throwOnMissingDefinitions) {
|
|
throw this.errors.missingElementDefinition(key);
|
|
}
|
|
}
|
|
}
|
|
this.counts.element += 1;
|
|
this.counts.component = 0;
|
|
}
|
|
onOpenComponent(buffer) {
|
|
if (this.segment === undefined) {
|
|
const error = this.errors.missingSegmentStart(undefined, this.throwOnMissingDefinitions);
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
switch (this.state) {
|
|
case ValidatorStates.ALL:
|
|
const name = this.segment.elements[this.counts.element];
|
|
if (this.element === undefined) {
|
|
throw this.errors.missingElementStart(name);
|
|
}
|
|
this.component = this.format(this.element.components[this.counts.component]);
|
|
if (this.component === undefined) {
|
|
return;
|
|
}
|
|
this.required = this.element.requires;
|
|
this.minimum = this.component.minimum;
|
|
this.maximum = this.component.maximum;
|
|
if (this.component.alpha) {
|
|
if (this.component.numeric) {
|
|
buffer.alphanumeric();
|
|
}
|
|
else {
|
|
buffer.alpha();
|
|
}
|
|
}
|
|
else {
|
|
if (this.component.numeric) {
|
|
buffer.numeric();
|
|
}
|
|
else {
|
|
buffer.alphanumeric();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
buffer.alphanumeric();
|
|
}
|
|
this.counts.component += 1;
|
|
}
|
|
onCloseComponent(buffer) {
|
|
let length;
|
|
switch (this.state) {
|
|
case ValidatorStates.ALL:
|
|
length = buffer.length();
|
|
let name;
|
|
if (this.segment) {
|
|
name = this.segment.elements[this.counts.element];
|
|
}
|
|
else {
|
|
const error = this.errors.missingSegmentStart(this.segment, this.throwOnMissingDefinitions);
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
if (this.required >= this.counts.component || length > 0) {
|
|
if (length < this.minimum) {
|
|
throw this.errors.invalidData(name, `'${buffer.content()}' length is less than minimum length ${this.minimum}`);
|
|
}
|
|
else if (length > this.maximum) {
|
|
throw this.errors.invalidData(name, `'${buffer.content()} exceeds maximum length ${this.maximum}`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
onCloseSegment(segment) {
|
|
let name;
|
|
switch (this.state) {
|
|
case ValidatorStates.ALL:
|
|
if (this.segment === undefined) {
|
|
const error = this.errors.missingSegmentStart(segment, this.throwOnMissingDefinitions);
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
if (this.element === undefined) {
|
|
throw this.errors.missingElementStart(segment);
|
|
}
|
|
if (this.counts.component < this.element.requires || this.counts.component > this.element.components.length) {
|
|
name = this.segment.elements[this.counts.element];
|
|
throw this.errors.countError("Element", name, this.element, this.counts.component);
|
|
}
|
|
case ValidatorStates.ELEMENTS:
|
|
if (this.segment === undefined) {
|
|
const error = this.errors.missingSegmentStart(segment, this.throwOnMissingDefinitions);
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
if (this.counts.element < this.segment.requires || this.counts.element > this.segment.elements.length) {
|
|
name = segment;
|
|
throw this.errors.countError("Segment", name, this.segment, this.counts.element);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
exports.ValidatorImpl = ValidatorImpl;
|
|
//# sourceMappingURL=validator.js.map
|