@ind-rcg/plugins-printengine 246.1010.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +37 -0
- package/README.md +7 -0
- package/dist/dev/fonts/LICENSE.txt +202 -0
- package/dist/dev/fonts/Roboto-Italic.ttf +0 -0
- package/dist/dev/fonts/Roboto-Medium.ttf +0 -0
- package/dist/dev/fonts/Roboto-MediumItalic.ttf +0 -0
- package/dist/dev/fonts/Roboto-Regular.ttf +0 -0
- package/dist/dev/printEngine.js +589 -0
- package/dist/dev/src/contractToIntermediateJSONClass.js +1659 -0
- package/dist/dev/src/formatClass.js +156 -0
- package/dist/dev/src/index.js +110 -0
- package/dist/dev/src/localizationClass.js +89 -0
- package/dist/dev/src/logClass.js +38 -0
- package/dist/dev/src/macroHandlerClass.js +132 -0
- package/dist/dev/src/pdfConverterClass.js +1123 -0
- package/dist/dev/src/printEngineParams.js +124 -0
- package/dist/dev/src/tableCellIdentifier.js +116 -0
- package/dist/dev/src/togglesClass.js +61 -0
- package/dist/prod/printEngine.js +2 -0
- package/dist/prod/printEngine.js.LICENSE.txt +50 -0
- package/package.json +79 -0
|
@@ -0,0 +1,1659 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* FILE_HEADER
|
|
3
|
+
*/
|
|
4
|
+
'use strict';
|
|
5
|
+
const parser = require('xml-js');
|
|
6
|
+
const _ = require('lodash');
|
|
7
|
+
const Localization = require('./localizationClass');
|
|
8
|
+
const MacroHandler = require('./macroHandlerClass');
|
|
9
|
+
const Format = require('./formatClass');
|
|
10
|
+
const LogClass = require('./logClass');
|
|
11
|
+
const TableCellIdentifier = require('./tableCellIdentifier');
|
|
12
|
+
|
|
13
|
+
const EACH_NODE = "each";
|
|
14
|
+
const TABLE_NODE = "table";
|
|
15
|
+
const TBODY_NODE = "tbody";
|
|
16
|
+
const THEAD_NODE = "thead";
|
|
17
|
+
const HEADER_NODE = "header";
|
|
18
|
+
const FOOTER_NODE = "footer";
|
|
19
|
+
const PRINT_LAYOUT_NODE = "PrintLayout";
|
|
20
|
+
const REPORT_LAYOUT_NODE = "ReportLayout";
|
|
21
|
+
const DECLARATIONS_NODE = "Declarations";
|
|
22
|
+
const DOCUMENT_PROPERTIES_NODE = "DocumentProperties";
|
|
23
|
+
const PROPERTY_NODE = "Property";
|
|
24
|
+
const H1 = "h1";
|
|
25
|
+
const H2 = "h2";
|
|
26
|
+
const PARAGRAPH = "p";
|
|
27
|
+
const IMAGE = "img";
|
|
28
|
+
const TR_NODE = "tr";
|
|
29
|
+
const TH_NODE = "th";
|
|
30
|
+
const TD_NODE = "td";
|
|
31
|
+
const SUM_NODE = "sum";
|
|
32
|
+
|
|
33
|
+
const FILTERS_NODE = "filters";
|
|
34
|
+
const FILTER_NODE = "filter";
|
|
35
|
+
const ORDERCRITERIA_NODE = "orderCriteria";
|
|
36
|
+
const ORDERCRITERION_NODE = "orderCriterion";
|
|
37
|
+
const CORRELATION_NODE = "correlation";
|
|
38
|
+
|
|
39
|
+
const COMPAREMODE_DEFAULT = "STRING";
|
|
40
|
+
const COMPAREMODE_NUMBER = "NUMBER";
|
|
41
|
+
|
|
42
|
+
const DIV_NODE = "div";
|
|
43
|
+
const DIV_VISIBILITY_NODE = "visibility";
|
|
44
|
+
const DIV_VISIBILITY_BINDING_NODE = "visibilityBinding";
|
|
45
|
+
const DIV_VISIBILITY_CONDITION_NODE = "visibilityCondition";
|
|
46
|
+
const SIGNATURE_SIZE_LIMIT = 200 * 1024;
|
|
47
|
+
|
|
48
|
+
const ELEMENT_TYPE = {
|
|
49
|
+
"TEXT": "text",
|
|
50
|
+
"ELEMENT": "element",
|
|
51
|
+
"COMMENT": "comment"
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
class ContractToIntermediateJSON {
|
|
55
|
+
constructor(log) {
|
|
56
|
+
if(!(log instanceof LogClass)) {
|
|
57
|
+
throw new Error("Invalid constructor parameters");
|
|
58
|
+
}
|
|
59
|
+
this.__log = log;
|
|
60
|
+
// addParent: true,
|
|
61
|
+
this.__xmlParserLibraryOptions = {
|
|
62
|
+
spaces: 2,
|
|
63
|
+
compact: false
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
this.__printLayoutName = null;
|
|
67
|
+
this.__declarationsNode = null;
|
|
68
|
+
this.__localization = null;
|
|
69
|
+
this.__toggles = null;
|
|
70
|
+
this.__macroHandler = new MacroHandler(log);
|
|
71
|
+
this.__integerStringRegExp = /^\d+$/g;
|
|
72
|
+
|
|
73
|
+
this.__decimalSeparator = ".";
|
|
74
|
+
this.__thousandSeparator = ",";
|
|
75
|
+
this.__format = null;
|
|
76
|
+
this.__clearAllCaches();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
__clearAllCaches(){
|
|
80
|
+
this.__tableIndex = {};
|
|
81
|
+
this.__sumTdThList = [];
|
|
82
|
+
this.__eachCache = {};
|
|
83
|
+
this.__divCache = [];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
__checkDataForDeclaredItems(params, declarationNode){
|
|
87
|
+
let errorMessage = "";
|
|
88
|
+
let bos = params.getBOs();
|
|
89
|
+
let images = params.getImages();
|
|
90
|
+
|
|
91
|
+
let dataMissing = function dataMissing(itemType, itemName) {
|
|
92
|
+
let dataMissingMsg = `Missing declared ${itemType} "${itemName}" in print data.`;
|
|
93
|
+
if(errorMessage.length === 0) {
|
|
94
|
+
errorMessage = errorMessage + dataMissingMsg;
|
|
95
|
+
} else {
|
|
96
|
+
errorMessage = errorMessage + "\n" + dataMissingMsg;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
if(!_.isNil(declarationNode) && !_.isNil(declarationNode.elements)) {
|
|
101
|
+
_.forEach(declarationNode.elements, (dataDeclaration) => {
|
|
102
|
+
if(!_.isNil(dataDeclaration.attributes)){
|
|
103
|
+
let itemName = dataDeclaration.attributes.name;
|
|
104
|
+
if(!_.isNil(dataDeclaration.attributes.type)) {
|
|
105
|
+
if (dataDeclaration.attributes.type === "Image") {
|
|
106
|
+
if(!_.isNil(itemName) && _.isNil(images[itemName])){
|
|
107
|
+
dataMissing("Image", itemName);
|
|
108
|
+
}
|
|
109
|
+
} else if (dataDeclaration.attributes.type === "Signature") {
|
|
110
|
+
if(!_.isNil(itemName) && _.isNil(images[itemName])){
|
|
111
|
+
dataMissing("Signature", itemName);
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
if(!_.isNil(itemName) && _.isNil(bos[itemName])){
|
|
115
|
+
dataMissing("BO", itemName);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if(errorMessage.length > 0){
|
|
123
|
+
throw new Error(errorMessage);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
__checkInput(contract, params) {
|
|
128
|
+
if(_.isNil(params) || !_.isObject(params) || _.isArray(params)) {
|
|
129
|
+
throw new Error("Invalid value for parameter 'params'.");
|
|
130
|
+
}
|
|
131
|
+
if(!_.isString(contract)) {
|
|
132
|
+
throw new Error("Invalid value for parameter 'contract'.");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
toJson(contract, params) {
|
|
137
|
+
this.__checkInput(contract, params);
|
|
138
|
+
this.__clearAllCaches();
|
|
139
|
+
this.__toggles = params.getToggles();
|
|
140
|
+
this.__format = new Format();
|
|
141
|
+
this.__localization = new Localization(params.getLocalization());
|
|
142
|
+
|
|
143
|
+
this.__decimalSeparator = this.__localization.separatorDecimal;
|
|
144
|
+
this.__thousandSeparator = this.__localization.separatorThousand;
|
|
145
|
+
|
|
146
|
+
let contractJson = this.__parse(contract);
|
|
147
|
+
|
|
148
|
+
this.__declarationsNode = this.__getDeclarationsNode(contractJson);
|
|
149
|
+
this.__checkDataForDeclaredItems(params, this.__declarationsNode);
|
|
150
|
+
|
|
151
|
+
this.__walkParseTree(contractJson, {}, "", params);
|
|
152
|
+
|
|
153
|
+
let printLayoutNode = this.__findPrintLayoutNode(contractJson);
|
|
154
|
+
let reportLayout = _.find(printLayoutNode.elements, {name:REPORT_LAYOUT_NODE});
|
|
155
|
+
|
|
156
|
+
if(_.isNil(reportLayout)) {
|
|
157
|
+
throw new Error("Missing ReportLayout node in PrintLayout.");
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
this.__processDivs(params);
|
|
161
|
+
this.__postProcessReportLayout(reportLayout);
|
|
162
|
+
this.__processSumRecords();
|
|
163
|
+
|
|
164
|
+
this.__addWatermark(reportLayout, params);
|
|
165
|
+
this.__configureAutomaticPageBreak(reportLayout, params);
|
|
166
|
+
|
|
167
|
+
let documentPropertiesRaw = _.find(printLayoutNode.elements, {name:DOCUMENT_PROPERTIES_NODE});
|
|
168
|
+
let documentProperties = this.__reformatDocumentProperties(documentPropertiesRaw);
|
|
169
|
+
|
|
170
|
+
return {"reportLayout": reportLayout, "documentProperties": documentProperties};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
__processDivs(params) {
|
|
174
|
+
if (!_.isNil(this.__divCache) && _.isArray(this.__divCache)) {
|
|
175
|
+
|
|
176
|
+
for (let index = 0; index < this.__divCache.length; index++) {
|
|
177
|
+
const divData = this.__divCache[index];
|
|
178
|
+
|
|
179
|
+
let result = this.__checkForDivToBeVisible(divData.divNode, params);
|
|
180
|
+
if (result) {
|
|
181
|
+
// rescue div children and put them in parent elements
|
|
182
|
+
let nodes = _.filter(divData.divNode.elements, node => node.type === ELEMENT_TYPE.ELEMENT && node.name !== DIV_VISIBILITY_NODE);
|
|
183
|
+
if (!_.isNil(nodes) && _.isArray(nodes)) {
|
|
184
|
+
// remember div id for future styling / layouting ...
|
|
185
|
+
_.forEach(nodes, node => {
|
|
186
|
+
this.__ensureAttributes(node);
|
|
187
|
+
node.attributes.div = divData.id;
|
|
188
|
+
});
|
|
189
|
+
let divIndex = _.findIndex(divData.parentNode.elements, node => _.isEqual(node, divData.divNode));
|
|
190
|
+
divData.parentNode.elements.splice(divIndex, 0, ..._.cloneDeep(nodes));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// remove div from parent
|
|
194
|
+
_.remove(divData.parentNode.elements, node => _.isEqual(node, divData.divNode));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
__postProcessReportLayout(reportLayoutNode) {
|
|
201
|
+
// get header node
|
|
202
|
+
let headerNode = _.find(reportLayoutNode.elements, {name: HEADER_NODE});
|
|
203
|
+
if (!_.isNil(headerNode)) {
|
|
204
|
+
// => check header node and remove empty tables
|
|
205
|
+
this.__removeEmptyTables(headerNode);
|
|
206
|
+
}
|
|
207
|
+
// get footer node
|
|
208
|
+
let footerNode = _.find(reportLayoutNode.elements, {name: FOOTER_NODE});
|
|
209
|
+
if (!_.isNil(footerNode)) {
|
|
210
|
+
// => check footer node and remove empty tables
|
|
211
|
+
this.__removeEmptyTables(footerNode);
|
|
212
|
+
}
|
|
213
|
+
// => check reportlayout node and remove empty tables & divs
|
|
214
|
+
this.__removeEmptyTables(reportLayoutNode);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
__removeEmptyTables(containerNode) {
|
|
218
|
+
if (_.isNil(containerNode) || (!_.isNil(containerNode) && !_.isUndefined(containerNode.elements) && containerNode.elements.length === 0)) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
let tablesToRemove = [];
|
|
222
|
+
_.forEach(containerNode.elements, node => {
|
|
223
|
+
if (node.type === ELEMENT_TYPE.ELEMENT && node.name === TABLE_NODE && node.toBeRemoved) {
|
|
224
|
+
tablesToRemove.push(node);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
if (tablesToRemove.length > 0) {
|
|
228
|
+
_.forEach(tablesToRemove, tableNode => {
|
|
229
|
+
_.remove(containerNode.elements, node => _.isEqual(node, tableNode));
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
__addWatermark(reportLayout, params){
|
|
235
|
+
if(_.isNil(reportLayout)){
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
this.__ensureAttributes(reportLayout);
|
|
239
|
+
let watermarkInMetadata = params.getMetadata()[params.getMetadataKeys().WATERMARK];
|
|
240
|
+
if(_.isString(watermarkInMetadata) && _.trim(watermarkInMetadata) !== "") {
|
|
241
|
+
reportLayout.attributes.watermark = watermarkInMetadata;
|
|
242
|
+
} else if (!_.isNil(watermarkInMetadata) && !_.isString(watermarkInMetadata)) {
|
|
243
|
+
this.__log.error("Invalid value for watermark.");
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
__configureAutomaticPageBreak(reportLayout, params){
|
|
249
|
+
if(_.isNil(reportLayout)){
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
this.__ensureAttributes(reportLayout);
|
|
253
|
+
let automaticPageBreak = false; // default
|
|
254
|
+
let automaticPageBreakInMetadata = params.getMetadata()[params.getMetadataKeys().AUTOMATIC_PAGEBREAK];
|
|
255
|
+
if(!_.isNil(automaticPageBreakInMetadata) && _.isBoolean(automaticPageBreakInMetadata)) {
|
|
256
|
+
automaticPageBreak = automaticPageBreakInMetadata;
|
|
257
|
+
}
|
|
258
|
+
reportLayout.attributes.automaticPageBreak = automaticPageBreak;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
__reformatDocumentProperties(documentPropertiesRaw){
|
|
262
|
+
let result = {};
|
|
263
|
+
if(!_.isNil(documentPropertiesRaw)){
|
|
264
|
+
// this means the contract has document properties set
|
|
265
|
+
_.forEach(documentPropertiesRaw.elements, ele => {
|
|
266
|
+
|
|
267
|
+
if(ele.type === ELEMENT_TYPE.ELEMENT){
|
|
268
|
+
let sanitizedKey = ele.attributes.key.replace(/\s/g, "");
|
|
269
|
+
result[sanitizedKey]= ele.attributes.value;
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
__findPrintLayoutNode(contractJson) {
|
|
277
|
+
let printLayoutNode = _.find(contractJson.elements, {name:PRINT_LAYOUT_NODE});
|
|
278
|
+
if(_.isNil(printLayoutNode)) {
|
|
279
|
+
throw new Error("Missing PrintLayout node.");
|
|
280
|
+
}
|
|
281
|
+
return printLayoutNode;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
__getDeclarationsNode(contractJson) {
|
|
285
|
+
let printLayoutNode = this.__findPrintLayoutNode(contractJson);
|
|
286
|
+
let declarationsNode = _.find(printLayoutNode.elements, {name: DECLARATIONS_NODE});
|
|
287
|
+
if(_.isNil(declarationsNode)) {
|
|
288
|
+
declarationsNode = {};
|
|
289
|
+
}
|
|
290
|
+
return declarationsNode;
|
|
291
|
+
}
|
|
292
|
+
__newXMLconvertibleJsonNode(type, children, otherAttributes) {
|
|
293
|
+
let newNode = {
|
|
294
|
+
"type": type
|
|
295
|
+
};
|
|
296
|
+
if(!_.isNil(children)) {
|
|
297
|
+
newNode.elements = _.castArray(children);
|
|
298
|
+
}
|
|
299
|
+
_.assign(newNode, otherAttributes);
|
|
300
|
+
return newNode;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
__walkParseTree(contractJson, parentElement, parentName, params) {
|
|
304
|
+
// processing ...
|
|
305
|
+
this.__processCurrentElement(contractJson, parentElement, parentName, params);
|
|
306
|
+
// recursion ...
|
|
307
|
+
if(!_.isNil(contractJson.elements)) {
|
|
308
|
+
_.remove(contractJson.elements, (ele)=> {
|
|
309
|
+
if (ele.type === ELEMENT_TYPE.COMMENT) {
|
|
310
|
+
return true;
|
|
311
|
+
} else {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
_.forEach(contractJson.elements, (ele) => {
|
|
316
|
+
this.__walkParseTree(ele, contractJson, contractJson.name, params);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
// post-processing ...
|
|
320
|
+
this.__postProcessCurrentElement(contractJson);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
__postProcessCurrentElement(currentJsonElement) {
|
|
324
|
+
if (!_.isNil(currentJsonElement)) {
|
|
325
|
+
if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT) {
|
|
326
|
+
if (currentJsonElement.name === TR_NODE) {
|
|
327
|
+
|
|
328
|
+
// perform colSpan handling ...
|
|
329
|
+
this.__applyColSpanHandling(currentJsonElement);
|
|
330
|
+
|
|
331
|
+
} else if (currentJsonElement.name === TABLE_NODE) {
|
|
332
|
+
|
|
333
|
+
// perform rowSpan handling ...
|
|
334
|
+
this.__applyRowSpanHandling(currentJsonElement);
|
|
335
|
+
// normalize table ...
|
|
336
|
+
this.__normalizeTable(currentJsonElement);
|
|
337
|
+
// check for empty table ...
|
|
338
|
+
this.__checkForEmptyTable(currentJsonElement);
|
|
339
|
+
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
__checkForDivToBeVisible(divNode, params) {
|
|
346
|
+
let result = true;
|
|
347
|
+
if (!_.isNil(divNode) && _.isArray(divNode.elements)) {
|
|
348
|
+
|
|
349
|
+
// set result to 'true' for easier evaluation ...
|
|
350
|
+
let divVisibilityNode = _.find(divNode.elements, {name: DIV_VISIBILITY_NODE});
|
|
351
|
+
if (!_.isNil(divVisibilityNode) && _.isArray(divVisibilityNode.elements)) {
|
|
352
|
+
|
|
353
|
+
// check for visibilityBinding elements ...
|
|
354
|
+
let divVisibilityBindingNodes = _.filter(divVisibilityNode.elements, {name: DIV_VISIBILITY_BINDING_NODE});
|
|
355
|
+
if (!_.isNil(divVisibilityBindingNodes) && _.isArray(divVisibilityBindingNodes) && divVisibilityBindingNodes.length > 0) {
|
|
356
|
+
for (let i = 0; i < divVisibilityBindingNodes.length; i++) {
|
|
357
|
+
// process visibilityBinding ...
|
|
358
|
+
let divVisibilityBindingNode = divVisibilityBindingNodes[i];
|
|
359
|
+
result = this.__evaluateVisibilityBinding(divVisibilityBindingNode, params);
|
|
360
|
+
// exit if visibility criteria cannot be met ...
|
|
361
|
+
if (!result) {
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (result) {
|
|
368
|
+
// check for visibilityCondition elements ...
|
|
369
|
+
let divVisibilityConditionNodes = _.filter(divVisibilityNode.elements, {name: DIV_VISIBILITY_CONDITION_NODE});
|
|
370
|
+
if (!_.isNil(divVisibilityConditionNodes) && _.isArray(divVisibilityConditionNodes) && divVisibilityConditionNodes.length > 0) {
|
|
371
|
+
for (let i = 0; i < divVisibilityConditionNodes.length; i++) {
|
|
372
|
+
// process visibilityCondition ...
|
|
373
|
+
let divVisibilityConditionNode = divVisibilityConditionNodes[i];
|
|
374
|
+
result = this.__evaluateVisibilityCondition(divVisibilityConditionNode);
|
|
375
|
+
// exit if visibility criteria cannot be met ...
|
|
376
|
+
if (!result) {
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// => remove visibility node ...
|
|
384
|
+
_.remove(divNode.elements, node => (node.type === ELEMENT_TYPE.ELEMENT && node.name === DIV_VISIBILITY_NODE));
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
}
|
|
388
|
+
return result;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
__evaluateVisibilityBinding(visiblityBindingNode, params) {
|
|
392
|
+
let result = true;
|
|
393
|
+
|
|
394
|
+
// <visiblityBinding binding="{{Declarations::header.itemCount}}" value="0" operator="GT" compareMode="NUMBER" />
|
|
395
|
+
if (!_.isNil(visiblityBindingNode)) {
|
|
396
|
+
|
|
397
|
+
let expression = this.__getVisibilityExpression(visiblityBindingNode, params);
|
|
398
|
+
if (!_.isNil(expression) && _.isFunction(expression)) {
|
|
399
|
+
result = expression();
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return result;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
__getVisibilityExpression(visiblityBindingOrCondition, params) {
|
|
407
|
+
let expression = null;
|
|
408
|
+
|
|
409
|
+
// extract attributes
|
|
410
|
+
let binding = null;
|
|
411
|
+
let eachName = null;
|
|
412
|
+
let compareMode = COMPAREMODE_DEFAULT;
|
|
413
|
+
let operator = visiblityBindingOrCondition.attributes.operator;
|
|
414
|
+
let value = visiblityBindingOrCondition.attributes.value;
|
|
415
|
+
let comparisonValue = null;
|
|
416
|
+
|
|
417
|
+
if (visiblityBindingOrCondition.type === ELEMENT_TYPE.ELEMENT && visiblityBindingOrCondition.name === DIV_VISIBILITY_BINDING_NODE) {
|
|
418
|
+
// => handle visibilityBinding
|
|
419
|
+
binding = visiblityBindingOrCondition.attributes.binding;
|
|
420
|
+
// get compareMode if available
|
|
421
|
+
if (_.has(visiblityBindingOrCondition.attributes, "compareMode")) {
|
|
422
|
+
compareMode = visiblityBindingOrCondition.attributes.compareMode;
|
|
423
|
+
}
|
|
424
|
+
// resolve binding
|
|
425
|
+
comparisonValue = this.__resolveScalarBinding(visiblityBindingOrCondition, binding, params);
|
|
426
|
+
if (_.isNil(comparisonValue)) {
|
|
427
|
+
// unknown binding => log error
|
|
428
|
+
this.__log.error("Unsupported binding '", binding, "' at <" + visiblityBindingOrCondition.name + "> element");
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
} else if (visiblityBindingOrCondition.type === ELEMENT_TYPE.ELEMENT && visiblityBindingOrCondition.name === DIV_VISIBILITY_CONDITION_NODE) {
|
|
432
|
+
// => handle visibilityCondition
|
|
433
|
+
eachName = visiblityBindingOrCondition.attributes.eachName;
|
|
434
|
+
// set compareMode to "NUMBER"
|
|
435
|
+
compareMode = COMPAREMODE_NUMBER;
|
|
436
|
+
// resolve eachName
|
|
437
|
+
if (_.has(this.__eachCache, eachName) && _.isArray(this.__eachCache[eachName])) {
|
|
438
|
+
comparisonValue = this.__eachCache[eachName].length;
|
|
439
|
+
}
|
|
440
|
+
if (_.isNil(comparisonValue)) {
|
|
441
|
+
// unknown eachName => log error
|
|
442
|
+
this.__log.error("Unsupported eachName '", eachName, "' at <" + visiblityBindingOrCondition.name + "> element");
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// normalize compareMode & operator
|
|
447
|
+
compareMode = _.toUpper(compareMode);
|
|
448
|
+
operator = _.toUpper(operator);
|
|
449
|
+
|
|
450
|
+
if (!_.isNil(comparisonValue) && !_.isNil(operator) && !_.isNil(value) && !_.isNil(compareMode)) {
|
|
451
|
+
|
|
452
|
+
let converter = this.__resolveConverter(compareMode);
|
|
453
|
+
if (!_.isNil(converter) && _.isFunction(converter)) {
|
|
454
|
+
|
|
455
|
+
// convert comparison value once
|
|
456
|
+
let x = converter(comparisonValue);
|
|
457
|
+
// convert value once
|
|
458
|
+
let y = converter(value);
|
|
459
|
+
|
|
460
|
+
let comparator = this.__resolveComparator(operator);
|
|
461
|
+
if (!_.isNil(comparator) && _.isFunction(comparator)) {
|
|
462
|
+
|
|
463
|
+
// build filter expression performing comparison
|
|
464
|
+
expression = ( () => {
|
|
465
|
+
return comparator(x, y);
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
} else {
|
|
469
|
+
// unknown operator => log error
|
|
470
|
+
this.__log.error("Unsupported operator '", operator, "' at <" + visiblityBindingOrCondition.name + "> element");
|
|
471
|
+
}
|
|
472
|
+
} else {
|
|
473
|
+
// unknown compareMode => log error
|
|
474
|
+
this.__log.error("Unsupported compareMode '", compareMode, "' at <" + visiblityBindingOrCondition.name + "> element");
|
|
475
|
+
}
|
|
476
|
+
} else {
|
|
477
|
+
// missing/invalid mandatory attribute => log error
|
|
478
|
+
this.__log.error("Missing/invalid mandatory attribute at <" + visiblityBindingOrCondition.name + "> element");
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return expression;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
__evaluateVisibilityCondition(visiblityConditionNode) {
|
|
485
|
+
let result = true;
|
|
486
|
+
|
|
487
|
+
// <visiblityCondition eachName="each1" value="0" operator="GT" />
|
|
488
|
+
if (!_.isNil(visiblityConditionNode)) {
|
|
489
|
+
let expression = this.__getVisibilityExpression(visiblityConditionNode, null);
|
|
490
|
+
if (!_.isNil(expression) && _.isFunction(expression)) {
|
|
491
|
+
result = expression();
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return result;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
__checkForEmptyTable(tableNode) {
|
|
499
|
+
if (!_.isNil(tableNode)) {
|
|
500
|
+
// check thead
|
|
501
|
+
let thead = _.find(tableNode.elements, {name:THEAD_NODE});
|
|
502
|
+
if (_.isNil(thead) || _.isUndefined(thead.elements) || thead.elements.length === 0) {
|
|
503
|
+
// check tbody
|
|
504
|
+
let tbody = _.find(tableNode.elements, {name:TBODY_NODE});
|
|
505
|
+
if (_.isNil(tbody) || (!_.isNil(tbody) && !_.isUndefined(tbody.elements) && tbody.elements.length === 0)) {
|
|
506
|
+
// table is empty => to be removed
|
|
507
|
+
tableNode.toBeRemoved = true;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
__applyColSpanHandling(tableRowNode) {
|
|
514
|
+
let newElements = [];
|
|
515
|
+
_.forEachRight(tableRowNode.elements, tdth => {
|
|
516
|
+
if (!_.isNil(tdth.attributes)) {
|
|
517
|
+
let colSpan = tdth.attributes.colSpan;
|
|
518
|
+
if (!_.isNil(colSpan)) {
|
|
519
|
+
colSpan = _.toInteger(colSpan);
|
|
520
|
+
if (!_.isNaN(colSpan) && colSpan > 1) {
|
|
521
|
+
let elementsToAdd = colSpan - 1;
|
|
522
|
+
let elementName = tdth.name;
|
|
523
|
+
|
|
524
|
+
let newAttributes = {
|
|
525
|
+
"name": elementName,
|
|
526
|
+
"doNotReplace": true
|
|
527
|
+
};
|
|
528
|
+
for (let i = 0; i < elementsToAdd; i++) {
|
|
529
|
+
let newElement = this.__newXMLconvertibleJsonNode(ELEMENT_TYPE.ELEMENT, null, newAttributes);
|
|
530
|
+
newElements.push(newElement);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
newElements.push(tdth);
|
|
536
|
+
});
|
|
537
|
+
// replace elements if applicable
|
|
538
|
+
let elementCount = 0;
|
|
539
|
+
if (!_.isNil(tableRowNode.elements)) {
|
|
540
|
+
elementCount = tableRowNode.elements.length;
|
|
541
|
+
}
|
|
542
|
+
if (newElements.length !== elementCount) {
|
|
543
|
+
tableRowNode.elements = _.reverse(newElements);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
__applyRowSpanHandling(tableNode) {
|
|
548
|
+
if (!_.isNil(tableNode)) {
|
|
549
|
+
// fix thead
|
|
550
|
+
this.__applyRowSpanHandlingToContainer(tableNode, THEAD_NODE);
|
|
551
|
+
|
|
552
|
+
// fix tbody
|
|
553
|
+
this.__applyRowSpanHandlingToContainer(tableNode, TBODY_NODE);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
__applyRowSpanHandlingToContainer(tableNode, trContainerNodeName) {
|
|
558
|
+
|
|
559
|
+
if (!_.isNil(tableNode) && !_.isNil(trContainerNodeName)) {
|
|
560
|
+
// check tbody / thead
|
|
561
|
+
let trContainerNode = _.find(tableNode.elements, {name:trContainerNodeName});
|
|
562
|
+
if (!_.isNil(trContainerNode) && !_.isNil(trContainerNode.elements)) {
|
|
563
|
+
for (let i = 0; i < trContainerNode.elements.length; i++) {
|
|
564
|
+
// check tr
|
|
565
|
+
let tr = trContainerNode.elements[i];
|
|
566
|
+
if (!_.isNil(tr) && !_.isNil(tr.elements)) {
|
|
567
|
+
for (let j = 0; j < tr.elements.length; j++) {
|
|
568
|
+
// check td / th
|
|
569
|
+
let tdth = tr.elements[j];
|
|
570
|
+
if (!_.isNil(tdth)) {
|
|
571
|
+
if (!_.isNil(tdth.attributes)) {
|
|
572
|
+
let rowSpan = tdth.attributes.rowSpan;
|
|
573
|
+
if (!_.isNil(rowSpan)) {
|
|
574
|
+
rowSpan = _.toInteger(rowSpan);
|
|
575
|
+
if (!_.isNaN(rowSpan) && rowSpan > 1) {
|
|
576
|
+
let rowsToUpdate = rowSpan - 1;
|
|
577
|
+
let elementsToAdd = 1; // rowSpan element
|
|
578
|
+
let elementName = tdth.name;
|
|
579
|
+
let colSpan = tdth.attributes.colSpan;
|
|
580
|
+
if (!_.isNil(colSpan)) {
|
|
581
|
+
colSpan = _.toInteger(colSpan);
|
|
582
|
+
if (!_.isNaN(colSpan) && colSpan > 1) {
|
|
583
|
+
elementsToAdd = elementsToAdd + (colSpan - 1); // colSpan elements
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
// update "spanned" rows
|
|
587
|
+
for (let k = 0; k < rowsToUpdate; k++) {
|
|
588
|
+
let rowIndex = i + k + 1;
|
|
589
|
+
if (rowIndex < trContainerNode.elements.length) {
|
|
590
|
+
let tr2 = trContainerNode.elements[rowIndex];
|
|
591
|
+
|
|
592
|
+
if (_.isNil(tr2.elements)) {
|
|
593
|
+
_.assign(tr2, {"elements": []});
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
let tr2Index = j;
|
|
597
|
+
if (tr2Index > tr2.elements.length) {
|
|
598
|
+
tr2Index = 0;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// insert elements ...
|
|
602
|
+
for (let l = 0; l < elementsToAdd; l++) {
|
|
603
|
+
let newElement = this.__newXMLconvertibleJsonNode(ELEMENT_TYPE.ELEMENT, null, {"name": elementName, "doNotReplace": true});
|
|
604
|
+
tr2.elements.splice(tr2Index, 0, newElement);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
__normalizeTable(tableNode) {
|
|
620
|
+
if (!_.isNil(tableNode)) {
|
|
621
|
+
// get minimum thead width
|
|
622
|
+
let minTableHeadWidth = this.__getTableContainerWidth(tableNode, THEAD_NODE);
|
|
623
|
+
|
|
624
|
+
// get minimum tbody width
|
|
625
|
+
let minTableBodyWidth = this.__getTableContainerWidth(tableNode, TBODY_NODE);
|
|
626
|
+
|
|
627
|
+
// determine minimum width for table
|
|
628
|
+
let minTableWidth = _.min([minTableHeadWidth, minTableBodyWidth]);
|
|
629
|
+
|
|
630
|
+
// repair thead
|
|
631
|
+
this.__normalizeTableWidth(tableNode, THEAD_NODE, minTableWidth);
|
|
632
|
+
|
|
633
|
+
// repair tbody
|
|
634
|
+
this.__normalizeTableWidth(tableNode, TBODY_NODE, minTableWidth);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
__getTableContainerWidth(tableNode, trContainerNodeName) {
|
|
639
|
+
let minWidth = Number.MAX_SAFE_INTEGER;
|
|
640
|
+
if (!_.isNil(tableNode) && !_.isNil(trContainerNodeName)) {
|
|
641
|
+
let trContainerNode = _.find(tableNode.elements, {name:trContainerNodeName});
|
|
642
|
+
if (!_.isNil(trContainerNode)) {
|
|
643
|
+
_.forEach(trContainerNode.elements, tr => {
|
|
644
|
+
if (!_.isNil(tr) && tr.name === TR_NODE && !_.isNil(tr.elements)) {
|
|
645
|
+
let thCount = tr.elements.length;
|
|
646
|
+
if (thCount < minWidth) {
|
|
647
|
+
minWidth = thCount;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return minWidth;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
__normalizeTableWidth(tableNode, trContainerNodeName, tableWidth) {
|
|
657
|
+
if (!_.isNil(tableNode) && !_.isNil(trContainerNodeName)) {
|
|
658
|
+
let trContainerNode = _.find(tableNode.elements, {name:trContainerNodeName});
|
|
659
|
+
if (!_.isNil(trContainerNode)) {
|
|
660
|
+
let normalized = false;
|
|
661
|
+
_.forEach(trContainerNode.elements, tr => {
|
|
662
|
+
if (!_.isNil(tr) && tr.name === TR_NODE) {
|
|
663
|
+
let trWidth = 0;
|
|
664
|
+
if (!_.isNil(tr.elements)) {
|
|
665
|
+
trWidth = tr.elements.length;
|
|
666
|
+
}
|
|
667
|
+
if (trWidth > tableWidth) {
|
|
668
|
+
// remove elements ...
|
|
669
|
+
tr.elements.splice(tableWidth, trWidth - tableWidth);
|
|
670
|
+
normalized = true;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
if (normalized) {
|
|
675
|
+
let tableName = tableNode.attributes.name;
|
|
676
|
+
let errorMessage = "<" + trContainerNodeName + "> element of <table> '" + tableName + "' has been normalized due to improper formatting";
|
|
677
|
+
this.__log.error(errorMessage);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
__processSumRecords() {
|
|
684
|
+
let idxSum;
|
|
685
|
+
for (idxSum=0; idxSum < this.__sumTdThList.length; idxSum++) {
|
|
686
|
+
let tdthNode = this.__sumTdThList[idxSum];
|
|
687
|
+
let sumNode = _.find(tdthNode.elements, {name:SUM_NODE});
|
|
688
|
+
let tableName = sumNode.attributes.table;
|
|
689
|
+
let tablePos = parseFloat(sumNode.attributes.col, 10);
|
|
690
|
+
let sumFormat = sumNode.attributes.numberFormat;
|
|
691
|
+
let tableNode = this.__tableIndex[tableName];
|
|
692
|
+
let sum = 0;
|
|
693
|
+
|
|
694
|
+
if (!_.isNil(tableNode)) {
|
|
695
|
+
let tBodyNode = _.find(tableNode.elements, {name:TBODY_NODE});
|
|
696
|
+
if (!_.isNil(tBodyNode) && !_.isNil(tBodyNode.elements)) {
|
|
697
|
+
_.forEach(tBodyNode.elements, (trNode) => {
|
|
698
|
+
let tdNode = trNode.elements[tablePos];
|
|
699
|
+
if(!_.isNil(tdNode)) {
|
|
700
|
+
let bSum = false;
|
|
701
|
+
let text = "";
|
|
702
|
+
let nonRoundedValue = null;
|
|
703
|
+
if (!_.isNil(tdNode.attributes)) {
|
|
704
|
+
nonRoundedValue = tdNode.attributes.nonRoundedValue;
|
|
705
|
+
}
|
|
706
|
+
_.forEach(tdNode.elements, childElement => {
|
|
707
|
+
if ((childElement.type === "text") && !_.isNil(childElement.isSum) && childElement.isSum) {
|
|
708
|
+
bSum = true;
|
|
709
|
+
} else if (childElement.type === "text") {
|
|
710
|
+
text = childElement.text;
|
|
711
|
+
} else if (childElement.type === "element" && childElement.name === SUM_NODE) {
|
|
712
|
+
bSum = true;
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
if (!bSum) {
|
|
716
|
+
if (!_.isNil(nonRoundedValue)) {
|
|
717
|
+
// nonRoundedValue only exists if a format was applied to the cell
|
|
718
|
+
sum += nonRoundedValue;
|
|
719
|
+
} else {
|
|
720
|
+
let value = parseFloat(text, 10);
|
|
721
|
+
if (!isNaN(value)) {
|
|
722
|
+
sum += value;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
} else {
|
|
730
|
+
sum = 0;
|
|
731
|
+
}
|
|
732
|
+
} else {
|
|
733
|
+
sum = 0;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
let txtSum;
|
|
737
|
+
|
|
738
|
+
if (!_.isNil(sumFormat)) {
|
|
739
|
+
txtSum = this.__format.formatDecimalV2(sum, sumFormat, this.__decimalSeparator, this.__thousandSeparator);
|
|
740
|
+
} else {
|
|
741
|
+
txtSum = "" + sum;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
let bText = false;
|
|
745
|
+
|
|
746
|
+
_.forEach(tdthNode.elements, childElement => {
|
|
747
|
+
if(childElement.type === "text") {
|
|
748
|
+
childElement.text = txtSum + childElement.text;
|
|
749
|
+
childElement.isSum = true;
|
|
750
|
+
bText = true;
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
if (!bText) {
|
|
755
|
+
if (txtSum.length > 0) {
|
|
756
|
+
tdthNode.elements.push(this.__newXMLconvertibleJsonNode(ELEMENT_TYPE.TEXT, null, {"text": txtSum, "doNotReplace": true, "isSum": true}));
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
this.__deleteInvalidNodes(tdthNode, [SUM_NODE], null);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
__processH1Node(currentJsonElement/*, params*/) {
|
|
765
|
+
this.__makeTextOnlyNode(currentJsonElement);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
__processH2Node(currentJsonElement/*, params*/) {
|
|
769
|
+
this.__makeTextOnlyNode(currentJsonElement);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
__processParagraphNode(currentJsonElement/*, params*/) {
|
|
773
|
+
this.__makeTextOnlyNode(currentJsonElement);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
__processPropertyNode(currentJsonElement, params){
|
|
777
|
+
let resolvedMacro = this.__resolveScalarBinding(currentJsonElement, currentJsonElement.attributes.value, params);
|
|
778
|
+
if(!_.isNil(resolvedMacro)) {
|
|
779
|
+
if(_.isObject(resolvedMacro)) {
|
|
780
|
+
resolvedMacro = JSON.stringify(resolvedMacro);
|
|
781
|
+
}
|
|
782
|
+
if(!_.isString(resolvedMacro)){
|
|
783
|
+
resolvedMacro = ""+resolvedMacro;
|
|
784
|
+
}
|
|
785
|
+
currentJsonElement.attributes.value = resolvedMacro;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
__processPrintLayoutNode(currentJsonElement/*, parentName, params*/){
|
|
790
|
+
this.__printLayoutName = currentJsonElement.attributes.name;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
__processCurrentElement(currentJsonElement, parentElement, parentName, params) {
|
|
794
|
+
if (currentJsonElement.doNotReplace) {
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
if(currentJsonElement.type === ELEMENT_TYPE.TEXT) {
|
|
798
|
+
this.__replaceMacrosInTextNodes(parentElement, currentJsonElement, params);
|
|
799
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === TBODY_NODE) {
|
|
800
|
+
this.__replaceEachTagsInTables(currentJsonElement, parentElement, params);
|
|
801
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === HEADER_NODE){
|
|
802
|
+
this.__processHeaderNode(currentJsonElement, params);
|
|
803
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === FOOTER_NODE){
|
|
804
|
+
this.__processFooterNode(currentJsonElement, params);
|
|
805
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === REPORT_LAYOUT_NODE){
|
|
806
|
+
this.__processReportLayoutNode(currentJsonElement, params);
|
|
807
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === TABLE_NODE){
|
|
808
|
+
this.__processTableNode(currentJsonElement, params);
|
|
809
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === THEAD_NODE){
|
|
810
|
+
this.__processTheadNode(currentJsonElement, params);
|
|
811
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === H1) {
|
|
812
|
+
this.__processH1Node(currentJsonElement, params);
|
|
813
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === H2) {
|
|
814
|
+
this.__processH2Node(currentJsonElement, params);
|
|
815
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === PARAGRAPH) {
|
|
816
|
+
this.__processParagraphNode(currentJsonElement, params);
|
|
817
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === IMAGE) {
|
|
818
|
+
this.__processImageNode(currentJsonElement, params);
|
|
819
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === PROPERTY_NODE) {
|
|
820
|
+
this.__processPropertyNode(currentJsonElement, params);
|
|
821
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === TR_NODE){
|
|
822
|
+
this.__processTrNode(currentJsonElement, parentName, params);
|
|
823
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === TD_NODE){
|
|
824
|
+
this.__processTdThNode(currentJsonElement, parentName, params);
|
|
825
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === TH_NODE){
|
|
826
|
+
this.__processTdThNode(currentJsonElement, parentName, params);
|
|
827
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === PRINT_LAYOUT_NODE){
|
|
828
|
+
this.__processPrintLayoutNode(currentJsonElement, parentName, params);
|
|
829
|
+
} else if (currentJsonElement.type === ELEMENT_TYPE.ELEMENT && currentJsonElement.name === DIV_NODE){
|
|
830
|
+
this.__processDivNode(currentJsonElement, parentElement);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
__processDivNode(divNode, parentNode) {
|
|
835
|
+
// cache divNode and parentNode for later ...
|
|
836
|
+
this.__divCache.push({
|
|
837
|
+
"id" : "div" + (this.__divCache.length + 1),
|
|
838
|
+
"divNode" : divNode, // div to evaluate
|
|
839
|
+
"parentNode": parentNode // parent to resolve
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
__parse(contract){
|
|
844
|
+
let contractJson = parser.xml2js(contract,this.__xmlParserLibraryOptions);
|
|
845
|
+
return contractJson;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
__isLo(object){
|
|
849
|
+
return _.isArray(object);
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
__makeTextOnlyNode(currentJsonElement) {
|
|
853
|
+
_.remove(currentJsonElement.elements, (ele)=> { return ele.type !== ELEMENT_TYPE.TEXT;});
|
|
854
|
+
if(currentJsonElement.elements.length === 0) {
|
|
855
|
+
currentJsonElement.elements.push({type:ELEMENT_TYPE.TEXT, text: ""});
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
__deleteInvalidNodes(currentJsonElement, deleteNames, preserveNames) {
|
|
860
|
+
//Remove invalid nodes by positive or negative lists.
|
|
861
|
+
let bDelete = !_.isNil(deleteNames) && _.isArray(deleteNames) && (deleteNames.length > 0);
|
|
862
|
+
let bPreserve = !_.isNil(preserveNames) && _.isArray(preserveNames) && (preserveNames.length > 0);
|
|
863
|
+
|
|
864
|
+
//It makes no sense to fill both lists or no list but we cannot provide a true/true or a false/false
|
|
865
|
+
//scenario via Unit Tests. So we keep both paths split to fulfill the branch coverage.
|
|
866
|
+
if (bDelete) {
|
|
867
|
+
_.remove(currentJsonElement.elements, (ele)=> {
|
|
868
|
+
let names = 0;
|
|
869
|
+
for (names=0; names<deleteNames.length; names++) {
|
|
870
|
+
if (ele.name === deleteNames[names]) {
|
|
871
|
+
return true;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
return false;
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
if (bPreserve) {
|
|
878
|
+
_.remove(currentJsonElement.elements, (ele)=> {
|
|
879
|
+
let names = 0;
|
|
880
|
+
for (names=0; names<preserveNames.length; names++) {
|
|
881
|
+
if (ele.name === preserveNames[names]) {
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
return true;
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
__processTheadNode(currentJsonElement/*, parentName, params*/){
|
|
891
|
+
this.__deleteInvalidNodes(currentJsonElement, [EACH_NODE], null);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
__processTableNode(currentJsonElement/*, parentName, params*/){
|
|
895
|
+
this.__deleteInvalidNodes(currentJsonElement, null, [THEAD_NODE, TBODY_NODE]);
|
|
896
|
+
if (_.isNil(this.__tableIndex[currentJsonElement.attributes.name])) {
|
|
897
|
+
this.__tableIndex[currentJsonElement.attributes.name] = currentJsonElement;
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
__processTrNode(currentJsonElement, parentName/*, params*/){
|
|
902
|
+
if (parentName === THEAD_NODE) {
|
|
903
|
+
this.__deleteInvalidNodes(currentJsonElement, null, [TH_NODE]);
|
|
904
|
+
} else if (parentName === TBODY_NODE) {
|
|
905
|
+
this.__deleteInvalidNodes(currentJsonElement, null, [TD_NODE]);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
__processTdThNode(currentJsonElement, /*, parentName, params*/){
|
|
910
|
+
let sumNode = _.find(currentJsonElement.elements, {name:SUM_NODE});
|
|
911
|
+
|
|
912
|
+
if (!_.isNil(sumNode)) {
|
|
913
|
+
this.__sumTdThList.push(currentJsonElement);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
__processReportLayoutNode(currentJsonElement/*, parentName, params*/) {
|
|
918
|
+
this.__deleteInvalidNodes(currentJsonElement, [EACH_NODE], null);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
__processHeaderNode(currentJsonElement/*, parentName, params*/) {
|
|
922
|
+
this.__deleteInvalidNodes(currentJsonElement, [EACH_NODE], null);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
__processFooterNode(currentJsonElement/*, parentName, params*/) {
|
|
926
|
+
this.__deleteInvalidNodes(currentJsonElement, [EACH_NODE], null);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
__createTableDataCache(tableRow, params) {
|
|
930
|
+
let tdCacheList = [];
|
|
931
|
+
|
|
932
|
+
_.forEach(tableRow.elements, subtag => {
|
|
933
|
+
let tdCacheElement = {};
|
|
934
|
+
tdCacheElement.elements = [];
|
|
935
|
+
|
|
936
|
+
if (subtag.name === "td") {
|
|
937
|
+
if (!_.isNil(subtag.elements)) {
|
|
938
|
+
let allTextNodeTexts = [];
|
|
939
|
+
_.forEach(subtag.elements, tdSubtag => {
|
|
940
|
+
if (tdSubtag.type === ELEMENT_TYPE.TEXT) {
|
|
941
|
+
this.__replaceMacrosInTextNodes(subtag, tdSubtag, params);
|
|
942
|
+
allTextNodeTexts.push(_.trim(tdSubtag.text));
|
|
943
|
+
} else if (tdSubtag.type === ELEMENT_TYPE.ELEMENT && (tdSubtag.name === IMAGE)) {
|
|
944
|
+
this.__processImageNode(tdSubtag, params);
|
|
945
|
+
tdSubtag.doNotReplace = true;
|
|
946
|
+
tdCacheElement.elements.push(tdSubtag);
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
tdCacheElement.text = allTextNodeTexts.join(' ');
|
|
951
|
+
tdCacheElement.macroList = [];
|
|
952
|
+
|
|
953
|
+
let macroRegex = this.__macroHandler.getMacroRegex();
|
|
954
|
+
let macroMatches = tdCacheElement.text.match(macroRegex);
|
|
955
|
+
|
|
956
|
+
_.forEach(macroMatches, match => {
|
|
957
|
+
let macroElement = {"match": match, "result": this.__macroHandler.parseMacro(match)};
|
|
958
|
+
tdCacheElement.macroList.push(macroElement);
|
|
959
|
+
});
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
} else {
|
|
963
|
+
tdCacheElement.text = "";
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
tdCacheElement.attributes = subtag.attributes;
|
|
967
|
+
tdCacheList.push(tdCacheElement);
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
|
|
971
|
+
return tdCacheList;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
__createTableTrForOneListItem(tdCacheList, listItem, trAttributes, isChildItem, eachName, listItemIndex, correlatedListItemIndex) {
|
|
975
|
+
let tdNodes = [];
|
|
976
|
+
let newText = null;
|
|
977
|
+
let newAttributes = null;
|
|
978
|
+
|
|
979
|
+
// id handling...
|
|
980
|
+
let cellId = null;
|
|
981
|
+
let columnIndex = -1;
|
|
982
|
+
|
|
983
|
+
_.forEach(tdCacheList, cacheElement => {
|
|
984
|
+
newText = cacheElement.text;
|
|
985
|
+
newAttributes = _.clone(cacheElement.attributes);
|
|
986
|
+
|
|
987
|
+
if (cacheElement.text.length > 0) {
|
|
988
|
+
_.forEach(cacheElement.macroList, macroElement => {
|
|
989
|
+
let macroResult = macroElement.result;
|
|
990
|
+
|
|
991
|
+
if (!_.isNil(macroResult) && !_.isNil(macroResult.path)) {
|
|
992
|
+
let listItemValue = listItem[macroResult.path];
|
|
993
|
+
|
|
994
|
+
if(typeof listItemValue !== "undefined") {
|
|
995
|
+
if (!_.isNil(macroResult.numberFormat)) {
|
|
996
|
+
if(_.isNil(newAttributes)) {newAttributes = {};}
|
|
997
|
+
listItemValue = this.__resolveNumberBinding(listItemValue, macroResult,newAttributes);
|
|
998
|
+
if(isChildItem){
|
|
999
|
+
// setting the nonRoundedValue to 0.0 makes sure that correlation items are ignored in the sum tag
|
|
1000
|
+
newAttributes.nonRoundedValue = 0.0;
|
|
1001
|
+
}
|
|
1002
|
+
} if(!_.isNil(macroResult.dateTimeFormat)) {
|
|
1003
|
+
listItemValue = this.__resolveDateBinding(listItemValue, macroResult);
|
|
1004
|
+
} else {
|
|
1005
|
+
listItemValue = this.__replaceTogglesIfApplicable(listItemValue, macroResult, this.__localization);
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
if(_.isString(listItemValue)){
|
|
1009
|
+
listItemValue = listItemValue.replace(/\$/g, "$$$$");
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
newText = newText.replace(macroElement.match, listItemValue);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
let newTextNode = [];
|
|
1019
|
+
if(newText.length > 0){
|
|
1020
|
+
newTextNode.push(this.__newXMLconvertibleJsonNode(ELEMENT_TYPE.TEXT, null, {"text": newText, "doNotReplace": true}));
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
// only apply id to cells with text OR child elements ...
|
|
1024
|
+
if (newTextNode.length > 0 || cacheElement.elements.length > 0) {
|
|
1025
|
+
columnIndex += 1;
|
|
1026
|
+
cellId = this.__getCellId(eachName, listItemIndex, correlatedListItemIndex, columnIndex);
|
|
1027
|
+
if (!_.isNil(cellId)) {
|
|
1028
|
+
if (_.isNil(newAttributes)) { newAttributes = {}; }
|
|
1029
|
+
newAttributes.id = cellId;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
let newTdNode = this.__newXMLconvertibleJsonNode(ELEMENT_TYPE.ELEMENT, newTextNode,
|
|
1034
|
+
{"name": "td", "attributes": newAttributes, "doNotReplace": true});
|
|
1035
|
+
|
|
1036
|
+
_.forEach(cacheElement.elements, element => {
|
|
1037
|
+
newTdNode.elements.push(element);
|
|
1038
|
+
});
|
|
1039
|
+
|
|
1040
|
+
tdNodes.push(newTdNode);
|
|
1041
|
+
});
|
|
1042
|
+
|
|
1043
|
+
let newTrNode = this.__newXMLconvertibleJsonNode(ELEMENT_TYPE.ELEMENT, tdNodes,
|
|
1044
|
+
{"name": "tr", "attributes": trAttributes, "doNotReplace": true});
|
|
1045
|
+
return newTrNode;
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
__createTableRowData(tableRow, tdCacheList, trNodes, listObject, correlationInfo, eachName) {
|
|
1049
|
+
|
|
1050
|
+
if (!_.isNil(tableRow) && !_.isNil(tdCacheList) && !_.isNil(trNodes) && !_.isNil(listObject) && !_.isNil(eachName)) {
|
|
1051
|
+
|
|
1052
|
+
let hasCorrelationInfo = !_.isNil(correlationInfo);
|
|
1053
|
+
let listItemIndex = -1;
|
|
1054
|
+
let correlatedListItemIndex = -1;
|
|
1055
|
+
|
|
1056
|
+
_.forEach(listObject, listItem => {
|
|
1057
|
+
|
|
1058
|
+
if (hasCorrelationInfo) {
|
|
1059
|
+
listItemIndex += 1;
|
|
1060
|
+
correlatedListItemIndex = -1;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
let newTrNode = this.__createTableTrForOneListItem(tdCacheList, listItem, tableRow.attributes, false, eachName, listItemIndex, correlatedListItemIndex);
|
|
1064
|
+
trNodes.push(newTrNode);
|
|
1065
|
+
|
|
1066
|
+
if (!_.isNil(correlationInfo) && !_.isNil(listItem[correlationInfo.key])) {
|
|
1067
|
+
// TODO: this implementation is slow and can be done faster.
|
|
1068
|
+
let correlatedItemsForCurrentLI = _.filter(correlationInfo.listObjectForCorrelation, (elem) => {
|
|
1069
|
+
return elem[correlationInfo.correlationKey] === listItem[correlationInfo.key];
|
|
1070
|
+
});
|
|
1071
|
+
|
|
1072
|
+
// (re)set correlatedListItemIndex...
|
|
1073
|
+
correlatedListItemIndex = -1;
|
|
1074
|
+
|
|
1075
|
+
_.forEach(correlatedItemsForCurrentLI, corrLi => {
|
|
1076
|
+
|
|
1077
|
+
// set correlatedListItemIndex...
|
|
1078
|
+
correlatedListItemIndex += 1;
|
|
1079
|
+
|
|
1080
|
+
let newCorrelationTrNode = this.__createTableTrForOneListItem(correlationInfo.tdCacheForCorrelation, corrLi, {}, true, eachName, listItemIndex, correlatedListItemIndex);
|
|
1081
|
+
trNodes.push(newCorrelationTrNode);
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
return trNodes;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
__buildCorrelationInfo(correlationNode, params){
|
|
1091
|
+
let correlationInfo = null;
|
|
1092
|
+
if(!_.isNil(correlationNode)){
|
|
1093
|
+
correlationInfo = {};
|
|
1094
|
+
correlationInfo.correlationTableRow = _.find(correlationNode.elements, {name:TR_NODE}); // eachNode.elements[0];
|
|
1095
|
+
correlationInfo.tdCacheForCorrelation = this.__createTableDataCache(correlationInfo.correlationTableRow, params);
|
|
1096
|
+
correlationInfo.listObjectForCorrelation = this.__resolveScalarBinding(correlationNode,
|
|
1097
|
+
correlationNode.attributes.value, params);
|
|
1098
|
+
// => get and apply filters
|
|
1099
|
+
correlationInfo.listObjectForCorrelation = this.__evaluateAndApplyFilters(correlationNode,
|
|
1100
|
+
correlationInfo.listObjectForCorrelation);
|
|
1101
|
+
// => get and apply orderCriteria
|
|
1102
|
+
correlationInfo.listObjectForCorrelation = this.__evaluateAndApplyOrderCriteria(correlationNode,
|
|
1103
|
+
correlationInfo.listObjectForCorrelation);
|
|
1104
|
+
correlationInfo.key = correlationNode.attributes.key;
|
|
1105
|
+
correlationInfo.correlationKey = correlationNode.attributes.correlationKey;
|
|
1106
|
+
}
|
|
1107
|
+
return correlationInfo;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
__resolveEachTag(eachNode, tableNode, params) {
|
|
1111
|
+
let trNodes = [];
|
|
1112
|
+
|
|
1113
|
+
if(!_.isNil(eachNode) && (eachNode.name === EACH_NODE)){
|
|
1114
|
+
let eachName = null;
|
|
1115
|
+
let listObject = null;
|
|
1116
|
+
|
|
1117
|
+
if (!_.isNil(eachNode.attributes)) {
|
|
1118
|
+
eachName = eachNode.attributes.name;
|
|
1119
|
+
listObject = this.__resolveScalarBinding(eachNode, eachNode.attributes.value, params);
|
|
1120
|
+
if(!this.__isLo(listObject)){
|
|
1121
|
+
listObject = null;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
if (_.isNil(listObject)) {
|
|
1126
|
+
if(!_.isNil(eachNode.attributes)) {
|
|
1127
|
+
trNodes.push(this.__newXMLconvertibleJsonNode(ELEMENT_TYPE.TEXT, null, {"text": eachNode.attributes.value,
|
|
1128
|
+
"doNotReplace": true}));
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
this.__deleteInvalidNodes(eachNode, null, [TR_NODE, FILTERS_NODE, ORDERCRITERIA_NODE, CORRELATION_NODE]);
|
|
1133
|
+
|
|
1134
|
+
if (!_.isNil(eachNode.elements) && (eachNode.elements.length > 0)) {
|
|
1135
|
+
|
|
1136
|
+
// => get and apply filters
|
|
1137
|
+
listObject = this.__evaluateAndApplyFilters(eachNode, listObject);
|
|
1138
|
+
// => get and apply orderCriteria
|
|
1139
|
+
listObject = this.__evaluateAndApplyOrderCriteria(eachNode, listObject);
|
|
1140
|
+
|
|
1141
|
+
// cache each data ...
|
|
1142
|
+
this.__eachCache[eachName] = listObject;
|
|
1143
|
+
|
|
1144
|
+
// the correlation node is needed for printing the correlated items
|
|
1145
|
+
const correlationNode = _.find(eachNode.elements, {name:CORRELATION_NODE});
|
|
1146
|
+
let correlationInfo = this.__buildCorrelationInfo(correlationNode, params);
|
|
1147
|
+
if (!_.isNil(correlationInfo)) {
|
|
1148
|
+
// each node with correlation => enable dynamicPageBreak for table
|
|
1149
|
+
tableNode.attributes.dynamicPageBreak = "true"; // as string to keep pdfconverter working ...
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
// => process table row (with filtered / sorted list object)
|
|
1153
|
+
let tableRow = _.find(eachNode.elements, {name:TR_NODE});
|
|
1154
|
+
if (!_.isNil(tableRow)) {
|
|
1155
|
+
|
|
1156
|
+
this.__deleteInvalidNodes(tableRow, null, [TD_NODE]);
|
|
1157
|
+
|
|
1158
|
+
if (!_.isNil(tableRow.elements) && (tableRow.elements.length > 0)) {
|
|
1159
|
+
let tdCacheList = this.__createTableDataCache(tableRow, params);
|
|
1160
|
+
trNodes = this.__createTableRowData(tableRow, tdCacheList, trNodes, listObject, correlationInfo, eachName);
|
|
1161
|
+
}
|
|
1162
|
+
} else {
|
|
1163
|
+
// no table row => log error
|
|
1164
|
+
this.__log.error("<each> element must contain a <tr> (table row) element");
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
return trNodes;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
__evaluateAndApplyFilters(iterableNode, listObject) {
|
|
1173
|
+
// <filters>
|
|
1174
|
+
// <filter fieldName="quantity" value="0" operator="GT" compareMode="NUMBER" />
|
|
1175
|
+
// <filter fieldName="movementDirection" value="In" operator="NE" />
|
|
1176
|
+
// </filters>
|
|
1177
|
+
|
|
1178
|
+
let filtersNode = _.find(iterableNode.elements, {name:FILTERS_NODE});
|
|
1179
|
+
if (!_.isNil(filtersNode)) {
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
this.__deleteInvalidNodes(filtersNode, null, [FILTER_NODE]);
|
|
1183
|
+
|
|
1184
|
+
if (!_.isNil(filtersNode.elements) && (filtersNode.elements.length > 0)) {
|
|
1185
|
+
_.forEach(filtersNode.elements, element => {
|
|
1186
|
+
|
|
1187
|
+
let filterExpression = this.__getAdvancedFilterExpression(element);
|
|
1188
|
+
if (!_.isNil(filterExpression) && _.isFunction(filterExpression)) {
|
|
1189
|
+
listObject = _.filter(listObject, filterExpression);
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
});
|
|
1193
|
+
} else {
|
|
1194
|
+
// no filter elements => log error
|
|
1195
|
+
this.__log.error("<each>.<filters> element must contain at least one <filter> element");
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
return listObject;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
__getAdvancedFilterExpression(filterNode) {
|
|
1202
|
+
let filterExpression = null;
|
|
1203
|
+
|
|
1204
|
+
// extract attributes
|
|
1205
|
+
let fieldName = filterNode.attributes.fieldName;
|
|
1206
|
+
let operator = filterNode.attributes.operator;
|
|
1207
|
+
let value = filterNode.attributes.value;
|
|
1208
|
+
|
|
1209
|
+
let compareMode = filterNode.attributes.compareMode;
|
|
1210
|
+
if (_.isNil(compareMode)) {
|
|
1211
|
+
compareMode = COMPAREMODE_DEFAULT;
|
|
1212
|
+
}
|
|
1213
|
+
// normalize compareMode
|
|
1214
|
+
compareMode = _.toUpper(compareMode);
|
|
1215
|
+
|
|
1216
|
+
if (!_.isNil(fieldName) && !_.isNil(operator) && !_.isNil(value) && !_.isNil(compareMode)) {
|
|
1217
|
+
|
|
1218
|
+
let converter = this.__resolveConverter(compareMode);
|
|
1219
|
+
if (!_.isNil(converter) && _.isFunction(converter)) {
|
|
1220
|
+
|
|
1221
|
+
// convert value just once
|
|
1222
|
+
let y = converter(value);
|
|
1223
|
+
|
|
1224
|
+
// normalize operator
|
|
1225
|
+
operator = _.toUpper(operator);
|
|
1226
|
+
|
|
1227
|
+
let comparator = this.__resolveComparator(operator);
|
|
1228
|
+
if (!_.isNil(comparator) && _.isFunction(comparator)) {
|
|
1229
|
+
|
|
1230
|
+
// build filter expression
|
|
1231
|
+
filterExpression = (object => {
|
|
1232
|
+
// convert listobject value
|
|
1233
|
+
let x = converter(object[fieldName]);
|
|
1234
|
+
// perform comparison
|
|
1235
|
+
return comparator(x, y);
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
} else {
|
|
1239
|
+
// unknown operator => log error
|
|
1240
|
+
this.__log.error("Unsupported operator '", operator, "' at <each>.<filters>.<filter> element");
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
} else {
|
|
1244
|
+
// unknown compareMode => log error
|
|
1245
|
+
this.__log.error("Unsupported compareMode '", compareMode, "' at <each>.<filters>.<filter> element");
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
} else {
|
|
1249
|
+
// missing mandatory attribute => log error
|
|
1250
|
+
this.__log.error("Missing mandatory attribute at <each>.<filters>.<filter> element");
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
return filterExpression;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
__resolveComparator(comparator) {
|
|
1257
|
+
const COMPARATORS = {
|
|
1258
|
+
"EQ" : function (x, y) { return (x === y); },
|
|
1259
|
+
"NE" : function (x, y) { return (x !== y); },
|
|
1260
|
+
"GT" : function (x, y) { return (x > y); },
|
|
1261
|
+
"GE" : function (x, y) { return (x >= y); },
|
|
1262
|
+
"LT" : function (x, y) { return (x < y); },
|
|
1263
|
+
"LE" : function (x, y) { return (x <= y); }
|
|
1264
|
+
};
|
|
1265
|
+
|
|
1266
|
+
return COMPARATORS[comparator];
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
__resolveConverter(compareMode) {
|
|
1270
|
+
const CONVERTERS = {
|
|
1271
|
+
//"NONE" : function (x) { return x; },
|
|
1272
|
+
"STRING" : function (x) {
|
|
1273
|
+
if (!_.isString(x)) {
|
|
1274
|
+
return _.toString(x);
|
|
1275
|
+
} else {
|
|
1276
|
+
return x;
|
|
1277
|
+
}
|
|
1278
|
+
},
|
|
1279
|
+
"NUMBER" : function (x) {
|
|
1280
|
+
if (!_.isNumber(x)) {
|
|
1281
|
+
return _.toNumber(x);
|
|
1282
|
+
} else {
|
|
1283
|
+
return x;
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
};
|
|
1287
|
+
|
|
1288
|
+
return CONVERTERS[compareMode];
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
__evaluateAndApplyOrderCriteria(iterableNode, listObject) {
|
|
1292
|
+
// <orderCriteria>
|
|
1293
|
+
// <orderCriterion fieldName="eAN" direction="ASC" compareMode="NUMBER" />
|
|
1294
|
+
// </orderCriteria>
|
|
1295
|
+
let orderCriteriaNode = _.find(iterableNode.elements, {name:ORDERCRITERIA_NODE});
|
|
1296
|
+
if (!_.isNil(orderCriteriaNode)) {
|
|
1297
|
+
|
|
1298
|
+
this.__deleteInvalidNodes(orderCriteriaNode, null, [ORDERCRITERION_NODE]);
|
|
1299
|
+
|
|
1300
|
+
if (!_.isNil(orderCriteriaNode.elements) && (orderCriteriaNode.elements.length > 0)) {
|
|
1301
|
+
|
|
1302
|
+
let selectors = [];
|
|
1303
|
+
let directions = [];
|
|
1304
|
+
|
|
1305
|
+
_.forEach(orderCriteriaNode.elements, element => {
|
|
1306
|
+
|
|
1307
|
+
// extract attributes
|
|
1308
|
+
let fieldName = element.attributes.fieldName;
|
|
1309
|
+
let direction = element.attributes.direction;
|
|
1310
|
+
|
|
1311
|
+
let compareMode = element.attributes.compareMode;
|
|
1312
|
+
if (_.isNil(compareMode)) {
|
|
1313
|
+
compareMode = COMPAREMODE_DEFAULT;
|
|
1314
|
+
}
|
|
1315
|
+
// normalize compareMode
|
|
1316
|
+
compareMode = _.toUpper(compareMode);
|
|
1317
|
+
|
|
1318
|
+
if (!_.isNil(fieldName) && !_.isNil(direction) && !_.isNil(compareMode)) {
|
|
1319
|
+
|
|
1320
|
+
// get converter
|
|
1321
|
+
let converter = this.__resolveConverter(compareMode);
|
|
1322
|
+
if (!_.isNil(converter) && _.isFunction(converter)) {
|
|
1323
|
+
|
|
1324
|
+
// build & store selector
|
|
1325
|
+
let selector = (object => {
|
|
1326
|
+
return converter(object[fieldName]);
|
|
1327
|
+
});
|
|
1328
|
+
selectors.push(selector);
|
|
1329
|
+
|
|
1330
|
+
// store direction
|
|
1331
|
+
directions.push(_.toLower(direction));
|
|
1332
|
+
|
|
1333
|
+
} else {
|
|
1334
|
+
// unknown compareMode => log error
|
|
1335
|
+
this.__log.error("Unsupported compareMode '", compareMode , "' at <each>.<orderCriteria>.<orderCriterion> element");
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
} else {
|
|
1339
|
+
// missing mandatory attribute => log error
|
|
1340
|
+
this.__log.error("Missing mandatory attribute at <each>.<orderCriteria>.<orderCriterion> element");
|
|
1341
|
+
}
|
|
1342
|
+
});
|
|
1343
|
+
|
|
1344
|
+
if (selectors.length > 0 && directions.length > 0 && selectors.length === directions.length) {
|
|
1345
|
+
// sort using selectors & directions
|
|
1346
|
+
listObject = _.orderBy(listObject, selectors, directions);
|
|
1347
|
+
} else {
|
|
1348
|
+
// no order criterion fields / directions => log error
|
|
1349
|
+
this.__log.error("<each>.<orderCriteria> element does not contain any applicable <orderCriterion> elements - sorting skipped");
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
} else {
|
|
1353
|
+
// no order criterion elements => log error
|
|
1354
|
+
this.__log.error("<each>.<orderCriteria> element must contain at least one <orderCriterion> element");
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
return listObject;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
__replaceEachTagsInTables(tbodyNode, tableNode, params) {
|
|
1361
|
+
let eachNode = _.find(tbodyNode.elements, {name:EACH_NODE});
|
|
1362
|
+
|
|
1363
|
+
if (!_.isNil(eachNode)){
|
|
1364
|
+
let newTableRows = [];
|
|
1365
|
+
|
|
1366
|
+
_.forEach(tbodyNode.elements, (rowNode) => {
|
|
1367
|
+
if (rowNode.name === EACH_NODE) {
|
|
1368
|
+
newTableRows = _.concat(newTableRows, this.__resolveEachTag(rowNode, tableNode, params));
|
|
1369
|
+
} else {
|
|
1370
|
+
newTableRows.push(rowNode);
|
|
1371
|
+
}
|
|
1372
|
+
});
|
|
1373
|
+
|
|
1374
|
+
tbodyNode.elements = newTableRows;
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
__isBoDeclared(boName){
|
|
1379
|
+
let isDeclared = false;
|
|
1380
|
+
|
|
1381
|
+
_.forEach(this.__declarationsNode.elements, declaration =>{
|
|
1382
|
+
if(declaration.name === "DataDeclaration") {
|
|
1383
|
+
if(declaration.attributes.name === boName){
|
|
1384
|
+
isDeclared = true;
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1388
|
+
|
|
1389
|
+
return isDeclared;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
__replaceTogglesIfApplicable(resolvedMacro, macroResult, localization){
|
|
1393
|
+
let result = resolvedMacro;
|
|
1394
|
+
if (!_.isNil(macroResult.toggleId)) {
|
|
1395
|
+
try {
|
|
1396
|
+
if (!_.isNil(macroResult.toggleField)) {
|
|
1397
|
+
result = this.__toggles.getToggleText(macroResult.toggleId, resolvedMacro, macroResult.toggleField);
|
|
1398
|
+
} else {
|
|
1399
|
+
result = this.__toggles.getToggleText(macroResult.toggleId, resolvedMacro);
|
|
1400
|
+
}
|
|
1401
|
+
} catch(ex){
|
|
1402
|
+
if(ex.message.indexOf("Invalid toggle value") > -1){
|
|
1403
|
+
|
|
1404
|
+
result = localization.resolve("Framework.PrintV2_ToggleValueNotFound", "Toggle value not found");
|
|
1405
|
+
result = result + ": " + resolvedMacro;
|
|
1406
|
+
} else if (ex.message.indexOf("Invalid toggle field") > -1) {
|
|
1407
|
+
result = localization.resolve("Framework.PrintV2_ToggleFieldNotFound", "Toggle field not found");
|
|
1408
|
+
result = result + ": " + macroResult.toggleField;
|
|
1409
|
+
} else {
|
|
1410
|
+
result = localization.resolve("Framework.PrintV2_ToggleNotFound", "Toggle not found");
|
|
1411
|
+
result = result + ": " + macroResult.toggleId;
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
return result;
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
__ensureAttributes(currentNode) {
|
|
1420
|
+
if(_.isNil(currentNode.attributes)){
|
|
1421
|
+
currentNode.attributes = {};
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
__resolveNumberBinding(resolvedMacro, macroResult, attributeNode){
|
|
1426
|
+
if(resolvedMacro !== "null" && !_.isNil(resolvedMacro)){
|
|
1427
|
+
attributeNode.nonRoundedValue = resolvedMacro;
|
|
1428
|
+
return this.__format.formatDecimalV2(resolvedMacro, macroResult.numberFormat,
|
|
1429
|
+
this.__decimalSeparator, this.__thousandSeparator);
|
|
1430
|
+
} else {
|
|
1431
|
+
return " ";
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
__resolveDateBinding(resolvedMacro, macroResult){
|
|
1437
|
+
if(resolvedMacro !== "null" && !_.isNil(resolvedMacro)) {
|
|
1438
|
+
let actualDateTimeFormat = macroResult.dateTimeFormat;
|
|
1439
|
+
switch (actualDateTimeFormat){
|
|
1440
|
+
case "shortDate": actualDateTimeFormat = this.__localization.shortDateFormat;
|
|
1441
|
+
break;
|
|
1442
|
+
case "date": actualDateTimeFormat = this.__localization.dateFormat;
|
|
1443
|
+
break;
|
|
1444
|
+
case "dateTime": actualDateTimeFormat = this.__localization.dateTimeFormat;
|
|
1445
|
+
break;
|
|
1446
|
+
case "time": actualDateTimeFormat = this.__localization.timeFormat;
|
|
1447
|
+
break;
|
|
1448
|
+
default: break;
|
|
1449
|
+
}
|
|
1450
|
+
return this.__format.formatDate(resolvedMacro, actualDateTimeFormat);
|
|
1451
|
+
} else {
|
|
1452
|
+
return " ";
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
__resolveScalarBinding(currentNode, bindingText, params) {
|
|
1457
|
+
let bos = params.getBOs();
|
|
1458
|
+
let localization = this.__localization;
|
|
1459
|
+
let resolvedMacro = null;
|
|
1460
|
+
let macroResult = this.__macroHandler.parseMacro(bindingText);
|
|
1461
|
+
|
|
1462
|
+
if (!_.isNil(macroResult) && !_.isNil(macroResult.scope) && !_.isNil(macroResult.path)) {
|
|
1463
|
+
let scope = macroResult.scope;
|
|
1464
|
+
let bindingPath = macroResult.path;
|
|
1465
|
+
|
|
1466
|
+
if (scope === "Globals") {
|
|
1467
|
+
let defaultLabel = macroResult.defaultLabel;
|
|
1468
|
+
resolvedMacro = localization.resolve(bindingPath, defaultLabel);
|
|
1469
|
+
}
|
|
1470
|
+
else if (scope === "Labels") {
|
|
1471
|
+
let defaultLabel = macroResult.defaultLabel;
|
|
1472
|
+
|
|
1473
|
+
if(bindingPath.indexOf(".") === -1) {
|
|
1474
|
+
// support for shortcut
|
|
1475
|
+
let lastUnderscoreIndex = this.__printLayoutName.lastIndexOf("_");
|
|
1476
|
+
let printLayoutNameWithoutSpecificVersion = this.__printLayoutName;
|
|
1477
|
+
if(lastUnderscoreIndex > -1) {
|
|
1478
|
+
printLayoutNameWithoutSpecificVersion =
|
|
1479
|
+
this.__printLayoutName.substr(0, lastUnderscoreIndex);
|
|
1480
|
+
}
|
|
1481
|
+
bindingPath = "PrintLayouts." + printLayoutNameWithoutSpecificVersion + "." + bindingPath;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
resolvedMacro = localization.resolve(bindingPath, defaultLabel);
|
|
1485
|
+
} else if (scope === "Declarations") {
|
|
1486
|
+
let boEndIndex = bindingPath.indexOf(".");
|
|
1487
|
+
let boName;
|
|
1488
|
+
|
|
1489
|
+
if(boEndIndex === -1){
|
|
1490
|
+
// this means it is a top level binding like Declarations::data
|
|
1491
|
+
boName = bindingPath;
|
|
1492
|
+
boEndIndex = bindingPath.length;
|
|
1493
|
+
}else {
|
|
1494
|
+
boName = bindingPath.substring(0, boEndIndex);
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
let isBoDeclared = this.__isBoDeclared(boName);
|
|
1498
|
+
|
|
1499
|
+
if(isBoDeclared){
|
|
1500
|
+
let deeperBindingPath = bindingPath.substring(boEndIndex + 1, bindingPath.length);
|
|
1501
|
+
let actualBo = _.get(bos, boName);
|
|
1502
|
+
|
|
1503
|
+
if(deeperBindingPath.length > 0){
|
|
1504
|
+
resolvedMacro = _.get(actualBo, deeperBindingPath);
|
|
1505
|
+
} else {
|
|
1506
|
+
// this means it is a top level binding like Declarations::data
|
|
1507
|
+
resolvedMacro = actualBo;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
if (!_.isNil(macroResult.numberFormat)) {
|
|
1511
|
+
this.__ensureAttributes(currentNode);
|
|
1512
|
+
resolvedMacro = this.__resolveNumberBinding(resolvedMacro, macroResult,currentNode.attributes);
|
|
1513
|
+
} if(!_.isNil(macroResult.dateTimeFormat)) {
|
|
1514
|
+
resolvedMacro = this.__resolveDateBinding(resolvedMacro, macroResult);
|
|
1515
|
+
} else {
|
|
1516
|
+
resolvedMacro = this.__replaceTogglesIfApplicable(resolvedMacro, macroResult, localization);
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
|
|
1520
|
+
} else {
|
|
1521
|
+
this.__log.error("Usage of undeclared BO:", boName);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
return resolvedMacro;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
__replaceMacrosInTextNodes(parentJsonElement, currentJsonElement, params){
|
|
1530
|
+
let xmlNodeText = currentJsonElement.text;
|
|
1531
|
+
let macroRegex = this.__macroHandler.getMacroRegex();
|
|
1532
|
+
let arrayMatches = xmlNodeText.match(macroRegex);
|
|
1533
|
+
|
|
1534
|
+
if(!_.isNil(arrayMatches) && arrayMatches.length > 0) {
|
|
1535
|
+
_.forEach(arrayMatches, currentMatch => {
|
|
1536
|
+
let resolvedMacro = this.__resolveScalarBinding(parentJsonElement, currentMatch, params);
|
|
1537
|
+
if (!_.isNil(resolvedMacro)){
|
|
1538
|
+
if(_.isString(resolvedMacro)){
|
|
1539
|
+
resolvedMacro = resolvedMacro.replace(/\$/g, "$$$$");
|
|
1540
|
+
}
|
|
1541
|
+
xmlNodeText = xmlNodeText.replace(currentMatch, resolvedMacro);
|
|
1542
|
+
currentJsonElement.text = xmlNodeText;
|
|
1543
|
+
}
|
|
1544
|
+
});
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
__isImageDeclared(imageName){
|
|
1549
|
+
let isDeclared = false;
|
|
1550
|
+
|
|
1551
|
+
_.forEach(this.__declarationsNode.elements, declaration => {
|
|
1552
|
+
if(declaration.name === "DataDeclaration") {
|
|
1553
|
+
if ((declaration.attributes.name === imageName) && (declaration.attributes.type === "Image" || declaration.attributes.type === "Signature")) {
|
|
1554
|
+
isDeclared = true;
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
});
|
|
1558
|
+
|
|
1559
|
+
return isDeclared;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
__sanitizeImageAttributes(currentJsonElement/*, params*/) {
|
|
1563
|
+
let width = currentJsonElement.attributes.width;
|
|
1564
|
+
let height = currentJsonElement.attributes.height;
|
|
1565
|
+
let fit = currentJsonElement.attributes.fit;
|
|
1566
|
+
this.__integerStringRegExp.lastIndex = 0; // reset last index
|
|
1567
|
+
if(!this.__integerStringRegExp.test(height)){
|
|
1568
|
+
delete currentJsonElement.attributes.height;
|
|
1569
|
+
}
|
|
1570
|
+
this.__integerStringRegExp.lastIndex = 0; // reset last index
|
|
1571
|
+
if(!this.__integerStringRegExp.test(width)){
|
|
1572
|
+
delete currentJsonElement.attributes.width;
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
let fitRegExp = /^\d+,\d+$/g;
|
|
1576
|
+
if(!fitRegExp.test(fit)){
|
|
1577
|
+
delete currentJsonElement.attributes.fit;
|
|
1578
|
+
}
|
|
1579
|
+
if(!_.isNil(width) || !_.isNil(height)){
|
|
1580
|
+
delete currentJsonElement.attributes.fit;
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
__processImageNode(currentJsonElement, params){
|
|
1585
|
+
this.__replaceMacrosInImageNodes(currentJsonElement, params);
|
|
1586
|
+
this.__sanitizeImageAttributes(currentJsonElement, params);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
__replaceMacrosInImageNodes(currentJsonElement, params){
|
|
1590
|
+
let images = params.getImages();
|
|
1591
|
+
let bindingText = currentJsonElement.attributes.src;
|
|
1592
|
+
let macroResult = this.__macroHandler.parseMacro(bindingText);
|
|
1593
|
+
|
|
1594
|
+
if (!_.isNil(macroResult) && !_.isNil(macroResult.scope) && !_.isNil(macroResult.path)) {
|
|
1595
|
+
let scope = macroResult.scope;
|
|
1596
|
+
let imageName = macroResult.path;
|
|
1597
|
+
if (scope === "Declarations") {
|
|
1598
|
+
if (this.__isImageDeclared(imageName)) {
|
|
1599
|
+
let imageObject = images[imageName];
|
|
1600
|
+
if(_.isNil(imageObject.src) && imageObject.type === "Signature") {
|
|
1601
|
+
currentJsonElement.name = "p";
|
|
1602
|
+
} else if (!_.isNil(imageObject) && !_.isNil(imageObject.src)
|
|
1603
|
+
&& !_.isNil(imageObject.mimeType) && (!_.isNil(imageObject.imageId) || imageObject.type === "Signature")) {
|
|
1604
|
+
let dataUrlStart = "data:" + imageObject.mimeType +";base64,";
|
|
1605
|
+
let dataUrl = imageObject.src;
|
|
1606
|
+
|
|
1607
|
+
if (!_.startsWith(dataUrl, dataUrlStart)) {
|
|
1608
|
+
dataUrl = dataUrlStart + dataUrl;
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
// => use imageName as id
|
|
1612
|
+
currentJsonElement.attributes.id = imageName;
|
|
1613
|
+
currentJsonElement.attributes.mimeType = imageObject.mimeType;
|
|
1614
|
+
|
|
1615
|
+
currentJsonElement.attributes.src = dataUrl;
|
|
1616
|
+
if (imageObject.type === "Signature") {
|
|
1617
|
+
// https://stackoverflow.com/questions/5515869/string-length-in-bytes-in-javascript
|
|
1618
|
+
const m = encodeURIComponent(dataUrl).match(/%[89ABab]/g);
|
|
1619
|
+
const sizeInBytes = dataUrl.length + (m ? m.length : 0);
|
|
1620
|
+
if (sizeInBytes > SIGNATURE_SIZE_LIMIT) {
|
|
1621
|
+
this.__log.error("Usage of signature larger than 200kb:", imageName);
|
|
1622
|
+
this.__assignFallbackImage(currentJsonElement);
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
} else {
|
|
1626
|
+
this.__log.error("Usage of undefined image:", imageName);
|
|
1627
|
+
this.__assignFallbackImage(currentJsonElement);
|
|
1628
|
+
}
|
|
1629
|
+
} else {
|
|
1630
|
+
this.__log.error("Usage of undeclared image:", imageName);
|
|
1631
|
+
this.__assignFallbackImage(currentJsonElement);
|
|
1632
|
+
}
|
|
1633
|
+
} else {
|
|
1634
|
+
this.__log.error("Invalid binding value:'"+ bindingText + "' found in image.");
|
|
1635
|
+
this.__assignFallbackImage(currentJsonElement);
|
|
1636
|
+
}
|
|
1637
|
+
} else {
|
|
1638
|
+
this.__log.error("Invalid value:'"+ bindingText + "' found in image.");
|
|
1639
|
+
this.__assignFallbackImage(currentJsonElement);
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
__assignFallbackImage(currentJsonElement) {
|
|
1644
|
+
const errorFallbackImage = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMi4wLjEsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAzOCAzOCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzggMzg7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsOiNGM0Y2Rjg7fQ0KCS5zdDF7ZmlsbDojQjRDN0Q0O30NCjwvc3R5bGU+DQo8Y2lyY2xlIGNsYXNzPSJzdDAiIGN4PSIxOSIgY3k9IjE5IiByPSIxOSIvPg0KPGNpcmNsZSBjbGFzcz0ic3QxIiBjeD0iMjkuMSIgY3k9IjExLjQiIHI9IjIuMyIvPg0KPGc+DQoJPGc+DQoJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0yMC43LDIyLjZsLTQtNC44bDAuNS0xLjdsLTIuMy00Yy0wLjEtMC4yLTAuMy0wLjItMC40LDBMNS4yLDI2LjljLTAuMSwwLjIsMCwwLjQsMC4yLDAuNGgxNUwxNywyMi41DQoJCQlMMjAuNywyMi42eiBNMzIuOCwyN2wtNy43LTljLTAuMS0wLjItMC40LTAuMy0wLjYtMC4xbC0yLjgsMmwxLjksNS41TDIwLDI0LjVsMS4yLDIuOGgxMS40QzMyLjksMjcuMywzMi45LDI3LjIsMzIuOCwyN3oiLz4NCgk8L2c+DQo8L2c+DQo8L3N2Zz4NCg==";
|
|
1645
|
+
if (!_.isNil(currentJsonElement) && !_.isUndefined(currentJsonElement.attributes)) {
|
|
1646
|
+
currentJsonElement.attributes.id = "$$$fallbackImage$$$";
|
|
1647
|
+
currentJsonElement.attributes.mimeType = "image/svg+xml";
|
|
1648
|
+
currentJsonElement.attributes.src = errorFallbackImage;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
__getCellId(eachName, listItemIndex, correlatedListItemIndex, columnIndex){
|
|
1653
|
+
let tcid = TableCellIdentifier.create(eachName, listItemIndex, correlatedListItemIndex, columnIndex);
|
|
1654
|
+
return tcid.toString();
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
module.exports = ContractToIntermediateJSON;
|