UNPKG

x12

Version:
200 lines (154 loc) 7.86 kB
'use strict'; import { QuerySyntaxError } from './Errors'; import { X12Parser } from './X12Parser'; import { X12Interchange } from './X12Interchange'; import { X12FunctionalGroup } from './X12FunctionalGroup'; import { X12Transaction } from './X12Transaction'; import { X12Segment } from './X12Segment'; import { X12Element } from './X12Element'; export class X12QueryEngine { constructor(private _parser: X12Parser) { } query(rawEdi: string, reference: string): X12QueryResult[] { let interchange = this._parser.parseX12(rawEdi); let hlPathMatch = reference.match(/HL\+(\w\+?)+[\+-]/g); // ex. HL+O+P+I let segPathMatch = reference.match(/([A-Z0-9]{2,3}-)+/g); // ex. PO1-N9- let elmRefMatch = reference.match(/[A-Z0-9]{2,3}[0-9]{2}[^\[]?/g); // ex. REF02; need to remove trailing ":" if exists let qualMatch = reference.match(/:[A-Za-z]{2,3}[0-9]{2,}\[\"[^\[\]\"\"]+\"\]/g); // ex. :REF01["PO"] let results = new Array<X12QueryResult>(); for (let i = 0; i < interchange.functionalGroups.length; i++) { let group = interchange.functionalGroups[i]; for (let j = 0; j < group.transactions.length; j++) { let txn = group.transactions[j]; let segments = txn.segments; if (hlPathMatch) { segments = this._evaluateHLQueryPart(txn, hlPathMatch[0]); } if (segPathMatch) { segments = this._evaluateSegmentPathQueryPart(segments, segPathMatch[0]); } if (!elmRefMatch) { throw new QuerySyntaxError('Element reference queries must contain an element reference!'); } let txnResults = this._evaluateElementReferenceQueryPart(interchange, group, txn, [].concat(segments, [interchange.header, group.header, txn.header, txn.trailer, group.trailer, interchange.trailer]), elmRefMatch[0], qualMatch); txnResults.forEach((res) => { results.push(res); }); } } return results; } querySingle(rawEdi: string, reference: string): X12QueryResult { let results = this.query(rawEdi, reference); return (results.length == 0) ? null : results[0]; } private _evaluateHLQueryPart(transaction: X12Transaction, hlPath: string): X12Segment[] { let qualified = false; let pathParts = hlPath.replace('-', '').split('+').filter((value, index, array) => { return (value !== 'HL' && value !== '' && value !== null); }) let matches = new Array<X12Segment>(); let lastParentIndex = -1; for (let i = 0, j = 0; i < transaction.segments.length; i++) { let segment = transaction.segments[i]; if (qualified && segment.tag === 'HL') { let parentIndex = parseInt(segment.valueOf(2, '-1')); if (parentIndex !== lastParentIndex) { j = 0; qualified = false; } } if (!qualified && transaction.segments[i].tag === 'HL' && transaction.segments[i].valueOf(3) == pathParts[j]) { lastParentIndex = parseInt(segment.valueOf(2, '-1')); j++; if (j == pathParts.length) { qualified = true; } } if (qualified) { matches.push(transaction.segments[i]); } } return matches; } private _evaluateSegmentPathQueryPart(segments: X12Segment[], segmentPath: string): X12Segment[] { let qualified = false; let pathParts = segmentPath.split('-').filter((value, index, array) => { return !!value; }); let matches = new Array<X12Segment>(); for (let i = 0, j = 0; i < segments.length; i++) { if (qualified && (segments[i].tag == 'HL' || pathParts.indexOf(segments[i].tag) > -1)) { j = 0; qualified = false; } if (!qualified && segments[i].tag == pathParts[j]) { j++; if (j == pathParts.length) { qualified = true; } } if (qualified) { matches.push(segments[i]); } } return matches; } private _evaluateElementReferenceQueryPart(interchange: X12Interchange, functionalGroup: X12FunctionalGroup, transaction: X12Transaction, segments: X12Segment[], elementReference: string, qualifiers: string[]): X12QueryResult[] { let reference = elementReference.replace(':', ''); let tag = reference.substr(0, reference.length - 2); let pos = reference.substr(reference.length - 2, 2); let posint = parseInt(pos); let results = new Array<X12QueryResult>(); for (let i = 0; i < segments.length; i++) { let segment = segments[i]; if (!segment) { continue; } if (segment.tag !== tag) { continue; } let value = segment.valueOf(posint, null); if (value && this._testQualifiers(transaction, segment, qualifiers)) { results.push(new X12QueryResult(interchange, functionalGroup, transaction, segment, segment.elements[posint - 1])); } } return results; } private _testQualifiers(transaction: X12Transaction, segment: X12Segment, qualifiers: string[]): boolean { if (!qualifiers) { return true; } for (let i = 0 ; i < qualifiers.length; i++) { let qualifier = qualifiers[i].substr(1); let elementReference = qualifier.substring(0, qualifier.indexOf('[')); let elementValue = qualifier.substring(qualifier.indexOf('[') + 2, qualifier.lastIndexOf(']') - 1); let tag = elementReference.substr(0, elementReference.length - 2); let pos = elementReference.substr(elementReference.length - 2, 2); let posint = parseInt(pos); for (let j = transaction.segments.indexOf(segment); j > -1; j--) { let seg = transaction.segments[j]; let value = seg.valueOf(posint); if (seg.tag === tag && seg.tag === segment.tag && value !== elementValue) { return false; } else if (seg.tag === tag && value === elementValue) { break; } if (j == 0) { return false; } } } return true; } } export class X12QueryResult { constructor(interchange?: X12Interchange, functionalGroup?: X12FunctionalGroup, transaction?: X12Transaction, segment?: X12Segment, element?: X12Element) { this.interchange = interchange; this.functionalGroup = functionalGroup; this.transaction = transaction; this.segment = segment; this.element = element; } interchange: X12Interchange; functionalGroup: X12FunctionalGroup; transaction: X12Transaction; segment: X12Segment; element: X12Element; }