Skip to content

Commit 376cc5a

Browse files
authored
refactor: ProgramCall.addParam to accept an object (#139)
1 parent 460feb7 commit 376cc5a

File tree

3 files changed

+121
-78
lines changed

3 files changed

+121
-78
lines changed

lib/Deprecated.js

+37-7
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,46 @@ class iPgm {
6464
* @param {string | array} data
6565
* @param {string} [type]
6666
* @param {object} options
67-
* @param {*} inDs
6867
*/
69-
addParam(data, type, options, inDs) {
70-
if (!Array.isArray(data) && !type) {
71-
iPgmDeprecate('defaulting parameter type to 1024a has been deprecated. You should specify a type instead.');
72-
// eslint-disable-next-line no-param-reassign
73-
type = '1024a';
68+
addParam(data, type, options) {
69+
const parameter = {};
70+
71+
if (Array.isArray(data)) { // DS parameter
72+
parameter.type = 'ds';
73+
parameter.fields = [];
74+
75+
if (typeof type === 'object') { // <ds> options
76+
Object.keys(type).forEach((key) => {
77+
parameter[key] = type[key];
78+
});
79+
}
80+
// convert 2D Array into fields [] of data objects
81+
for (let i = 0; i < data.length; i += 1) {
82+
const field = { type: data[i][1], value: data[i][0] };
83+
if (typeof data[i][2] === 'object') {
84+
Object.keys(data[i][2]).forEach((key) => { // <data> options
85+
field[key] = data[i][2][key];
86+
});
87+
}
88+
parameter.fields.push(field);
89+
}
90+
} else {
91+
parameter.type = type;
92+
parameter.value = data;
93+
if (!type) {
94+
iPgmDeprecate('defaulting parameter type to 1024a has been deprecated. You should specify a type instead.');
95+
parameter.type = '1024a';
96+
}
97+
98+
if (typeof options === 'object') { // <data> options
99+
Object.keys(options).forEach((key) => {
100+
parameter[key] = options[key];
101+
});
102+
}
74103
}
104+
75105
iPgmDeprecate('As of v1.0, \'iPgm.addParam()\' is deprecated. Please use \'ProgramCall.addParam()\' instead.');
76-
return this.ProgramCall.addParam(data, type, options, inDs);
106+
return this.ProgramCall.addParam(parameter);
77107
}
78108

79109
/**

lib/ProgramCall.js

+50-45
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1616
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1717

18+
/* eslint-disable no-underscore-dangle */
19+
1820
class ProgramCall {
1921
/**
2022
* @description creates a new ProgramCall object
@@ -30,59 +32,62 @@ class ProgramCall {
3032
}
3133

3234
/**
33-
* @description adds a parameter to the program XML
34-
* @param {string | array} data
35-
* @param {string} [type]
36-
* @param {object} options
37-
* @param {*} inDs
38-
*/
39-
addParam(data, type, options, inDs = null) {
40-
let opt;
41-
// DS element has no 'type', so if the second param 'type' is an Object, then it is the options.
42-
if (Array.isArray(data)) {
43-
opt = type;
44-
} else {
45-
opt = options;
46-
if (type === undefined) {
47-
throw new Error('Specifying the parameter type is required.');
48-
}
49-
}
50-
if (!inDs) { // In recursive mode, if it is an element in DS, then no <parm> or </parm> needed.
51-
this.xml += '<parm';
52-
if (opt && typeof opt === 'object') { // append <param> options
53-
if (opt.io) { this.xml += ` io='${opt.io}'`; }
54-
if (opt.by) { this.xml += ` by='${opt.by}'`; }
55-
}
56-
this.xml += '>';
57-
}
58-
59-
if (Array.isArray(data)) { // If it is a struct parameter, recursively parse its children.
35+
* Internal function to handle ds and data within <parm> node
36+
* There is an open propsal to add private methods to JS.
37+
* https://github.com/tc39/proposal-private-methods
38+
* We should update to use private methods in the future.
39+
* @param {object} data
40+
*/
41+
__addData__(data = {}) {
42+
if (data.type === 'ds') {
6043
this.xml += '<ds';
61-
if (opt && typeof opt === 'object') { // append <ds> options
62-
if (opt.dim) { this.xml += ` dim='${opt.dim}'`; }
63-
if (opt.dou) { this.xml += ` dou='${opt.dou}'`; }
64-
if (opt.len) { this.xml += ` len='${opt.len}'`; }
65-
if (opt.data) { this.xml += ` data='${opt.data}'`; }
66-
}
44+
// append <ds> options
45+
if (data.name) { this.xml += ` name='${data.name}'`; }
46+
if (data.dim) { this.xml += ` dim='${data.dim}'`; }
47+
if (data.dou) { this.xml += ` dou='${data.dou}'`; }
48+
if (data.len) { this.xml += ` len='${data.len}'`; }
49+
if (data.data) { this.xml += ` data='${data.data}'`; }
6750
this.xml += '>';
6851

69-
for (let i = 0; i < data.length; i += 1) {
70-
this.addParam(data[i][0], data[i][1], data[i][2], true);
52+
for (let i = 0; i < data.fields.length; i += 1) {
53+
this.__addData__(data.fields[i]);
7154
}
7255
this.xml += '</ds>';
73-
} else { // A simple parameter
74-
this.xml += `<data type='${type}'`;
75-
if (opt && typeof opt === 'object') { // append <data> options
76-
Object.keys(opt).forEach((key) => {
77-
this.xml += ` ${key}='${opt[key]}'`;
78-
});
79-
}
80-
this.xml += `>${data}</data>`;
56+
} else {
57+
this.xml += `<data type='${data.type}'`;
58+
// append <data> options
59+
if (data.name) { this.xml += ` name='${data.name}'`; }
60+
if (data.varying) { this.xml += ` varying='${data.varying}'`; }
61+
if (data.enddo) { this.xml += ` enddo='${data.enddo}'`; }
62+
if (data.setlen) { this.xml += ` setlen='${data.setlen}'`; }
63+
if (data.offset) { this.xml += ` offset='${data.offset}'`; }
64+
if (data.hex) { this.xml += ` hex='${data.hex}'`; }
65+
if (data.trim) { this.xml += ` trim='${data.trim}'`; }
66+
if (data.next) { this.xml += ` next='${data.next}'`; }
67+
this.xml += `>${data.value}</data>`;
8168
}
69+
}
8270

83-
if (!inDs) { // In recursive mode, if it is an element in DS, then no <parm> or </parm> needed.
84-
this.xml += '</parm>';
71+
/**
72+
* @description adds a parameter to the program XML
73+
* @param {object} parmeter
74+
*/
75+
addParam(parameter = {}) {
76+
if (typeof parameter !== 'object') {
77+
throw new Error('Expected the first parameter to be an object');
78+
}
79+
if (parameter.type === undefined) {
80+
throw new Error('Expected \'type\' key on the parameter object');
8581
}
82+
this.xml += '<parm';
83+
84+
if (parameter.name) { this.xml += ` name='${parameter.name}'`; }
85+
if (parameter.io) { this.xml += ` io='${parameter.io}'`; }
86+
if (parameter.by) { this.xml += ` by='${parameter.by}'`; }
87+
88+
this.xml += '>';
89+
this.__addData__(parameter);
90+
this.xml += '</parm>';
8691
}
8792

8893
/**

test/unit/ProgamCallUnit.js

+34-26
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,20 @@ const { expect } = require('chai');
2222
const { ProgramCall } = require('../../lib/itoolkit');
2323

2424
const outBuf = [
25-
[0, '10i0'],
26-
[0, '10i0'],
27-
['', '36h'],
28-
['', '10A'],
29-
['', '1A'],
30-
['', '1A'],
31-
[0, '10i0'],
32-
[0, '10i0'],
25+
{ type: '10i0', value: 0 },
26+
{ type: '10i0', value: 0 },
27+
{ type: '36h', value: '' },
28+
{ type: '10A', value: '' },
29+
{ type: '1A', value: '' },
30+
{ type: '1A', value: '' },
31+
{ type: '10i0', value: 0 },
32+
{ type: '10i0', value: 0 },
3333
];
3434
const errno = [
35-
[0, '10i0'],
36-
[0, '10i0', { setlen: 'rec2' }],
37-
['', '7A'],
38-
['', '1A'],
35+
{ type: '10i0', value: 0 },
36+
{ type: '10i0', value: 0, setlen: 'rec2' },
37+
{ type: '7A', value: '' },
38+
{ type: '1A', value: '' },
3939
];
4040

4141
describe('ProgramCall Class Unit Tests', () => {
@@ -70,7 +70,7 @@ describe('ProgramCall Class Unit Tests', () => {
7070
error: 'fast',
7171
});
7272

73-
pgm.addParam(outBuf, { io: 'out' });
73+
pgm.addParam({ type: 'ds', io: 'out', fields: outBuf });
7474

7575
let expectedXML = '<pgm name=\'QTOCNETSTS\' lib=\'QSYS\' func=\'QtoRtvTCPA\' error=\'fast\'>'
7676
+ '<parm io=\'out\'><ds><data type=\'10i0\'>0</data><data type=\'10i0\'>'
@@ -80,7 +80,7 @@ describe('ProgramCall Class Unit Tests', () => {
8080

8181
expect(pgm.toXML()).to.equal(expectedXML);
8282

83-
pgm.addParam(66, '10i0');
83+
pgm.addParam({ value: 66, type: '10i0' });
8484

8585
expectedXML = '<pgm name=\'QTOCNETSTS\' lib=\'QSYS\' func=\'QtoRtvTCPA\' error=\'fast\'>'
8686
+ '<parm io=\'out\'><ds><data type=\'10i0\'>0</data><data type=\'10i0\'>'
@@ -91,7 +91,7 @@ describe('ProgramCall Class Unit Tests', () => {
9191

9292
expect(pgm.toXML()).to.equal(expectedXML);
9393

94-
pgm.addParam(1, '10i0');
94+
pgm.addParam({ value: 1, type: '10i0' });
9595

9696
expectedXML = '<pgm name=\'QTOCNETSTS\' lib=\'QSYS\' func=\'QtoRtvTCPA\' error=\'fast\'>'
9797
+ '<parm io=\'out\'><ds><data type=\'10i0\'>0</data><data type=\'10i0\'>'
@@ -103,7 +103,7 @@ describe('ProgramCall Class Unit Tests', () => {
103103

104104
expect(pgm.toXML()).to.equal(expectedXML);
105105

106-
pgm.addParam('QCCSID', '10A');
106+
pgm.addParam({ value: 'QCCSID', type: '10A' });
107107

108108
expectedXML = '<pgm name=\'QTOCNETSTS\' lib=\'QSYS\' func=\'QtoRtvTCPA\' error=\'fast\'>'
109109
+ '<parm io=\'out\'><ds><data type=\'10i0\'>0</data><data type=\'10i0\'>'
@@ -116,7 +116,9 @@ describe('ProgramCall Class Unit Tests', () => {
116116

117117
expect(pgm.toXML()).to.equal(expectedXML);
118118

119-
pgm.addParam(errno, { io: 'both', len: 'rec2' });
119+
pgm.addParam({
120+
type: 'ds', io: 'both', len: 'rec2', fields: errno,
121+
});
120122

121123
expectedXML = '<pgm name=\'QTOCNETSTS\' lib=\'QSYS\' func=\'QtoRtvTCPA\' error=\'fast\'>'
122124
+ '<parm io=\'out\'><ds><data type=\'10i0\'>0</data><data type=\'10i0\'>'
@@ -136,8 +138,8 @@ describe('ProgramCall Class Unit Tests', () => {
136138
it('regular <parm> contains by=\'val\'', () => {
137139
const pgm = new ProgramCall('MYPGM', { lib: 'MYLIB', func: 'MY_PROCEDURE' });
138140

139-
pgm.addParam('', '1A', { by: 'val' });
140-
pgm.addReturn('', '2A', { name: 'output' });
141+
pgm.addParam({ value: '', type: '1A', by: 'val' });
142+
pgm.addReturn('', '2A', 'output');
141143

142144
const lookAtXML = pgm.toXML();
143145
expect(lookAtXML).to.match(/<parm .*by='val'.*>/);
@@ -147,11 +149,13 @@ describe('ProgramCall Class Unit Tests', () => {
147149
const pgm = new ProgramCall('MYPGM', { lib: 'MYLIB', func: 'MY_PROCEDURE' });
148150

149151
const params = [
150-
[0, '3s0'],
151-
[0, '7s0', { name: 'ds_fld2' }],
152+
{ type: '3s0', value: 0 },
153+
{ type: '7s0', value: 0, name: 'ds_fld2' },
152154
];
153155

154-
pgm.addParam(params, { name: 'inds', by: 'val' });
156+
pgm.addParam({
157+
name: 'inds', type: 'ds', by: 'val', fields: params,
158+
});
155159
pgm.addReturn('', '2A', { name: 'output' });
156160

157161
const lookAtXML = pgm.toXML();
@@ -161,7 +165,9 @@ describe('ProgramCall Class Unit Tests', () => {
161165
it('regular <parm> contains by=\'val\', with io=\'both\'', () => {
162166
const pgm = new ProgramCall('MYPGM', { lib: 'MYLIB', func: 'MY_PROCEDURE' });
163167

164-
pgm.addParam('', '1A', { by: 'val', io: 'both' });
168+
pgm.addParam({
169+
value: '', type: '1A', by: 'val', io: 'both',
170+
});
165171
pgm.addReturn('', '2A', { name: 'output' });
166172

167173
const lookAtXML = pgm.toXML();
@@ -173,11 +179,13 @@ describe('ProgramCall Class Unit Tests', () => {
173179
const pgm = new ProgramCall('MYPGM', { lib: 'MYLIB', func: 'MY_PROCEDURE' });
174180

175181
const params = [
176-
[0, '3s0'],
177-
[0, '7s0', { name: 'ds_fld2' }],
182+
{ type: '3s0', value: 0 },
183+
{ type: '7s0', value: 0, name: 'ds_fld2' },
178184
];
179185

180-
pgm.addParam(params, { name: 'inds', by: 'val', io: 'both' });
186+
pgm.addParam({
187+
name: 'inds', type: 'ds', by: 'val', io: 'both', fields: params,
188+
});
181189
pgm.addReturn('', '2A', { name: 'output' });
182190

183191
const lookAtXML = pgm.toXML();

0 commit comments

Comments
 (0)