Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
tdecaluwe committed Nov 15, 2016
1 parent 3386e43 commit 11826b7
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 42 deletions.
52 changes: 31 additions & 21 deletions letterbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

'use strict'

var Writable = require('stream').Writable;
var Tracker = require('./tracker.js');

/**
* Construct a new letterbox accepting EDIFACT envelopes. A letterbox is a
* Writable stream accepting segment objects. Enveloping is optional, so a
Expand All @@ -26,22 +29,29 @@
*
* @constructs Letterbox
*/
var Letterbox = function () {
var letterbox = this;
var Letterbox = function (path) {
var that = this;

Writable.call(this, {
write: this.accept,
objectMode: true
});

this.path = path;

this.depth = {};
this.depth.current = 0;
this.depth.minimum = 0;
this.depth.maximum = 2;

this.next = function () {
letterbox.depth.current -= 1;
this.next = function (segment) {
that.depth.current -= 1;
};
}

module.exports = Letterbox;
Letterbox.prototype = Object.create(Writable.prototype);

function open_envelope(name, level) {
function openEnvelope(name, level) {
var message = '';
var depth = this.depth.current + 1;

Expand All @@ -57,7 +67,7 @@ function open_envelope(name, level) {
}
}

function close_envelope(name, level) {
function closeEnvelope(name, level) {
var message = '';
var depth = this.depth.current - 1;

Expand All @@ -69,46 +79,46 @@ function close_envelope(name, level) {
}
}

/**
* Accept a segment.
*
* @param {String} segment A segment object.
*/
Letterbox.prototype.write = function (segment) {
Letterbox.prototype.accept = function (segment) {
// Most of the time we are tracking segments in a message. To optimize for
// this case we start by detecting if we are currently in the middle of a
// message. We can do this with only one comparison.
if (this.depth.current > this.depth.maximum) {
this.track(segment);
this.tracker.accept(segment.name);
} else {
switch (segment.name) {
case 'UNB':
open_envelope.call(this, 'interchange', 0);
openEnvelope.call(this, 'interchange', 0);
break;
case 'UNG':
open_envelope.call(this, 'group', 1);
openEnvelope.call(this, 'group', 1);
break;
case 'UNH':
if (this.depth.current < this.depth.minimum) {
throw Error('Cannot omit an envelope');
} else {
this.depth.maximum = this.depth.current;
this.depth.current += 1;
this.track(segment);
this.setup(segment);
}
break;
case 'UNE':
close_envelope.call(this, 'group', 1);
closeEnvelope.call(this, 'group', 1);
break;
case 'UNZ':
close_envelope.call(this, 'interchange', 0);
closeEnvelope.call(this, 'interchange', 0);
break;
default:
throw Error('Did not expect a ' + segment + ' segment');
}
}
};
}

Letterbox.prototype.track = function () {};
Letterbox.prototype.setup = function (segment) {
this.cork();
this.tracker = new Tracker(require(this.path + '/' + segment.components[1]));
this.tracker.accept(segment.name);
this.uncork();
};

module.exports = Letterbox;
44 changes: 23 additions & 21 deletions spec/LetterboxSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,80 +6,82 @@ describe('Letterbox', function () {
let letterbox;
beforeEach(function () {
letterbox = new Letterbox();
spyOn(letterbox, 'track');
letterbox.tracker = { accept: function () {} };
spyOn(letterbox, 'setup');
spyOn(letterbox.tracker, 'accept');
});
it('should accept a message without an envelope', function () {
expect(function () { letterbox.write({ name: 'UNH' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNH' }); }).not.toThrow();
expect(letterbox.depth.maximum).toEqual(0);
expect(letterbox.depth.current).toEqual(1);
expect(function () { letterbox.next(); }).not.toThrow();
expect(letterbox.depth.current).toEqual(0);
});
it('cannot nest interchanges', function () {
expect(function () { letterbox.write({ name: 'UNB' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNB' }); }).not.toThrow();
expect(letterbox.depth.minimum).toEqual(1);
expect(letterbox.depth.current).toEqual(1);
expect(function () { letterbox.write({ name: 'UNB' }); }).toThrow();
expect(function () { letterbox.accept({ name: 'UNB' }); }).toThrow();
});
it('cannot open an interchange after a single message', function () {
expect(function () { letterbox.write({ name: 'UNH' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNH' }); }).not.toThrow();
expect(letterbox.depth.maximum).toEqual(0);
expect(letterbox.depth.current).toEqual(1);
expect(function () { letterbox.next(); }).not.toThrow();
expect(letterbox.depth.current).toEqual(0);
expect(function () { letterbox.write({ name: 'UNB' }); }).toThrow();
expect(function () { letterbox.accept({ name: 'UNB' }); }).toThrow();
});
it('cannot open a group without an interchange', function () {
expect(function () { letterbox.write({ name: 'UNG' }); }).toThrow();
expect(function () { letterbox.accept({ name: 'UNG' }); }).toThrow();
});
for (var name of ['UNB', 'UNZ', 'UNG', 'UNE']) {
it('should not validate a ' + name + ' segment while tracking a message', function () {
// While no valid message contains an enveloping segment in it's segment
// table, this test is the equivalence of allowing such a messsage
// definition. Prohibiting enveloping segments in messages should be
// done by providing a correct segment table, not by algorithm design.
expect(function () { letterbox.write({ name: 'UNH' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNH' }); }).not.toThrow();
expect(letterbox.depth.maximum).toEqual(0);
expect(letterbox.depth.current).toEqual(1);
expect(function () { letterbox.write({ name: name }); }).not.toThrow();
expect(letterbox.track).toHaveBeenCalled();
expect(function () { letterbox.accept({ name: name }); }).not.toThrow();
expect(letterbox.tracker.accept).toHaveBeenCalled();
});
}
it('should accept a message in an interchange', function () {
expect(function () { letterbox.write({ name: 'UNB' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNB' }); }).not.toThrow();
expect(letterbox.depth.minimum).toEqual(1);
expect(letterbox.depth.current).toEqual(1);
expect(function () { letterbox.write({ name: 'UNH' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNH' }); }).not.toThrow();
expect(letterbox.depth.maximum).toEqual(1);
expect(letterbox.depth.current).toEqual(2);
expect(function () { letterbox.next(); }).not.toThrow();
expect(letterbox.depth.current).toEqual(1);
expect(function () { letterbox.write({ name: 'UNZ' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNZ' }); }).not.toThrow();
expect(letterbox.depth.current).toEqual(0);
});
it('should not accept a group after a message', function () {
expect(function () { letterbox.write({ name: 'UNB' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNB' }); }).not.toThrow();
expect(letterbox.depth.minimum).toEqual(1);
expect(letterbox.depth.current).toEqual(1);
expect(function () { letterbox.write({ name: 'UNH' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNH' }); }).not.toThrow();
expect(letterbox.depth.maximum).toEqual(1);
expect(letterbox.depth.current).toEqual(2);
expect(function () { letterbox.next(); }).not.toThrow();
expect(letterbox.depth.current).toEqual(1);
expect(function () { letterbox.write({ name: 'UNG' }); }).toThrow();
expect(function () { letterbox.accept({ name: 'UNG' }); }).toThrow();
});
it('should not accept a group without an interchange', function () {
expect(function () { letterbox.write({ name: 'UNG' }); }).toThrow();
expect(function () { letterbox.accept({ name: 'UNG' }); }).toThrow();
});
it('should not accept a message after a group', function () {
expect(function () { letterbox.write({ name: 'UNB' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNB' }); }).not.toThrow();
expect(letterbox.depth.minimum).toEqual(1);
expect(letterbox.depth.current).toEqual(1);
expect(function () { letterbox.write({ name: 'UNG' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNG' }); }).not.toThrow();
expect(letterbox.depth.minimum).toEqual(2);
expect(letterbox.depth.current).toEqual(2);
expect(function () { letterbox.write({ name: 'UNE' }); }).not.toThrow();
expect(function () { letterbox.accept({ name: 'UNE' }); }).not.toThrow();
expect(letterbox.depth.current).toEqual(1);
expect(function () { letterbox.write({ name: 'UNH' }); }).toThrow();
expect(function () { letterbox.accept({ name: 'UNH' }); }).toThrow();
});
});

0 comments on commit 11826b7

Please sign in to comment.