Skip to content

Commit ce1442d

Browse files
committed
WIP
1 parent 3386e43 commit ce1442d

File tree

3 files changed

+122
-108
lines changed

3 files changed

+122
-108
lines changed

letterbox.js renamed to interchange.js

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,40 @@
1818

1919
'use strict'
2020

21+
var Writable = require('stream').Writable;
22+
var Tracker = require('./tracker.js');
23+
2124
/**
2225
* Construct a new letterbox accepting EDIFACT envelopes. A letterbox is a
2326
* Writable stream accepting segment objects. Enveloping is optional, so a
2427
* single message will also be accepted. Groups inside an envelope are optional
2528
* as well. When used however, every message should be in a group.
2629
*
27-
* @constructs Letterbox
30+
* @constructs Interchange
2831
*/
29-
var Letterbox = function () {
30-
var letterbox = this;
32+
var Interchange = function (path) {
33+
var that = this;
34+
35+
Writable.call(this, {
36+
write: this.accept,
37+
objectMode: true
38+
});
39+
40+
this.path = path;
3141

3242
this.depth = {};
3343
this.depth.current = 0;
3444
this.depth.minimum = 0;
3545
this.depth.maximum = 2;
3646

37-
this.next = function () {
38-
letterbox.depth.current -= 1;
47+
this.next = function (segment) {
48+
that.depth.current -= 1;
3949
};
4050
}
4151

42-
module.exports = Letterbox;
52+
Interchange.prototype = Object.create(Writable.prototype);
4353

44-
function open_envelope(name, level) {
54+
function openEnvelope(name, level) {
4555
var message = '';
4656
var depth = this.depth.current + 1;
4757

@@ -57,7 +67,7 @@ function open_envelope(name, level) {
5767
}
5868
}
5969

60-
function close_envelope(name, level) {
70+
function closeEnvelope(name, level) {
6171
var message = '';
6272
var depth = this.depth.current - 1;
6373

@@ -69,46 +79,46 @@ function close_envelope(name, level) {
6979
}
7080
}
7181

72-
/**
73-
* Accept a segment.
74-
*
75-
* @param {String} segment A segment object.
76-
*/
77-
Letterbox.prototype.write = function (segment) {
82+
Interchange.prototype.accept = function (segment) {
7883
// Most of the time we are tracking segments in a message. To optimize for
7984
// this case we start by detecting if we are currently in the middle of a
8085
// message. We can do this with only one comparison.
8186
if (this.depth.current > this.depth.maximum) {
82-
this.track(segment);
87+
this.tracker.accept(segment.name);
8388
} else {
8489
switch (segment.name) {
8590
case 'UNB':
86-
open_envelope.call(this, 'interchange', 0);
91+
openEnvelope.call(this, 'interchange', 0);
8792
break;
8893
case 'UNG':
89-
open_envelope.call(this, 'group', 1);
94+
openEnvelope.call(this, 'group', 1);
9095
break;
9196
case 'UNH':
9297
if (this.depth.current < this.depth.minimum) {
9398
throw Error('Cannot omit an envelope');
9499
} else {
95100
this.depth.maximum = this.depth.current;
96101
this.depth.current += 1;
97-
this.track(segment);
102+
this.setup(segment);
98103
}
99104
break;
100105
case 'UNE':
101-
close_envelope.call(this, 'group', 1);
106+
closeEnvelope.call(this, 'group', 1);
102107
break;
103108
case 'UNZ':
104-
close_envelope.call(this, 'interchange', 0);
109+
closeEnvelope.call(this, 'interchange', 0);
105110
break;
106111
default:
107112
throw Error('Did not expect a ' + segment + ' segment');
108113
}
109114
}
110-
};
115+
}
111116

112-
Letterbox.prototype.track = function () {};
117+
Interchange.prototype.setup = function (segment) {
118+
this.cork();
119+
this.tracker = new Tracker(require(this.path + '/' + segment.components[1]));
120+
this.tracker.accept(segment.name);
121+
this.uncork();
122+
};
113123

114-
module.exports = Letterbox;
124+
module.exports = Interchange;

spec/InterchangeSpec.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
'use strict'
2+
3+
let Interchange = require('../interchange.js');
4+
5+
describe('Interchange', function () {
6+
let interchange;
7+
beforeEach(function () {
8+
interchange = new Interchange();
9+
interchange.tracker = { accept: function () {} };
10+
spyOn(interchange, 'setup');
11+
spyOn(interchange.tracker, 'accept');
12+
});
13+
it('should accept a message without an envelope', function () {
14+
expect(function () { interchange.accept({ name: 'UNH' }); }).not.toThrow();
15+
expect(interchange.depth.maximum).toEqual(0);
16+
expect(interchange.depth.current).toEqual(1);
17+
expect(function () { interchange.next(); }).not.toThrow();
18+
expect(interchange.depth.current).toEqual(0);
19+
});
20+
it('cannot nest interchanges', function () {
21+
expect(function () { interchange.accept({ name: 'UNB' }); }).not.toThrow();
22+
expect(interchange.depth.minimum).toEqual(1);
23+
expect(interchange.depth.current).toEqual(1);
24+
expect(function () { interchange.accept({ name: 'UNB' }); }).toThrow();
25+
});
26+
it('cannot open an interchange after a single message', function () {
27+
expect(function () { interchange.accept({ name: 'UNH' }); }).not.toThrow();
28+
expect(interchange.depth.maximum).toEqual(0);
29+
expect(interchange.depth.current).toEqual(1);
30+
expect(function () { interchange.next(); }).not.toThrow();
31+
expect(interchange.depth.current).toEqual(0);
32+
expect(function () { interchange.accept({ name: 'UNB' }); }).toThrow();
33+
});
34+
it('cannot open a group without an interchange', function () {
35+
expect(function () { interchange.accept({ name: 'UNG' }); }).toThrow();
36+
});
37+
for (var name of ['UNB', 'UNZ', 'UNG', 'UNE']) {
38+
it('should not validate a ' + name + ' segment while tracking a message', function () {
39+
// While no valid message contains an enveloping segment in it's segment
40+
// table, this test is the equivalence of allowing such a messsage
41+
// definition. Prohibiting enveloping segments in messages should be
42+
// done by providing a correct segment table, not by algorithm design.
43+
expect(function () {
44+
interchange.accept({ name: 'UNH' });
45+
}).not.toThrow();
46+
expect(interchange.depth.maximum).toEqual(0);
47+
expect(interchange.depth.current).toEqual(1);
48+
expect(function () { interchange.accept({ name: name }); }).not.toThrow();
49+
expect(interchange.tracker.accept).toHaveBeenCalled();
50+
});
51+
}
52+
it('should accept a message in an interchange', function () {
53+
expect(function () { interchange.accept({ name: 'UNB' }); }).not.toThrow();
54+
expect(interchange.depth.minimum).toEqual(1);
55+
expect(interchange.depth.current).toEqual(1);
56+
expect(function () { interchange.accept({ name: 'UNH' }); }).not.toThrow();
57+
expect(interchange.depth.maximum).toEqual(1);
58+
expect(interchange.depth.current).toEqual(2);
59+
expect(function () { interchange.next(); }).not.toThrow();
60+
expect(interchange.depth.current).toEqual(1);
61+
expect(function () { interchange.accept({ name: 'UNZ' }); }).not.toThrow();
62+
expect(interchange.depth.current).toEqual(0);
63+
});
64+
it('should not accept a group after a message', function () {
65+
expect(function () { interchange.accept({ name: 'UNB' }); }).not.toThrow();
66+
expect(interchange.depth.minimum).toEqual(1);
67+
expect(interchange.depth.current).toEqual(1);
68+
expect(function () { interchange.accept({ name: 'UNH' }); }).not.toThrow();
69+
expect(interchange.depth.maximum).toEqual(1);
70+
expect(interchange.depth.current).toEqual(2);
71+
expect(function () { interchange.next(); }).not.toThrow();
72+
expect(interchange.depth.current).toEqual(1);
73+
expect(function () { interchange.accept({ name: 'UNG' }); }).toThrow();
74+
});
75+
it('should not accept a group without an interchange', function () {
76+
expect(function () { interchange.accept({ name: 'UNG' }); }).toThrow();
77+
});
78+
it('should not accept a message after a group', function () {
79+
expect(function () { interchange.accept({ name: 'UNB' }); }).not.toThrow();
80+
expect(interchange.depth.minimum).toEqual(1);
81+
expect(interchange.depth.current).toEqual(1);
82+
expect(function () { interchange.accept({ name: 'UNG' }); }).not.toThrow();
83+
expect(interchange.depth.minimum).toEqual(2);
84+
expect(interchange.depth.current).toEqual(2);
85+
expect(function () { interchange.accept({ name: 'UNE' }); }).not.toThrow();
86+
expect(interchange.depth.current).toEqual(1);
87+
expect(function () { interchange.accept({ name: 'UNH' }); }).toThrow();
88+
});
89+
});

spec/LetterboxSpec.js

Lines changed: 0 additions & 85 deletions
This file was deleted.

0 commit comments

Comments
 (0)