data-restructor 3.3.4 → 3.4.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/.github/workflows/codeql-analysis.yml +4 -4
- package/.github/workflows/continuous-integration.yaml +84 -0
- package/CHANGELOG.md +98 -76
- package/CONTRIBUTING.md +51 -43
- package/Commands.md +15 -15
- package/README.md +188 -137
- package/SECURITY.md +2 -2
- package/coverage/coverage-summary.json +3 -3
- package/coverage/datarestructor.js.html +133 -133
- package/coverage/describedfield.js.html +45 -45
- package/coverage/index.html +1 -1
- package/coverage/templateResolver.js.html +26 -26
- package/devdist/datarestructor-ie.js +1479 -1665
- package/devdist/datarestructor.js +1439 -1608
- package/devdist/describedfield-ie.js +259 -279
- package/devdist/describedfield.js +257 -277
- package/devdist/templateResolver-ie.js +220 -252
- package/devdist/templateResolver.js +196 -227
- package/dist/datarestructor-ie.js +1 -1
- package/dist/datarestructor-ie.js.map +1 -1
- package/dist/datarestructor.js +1 -1
- package/dist/datarestructor.js.map +1 -1
- package/dist/describedfield-ie.js +1 -1
- package/dist/describedfield-ie.js.map +1 -1
- package/dist/describedfield.js +1 -1
- package/dist/describedfield.js.map +1 -1
- package/dist/templateResolver-ie.js +1 -1
- package/dist/templateResolver-ie.js.map +1 -1
- package/dist/templateResolver.js +1 -1
- package/dist/templateResolver.js.map +1 -1
- package/docs/datarestructor.js.html +1 -1
- package/docs/describedfield.js.html +1 -1
- package/docs/index.html +49 -44
- package/docs/module-datarestructor.DescribedEntryCreator.html +1 -1
- package/docs/module-datarestructor.PropertyStructureDescriptionBuilder.html +1 -1
- package/docs/module-datarestructor.Restructor.html +1 -1
- package/docs/module-datarestructor.Transform.html +1 -1
- package/docs/module-datarestructor.html +1 -1
- package/docs/module-described_field.DescribedDataFieldBuilder.html +1 -1
- package/docs/module-described_field.DescribedDataFieldGroup.html +1 -1
- package/docs/module-described_field.html +1 -1
- package/docs/module-template_resolver.Resolver.html +1 -1
- package/docs/module-template_resolver.html +1 -1
- package/docs/templateResolver.js.html +1 -1
- package/package.json +16 -14
- package/renovate.json +20 -0
- package/.github/workflows/action.yaml +0 -44
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// anything defined in a previous bundle is accessed via the
|
|
7
7
|
// orig method which is the require for previous bundles
|
|
8
8
|
|
|
9
|
-
(function(modules, entry, mainEntry, parcelRequireName, globalName) {
|
|
9
|
+
(function (modules, entry, mainEntry, parcelRequireName, globalName) {
|
|
10
10
|
/* eslint-disable no-undef */
|
|
11
11
|
var globalObject =
|
|
12
12
|
typeof globalThis !== 'undefined'
|
|
@@ -80,11 +80,13 @@
|
|
|
80
80
|
return cache[name].exports;
|
|
81
81
|
|
|
82
82
|
function localRequire(x) {
|
|
83
|
-
|
|
83
|
+
var res = localRequire.resolve(x);
|
|
84
|
+
return res === false ? {} : newRequire(res);
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
function resolve(x) {
|
|
87
|
-
|
|
88
|
+
var id = modules[name][1][x];
|
|
89
|
+
return id != null ? id : x;
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
92
|
|
|
@@ -99,9 +101,9 @@
|
|
|
99
101
|
newRequire.modules = modules;
|
|
100
102
|
newRequire.cache = cache;
|
|
101
103
|
newRequire.parent = previousRequire;
|
|
102
|
-
newRequire.register = function(id, exports) {
|
|
104
|
+
newRequire.register = function (id, exports) {
|
|
103
105
|
modules[id] = [
|
|
104
|
-
function(require, module) {
|
|
106
|
+
function (require, module) {
|
|
105
107
|
module.exports = exports;
|
|
106
108
|
},
|
|
107
109
|
{},
|
|
@@ -109,7 +111,7 @@
|
|
|
109
111
|
};
|
|
110
112
|
|
|
111
113
|
Object.defineProperty(newRequire, 'root', {
|
|
112
|
-
get: function() {
|
|
114
|
+
get: function () {
|
|
113
115
|
return globalObject[parcelRequireName];
|
|
114
116
|
},
|
|
115
117
|
});
|
|
@@ -131,7 +133,7 @@
|
|
|
131
133
|
|
|
132
134
|
// RequireJS
|
|
133
135
|
} else if (typeof define === 'function' && define.amd) {
|
|
134
|
-
define(function() {
|
|
136
|
+
define(function () {
|
|
135
137
|
return mainExports;
|
|
136
138
|
});
|
|
137
139
|
|
|
@@ -140,7 +142,7 @@
|
|
|
140
142
|
this[globalName] = mainExports;
|
|
141
143
|
}
|
|
142
144
|
}
|
|
143
|
-
})({"
|
|
145
|
+
})({"2gjIT":[function(require,module,exports) {
|
|
144
146
|
"use strict";
|
|
145
147
|
require("../../lib/js/polyfills/isArrayPolyfill.js");
|
|
146
148
|
require("../../lib/js/polyfills/arrayFilterPolyfill.js");
|
|
@@ -148,1762 +150,1574 @@ require("../../lib/js/polyfills/indexOfPolyfill.js");
|
|
|
148
150
|
require("../../lib/js/polyfills/objectKeysPolyfill.js");
|
|
149
151
|
var datarestructor = require("../../src/js/datarestructor.js");
|
|
150
152
|
module.exports = {
|
|
151
|
-
|
|
153
|
+
datarestructor: datarestructor
|
|
152
154
|
};
|
|
153
155
|
|
|
154
|
-
},{"../../lib/js/polyfills/isArrayPolyfill.js":"
|
|
156
|
+
},{"../../lib/js/polyfills/isArrayPolyfill.js":"1e7Zo","../../lib/js/polyfills/arrayFilterPolyfill.js":"47djm","../../lib/js/polyfills/indexOfPolyfill.js":"6WEQI","../../lib/js/polyfills/objectKeysPolyfill.js":"cXkCN","../../src/js/datarestructor.js":"7hzxy"}],"1e7Zo":[function(require,module,exports) {
|
|
155
157
|
// https://gist.github.com/brianonn/4ef965a06b9e950d80e4e8b8e4c527f9
|
|
156
158
|
// https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
|
|
157
|
-
if (!Array.isArray) {
|
|
158
|
-
Array.isArray = function (arg) {
|
|
159
|
+
if (!Array.isArray) Array.isArray = function(arg) {
|
|
159
160
|
return Object.prototype.toString.call(arg) === '[object Array]';
|
|
160
|
-
|
|
161
|
-
}
|
|
161
|
+
};
|
|
162
162
|
|
|
163
|
-
},{}],"
|
|
163
|
+
},{}],"47djm":[function(require,module,exports) {
|
|
164
164
|
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Polyfill
|
|
165
|
-
if (!Array.prototype.filter) {
|
|
166
|
-
Array.prototype.filter = function (func, thisArg) {
|
|
167
|
-
"use strict";
|
|
165
|
+
if (!Array.prototype.filter) Array.prototype.filter = function(func, thisArg) {
|
|
168
166
|
if (!((typeof func === 'Function' || typeof func === 'function') && this)) throw new TypeError();
|
|
169
|
-
var len = this.length >>> 0, res = new Array(len),
|
|
170
|
-
t = this, c = 0, i = -1;
|
|
167
|
+
var len = this.length >>> 0, res = new Array(len), t = this, c = 0, i = -1;
|
|
171
168
|
var kValue;
|
|
172
169
|
if (thisArg === undefined) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// in case t is changed in callback
|
|
178
|
-
if (func(t[i], i, t)) {
|
|
179
|
-
res[c++] = kValue;
|
|
180
|
-
}
|
|
170
|
+
while(++i !== len)// checks to see if the key was set
|
|
171
|
+
if (i in this) {
|
|
172
|
+
kValue = t[i]; // in case t is changed in callback
|
|
173
|
+
if (func(t[i], i, t)) res[c++] = kValue;
|
|
181
174
|
}
|
|
182
|
-
}
|
|
183
175
|
} else {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (func.call(thisArg, t[i], i, t)) {
|
|
189
|
-
res[c++] = kValue;
|
|
190
|
-
}
|
|
176
|
+
while(++i !== len)// checks to see if the key was set
|
|
177
|
+
if (i in this) {
|
|
178
|
+
kValue = t[i];
|
|
179
|
+
if (func.call(thisArg, t[i], i, t)) res[c++] = kValue;
|
|
191
180
|
}
|
|
192
|
-
}
|
|
193
181
|
}
|
|
194
|
-
res.length = c;
|
|
195
|
-
// shrink down array to proper size
|
|
182
|
+
res.length = c; // shrink down array to proper size
|
|
196
183
|
return res;
|
|
197
|
-
|
|
198
|
-
}
|
|
184
|
+
};
|
|
199
185
|
|
|
200
|
-
},{}],"
|
|
201
|
-
//
|
|
202
|
-
if (!Array.prototype.indexOf) Array.prototype.indexOf = (function
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
};
|
|
186
|
+
},{}],"6WEQI":[function(require,module,exports) {
|
|
187
|
+
//https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Polyfill
|
|
188
|
+
if (!Array.prototype.indexOf) Array.prototype.indexOf = (function(Object, max, min) {
|
|
189
|
+
return function indexOf(member, fromIndex) {
|
|
190
|
+
if (this === null || this === undefined) throw TypeError("Array.prototype.indexOf called on null or undefined");
|
|
191
|
+
var that = Object(this), Len = that.length >>> 0, i = min(fromIndex | 0, Len);
|
|
192
|
+
if (i < 0) i = max(0, Len + i);
|
|
193
|
+
else if (i >= Len) return -1;
|
|
194
|
+
if (member === void 0) {
|
|
195
|
+
for(; i !== Len; ++i)if (that[i] === void 0 && i in that) return i; // undefined
|
|
196
|
+
} else if (member !== member) {
|
|
197
|
+
for(; i !== Len; ++i)if (that[i] !== that[i]) return i; // NaN
|
|
198
|
+
} else for(; i !== Len; ++i)if (that[i] === member) return i; // all else
|
|
199
|
+
return -1; // if the value was not found, then return -1
|
|
200
|
+
};
|
|
216
201
|
})(Object, Math.max, Math.min);
|
|
217
202
|
|
|
218
|
-
},{}],"
|
|
219
|
-
//
|
|
220
|
-
if (!Object.keys) Object.keys = function
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
203
|
+
},{}],"cXkCN":[function(require,module,exports) {
|
|
204
|
+
//http://tokenposts.blogspot.com/2012/04/javascript-objectkeys-browser.html
|
|
205
|
+
if (!Object.keys) Object.keys = function(o) {
|
|
206
|
+
if (o !== Object(o)) throw new TypeError('Object.keys called on a non-object');
|
|
207
|
+
var k = [], p;
|
|
208
|
+
for(p in o)if (Object.prototype.hasOwnProperty.call(o, p)) k.push(p);
|
|
209
|
+
return k;
|
|
225
210
|
};
|
|
226
211
|
|
|
227
|
-
},{}],"
|
|
212
|
+
},{}],"7hzxy":[function(require,module,exports) {
|
|
228
213
|
/**
|
|
229
|
-
* @file datarestructor transforms parsed JSON objects into a uniform data structure
|
|
230
|
-
* @version {@link https://github.com/JohT/data-restructor-js/releases/latest latest version}
|
|
231
|
-
* @author JohT
|
|
232
|
-
*/
|
|
233
|
-
|
|
234
|
-
var module = datarestructorInternalCreateIfNotExists(module);
|
|
235
|
-
// Fallback for vanilla js without modules
|
|
214
|
+
* @file datarestructor transforms parsed JSON objects into a uniform data structure
|
|
215
|
+
* @version {@link https://github.com/JohT/data-restructor-js/releases/latest latest version}
|
|
216
|
+
* @author JohT
|
|
217
|
+
*/ "use strict";
|
|
218
|
+
var module = datarestructorInternalCreateIfNotExists(module); // Fallback for vanilla js without modules
|
|
236
219
|
function datarestructorInternalCreateIfNotExists(objectToCheck) {
|
|
237
|
-
|
|
220
|
+
return objectToCheck || {
|
|
221
|
+
};
|
|
238
222
|
}
|
|
239
223
|
/**
|
|
240
|
-
* datarestructor namespace and module declaration.
|
|
241
|
-
* It contains all functions to convert an object (e.g. parsed JSON) into uniform enumerated list of described field entries.
|
|
242
|
-
*
|
|
243
|
-
* <b>Transformation steps:</b>
|
|
244
|
-
* - JSON
|
|
245
|
-
* - flatten
|
|
246
|
-
* - mark and identify
|
|
247
|
-
* - add array fields
|
|
248
|
-
* - deduplicate
|
|
249
|
-
* - group
|
|
250
|
-
* - flatten again
|
|
251
|
-
* @module datarestructor
|
|
252
|
-
*/
|
|
253
|
-
|
|
254
|
-
// Export module for npm...
|
|
224
|
+
* datarestructor namespace and module declaration.
|
|
225
|
+
* It contains all functions to convert an object (e.g. parsed JSON) into uniform enumerated list of described field entries.
|
|
226
|
+
*
|
|
227
|
+
* <b>Transformation steps:</b>
|
|
228
|
+
* - JSON
|
|
229
|
+
* - flatten
|
|
230
|
+
* - mark and identify
|
|
231
|
+
* - add array fields
|
|
232
|
+
* - deduplicate
|
|
233
|
+
* - group
|
|
234
|
+
* - flatten again
|
|
235
|
+
* @module datarestructor
|
|
236
|
+
*/ var datarestructor = module.exports = {
|
|
237
|
+
}; // Export module for npm...
|
|
255
238
|
datarestructor.internalCreateIfNotExists = datarestructorInternalCreateIfNotExists;
|
|
256
|
-
var internal_object_tools = internal_object_tools || require("../../lib/js/flattenToArray");
|
|
257
|
-
// supports vanilla js & npm
|
|
258
|
-
var
|
|
259
|
-
// supports vanilla js & npm
|
|
260
|
-
var described_field = described_field || require("../../src/js/describedfield");
|
|
261
|
-
// supports vanilla js & npm
|
|
262
|
-
/**
|
|
263
|
-
* Takes the full qualified original property name and extracts a simple name out of it.
|
|
264
|
-
*
|
|
265
|
-
* @callback module:datarestructor.propertyNameFunction
|
|
266
|
-
* @param {string} propertyName full qualified, point separated property name
|
|
267
|
-
* @return {String} extracted, simple name
|
|
268
|
-
*/
|
|
239
|
+
var internal_object_tools = internal_object_tools || require("../../lib/js/flattenToArray"); // supports vanilla js & npm
|
|
240
|
+
var template_resolver = template_resolver || require("../../src/js/templateResolver"); // supports vanilla js & npm
|
|
241
|
+
var described_field = described_field || require("../../src/js/describedfield"); // supports vanilla js & npm
|
|
269
242
|
/**
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
* @
|
|
274
|
-
* @
|
|
275
|
-
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
* @
|
|
280
|
-
* @property {string}
|
|
281
|
-
* @property {
|
|
282
|
-
* @property {
|
|
283
|
-
* @property {string}
|
|
284
|
-
* @property {
|
|
285
|
-
* @property {string}
|
|
286
|
-
* @property {string}
|
|
287
|
-
* @property {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
*/
|
|
296
|
-
function PropertyStructureDescription() {
|
|
297
|
-
/**
|
|
298
|
-
* @type {module:datarestructor.PropertyStructureDescription}
|
|
299
|
-
*/
|
|
300
|
-
this.description = {
|
|
301
|
-
type: "",
|
|
302
|
-
category: "",
|
|
303
|
-
abbreviation: "",
|
|
304
|
-
image: "",
|
|
305
|
-
propertyPatternTemplateMode: false,
|
|
306
|
-
propertyPattern: "",
|
|
307
|
-
indexStartsWith: "",
|
|
308
|
-
groupName: "group",
|
|
309
|
-
groupPattern: "",
|
|
310
|
-
groupDestinationPattern: "",
|
|
311
|
-
groupDestinationName: null,
|
|
312
|
-
deduplicationPattern: "",
|
|
313
|
-
getDisplayNameForPropertyName: null,
|
|
314
|
-
getFieldNameForPropertyName: null,
|
|
315
|
-
matchesPropertyName: null
|
|
316
|
-
};
|
|
317
|
-
/**
|
|
318
|
-
* Sets the type.
|
|
319
|
-
*
|
|
320
|
-
* Contains the type of the entry, for example:
|
|
321
|
-
* - "summary" for e.g. a list overview.
|
|
322
|
-
* - "detail" e.g. when a summary is selected.
|
|
323
|
-
* - "filter" e.g. for field/value pair results that can be selected as search parameters.
|
|
324
|
-
*
|
|
325
|
-
* @function
|
|
326
|
-
* @param {String} [value=""]
|
|
327
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
328
|
-
* @example type("summary")
|
|
329
|
-
*/
|
|
330
|
-
this.type = function (value) {
|
|
331
|
-
this.description.type = withDefault(value, "");
|
|
332
|
-
return this;
|
|
333
|
-
};
|
|
334
|
-
/**
|
|
335
|
-
* Sets the category.
|
|
336
|
-
*
|
|
337
|
-
* Contains a short domain nam, for example:
|
|
338
|
-
* - "product" for products
|
|
339
|
-
* - "vendor" for vendors
|
|
340
|
-
*
|
|
341
|
-
* @function
|
|
342
|
-
* @param {String} [value=""]
|
|
343
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
344
|
-
* @example category("Product")
|
|
345
|
-
*/
|
|
346
|
-
this.category = function (value) {
|
|
347
|
-
this.description.category = withDefault(value, "");
|
|
348
|
-
return this;
|
|
349
|
-
};
|
|
350
|
-
/**
|
|
351
|
-
* Sets the optional abbreviation.
|
|
352
|
-
*
|
|
353
|
-
* Contains a symbol character or a very short abbreviation of the category.
|
|
354
|
-
* - "P" for products
|
|
355
|
-
* - "V" for vendors
|
|
356
|
-
*
|
|
357
|
-
* @function
|
|
358
|
-
* @param {String} [value=""]
|
|
359
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
360
|
-
* @example abbreviation("P")
|
|
361
|
-
*/
|
|
362
|
-
this.abbreviation = function (value) {
|
|
363
|
-
this.description.abbreviation = withDefault(value, "");
|
|
364
|
-
return this;
|
|
365
|
-
};
|
|
366
|
-
/**
|
|
367
|
-
* Sets the optional path to an image resource.
|
|
368
|
-
*
|
|
369
|
-
* @function
|
|
370
|
-
* @param {String} [value=""]
|
|
371
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
372
|
-
* @example image("img/product.png")
|
|
373
|
-
*/
|
|
374
|
-
this.image = function (value) {
|
|
375
|
-
this.description.image = withDefault(value, "");
|
|
376
|
-
return this;
|
|
377
|
-
};
|
|
378
|
-
/**
|
|
379
|
-
* Sets "equal mode" for the property pattern.
|
|
380
|
-
*
|
|
381
|
-
* "propertyPattern" need to match exactly if this mode is activated.
|
|
382
|
-
* It clears propertyPatternTemplateMode which means "equal" mode.
|
|
383
|
-
* @function
|
|
384
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
385
|
-
*/
|
|
386
|
-
this.propertyPatternEqualMode = function () {
|
|
387
|
-
this.description.propertyPatternTemplateMode = false;
|
|
388
|
-
return this;
|
|
389
|
-
};
|
|
390
|
-
/**
|
|
391
|
-
* Sets "template mode" for the property pattern.
|
|
392
|
-
*
|
|
393
|
-
* "propertyPattern" can contain variables like {{fieldName}} and
|
|
394
|
-
* doesn't need to match the property name exactly. If the "propertyPattern"
|
|
395
|
-
* is shorter than the property name, it also matches when the property name
|
|
396
|
-
* starts with the "propertyPattern".
|
|
397
|
-
*
|
|
398
|
-
* @function
|
|
399
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
400
|
-
*/
|
|
401
|
-
this.propertyPatternTemplateMode = function () {
|
|
402
|
-
this.description.propertyPatternTemplateMode = true;
|
|
403
|
-
return this;
|
|
404
|
-
};
|
|
405
|
-
/**
|
|
406
|
-
* Sets the property name pattern.
|
|
407
|
-
*
|
|
408
|
-
* Contains single property names with sub types separated by "." without array indices.
|
|
409
|
-
* May contain variables in double curly brackets.
|
|
410
|
-
*
|
|
411
|
-
* Example:
|
|
412
|
-
* - responses.hits.hits._source.{{fieldName}}
|
|
413
|
-
* @function
|
|
414
|
-
* @param {String} [value=""]
|
|
415
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
416
|
-
* @example propertyPattern("responses.hits.hits._source.{{fieldName}}")
|
|
417
|
-
*/
|
|
418
|
-
this.propertyPattern = function (value) {
|
|
419
|
-
this.description.propertyPattern = withDefault(value, "");
|
|
420
|
-
return this;
|
|
421
|
-
};
|
|
422
|
-
/**
|
|
423
|
-
* Sets the optional beginning of the id that needs to match.
|
|
424
|
-
* Matches all indices if set to "" (or not called).
|
|
425
|
-
*
|
|
426
|
-
* For example:
|
|
427
|
-
* - "1." will match id="1.3.4" but not "0.1.2".
|
|
428
|
-
* @function
|
|
429
|
-
* @param {String} [value=""]
|
|
430
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
431
|
-
* @example indexStartsWith("1.")
|
|
432
|
-
*/
|
|
433
|
-
this.indexStartsWith = function (value) {
|
|
434
|
-
this.description.indexStartsWith = withDefault(value, "");
|
|
435
|
-
return this;
|
|
436
|
-
};
|
|
437
|
-
/**
|
|
438
|
-
* Overrides the display name of the property.
|
|
439
|
-
*
|
|
440
|
-
* If it is not set or set to "" then it will be derived from the
|
|
441
|
-
* last part of original property name starting with an upper case character.
|
|
442
|
-
*
|
|
443
|
-
* For example:
|
|
444
|
-
* - "Product"
|
|
445
|
-
* @function
|
|
446
|
-
* @param {String} [value=""]
|
|
447
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
448
|
-
* @example displayPropertyName("Product")
|
|
449
|
-
*/
|
|
450
|
-
this.displayPropertyName = function (value) {
|
|
451
|
-
this.description.getDisplayNameForPropertyName = createNameExtractFunction(value, this.description);
|
|
452
|
-
if (isSpecifiedString(value)) {
|
|
453
|
-
return this;
|
|
454
|
-
}
|
|
455
|
-
this.description.getDisplayNameForPropertyName = removeArrayValuePropertyPostfixFunction(this.description.getDisplayNameForPropertyName);
|
|
456
|
-
this.description.getDisplayNameForPropertyName = upperCaseFirstLetterForFunction(this.description.getDisplayNameForPropertyName);
|
|
457
|
-
return this;
|
|
458
|
-
};
|
|
459
|
-
/**
|
|
460
|
-
* Overrides the (technical) field name of the property.
|
|
461
|
-
*
|
|
462
|
-
* If it is not set or set to "" then it will be derived from the
|
|
463
|
-
* last part of original property name.
|
|
464
|
-
*
|
|
465
|
-
* For example:
|
|
466
|
-
* - "product"
|
|
467
|
-
* @function
|
|
468
|
-
* @param {String} [value=""]
|
|
469
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
470
|
-
* @example fieldName("product")
|
|
471
|
-
*/
|
|
472
|
-
this.fieldName = function (value) {
|
|
473
|
-
this.description.getFieldNameForPropertyName = createNameExtractFunction(value, this.description);
|
|
474
|
-
return this;
|
|
475
|
-
};
|
|
476
|
-
/**
|
|
477
|
-
* Sets the name of the property, that contains grouped entries.
|
|
478
|
-
*
|
|
479
|
-
* @function
|
|
480
|
-
* @param {String} [value=""]
|
|
481
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
482
|
-
* @example groupName("details")
|
|
483
|
-
*/
|
|
484
|
-
this.groupName = function (value) {
|
|
485
|
-
this.description.groupName = withDefault(value, "");
|
|
486
|
-
return this;
|
|
487
|
-
};
|
|
488
|
-
/**
|
|
489
|
-
* Sets the pattern that describes how to group entries.
|
|
490
|
-
*
|
|
491
|
-
* "groupName" defines the name of this group.
|
|
492
|
-
* A pattern may contain variables in double curly brackets {{variable}}.
|
|
493
|
-
* @function
|
|
494
|
-
* @param {String} [value=""]
|
|
495
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
496
|
-
* @example groupPattern("{{type}}-{{category}}")
|
|
497
|
-
*/
|
|
498
|
-
this.groupPattern = function (value) {
|
|
499
|
-
this.description.groupPattern = withDefault(value, "");
|
|
500
|
-
return this;
|
|
501
|
-
};
|
|
502
|
-
/**
|
|
503
|
-
* Sets the pattern that describes where the group should be moved to.
|
|
504
|
-
*
|
|
505
|
-
* Default=""=Group will not be moved.
|
|
506
|
-
* A pattern may contain variables in double curly brackets {{variable}}.
|
|
507
|
-
* @function
|
|
508
|
-
* @param {String} [value=""]
|
|
509
|
-
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
510
|
-
* @example groupDestinationPattern("main-{{category}}")
|
|
511
|
-
*/
|
|
512
|
-
this.groupDestinationPattern = function (value) {
|
|
513
|
-
this.description.groupDestinationPattern = withDefault(value, "");
|
|
514
|
-
return this;
|
|
515
|
-
};
|
|
243
|
+
* Takes the full qualified original property name and extracts a simple name out of it.
|
|
244
|
+
*
|
|
245
|
+
* @callback module:datarestructor.propertyNameFunction
|
|
246
|
+
* @param {string} propertyName full qualified, point separated property name
|
|
247
|
+
* @return {String} extracted, simple name
|
|
248
|
+
*/ /**
|
|
249
|
+
* Describes a selected part of the incoming data structure and defines,
|
|
250
|
+
* how the data should be transformed.
|
|
251
|
+
*
|
|
252
|
+
* @typedef {Object} module:datarestructor.PropertyStructureDescription
|
|
253
|
+
* @property {string} type - ""(default). Some examples: "summary" for e.g. a list overview. "detail" e.g. when a summary is selected. "filter" e.g. for field/value pair results that can be selected as search parameters.
|
|
254
|
+
* @property {string} category - name of the category. Default = "". Could contain a short domain name like "product" or "vendor".
|
|
255
|
+
* @property {string} [abbreviation=""] - one optional character, a symbol character or a short abbreviation of the category
|
|
256
|
+
* @property {string} [image=""] - one optional path to an image resource
|
|
257
|
+
* @property {boolean} propertyPatternTemplateMode - "false"(default): property name needs to be equal to the pattern. "true" allows variables like "{{fieldName}}" inside the pattern.
|
|
258
|
+
* @property {string} propertyPattern - property name pattern (without array indices) to match
|
|
259
|
+
* @property {string} indexStartsWith - ""(default) matches all ids. String that needs to match the beginning of the id. E.g. "1." will match id="1.3.4" but not "0.1.2".
|
|
260
|
+
* @property {module:datarestructor.propertyNameFunction} getDisplayNameForPropertyName - display name for the property. ""(default) last property name element with upper case first letter.
|
|
261
|
+
* @property {module:datarestructor.propertyNameFunction} getFieldNameForPropertyName - field name for the property. "" (default) last property name element.
|
|
262
|
+
* @property {string} groupName - name of the property, that contains grouped entries. Default="group".
|
|
263
|
+
* @property {string} groupPattern - Pattern that describes how to group entries. "groupName" defines the name of this group. A pattern may contain variables in double curly brackets {{variable}}.
|
|
264
|
+
* @property {string} groupDestinationPattern - Pattern that describes where the group should be moved to. Default=""=Group will not be moved. A pattern may contain variables in double curly brackets {{variable}}.
|
|
265
|
+
* @property {string} groupDestinationName - (default=groupName) Name of the group when it had been moved to the destination.
|
|
266
|
+
* @property {string} deduplicationPattern - Pattern to use to remove duplicate entries. A pattern may contain variables in double curly brackets {{variable}}.
|
|
267
|
+
*/ datarestructor.PropertyStructureDescriptionBuilder = (function() {
|
|
516
268
|
/**
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
269
|
+
* Builder for a {@link PropertyStructureDescription}.
|
|
270
|
+
* @constructs PropertyStructureDescriptionBuilder
|
|
271
|
+
* @alias module:datarestructor.PropertyStructureDescriptionBuilder
|
|
272
|
+
*/ function PropertyStructureDescription() {
|
|
273
|
+
/**
|
|
274
|
+
* @type {module:datarestructor.PropertyStructureDescription}
|
|
275
|
+
*/ this.description = {
|
|
276
|
+
type: "",
|
|
277
|
+
category: "",
|
|
278
|
+
abbreviation: "",
|
|
279
|
+
image: "",
|
|
280
|
+
propertyPatternTemplateMode: false,
|
|
281
|
+
propertyPattern: "",
|
|
282
|
+
indexStartsWith: "",
|
|
283
|
+
groupName: "group",
|
|
284
|
+
groupPattern: "",
|
|
285
|
+
groupDestinationPattern: "",
|
|
286
|
+
groupDestinationName: null,
|
|
287
|
+
deduplicationPattern: "",
|
|
288
|
+
getDisplayNameForPropertyName: null,
|
|
289
|
+
getFieldNameForPropertyName: null,
|
|
290
|
+
matchesPropertyName: null
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* Sets the type.
|
|
294
|
+
*
|
|
295
|
+
* Contains the type of the entry, for example:
|
|
296
|
+
* - "summary" for e.g. a list overview.
|
|
297
|
+
* - "detail" e.g. when a summary is selected.
|
|
298
|
+
* - "filter" e.g. for field/value pair results that can be selected as search parameters.
|
|
299
|
+
*
|
|
300
|
+
* @function
|
|
301
|
+
* @param {String} [value=""]
|
|
302
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
303
|
+
* @example type("summary")
|
|
304
|
+
*/ this.type = function(value) {
|
|
305
|
+
this.description.type = withDefault(value, "");
|
|
306
|
+
return this;
|
|
307
|
+
};
|
|
308
|
+
/**
|
|
309
|
+
* Sets the category.
|
|
310
|
+
*
|
|
311
|
+
* Contains a short domain nam, for example:
|
|
312
|
+
* - "product" for products
|
|
313
|
+
* - "vendor" for vendors
|
|
314
|
+
*
|
|
315
|
+
* @function
|
|
316
|
+
* @param {String} [value=""]
|
|
317
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
318
|
+
* @example category("Product")
|
|
319
|
+
*/ this.category = function(value) {
|
|
320
|
+
this.description.category = withDefault(value, "");
|
|
321
|
+
return this;
|
|
322
|
+
};
|
|
323
|
+
/**
|
|
324
|
+
* Sets the optional abbreviation.
|
|
325
|
+
*
|
|
326
|
+
* Contains a symbol character or a very short abbreviation of the category.
|
|
327
|
+
* - "P" for products
|
|
328
|
+
* - "V" for vendors
|
|
329
|
+
*
|
|
330
|
+
* @function
|
|
331
|
+
* @param {String} [value=""]
|
|
332
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
333
|
+
* @example abbreviation("P")
|
|
334
|
+
*/ this.abbreviation = function(value) {
|
|
335
|
+
this.description.abbreviation = withDefault(value, "");
|
|
336
|
+
return this;
|
|
337
|
+
};
|
|
338
|
+
/**
|
|
339
|
+
* Sets the optional path to an image resource.
|
|
340
|
+
*
|
|
341
|
+
* @function
|
|
342
|
+
* @param {String} [value=""]
|
|
343
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
344
|
+
* @example image("img/product.png")
|
|
345
|
+
*/ this.image = function(value) {
|
|
346
|
+
this.description.image = withDefault(value, "");
|
|
347
|
+
return this;
|
|
348
|
+
};
|
|
349
|
+
/**
|
|
350
|
+
* Sets "equal mode" for the property pattern.
|
|
351
|
+
*
|
|
352
|
+
* "propertyPattern" need to match exactly if this mode is activated.
|
|
353
|
+
* It clears propertyPatternTemplateMode which means "equal" mode.
|
|
354
|
+
* @function
|
|
355
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
356
|
+
*/ this.propertyPatternEqualMode = function() {
|
|
357
|
+
this.description.propertyPatternTemplateMode = false;
|
|
358
|
+
return this;
|
|
359
|
+
};
|
|
360
|
+
/**
|
|
361
|
+
* Sets "template mode" for the property pattern.
|
|
362
|
+
*
|
|
363
|
+
* "propertyPattern" can contain variables like {{fieldName}} and
|
|
364
|
+
* doesn't need to match the property name exactly. If the "propertyPattern"
|
|
365
|
+
* is shorter than the property name, it also matches when the property name
|
|
366
|
+
* starts with the "propertyPattern".
|
|
367
|
+
*
|
|
368
|
+
* @function
|
|
369
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
370
|
+
*/ this.propertyPatternTemplateMode = function() {
|
|
371
|
+
this.description.propertyPatternTemplateMode = true;
|
|
372
|
+
return this;
|
|
373
|
+
};
|
|
374
|
+
/**
|
|
375
|
+
* Sets the property name pattern.
|
|
376
|
+
*
|
|
377
|
+
* Contains single property names with sub types separated by "." without array indices.
|
|
378
|
+
* May contain variables in double curly brackets.
|
|
379
|
+
*
|
|
380
|
+
* Example:
|
|
381
|
+
* - responses.hits.hits._source.{{fieldName}}
|
|
382
|
+
* @function
|
|
383
|
+
* @param {String} [value=""]
|
|
384
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
385
|
+
* @example propertyPattern("responses.hits.hits._source.{{fieldName}}")
|
|
386
|
+
*/ this.propertyPattern = function(value) {
|
|
387
|
+
this.description.propertyPattern = withDefault(value, "");
|
|
388
|
+
return this;
|
|
389
|
+
};
|
|
390
|
+
/**
|
|
391
|
+
* Sets the optional beginning of the id that needs to match.
|
|
392
|
+
* Matches all indices if set to "" (or not called).
|
|
393
|
+
*
|
|
394
|
+
* For example:
|
|
395
|
+
* - "1." will match id="1.3.4" but not "0.1.2".
|
|
396
|
+
* @function
|
|
397
|
+
* @param {String} [value=""]
|
|
398
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
399
|
+
* @example indexStartsWith("1.")
|
|
400
|
+
*/ this.indexStartsWith = function(value) {
|
|
401
|
+
this.description.indexStartsWith = withDefault(value, "");
|
|
402
|
+
return this;
|
|
403
|
+
};
|
|
404
|
+
/**
|
|
405
|
+
* Overrides the display name of the property.
|
|
406
|
+
*
|
|
407
|
+
* If it is not set or set to "" then it will be derived from the
|
|
408
|
+
* last part of original property name starting with an upper case character.
|
|
409
|
+
*
|
|
410
|
+
* For example:
|
|
411
|
+
* - "Product"
|
|
412
|
+
* @function
|
|
413
|
+
* @param {String} [value=""]
|
|
414
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
415
|
+
* @example displayPropertyName("Product")
|
|
416
|
+
*/ this.displayPropertyName = function(value) {
|
|
417
|
+
this.description.getDisplayNameForPropertyName = createNameExtractFunction(value, this.description);
|
|
418
|
+
if (isSpecifiedString(value)) return this;
|
|
419
|
+
this.description.getDisplayNameForPropertyName = removeArrayValuePropertyPostfixFunction(this.description.getDisplayNameForPropertyName);
|
|
420
|
+
this.description.getDisplayNameForPropertyName = upperCaseFirstLetterForFunction(this.description.getDisplayNameForPropertyName);
|
|
421
|
+
return this;
|
|
422
|
+
};
|
|
423
|
+
/**
|
|
424
|
+
* Overrides the (technical) field name of the property.
|
|
425
|
+
*
|
|
426
|
+
* If it is not set or set to "" then it will be derived from the
|
|
427
|
+
* last part of original property name.
|
|
428
|
+
*
|
|
429
|
+
* For example:
|
|
430
|
+
* - "product"
|
|
431
|
+
* @function
|
|
432
|
+
* @param {String} [value=""]
|
|
433
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
434
|
+
* @example fieldName("product")
|
|
435
|
+
*/ this.fieldName = function(value) {
|
|
436
|
+
this.description.getFieldNameForPropertyName = createNameExtractFunction(value, this.description);
|
|
437
|
+
return this;
|
|
438
|
+
};
|
|
439
|
+
/**
|
|
440
|
+
* Sets the name of the property, that contains grouped entries.
|
|
441
|
+
*
|
|
442
|
+
* @function
|
|
443
|
+
* @param {String} [value=""]
|
|
444
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
445
|
+
* @example groupName("details")
|
|
446
|
+
*/ this.groupName = function(value) {
|
|
447
|
+
this.description.groupName = withDefault(value, "");
|
|
448
|
+
return this;
|
|
449
|
+
};
|
|
450
|
+
/**
|
|
451
|
+
* Sets the pattern that describes how to group entries.
|
|
452
|
+
*
|
|
453
|
+
* "groupName" defines the name of this group.
|
|
454
|
+
* A pattern may contain variables in double curly brackets {{variable}}.
|
|
455
|
+
* @function
|
|
456
|
+
* @param {String} [value=""]
|
|
457
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
458
|
+
* @example groupPattern("{{type}}-{{category}}")
|
|
459
|
+
*/ this.groupPattern = function(value) {
|
|
460
|
+
this.description.groupPattern = withDefault(value, "");
|
|
461
|
+
return this;
|
|
462
|
+
};
|
|
463
|
+
/**
|
|
464
|
+
* Sets the pattern that describes where the group should be moved to.
|
|
465
|
+
*
|
|
466
|
+
* Default=""=Group will not be moved.
|
|
467
|
+
* A pattern may contain variables in double curly brackets {{variable}}.
|
|
468
|
+
* @function
|
|
469
|
+
* @param {String} [value=""]
|
|
470
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
471
|
+
* @example groupDestinationPattern("main-{{category}}")
|
|
472
|
+
*/ this.groupDestinationPattern = function(value) {
|
|
473
|
+
this.description.groupDestinationPattern = withDefault(value, "");
|
|
474
|
+
return this;
|
|
475
|
+
};
|
|
476
|
+
/**
|
|
477
|
+
* Sets the name of the group when it had been moved to the destination.
|
|
478
|
+
*
|
|
479
|
+
* The default value is the groupName, which will be used when the value is not valid (null or empty)
|
|
480
|
+
* @function
|
|
481
|
+
* @param {String} [value=""]
|
|
482
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
483
|
+
* @example groupDestinationPattern("options")
|
|
484
|
+
*/ this.groupDestinationName = function(value) {
|
|
485
|
+
this.description.groupDestinationName = withDefault(value, this.description.groupName);
|
|
486
|
+
return this;
|
|
487
|
+
};
|
|
488
|
+
/**
|
|
489
|
+
* Sets the pattern to be used to remove duplicate entries.
|
|
490
|
+
*
|
|
491
|
+
* A pattern may contain variables in double curly brackets {{variable}}.
|
|
492
|
+
* A pattern may contain variables in double curly brackets {{variable}}.
|
|
493
|
+
* @function
|
|
494
|
+
* @param {String} [value=""]
|
|
495
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
496
|
+
* @example deduplicationPattern("{{category}}--{{type}}--{{index[0]}}--{{index[1]}}--{{fieldName}}")
|
|
497
|
+
*/ this.deduplicationPattern = function(value) {
|
|
498
|
+
this.description.deduplicationPattern = withDefault(value, "");
|
|
499
|
+
return this;
|
|
500
|
+
};
|
|
501
|
+
/**
|
|
502
|
+
* Finalizes the settings and builds the PropertyStructureDescription.
|
|
503
|
+
* @function
|
|
504
|
+
* @returns {module:datarestructor.PropertyStructureDescription}
|
|
505
|
+
*/ this.build = function() {
|
|
506
|
+
this.description.matchesPropertyName = createFunctionMatchesPropertyName(this.description);
|
|
507
|
+
if (this.description.getDisplayNameForPropertyName == null) this.displayPropertyName("");
|
|
508
|
+
if (this.description.getFieldNameForPropertyName == null) this.fieldName("");
|
|
509
|
+
if (this.description.groupDestinationName == null) this.groupDestinationName("");
|
|
510
|
+
return this.description;
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
function createNameExtractFunction(value, description) {
|
|
514
|
+
if (isSpecifiedString(value)) return function() {
|
|
515
|
+
return value;
|
|
516
|
+
};
|
|
517
|
+
if (description.propertyPatternTemplateMode) {
|
|
518
|
+
var patternToMatch = description.propertyPattern; // closure (closed over) parameter
|
|
519
|
+
return extractNameUsingTemplatePattern(patternToMatch);
|
|
520
|
+
}
|
|
521
|
+
return extractNameUsingRightMostPropertyNameElement();
|
|
522
|
+
}
|
|
523
|
+
function createFunctionMatchesPropertyName(description) {
|
|
524
|
+
var propertyPatternToMatch = description.propertyPattern; // closure (closed over) parameter
|
|
525
|
+
if (!isSpecifiedString(propertyPatternToMatch)) return function() {
|
|
526
|
+
return false; // Without a propertyPattern, no property will match (deactivated mark/identify).
|
|
527
|
+
};
|
|
528
|
+
if (description.propertyPatternTemplateMode) return function(propertyNameWithoutArrayIndices) {
|
|
529
|
+
return templateModePatternRegexForPattern(propertyPatternToMatch).exec(propertyNameWithoutArrayIndices) != null;
|
|
530
|
+
};
|
|
531
|
+
return function(propertyNameWithoutArrayIndices) {
|
|
532
|
+
return propertyNameWithoutArrayIndices === propertyPatternToMatch;
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
function rightMostPropertyNameElement(propertyName) {
|
|
536
|
+
var regularExpression = new RegExp("(\\w+)$", "gi");
|
|
537
|
+
var match = propertyName.match(regularExpression);
|
|
538
|
+
if (match != null) return match[0];
|
|
539
|
+
return propertyName;
|
|
540
|
+
}
|
|
541
|
+
function upperCaseFirstLetter(value) {
|
|
542
|
+
if (value.length > 1) return value.charAt(0).toUpperCase() + value.slice(1);
|
|
565
543
|
return value;
|
|
566
|
-
};
|
|
567
544
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
545
|
+
function upperCaseFirstLetterForFunction(nameExtractFunction) {
|
|
546
|
+
return function(propertyName) {
|
|
547
|
+
return upperCaseFirstLetter(nameExtractFunction(propertyName));
|
|
548
|
+
};
|
|
572
549
|
}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
return function () {
|
|
580
|
-
return false;
|
|
581
|
-
};
|
|
550
|
+
function removeArrayValuePropertyPostfixFunction(nameExtractFunction) {
|
|
551
|
+
return function(propertyName) {
|
|
552
|
+
var name = nameExtractFunction(propertyName);
|
|
553
|
+
name = name != null ? name : "";
|
|
554
|
+
return name.replace("_comma_separated_values", "");
|
|
555
|
+
};
|
|
582
556
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
557
|
+
function extractNameUsingTemplatePattern(propertyPattern) {
|
|
558
|
+
return function(propertyName) {
|
|
559
|
+
var regex = templateModePatternRegexForPatternAndVariable(propertyPattern, "{{fieldName}}");
|
|
560
|
+
var match = regex.exec(propertyName);
|
|
561
|
+
if (match && match[1] != "") return match[1];
|
|
562
|
+
return rightMostPropertyNameElement(propertyName);
|
|
563
|
+
};
|
|
587
564
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
function rightMostPropertyNameElement(propertyName) {
|
|
593
|
-
var regularExpression = new RegExp("(\\w+)$", "gi");
|
|
594
|
-
var match = propertyName.match(regularExpression);
|
|
595
|
-
if (match != null) {
|
|
596
|
-
return match[0];
|
|
565
|
+
function extractNameUsingRightMostPropertyNameElement() {
|
|
566
|
+
return function(propertyName) {
|
|
567
|
+
return rightMostPropertyNameElement(propertyName);
|
|
568
|
+
};
|
|
597
569
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
if (value.length > 1) {
|
|
602
|
-
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
570
|
+
function templateModePatternRegexForPattern(propertyPatternToUse) {
|
|
571
|
+
var placeholderInDoubleCurlyBracketsRegEx = new RegExp("\\\\\\{\\\\\\{[-\\w]+\\\\\\}\\\\\\}", "gi");
|
|
572
|
+
return templateModePatternRegexForPatternAndVariable(propertyPatternToUse, placeholderInDoubleCurlyBracketsRegEx);
|
|
603
573
|
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
}
|
|
611
|
-
function removeArrayValuePropertyPostfixFunction(nameExtractFunction) {
|
|
612
|
-
return function (propertyName) {
|
|
613
|
-
var name = nameExtractFunction(propertyName);
|
|
614
|
-
name = name != null ? name : "";
|
|
615
|
-
return name.replace("_comma_separated_values", "");
|
|
616
|
-
};
|
|
617
|
-
}
|
|
618
|
-
function extractNameUsingTemplatePattern(propertyPattern) {
|
|
619
|
-
return function (propertyName) {
|
|
620
|
-
var regex = templateModePatternRegexForPatternAndVariable(propertyPattern, "{{fieldName}}");
|
|
621
|
-
var match = regex.exec(propertyName);
|
|
622
|
-
if (match && match[1] != "") {
|
|
623
|
-
return match[1];
|
|
624
|
-
}
|
|
625
|
-
return rightMostPropertyNameElement(propertyName);
|
|
626
|
-
};
|
|
627
|
-
}
|
|
628
|
-
function extractNameUsingRightMostPropertyNameElement() {
|
|
629
|
-
return function (propertyName) {
|
|
630
|
-
return rightMostPropertyNameElement(propertyName);
|
|
631
|
-
};
|
|
632
|
-
}
|
|
633
|
-
function templateModePatternRegexForPattern(propertyPatternToUse) {
|
|
634
|
-
var placeholderInDoubleCurlyBracketsRegEx = new RegExp("\\\\\\{\\\\\\{[-\\w]+\\\\\\}\\\\\\}", "gi");
|
|
635
|
-
return templateModePatternRegexForPatternAndVariable(propertyPatternToUse, placeholderInDoubleCurlyBracketsRegEx);
|
|
636
|
-
}
|
|
637
|
-
function templateModePatternRegexForPatternAndVariable(propertyPatternToUse, variablePattern) {
|
|
638
|
-
var pattern = escapeCharsForRegEx(propertyPatternToUse);
|
|
639
|
-
if (typeof variablePattern === "string") {
|
|
640
|
-
variablePattern = escapeCharsForRegEx(variablePattern);
|
|
574
|
+
function templateModePatternRegexForPatternAndVariable(propertyPatternToUse, variablePattern) {
|
|
575
|
+
var pattern = escapeCharsForRegEx(propertyPatternToUse);
|
|
576
|
+
if (typeof variablePattern === "string") variablePattern = escapeCharsForRegEx(variablePattern);
|
|
577
|
+
pattern = pattern.replace(variablePattern, "([-\\w]+)");
|
|
578
|
+
pattern = "^" + pattern;
|
|
579
|
+
return new RegExp(pattern, "i");
|
|
641
580
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
function isSpecifiedString(value) {
|
|
654
|
-
return typeof value === "string" && value != null && value != "";
|
|
655
|
-
}
|
|
656
|
-
return PropertyStructureDescription;
|
|
581
|
+
function escapeCharsForRegEx(characters) {
|
|
582
|
+
var nonWordCharactersRegEx = new RegExp("([^-\\w])", "gi");
|
|
583
|
+
return characters.replace(nonWordCharactersRegEx, "\\$1");
|
|
584
|
+
}
|
|
585
|
+
function withDefault(value, defaultValue) {
|
|
586
|
+
return isSpecifiedString(value) ? value : defaultValue;
|
|
587
|
+
}
|
|
588
|
+
function isSpecifiedString(value) {
|
|
589
|
+
return typeof value === "string" && value != null && value != "";
|
|
590
|
+
}
|
|
591
|
+
return PropertyStructureDescription;
|
|
657
592
|
})();
|
|
658
593
|
/**
|
|
659
|
-
* Adds a group item/entry to the {@link module:datarestructor.DescribedEntry}.
|
|
660
|
-
*
|
|
661
|
-
* @callback module:datarestructor.addGroupEntryFunction
|
|
662
|
-
* @param {String} groupName name of the group that should be added
|
|
663
|
-
* @param {module:datarestructor.DescribedEntry} describedEntry entry that should be added to the group
|
|
664
|
-
*/
|
|
665
|
-
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
* @
|
|
669
|
-
* @param {
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
* @
|
|
674
|
-
* @property {string}
|
|
675
|
-
* @property {string}
|
|
676
|
-
* @property {string}
|
|
677
|
-
* @property {string}
|
|
678
|
-
* @property {string}
|
|
679
|
-
* @property {string}
|
|
680
|
-
* @property {string}
|
|
681
|
-
* @property {
|
|
682
|
-
* @property {
|
|
683
|
-
* @property {
|
|
684
|
-
* @property {
|
|
685
|
-
* @property {
|
|
686
|
-
* @property {
|
|
687
|
-
* @property {string} _identifier.
|
|
688
|
-
* @property {string} _identifier.
|
|
689
|
-
* @property {string} _identifier.
|
|
690
|
-
* @property {string} _identifier.
|
|
691
|
-
* @property {string} _identifier.
|
|
692
|
-
* @property {
|
|
693
|
-
|
|
694
|
-
*
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
*
|
|
698
|
-
*
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
* @returns {String} field value
|
|
702
|
-
*/
|
|
703
|
-
datarestructor.DescribedEntryCreator = (function () {
|
|
704
|
-
"use strict";
|
|
705
|
-
var removeArrayBracketsRegEx = new RegExp("\\[\\d+\\]", "gi");
|
|
706
|
-
/**
|
|
707
|
-
* Creates a {@link module:datarestructor.DescribedEntry}.
|
|
708
|
-
* @constructs DescribedEntryCreator
|
|
709
|
-
* @alias module:datarestructor.DescribedEntryCreator
|
|
710
|
-
*/
|
|
711
|
-
function DescribedEntry(entry, description) {
|
|
712
|
-
var indices = indicesOf(entry.name);
|
|
713
|
-
var propertyNameWithoutArrayIndices = entry.name.replace(removeArrayBracketsRegEx, "");
|
|
714
|
-
var templateResolver = new template_resolver.Resolver(this);
|
|
715
|
-
this.category = description.category;
|
|
716
|
-
this.type = description.type;
|
|
717
|
-
this.abbreviation = description.abbreviation;
|
|
718
|
-
this.image = description.image;
|
|
594
|
+
* Adds a group item/entry to the {@link module:datarestructor.DescribedEntry}.
|
|
595
|
+
*
|
|
596
|
+
* @callback module:datarestructor.addGroupEntryFunction
|
|
597
|
+
* @param {String} groupName name of the group that should be added
|
|
598
|
+
* @param {module:datarestructor.DescribedEntry} describedEntry entry that should be added to the group
|
|
599
|
+
*/ /**
|
|
600
|
+
* Adds some group items/entries to the {@link module:datarestructor.DescribedEntry}.
|
|
601
|
+
*
|
|
602
|
+
* @callback module:datarestructor.addGroupEntriesFunction
|
|
603
|
+
* @param {String} groupName name of the group that should be added
|
|
604
|
+
* @param {module:datarestructor.DescribedEntry[]} describedEntry entries that should be added to the group
|
|
605
|
+
*/ /**
|
|
606
|
+
* @typedef {Object} module:datarestructor.DescribedEntry
|
|
607
|
+
* @property {string} category - category of the result from the PropertyStructureDescription using a short name or e.g. a symbol character
|
|
608
|
+
* @property {string} type - type of the result from PropertyStructureDescription
|
|
609
|
+
* @property {string} [abbreviation=""] - one optional character, a symbol character or a short abbreviation of the category
|
|
610
|
+
* @property {string} [image=""] - one optional path to an image resource
|
|
611
|
+
* @property {string} index - array of numbers containing the split index. Example: "responses[2].hits.hits[4]._source.name" leads to an array with the two elements: [2,4]
|
|
612
|
+
* @property {string} displayName - display name extracted from the point separated hierarchical property name, e.g. "Name"
|
|
613
|
+
* @property {string} fieldName - field name extracted from the point separated hierarchical property name, e.g. "name"
|
|
614
|
+
* @property {string} value - content of the field
|
|
615
|
+
* @property {string[]} groupNames - array of names of all dynamically added properties representing groups
|
|
616
|
+
* @property {module:datarestructor.addGroupEntryFunction} addGroupEntry - function, that adds an entry to the given group. If the group does not exist, it will be created.
|
|
617
|
+
* @property {module:datarestructor.addGroupEntriesFunction} addGroupEntries - function, that adds entries to the given group. If the group does not exist, it will be created.
|
|
618
|
+
* @property {boolean} _isMatchingIndex - true, when _identifier.index matches the described "indexStartsWith"
|
|
619
|
+
* @property {Object} _identifier - internal structure for identifier. Avoid using it outside since it may change.
|
|
620
|
+
* @property {string} _identifier.index - array indices in hierarchical order separated by points, e.g. "0.0"
|
|
621
|
+
* @property {string} _identifier.value - the (single) value of the "flattened" property, e.g. "Smith"
|
|
622
|
+
* @property {string} _identifier.propertyNameWithArrayIndices - the "original" flattened property name in hierarchical order separated by points, e.g. "responses[0].hits.hits[0]._source.name"
|
|
623
|
+
* @property {string} _identifier.propertyNameWithoutArrayIndices - same as propertyNamesWithArrayIndices but without array indices, e.g. "responses.hits.hits._source.name"
|
|
624
|
+
* @property {string} _identifier.groupId - Contains the resolved groupPattern from the PropertyStructureDescription. Entries with the same id will be grouped into the "groupName" of the PropertyStructureDescription.
|
|
625
|
+
* @property {string} _identifier.groupDestinationId - Contains the resolved groupDestinationPattern from the PropertyStructureDescription. Entries with this id will be moved to the given destination group.
|
|
626
|
+
* @property {string} _identifier.deduplicationId - Contains the resolved deduplicationPattern from the PropertyStructureDescription. Entries with the same id will be considered to be a duplicate and hence removed.
|
|
627
|
+
* @property {Object} _description - PropertyStructureDescription for internal use. Avoid using it outside since it may change.
|
|
628
|
+
*/ /**
|
|
629
|
+
* Returns a field value of the given {@link module:datarestructor.DescribedEntry}.
|
|
630
|
+
*
|
|
631
|
+
* @callback module:datarestructor.stringFieldOfDescribedEntryFunction
|
|
632
|
+
* @param {module:datarestructor.DescribedEntry} entry described entry that contains the field that should be returned
|
|
633
|
+
* @returns {String} field value
|
|
634
|
+
*/ datarestructor.DescribedEntryCreator = (function() {
|
|
635
|
+
var removeArrayBracketsRegEx = new RegExp("\\[\\d+\\]", "gi");
|
|
719
636
|
/**
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
637
|
+
* Creates a {@link module:datarestructor.DescribedEntry}.
|
|
638
|
+
* @constructs DescribedEntryCreator
|
|
639
|
+
* @alias module:datarestructor.DescribedEntryCreator
|
|
640
|
+
*/ function DescribedEntry(entry, description) {
|
|
641
|
+
var indices = indicesOf(entry.name);
|
|
642
|
+
var propertyNameWithoutArrayIndices = entry.name.replace(removeArrayBracketsRegEx, "");
|
|
643
|
+
var templateResolver = new template_resolver.Resolver(this);
|
|
644
|
+
this.category = description.category;
|
|
645
|
+
this.type = description.type;
|
|
646
|
+
this.abbreviation = description.abbreviation;
|
|
647
|
+
this.image = description.image;
|
|
648
|
+
/**
|
|
649
|
+
* Array of numbers containing the split index.
|
|
650
|
+
* Example: "responses[2].hits.hits[4]._source.name" leads to an array with two elements: [2,4]
|
|
651
|
+
* This is the public version of the internal variable _identifier.index, which contains in contrast all index elements in one point separated string (e.g. "2.4").
|
|
652
|
+
* @type {number[]}
|
|
653
|
+
*/ this.index = indices.numberArray;
|
|
654
|
+
this.displayName = description.getDisplayNameForPropertyName(propertyNameWithoutArrayIndices);
|
|
655
|
+
this.fieldName = description.getFieldNameForPropertyName(propertyNameWithoutArrayIndices);
|
|
656
|
+
this.value = entry.value;
|
|
657
|
+
this.groupNames = [];
|
|
658
|
+
this._isMatchingIndex = indices.pointDelimited.indexOf(description.indexStartsWith) == 0;
|
|
659
|
+
this._description = description;
|
|
660
|
+
this._identifier = {
|
|
661
|
+
index: indices.pointDelimited,
|
|
662
|
+
propertyNameWithArrayIndices: entry.name,
|
|
663
|
+
propertyNameWithoutArrayIndices: propertyNameWithoutArrayIndices,
|
|
664
|
+
groupId: "",
|
|
665
|
+
groupDestinationId: "",
|
|
666
|
+
deduplicationId: ""
|
|
667
|
+
};
|
|
668
|
+
this._identifier.groupId = templateResolver.replaceResolvableFields(description.groupPattern, templateResolver.resolvableFieldsOfAll(this, this._description, this._identifier));
|
|
669
|
+
this._identifier.groupDestinationId = templateResolver.replaceResolvableFields(description.groupDestinationPattern, templateResolver.resolvableFieldsOfAll(this, this._description, this._identifier));
|
|
670
|
+
this._identifier.deduplicationId = templateResolver.replaceResolvableFields(description.deduplicationPattern, templateResolver.resolvableFieldsOfAll(this, this._description, this._identifier));
|
|
671
|
+
/**
|
|
672
|
+
* Adds an entry to the given group. If the group does not exist, it will be created.
|
|
673
|
+
* @param {String} groupName name of the group that should be added
|
|
674
|
+
* @param {module:datarestructor.DescribedEntry} describedEntry entry that should be added to the group
|
|
675
|
+
*/ this.addGroupEntry = function(groupName, describedEntry) {
|
|
676
|
+
this.addGroupEntries(groupName, [
|
|
677
|
+
describedEntry
|
|
678
|
+
]);
|
|
679
|
+
};
|
|
680
|
+
/**
|
|
681
|
+
* Adds entries to the given group. If the group does not exist, it will be created.
|
|
682
|
+
* @param {String} groupName
|
|
683
|
+
* @param {module:datarestructor.DescribedEntry[]} describedEntries
|
|
684
|
+
*/ this.addGroupEntries = function(groupName, describedEntries) {
|
|
685
|
+
if (!this[groupName]) {
|
|
686
|
+
this.groupNames.push(groupName);
|
|
687
|
+
this[groupName] = [];
|
|
688
|
+
}
|
|
689
|
+
var index;
|
|
690
|
+
var describedEntry;
|
|
691
|
+
for(index = 0; index < describedEntries.length; index += 1){
|
|
692
|
+
describedEntry = describedEntries[index];
|
|
693
|
+
this[groupName].push(describedEntry);
|
|
694
|
+
}
|
|
695
|
+
};
|
|
696
|
+
}
|
|
743
697
|
/**
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
698
|
+
* @typedef {Object} module:datarestructor.ExtractedIndices
|
|
699
|
+
* @property {string} pointDelimited - bracket indices separated by points
|
|
700
|
+
* @property {number[]} numberArray as array of numbers
|
|
701
|
+
*/ /**
|
|
702
|
+
* Returns "1.12.123" and [1,12,123] for "results[1].hits.hits[12].aggregates[123]".
|
|
703
|
+
*
|
|
704
|
+
* @param {String} fullPropertyName
|
|
705
|
+
* @return {module:datarestructor.ExtractedIndices} extracted indices in different representations
|
|
706
|
+
* @protected
|
|
707
|
+
* @memberof module:datarestructor.DescribedEntryCreator
|
|
708
|
+
*/ function indicesOf(fullPropertyName) {
|
|
709
|
+
var arrayBracketsRegEx = new RegExp("\\[(\\d+)\\]", "gi");
|
|
710
|
+
return indicesOfWithRegex(fullPropertyName, arrayBracketsRegEx);
|
|
711
|
+
}
|
|
751
712
|
/**
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
* @param {String} fullPropertyName
|
|
778
|
-
* @return {module:datarestructor.ExtractedIndices} extracted indices in different representations
|
|
779
|
-
* @protected
|
|
780
|
-
* @memberof module:datarestructor.DescribedEntryCreator
|
|
781
|
-
*/
|
|
782
|
-
function indicesOf(fullPropertyName) {
|
|
783
|
-
var arrayBracketsRegEx = new RegExp("\\[(\\d+)\\]", "gi");
|
|
784
|
-
return indicesOfWithRegex(fullPropertyName, arrayBracketsRegEx);
|
|
785
|
-
}
|
|
786
|
-
/**
|
|
787
|
-
* Returns "1.12.123" and [1,12,123] for "results[1].hits.hits[12].aggregates[123]".
|
|
788
|
-
*
|
|
789
|
-
* @param {string} fullPropertyName
|
|
790
|
-
* @param {RegExp} regexWithOneNumberGroup
|
|
791
|
-
* @return {module:datarestructor.ExtractedIndices} extracted indices in different representations
|
|
792
|
-
* @protected
|
|
793
|
-
* @memberof module:datarestructor.DescribedEntryCreator
|
|
794
|
-
*/
|
|
795
|
-
function indicesOfWithRegex(fullPropertyName, regexWithOneNumberGroup) {
|
|
796
|
-
var pointDelimited = "";
|
|
797
|
-
var numberArray = [];
|
|
798
|
-
var match;
|
|
799
|
-
do {
|
|
800
|
-
match = regexWithOneNumberGroup.exec(fullPropertyName);
|
|
801
|
-
if (match) {
|
|
802
|
-
if (pointDelimited.length > 0) {
|
|
803
|
-
pointDelimited += ".";
|
|
804
|
-
}
|
|
805
|
-
pointDelimited += match[1];
|
|
806
|
-
numberArray.push(parseInt(match[1]));
|
|
807
|
-
}
|
|
808
|
-
} while (match);
|
|
809
|
-
return {
|
|
810
|
-
pointDelimited: pointDelimited,
|
|
811
|
-
numberArray: numberArray
|
|
812
|
-
};
|
|
813
|
-
}
|
|
814
|
-
return DescribedEntry;
|
|
713
|
+
* Returns "1.12.123" and [1,12,123] for "results[1].hits.hits[12].aggregates[123]".
|
|
714
|
+
*
|
|
715
|
+
* @param {string} fullPropertyName
|
|
716
|
+
* @param {RegExp} regexWithOneNumberGroup
|
|
717
|
+
* @return {module:datarestructor.ExtractedIndices} extracted indices in different representations
|
|
718
|
+
* @protected
|
|
719
|
+
* @memberof module:datarestructor.DescribedEntryCreator
|
|
720
|
+
*/ function indicesOfWithRegex(fullPropertyName, regexWithOneNumberGroup) {
|
|
721
|
+
var pointDelimited = "";
|
|
722
|
+
var numberArray = [];
|
|
723
|
+
var match;
|
|
724
|
+
do {
|
|
725
|
+
match = regexWithOneNumberGroup.exec(fullPropertyName);
|
|
726
|
+
if (match) {
|
|
727
|
+
if (pointDelimited.length > 0) pointDelimited += ".";
|
|
728
|
+
pointDelimited += match[1];
|
|
729
|
+
numberArray.push(parseInt(match[1]));
|
|
730
|
+
}
|
|
731
|
+
}while (match)
|
|
732
|
+
return {
|
|
733
|
+
pointDelimited: pointDelimited,
|
|
734
|
+
numberArray: numberArray
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
return DescribedEntry;
|
|
815
738
|
})();
|
|
816
739
|
/**
|
|
817
|
-
* @typedef {Object} module:datarestructor.TransformConfig
|
|
818
|
-
* @property {boolean} debugMode enables/disables detailed logging
|
|
819
|
-
* @property {number} [maxRecursionDepth=8] Maximum recursion depth
|
|
820
|
-
* @property {number} [removeDuplicationAboveRecursionDepth=1] Duplications will be removed above the given recursion depth value and remain unchanged below it.
|
|
821
|
-
*/
|
|
822
|
-
datarestructor.Transform = (function () {
|
|
823
|
-
"use strict";
|
|
824
|
-
/**
|
|
825
|
-
* Main class for the data transformation.
|
|
826
|
-
* @param {module:datarestructor.PropertyStructureDescription[]} descriptions
|
|
827
|
-
* @constructs Transform
|
|
828
|
-
* @alias module:datarestructor.Transform
|
|
829
|
-
*/
|
|
830
|
-
function Transform(descriptions) {
|
|
831
|
-
/**
|
|
832
|
-
* Descriptions of the input data that define the behaviour of the transformation.
|
|
833
|
-
* @type {module:datarestructor.DescribedEntry[]}
|
|
834
|
-
*/
|
|
835
|
-
this.descriptions = descriptions;
|
|
836
|
-
/**
|
|
837
|
-
* Configuration for the transformation.
|
|
838
|
-
* @protected
|
|
839
|
-
* @type {module:datarestructor.TransformConfig}
|
|
840
|
-
*/
|
|
841
|
-
this.config = {
|
|
842
|
-
/**
|
|
843
|
-
* Debug mode switch, that enables/disables detailed logging.
|
|
844
|
-
* @protected
|
|
845
|
-
* @type {boolean}
|
|
846
|
-
*/
|
|
847
|
-
debugMode: false,
|
|
848
|
-
/**
|
|
849
|
-
* Maximum recursion depth. Defaults to 8.
|
|
850
|
-
* @protected
|
|
851
|
-
* @type {number}
|
|
852
|
-
*/
|
|
853
|
-
maxRecursionDepth: 8,
|
|
854
|
-
/**
|
|
855
|
-
* Duplications will be removed above the given recursion depth and remain below it.
|
|
856
|
-
* Defaults to 1.
|
|
857
|
-
*
|
|
858
|
-
* Since fields can contain groups of fields that can contain groups of fields..., cyclic
|
|
859
|
-
* data structures are possible by nature and will lead to duplications. Some of them
|
|
860
|
-
* might be intended e.g. to take one (sub-)field with all (duplicated) groups.
|
|
861
|
-
* To restrict duplications and improve performance it is beneficial to define a
|
|
862
|
-
* recursion depth, above which further duplication won't be used and should be removed/avoided.
|
|
863
|
-
*
|
|
864
|
-
* @protected
|
|
865
|
-
* @type {number}
|
|
866
|
-
*/
|
|
867
|
-
removeDuplicationAboveRecursionDepth: 1
|
|
868
|
-
};
|
|
740
|
+
* @typedef {Object} module:datarestructor.TransformConfig
|
|
741
|
+
* @property {boolean} debugMode enables/disables detailed logging
|
|
742
|
+
* @property {number} [maxRecursionDepth=8] Maximum recursion depth
|
|
743
|
+
* @property {number} [removeDuplicationAboveRecursionDepth=1] Duplications will be removed above the given recursion depth value and remain unchanged below it.
|
|
744
|
+
*/ datarestructor.Transform = (function() {
|
|
869
745
|
/**
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
console.log("describedData data:");
|
|
954
|
-
console.log(processedData);
|
|
746
|
+
* Main class for the data transformation.
|
|
747
|
+
* @param {module:datarestructor.PropertyStructureDescription[]} descriptions
|
|
748
|
+
* @constructs Transform
|
|
749
|
+
* @alias module:datarestructor.Transform
|
|
750
|
+
*/ function Transform(descriptions) {
|
|
751
|
+
/**
|
|
752
|
+
* Descriptions of the input data that define the behaviour of the transformation.
|
|
753
|
+
* @type {module:datarestructor.DescribedEntry[]}
|
|
754
|
+
*/ this.descriptions = descriptions;
|
|
755
|
+
/**
|
|
756
|
+
* Configuration for the transformation.
|
|
757
|
+
* @protected
|
|
758
|
+
* @type {module:datarestructor.TransformConfig}
|
|
759
|
+
*/ this.config = {
|
|
760
|
+
/**
|
|
761
|
+
* Debug mode switch, that enables/disables detailed logging.
|
|
762
|
+
* @protected
|
|
763
|
+
* @type {boolean}
|
|
764
|
+
*/ debugMode: false,
|
|
765
|
+
/**
|
|
766
|
+
* Maximum recursion depth. Defaults to 8.
|
|
767
|
+
* @protected
|
|
768
|
+
* @type {number}
|
|
769
|
+
*/ maxRecursionDepth: 8,
|
|
770
|
+
/**
|
|
771
|
+
* Duplications will be removed above the given recursion depth and remain below it.
|
|
772
|
+
* Defaults to 1.
|
|
773
|
+
*
|
|
774
|
+
* Since fields can contain groups of fields that can contain groups of fields..., cyclic
|
|
775
|
+
* data structures are possible by nature and will lead to duplications. Some of them
|
|
776
|
+
* might be intended e.g. to take one (sub-)field with all (duplicated) groups.
|
|
777
|
+
* To restrict duplications and improve performance it is beneficial to define a
|
|
778
|
+
* recursion depth, above which further duplication won't be used and should be removed/avoided.
|
|
779
|
+
*
|
|
780
|
+
* @protected
|
|
781
|
+
* @type {number}
|
|
782
|
+
*/ removeDuplicationAboveRecursionDepth: 1
|
|
783
|
+
};
|
|
784
|
+
/**
|
|
785
|
+
* Enables debug mode. Logs additional information.
|
|
786
|
+
* @returns {module:datarestructor.Transform}
|
|
787
|
+
*/ this.enableDebugMode = function() {
|
|
788
|
+
this.config.debugMode = true;
|
|
789
|
+
return this;
|
|
790
|
+
};
|
|
791
|
+
/**
|
|
792
|
+
* Sets the maximum recursion depth. Defaults to 8 if not set.
|
|
793
|
+
* @param {number} value non negative number.
|
|
794
|
+
* @returns {module:datarestructor.Transform}
|
|
795
|
+
*/ this.setMaxRecursionDepth = function(value) {
|
|
796
|
+
if (typeof value !== "number" || value < 0) throw "Invalid max recursion depth value: " + value;
|
|
797
|
+
this.config.maxRecursionDepth = value;
|
|
798
|
+
return this;
|
|
799
|
+
};
|
|
800
|
+
/**
|
|
801
|
+
* Sets the recursion depth above which duplication will be removed. Duplications below it remain unchanged.
|
|
802
|
+
* Defaults to 1.
|
|
803
|
+
*
|
|
804
|
+
* Since fields can contain groups of fields that can contain groups of fields..., cyclic
|
|
805
|
+
* data structures are possible by nature and will lead to duplications. Some of them
|
|
806
|
+
* might be intended e.g. to take one (sub-)field with all (duplicated) groups.
|
|
807
|
+
* To restrict duplications and improve performance it is beneficial to define a
|
|
808
|
+
* recursion depth, above which further duplication won't be used and should be removed/avoided.
|
|
809
|
+
*
|
|
810
|
+
* @param {number} value non negative number.
|
|
811
|
+
* @returns {module:datarestructor.Transform}
|
|
812
|
+
*/ this.setRemoveDuplicationAboveRecursionDepth = function(value) {
|
|
813
|
+
if (typeof value !== "number" || value < 0) throw "Invalid remove duplications above recursion depth value: " + value;
|
|
814
|
+
this.config.removeDuplicationAboveRecursionDepth = value;
|
|
815
|
+
return this;
|
|
816
|
+
};
|
|
817
|
+
/**
|
|
818
|
+
* "Assembly line", that takes the (pared JSON) data and processes it using all given descriptions in their given order.
|
|
819
|
+
* @param {object} data - parsed JSON data or any other data object
|
|
820
|
+
* @returns {module:datarestructor.DescribedEntry[]}
|
|
821
|
+
* @example
|
|
822
|
+
* var allDescriptions = [];
|
|
823
|
+
* allDescriptions.push(summariesDescription());
|
|
824
|
+
* allDescriptions.push(detailsDescription());
|
|
825
|
+
* var result = new datarestructor.Transform(allDescriptions).processJson(jsonData);
|
|
826
|
+
*/ this.processJson = function(data) {
|
|
827
|
+
return processJsonUsingDescriptions(data, this.descriptions, this.config);
|
|
828
|
+
};
|
|
955
829
|
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
830
|
+
/**
|
|
831
|
+
* "Assembly line", that takes the jsonData and processes it using all given descriptions in their given order.
|
|
832
|
+
* @param {object} jsonData parsed JSON data or any other data object
|
|
833
|
+
* @param {module:datarestructor.PropertyStructureDescription[]} descriptions - already grouped entries
|
|
834
|
+
* @param {module:datarestructor.TransformConfig} config configuration for the data transformation
|
|
835
|
+
* @returns {module:datarestructor.DescribedEntry[]}
|
|
836
|
+
* @protected
|
|
837
|
+
* @memberof module:datarestructor.Transform
|
|
838
|
+
*/ function processJsonUsingDescriptions(jsonData, descriptions, config) {
|
|
839
|
+
// "Flatten" the hierarchical input json to an array of property names (point separated "folders") and values.
|
|
840
|
+
var processedData = internal_object_tools.flattenToArray(jsonData);
|
|
841
|
+
// Fill in properties ending with the name "_comma_separated_values" for array values to make it easier to display them.
|
|
842
|
+
processedData = fillInArrayValues(processedData);
|
|
843
|
+
if (config.debugMode) {
|
|
844
|
+
console.log("flattened data with array values:");
|
|
845
|
+
console.log(processedData);
|
|
846
|
+
}
|
|
847
|
+
// Mark, identify and harmonize the flattened data by applying one description after another in their given order.
|
|
848
|
+
var describedData = [];
|
|
849
|
+
var descriptionIndex, description, dataWithDescription;
|
|
850
|
+
for(descriptionIndex = 0; descriptionIndex < descriptions.length; descriptionIndex += 1){
|
|
851
|
+
description = descriptions[descriptionIndex];
|
|
852
|
+
// Filter all entries that match the current description and enrich them with it
|
|
853
|
+
dataWithDescription = extractEntriesByDescription(processedData, description);
|
|
854
|
+
// Remove duplicate entries where a deduplicationPattern is described
|
|
855
|
+
describedData = deduplicateFlattenedData(describedData, dataWithDescription);
|
|
856
|
+
}
|
|
857
|
+
processedData = describedData;
|
|
858
|
+
if (config.debugMode) {
|
|
859
|
+
console.log("describedData data:");
|
|
860
|
+
console.log(processedData);
|
|
861
|
+
}
|
|
862
|
+
// Group entries where a groupPattern is described
|
|
863
|
+
processedData = groupFlattenedData(processedData);
|
|
864
|
+
if (config.debugMode) {
|
|
865
|
+
console.log("grouped describedData data:");
|
|
866
|
+
console.log(processedData);
|
|
867
|
+
}
|
|
868
|
+
// Move group entries where a groupDestinationPattern is described
|
|
869
|
+
processedData = applyGroupDestinationPattern(processedData);
|
|
870
|
+
if (config.debugMode) {
|
|
871
|
+
console.log("moved grouped describedData data:");
|
|
872
|
+
console.log(processedData);
|
|
873
|
+
}
|
|
874
|
+
// Turns the grouped object back into an array of DescribedEntry-Objects
|
|
875
|
+
processedData = propertiesAsArray(processedData);
|
|
876
|
+
// Converts the internal described entries into described fields
|
|
877
|
+
processedData = toDescribedFields(processedData, config);
|
|
878
|
+
if (config.debugMode) {
|
|
879
|
+
console.log("transformed result:");
|
|
880
|
+
console.log(processedData);
|
|
881
|
+
}
|
|
882
|
+
return processedData;
|
|
967
883
|
}
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
884
|
+
/**
|
|
885
|
+
* Takes two arrays of objects, e.g. [{id: B, value: 2},{id: C, value: 3}]
|
|
886
|
+
* and [{id: A, value: 1},{id: B, value: 4}] and merges them into one:
|
|
887
|
+
* [{id: C, value: 3},{id: A, value: 1},{id: B, value: 4}]
|
|
888
|
+
*
|
|
889
|
+
* Entries with the same id ("duplicates") will be overwritten.
|
|
890
|
+
* Only the last element with the same id remains. The order is
|
|
891
|
+
* determined by the order of the array elements, whereas the first
|
|
892
|
+
* array comes before the second one. This means, that entries with the
|
|
893
|
+
* same id in the second array overwrite entries in the first array,
|
|
894
|
+
* and entries that occur later in the array overwrite earlier ones,
|
|
895
|
+
* if they have the same id.
|
|
896
|
+
*
|
|
897
|
+
* The id is extracted from every element using the given function.
|
|
898
|
+
*
|
|
899
|
+
* @param {module:datarestructor.DescribedEntry[]} entries
|
|
900
|
+
* @param {module:datarestructor.DescribedEntry[]} entriesToMerge
|
|
901
|
+
* @param {module:datarestructor.stringFieldOfDescribedEntryFunction} idOfElementFunction returns the id of an DescribedEntry
|
|
902
|
+
* @protected
|
|
903
|
+
* @memberof module:datarestructor.Transform
|
|
904
|
+
*/ function mergeFlattenedData(entries, entriesToMerge, idOfElementFunction) {
|
|
905
|
+
var entriesToMergeById = asIdBasedObject(entriesToMerge, idOfElementFunction);
|
|
906
|
+
var merged = [];
|
|
907
|
+
var index, entry, id;
|
|
908
|
+
for(index = 0; index < entries.length; index += 1){
|
|
909
|
+
entry = entries[index];
|
|
910
|
+
id = idOfElementFunction(entry);
|
|
911
|
+
if (id == null || id === "" || entriesToMergeById[id] == null) merged.push(entry);
|
|
912
|
+
}
|
|
913
|
+
for(index = 0; index < entriesToMerge.length; index += 1){
|
|
914
|
+
entry = entriesToMerge[index];
|
|
915
|
+
merged.push(entry);
|
|
916
|
+
}
|
|
917
|
+
return merged;
|
|
975
918
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
id = idOfElementFunction(entry);
|
|
1006
|
-
if (id == null || id === "" || entriesToMergeById[id] == null) {
|
|
1007
|
-
merged.push(entry);
|
|
1008
|
-
}
|
|
919
|
+
/**
|
|
920
|
+
* Takes two arrays of objects, e.g. [{id: B, value: 2},{id: C, value: 3}]
|
|
921
|
+
* and [{id: A, value: 1},{id: B, value: 4}] and merges them into one:
|
|
922
|
+
* [{id: C, value: 3},{id: A, value: 1},{id: B, value: 4}]
|
|
923
|
+
*
|
|
924
|
+
* Entries with the same id ("duplicates") will be overwritten.
|
|
925
|
+
* Only the last element with the same id remains. The order is
|
|
926
|
+
* determined by the order of the array elements, whereas the first
|
|
927
|
+
* array comes before the second one. This means, that entries with the
|
|
928
|
+
* same id in the second array overwrite entries in the first array,
|
|
929
|
+
* and entries occurring later in the array overwrite earlier ones,
|
|
930
|
+
* if they have the same id.
|
|
931
|
+
*
|
|
932
|
+
* "entriesToMerge" will be returned directly, if "entries" is null or empty.
|
|
933
|
+
*
|
|
934
|
+
* The id is extracted from every element using their deduplication pattern (if available).
|
|
935
|
+
*
|
|
936
|
+
* @param {module:datarestructor.DescribedEntry[]} entries
|
|
937
|
+
* @param {module:datarestructor.DescribedEntry[]} entriesToMerge
|
|
938
|
+
* @param {module:datarestructor.stringFieldOfDescribedEntryFunction} idOfElementFunction returns the id of an DescribedEntry
|
|
939
|
+
* @see mergeFlattenedData
|
|
940
|
+
* @protected
|
|
941
|
+
* @memberof module:datarestructor.Transform
|
|
942
|
+
*/ function deduplicateFlattenedData(entries, entriesToMerge) {
|
|
943
|
+
if (entries == null || entries.length == 0) return entriesToMerge;
|
|
944
|
+
var idOfElementFunction = function(entry) {
|
|
945
|
+
return entry._identifier.deduplicationId;
|
|
946
|
+
};
|
|
947
|
+
return mergeFlattenedData(entries, entriesToMerge, idOfElementFunction);
|
|
1009
948
|
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
949
|
+
/**
|
|
950
|
+
* Converts the given elements to an object, that provides these
|
|
951
|
+
* entries by their id. For example, [{id: A, value: 1}] becomes
|
|
952
|
+
* result['A'] = 1.
|
|
953
|
+
* @param {module:datarestructor.DescribedEntry[]} elements of DescribedEntry elements
|
|
954
|
+
* @param {module:datarestructor.stringFieldOfDescribedEntryFunction} idOfElementFunction returns the id of an DescribedEntry
|
|
955
|
+
* @return {module:datarestructor.DescribedEntry[] entries indexed by id
|
|
956
|
+
* @protected
|
|
957
|
+
* @memberof module:datarestructor.Transform
|
|
958
|
+
*/ function asIdBasedObject(elements, idOfElementFunction) {
|
|
959
|
+
var idIndexedObject = new Object();
|
|
960
|
+
for(var index = 0; index < elements.length; index++){
|
|
961
|
+
var element = elements[index];
|
|
962
|
+
idIndexedObject[idOfElementFunction(element)] = element;
|
|
963
|
+
}
|
|
964
|
+
return idIndexedObject;
|
|
1013
965
|
}
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
*
|
|
1033
|
-
* @param {module:datarestructor.DescribedEntry[]} entries
|
|
1034
|
-
* @param {module:datarestructor.DescribedEntry[]} entriesToMerge
|
|
1035
|
-
* @param {module:datarestructor.stringFieldOfDescribedEntryFunction} idOfElementFunction returns the id of an DescribedEntry
|
|
1036
|
-
* @see mergeFlattenedData
|
|
1037
|
-
* @protected
|
|
1038
|
-
* @memberof module:datarestructor.Transform
|
|
1039
|
-
*/
|
|
1040
|
-
function deduplicateFlattenedData(entries, entriesToMerge) {
|
|
1041
|
-
if (entries == null || entries.length == 0) {
|
|
1042
|
-
return entriesToMerge;
|
|
966
|
+
/**
|
|
967
|
+
* Converts the given elements into an object, that provides these
|
|
968
|
+
* entries by their id (determined by the entry's groupPattern).
|
|
969
|
+
* For example, [{id: A, value: 1}] becomes result['A'] = 1.
|
|
970
|
+
*
|
|
971
|
+
* Furthermore, this function creates a group property (determined by the entry's groupName)
|
|
972
|
+
* and collects all related elements (specified by their group pattern) in it.
|
|
973
|
+
*
|
|
974
|
+
* @param {module:datarestructor.DescribedEntry[]} elements of DescribedEntry elements
|
|
975
|
+
* @return {module:datarestructor.DescribedEntry[] entries indexed by id
|
|
976
|
+
* @protected
|
|
977
|
+
* @memberof module:datarestructor.Transform
|
|
978
|
+
*/ function groupFlattenedData(flattenedData) {
|
|
979
|
+
return groupById(flattenedData, function(entry) {
|
|
980
|
+
return entry._identifier.groupId;
|
|
981
|
+
}, function(entry) {
|
|
982
|
+
return entry._description.groupName;
|
|
983
|
+
});
|
|
1043
984
|
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
985
|
+
/**
|
|
986
|
+
* Converts the given elements into an object, that provides these
|
|
987
|
+
* entries by their id. For example, [{id: A, value: 1}] becomes
|
|
988
|
+
* result['A'] = 1. Furthermore, this function creates a group property (with the name )
|
|
989
|
+
* and collects all related elements (specified by their group pattern) in it.
|
|
990
|
+
*
|
|
991
|
+
* @param {module:datarestructor.DescribedEntry[]} elements of DescribedEntry elements
|
|
992
|
+
* @param {module:datarestructor.stringFieldOfDescribedEntryFunction} groupNameOfElementFunction function, that returns the name of the group property that will be created inside the "main" element.
|
|
993
|
+
* @param {module:datarestructor.stringFieldOfDescribedEntryFunction} groupIdOfElementFunction returns the group id of an DescribedEntry
|
|
994
|
+
* @return {module:datarestructor.DescribedEntry[] entries indexed by id
|
|
995
|
+
* @protected
|
|
996
|
+
* @memberof module:datarestructor.Transform
|
|
997
|
+
*/ function groupById(elements, groupIdOfElementFunction, groupNameOfElementFunction) {
|
|
998
|
+
var groupedResult = new Object();
|
|
999
|
+
for(var index = 0; index < elements.length; index++){
|
|
1000
|
+
var element = elements[index];
|
|
1001
|
+
var groupId = groupIdOfElementFunction(element);
|
|
1002
|
+
if (groupId === "") continue;
|
|
1003
|
+
var groupName = groupNameOfElementFunction(element);
|
|
1004
|
+
if (groupName == null || groupName === "") continue;
|
|
1005
|
+
if (!groupedResult[groupId]) groupedResult[groupId] = element;
|
|
1006
|
+
groupedResult[groupId].addGroupEntry(groupName, element);
|
|
1007
|
+
}
|
|
1008
|
+
return groupedResult;
|
|
1064
1009
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
});
|
|
1086
|
-
}
|
|
1087
|
-
/**
|
|
1088
|
-
* Converts the given elements into an object, that provides these
|
|
1089
|
-
* entries by their id. For example, [{id: A, value: 1}] becomes
|
|
1090
|
-
* result['A'] = 1. Furthermore, this function creates a group property (with the name )
|
|
1091
|
-
* and collects all related elements (specified by their group pattern) in it.
|
|
1092
|
-
*
|
|
1093
|
-
* @param {module:datarestructor.DescribedEntry[]} elements of DescribedEntry elements
|
|
1094
|
-
* @param {module:datarestructor.stringFieldOfDescribedEntryFunction} groupNameOfElementFunction function, that returns the name of the group property that will be created inside the "main" element.
|
|
1095
|
-
* @param {module:datarestructor.stringFieldOfDescribedEntryFunction} groupIdOfElementFunction returns the group id of an DescribedEntry
|
|
1096
|
-
* @return {module:datarestructor.DescribedEntry[] entries indexed by id
|
|
1097
|
-
* @protected
|
|
1098
|
-
* @memberof module:datarestructor.Transform
|
|
1099
|
-
*/
|
|
1100
|
-
function groupById(elements, groupIdOfElementFunction, groupNameOfElementFunction) {
|
|
1101
|
-
var groupedResult = new Object();
|
|
1102
|
-
for (var index = 0; index < elements.length; index++) {
|
|
1103
|
-
var element = elements[index];
|
|
1104
|
-
var groupId = groupIdOfElementFunction(element);
|
|
1105
|
-
if (groupId === "") {
|
|
1106
|
-
continue;
|
|
1107
|
-
}
|
|
1108
|
-
var groupName = groupNameOfElementFunction(element);
|
|
1109
|
-
if (groupName == null || groupName === "") {
|
|
1110
|
-
continue;
|
|
1111
|
-
}
|
|
1112
|
-
if (!groupedResult[groupId]) {
|
|
1113
|
-
groupedResult[groupId] = element;
|
|
1114
|
-
}
|
|
1115
|
-
groupedResult[groupId].addGroupEntry(groupName, element);
|
|
1010
|
+
/**
|
|
1011
|
+
* Extracts entries out of "flattened" JSON data and provides an array of objects.
|
|
1012
|
+
* @param {Object[]} flattenedData - flattened json from search query result
|
|
1013
|
+
* @param {string} flattenedData[].name - name of the property in hierarchical order separated by points
|
|
1014
|
+
* @param {string} flattenedData[].value - value of the property as string
|
|
1015
|
+
* @param {module:datarestructor.PropertyStructureDescription} - description of structure of the entries that should be extracted
|
|
1016
|
+
* @return {module:datarestructor.DescribedEntry[]}
|
|
1017
|
+
* @protected
|
|
1018
|
+
* @memberof module:datarestructor.Transform
|
|
1019
|
+
*/ function extractEntriesByDescription(flattenedData, description) {
|
|
1020
|
+
var removeArrayBracketsRegEx = new RegExp("\\[\\d+\\]", "gi");
|
|
1021
|
+
var filtered = [];
|
|
1022
|
+
flattenedData.filter(function(entry) {
|
|
1023
|
+
var propertyNameWithoutArrayIndices = entry.name.replace(removeArrayBracketsRegEx, "");
|
|
1024
|
+
if (description.matchesPropertyName(propertyNameWithoutArrayIndices)) {
|
|
1025
|
+
var describedEntry = new datarestructor.DescribedEntryCreator(entry, description);
|
|
1026
|
+
if (describedEntry._isMatchingIndex) filtered.push(describedEntry);
|
|
1027
|
+
}
|
|
1028
|
+
});
|
|
1029
|
+
return filtered;
|
|
1116
1030
|
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1031
|
+
/**
|
|
1032
|
+
* Takes already grouped {@link module:datarestructor.DescribedEntry} objects and
|
|
1033
|
+
* uses their "_identifier.groupDestinationId" (if exists)
|
|
1034
|
+
* to move groups to the given destination.
|
|
1035
|
+
*
|
|
1036
|
+
* This is useful, if separately described groups like "summary" and "detail" should be put together,
|
|
1037
|
+
* so that every summery contains a group with the regarding details.
|
|
1038
|
+
*
|
|
1039
|
+
* @param {module:datarestructor.DescribedEntry[]} groupedObject - already grouped entries
|
|
1040
|
+
* @return {module:datarestructor.DescribedEntry[]}
|
|
1041
|
+
* @protected
|
|
1042
|
+
* @memberof module:datarestructor.Transform
|
|
1043
|
+
*/ function applyGroupDestinationPattern(groupedObject) {
|
|
1044
|
+
var keys = Object.keys(groupedObject);
|
|
1045
|
+
var keysToDelete = [];
|
|
1046
|
+
for(var index = 0; index < keys.length; index++){
|
|
1047
|
+
var key = keys[index];
|
|
1048
|
+
var entry = groupedObject[key];
|
|
1049
|
+
if (entry._description.groupDestinationPattern != "") {
|
|
1050
|
+
var destinationKey = entry._identifier.groupDestinationId;
|
|
1051
|
+
if (groupedObject[destinationKey] != null) {
|
|
1052
|
+
var newGroup = entry[entry._description.groupName];
|
|
1053
|
+
groupedObject[destinationKey].addGroupEntries(entry._description.groupDestinationName, newGroup);
|
|
1054
|
+
keysToDelete.push(key);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1138
1057
|
}
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
/**
|
|
1144
|
-
* Takes already grouped {@link module:datarestructor.DescribedEntry} objects and
|
|
1145
|
-
* uses their "_identifier.groupDestinationId" (if exists)
|
|
1146
|
-
* to move groups to the given destination.
|
|
1147
|
-
*
|
|
1148
|
-
* This is useful, if separately described groups like "summary" and "detail" should be put together,
|
|
1149
|
-
* so that every summery contains a group with the regarding details.
|
|
1150
|
-
*
|
|
1151
|
-
* @param {module:datarestructor.DescribedEntry[]} groupedObject - already grouped entries
|
|
1152
|
-
* @return {module:datarestructor.DescribedEntry[]}
|
|
1153
|
-
* @protected
|
|
1154
|
-
* @memberof module:datarestructor.Transform
|
|
1155
|
-
*/
|
|
1156
|
-
function applyGroupDestinationPattern(groupedObject) {
|
|
1157
|
-
var keys = Object.keys(groupedObject);
|
|
1158
|
-
var keysToDelete = [];
|
|
1159
|
-
for (var index = 0; index < keys.length; index++) {
|
|
1160
|
-
var key = keys[index];
|
|
1161
|
-
var entry = groupedObject[key];
|
|
1162
|
-
if (entry._description.groupDestinationPattern != "") {
|
|
1163
|
-
var destinationKey = entry._identifier.groupDestinationId;
|
|
1164
|
-
if (groupedObject[destinationKey] != null) {
|
|
1165
|
-
var newGroup = entry[entry._description.groupName];
|
|
1166
|
-
groupedObject[destinationKey].addGroupEntries(entry._description.groupDestinationName, newGroup);
|
|
1167
|
-
keysToDelete.push(key);
|
|
1058
|
+
// delete all moved entries that had been collected by their key
|
|
1059
|
+
for(index = 0; index < keysToDelete.length; index += 1){
|
|
1060
|
+
var keyToDelete = keysToDelete[index];
|
|
1061
|
+
delete groupedObject[keyToDelete];
|
|
1168
1062
|
}
|
|
1169
|
-
|
|
1063
|
+
return groupedObject;
|
|
1170
1064
|
}
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1065
|
+
/**
|
|
1066
|
+
* Fills in extra "_comma_separated_values" properties into the flattened data
|
|
1067
|
+
* for properties that end with an array. E.g. response.hits.hits.tags[0]="active" and response.hits.hits.tags[0]="ready"
|
|
1068
|
+
* will lead to the extra element "response.hits.hits.tags_comma_separated_values="active, ready".
|
|
1069
|
+
*
|
|
1070
|
+
* @return flattened data with filled in "_comma_separated_values" properties
|
|
1071
|
+
* @protected
|
|
1072
|
+
* @memberof module:datarestructor.Transform
|
|
1073
|
+
*/ function fillInArrayValues(flattenedData) {
|
|
1074
|
+
var trailingArrayIndexRegEx = new RegExp("\\[\\d+\\]$", "gi");
|
|
1075
|
+
var result = [];
|
|
1076
|
+
var lastArrayProperty = "";
|
|
1077
|
+
var lastArrayPropertyValue = "";
|
|
1078
|
+
flattenedData.filter(function(entry) {
|
|
1079
|
+
if (!entry.name.match(trailingArrayIndexRegEx)) {
|
|
1080
|
+
if (lastArrayProperty !== "") {
|
|
1081
|
+
result.push({
|
|
1082
|
+
name: lastArrayProperty + "_comma_separated_values",
|
|
1083
|
+
value: lastArrayPropertyValue
|
|
1084
|
+
});
|
|
1085
|
+
lastArrayProperty = "";
|
|
1086
|
+
}
|
|
1087
|
+
result.push(entry);
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
var propertyNameWithoutTrailingArrayIndex = entry.name.replace(trailingArrayIndexRegEx, "");
|
|
1091
|
+
if (lastArrayProperty === propertyNameWithoutTrailingArrayIndex) lastArrayPropertyValue += ", " + entry.value;
|
|
1092
|
+
else {
|
|
1093
|
+
if (lastArrayProperty !== "") {
|
|
1094
|
+
result.push({
|
|
1095
|
+
name: lastArrayProperty + "_comma_separated_values",
|
|
1096
|
+
value: lastArrayPropertyValue
|
|
1097
|
+
});
|
|
1098
|
+
lastArrayProperty = "";
|
|
1099
|
+
}
|
|
1100
|
+
lastArrayProperty = propertyNameWithoutTrailingArrayIndex;
|
|
1101
|
+
lastArrayPropertyValue = entry.value;
|
|
1102
|
+
}
|
|
1103
|
+
result.push(entry);
|
|
1104
|
+
});
|
|
1105
|
+
return result;
|
|
1175
1106
|
}
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
* @return flattened data with filled in "_comma_separated_values" properties
|
|
1184
|
-
* @protected
|
|
1185
|
-
* @memberof module:datarestructor.Transform
|
|
1186
|
-
*/
|
|
1187
|
-
function fillInArrayValues(flattenedData) {
|
|
1188
|
-
var trailingArrayIndexRegEx = new RegExp("\\[\\d+\\]$", "gi");
|
|
1189
|
-
var result = [];
|
|
1190
|
-
var lastArrayProperty = "";
|
|
1191
|
-
var lastArrayPropertyValue = "";
|
|
1192
|
-
flattenedData.filter(function (entry) {
|
|
1193
|
-
if (!entry.name.match(trailingArrayIndexRegEx)) {
|
|
1194
|
-
if (lastArrayProperty !== "") {
|
|
1195
|
-
result.push({
|
|
1196
|
-
name: lastArrayProperty + "_comma_separated_values",
|
|
1197
|
-
value: lastArrayPropertyValue
|
|
1198
|
-
});
|
|
1199
|
-
lastArrayProperty = "";
|
|
1107
|
+
function propertiesAsArray(groupedData) {
|
|
1108
|
+
var result = [];
|
|
1109
|
+
var propertyNames = Object.keys(groupedData);
|
|
1110
|
+
for(var propertyIndex = 0; propertyIndex < propertyNames.length; propertyIndex++){
|
|
1111
|
+
var propertyName = propertyNames[propertyIndex];
|
|
1112
|
+
var propertyValue = groupedData[propertyName];
|
|
1113
|
+
result.push(propertyValue);
|
|
1200
1114
|
}
|
|
1201
|
-
result
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1115
|
+
return result;
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Converts described entries (internal data structure) to described fields (external data structure).
|
|
1119
|
+
* Since the structure of a described field is hierarchical, every field needs to be converted
|
|
1120
|
+
* in a recursive manner. The maximum recursion depth is taken as the second parameter.
|
|
1121
|
+
* @param {module:datarestructor.DescribedEntry[]} describedEntries
|
|
1122
|
+
* @param {module:datarestructor.TransformConfig} config configuration for the data transformation
|
|
1123
|
+
* @returns {module:described_field.DescribedDataField[]}
|
|
1124
|
+
* @protected
|
|
1125
|
+
* @memberof module:datarestructor.Transform
|
|
1126
|
+
*/ function toDescribedFields(describedEntries, config) {
|
|
1127
|
+
var result = [];
|
|
1128
|
+
var index;
|
|
1129
|
+
var describedEntity;
|
|
1130
|
+
for(index = 0; index < describedEntries.length; index += 1){
|
|
1131
|
+
describedEntity = describedEntries[index];
|
|
1132
|
+
result.push(toDescribedField(describedEntity, {
|
|
1133
|
+
recursionDepth: 0,
|
|
1134
|
+
config: config,
|
|
1135
|
+
groupToSkip: ""
|
|
1136
|
+
}));
|
|
1214
1137
|
}
|
|
1215
|
-
|
|
1216
|
-
lastArrayPropertyValue = entry.value;
|
|
1217
|
-
}
|
|
1218
|
-
result.push(entry);
|
|
1219
|
-
});
|
|
1220
|
-
return result;
|
|
1221
|
-
}
|
|
1222
|
-
function propertiesAsArray(groupedData) {
|
|
1223
|
-
var result = [];
|
|
1224
|
-
var propertyNames = Object.keys(groupedData);
|
|
1225
|
-
for (var propertyIndex = 0; propertyIndex < propertyNames.length; propertyIndex++) {
|
|
1226
|
-
var propertyName = propertyNames[propertyIndex];
|
|
1227
|
-
var propertyValue = groupedData[propertyName];
|
|
1228
|
-
result.push(propertyValue);
|
|
1138
|
+
return result;
|
|
1229
1139
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1140
|
+
/**
|
|
1141
|
+
* Describes the context type for the recursive DescribedDataField conversion,
|
|
1142
|
+
* that contains everything that needs to be accessible throughout recursion regardless of the
|
|
1143
|
+
* recursion depth.
|
|
1144
|
+
*
|
|
1145
|
+
* @typedef {Object} module:datarestructor.DescribedFieldRecursionContext
|
|
1146
|
+
* @param {number} recursionDepth current recursion depth
|
|
1147
|
+
* @param {String} groupToSkip name of a group to skip or "" when no group should be skipped.
|
|
1148
|
+
* @param {module:datarestructor.TransformConfig} config configuration for the data transformation
|
|
1149
|
+
*/ /**
|
|
1150
|
+
* Converts a internal described entry to a newly created public described field.
|
|
1151
|
+
* Since the structure of a described field is hierarchical, this function is called recursively.
|
|
1152
|
+
* Because the internal described entries may very likely contain cyclic references, the depth of recursion
|
|
1153
|
+
* needs to be limited. Therefore, the current recursion depth is taken as second parameter
|
|
1154
|
+
* and the maximum recursion depth is taken as third parameter.
|
|
1155
|
+
* @param {module:datarestructor.DescribedEntry} entry the internal entry that will be converted
|
|
1156
|
+
* @param {module:datarestructor.DescribedFieldRecursionContext} recursionContext context contains everything that needs to be accessible throughout the recursion.
|
|
1157
|
+
* @returns {module:described_field.DescribedDataField}
|
|
1158
|
+
* @protected
|
|
1159
|
+
* @memberof module:datarestructor.Transform
|
|
1160
|
+
*/ function toDescribedField(entry, recursionContext) {
|
|
1161
|
+
var field = new described_field.DescribedDataFieldBuilder().category(entry.category).type(entry.type).abbreviation(entry.abbreviation).image(entry.image).index(entry.index).displayName(entry.displayName).fieldName(entry.fieldName).value(entry.value).build();
|
|
1162
|
+
if (recursionContext.recursionDepth > recursionContext.config.maxRecursionDepth) return field;
|
|
1163
|
+
var nextRecursionContext = null;
|
|
1164
|
+
var duplicateGroupNameToSkip = "";
|
|
1165
|
+
var fieldGroups = new described_field.DescribedDataFieldGroup(field);
|
|
1166
|
+
forEachGroupEntry(entry, function(groupName, groupEntry, allGroupEntries) {
|
|
1167
|
+
if (recursionContext.groupToSkip === groupName) {
|
|
1168
|
+
if (recursionContext.config.debugMode) console.log("Removed duplicate group " + groupName + " at recursion depth " + recursionContext.recursionDepth);
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
duplicateGroupNameToSkip = "";
|
|
1172
|
+
if (recursionContext.recursionDepth >= recursionContext.config.removeDuplicationAboveRecursionDepth) duplicateGroupNameToSkip = arraysEqual(groupEntry[groupName], allGroupEntries, describedFieldEqual) ? groupName : "";
|
|
1173
|
+
nextRecursionContext = {
|
|
1174
|
+
recursionDepth: recursionContext.recursionDepth + 1,
|
|
1175
|
+
config: recursionContext.config,
|
|
1176
|
+
groupToSkip: duplicateGroupNameToSkip
|
|
1177
|
+
};
|
|
1178
|
+
fieldGroups.addGroupEntry(groupName, toDescribedField(groupEntry, nextRecursionContext));
|
|
1179
|
+
});
|
|
1180
|
+
return field;
|
|
1253
1181
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
/**
|
|
1257
|
-
* Describes the context type for the recursive DescribedDataField conversion,
|
|
1258
|
-
* that contains everything that needs to be accessible throughout recursion regardless of the
|
|
1259
|
-
* recursion depth.
|
|
1260
|
-
*
|
|
1261
|
-
* @typedef {Object} module:datarestructor.DescribedFieldRecursionContext
|
|
1262
|
-
* @param {number} recursionDepth current recursion depth
|
|
1263
|
-
* @param {String} groupToSkip name of a group to skip or "" when no group should be skipped.
|
|
1264
|
-
* @param {module:datarestructor.TransformConfig} config configuration for the data transformation
|
|
1265
|
-
*/
|
|
1266
|
-
/**
|
|
1267
|
-
* Converts a internal described entry to a newly created public described field.
|
|
1268
|
-
* Since the structure of a described field is hierarchical, this function is called recursively.
|
|
1269
|
-
* Because the internal described entries may very likely contain cyclic references, the depth of recursion
|
|
1270
|
-
* needs to be limited. Therefore, the current recursion depth is taken as second parameter
|
|
1271
|
-
* and the maximum recursion depth is taken as third parameter.
|
|
1272
|
-
* @param {module:datarestructor.DescribedEntry} entry the internal entry that will be converted
|
|
1273
|
-
* @param {module:datarestructor.DescribedFieldRecursionContext} recursionContext context contains everything that needs to be accessible throughout the recursion.
|
|
1274
|
-
* @returns {module:described_field.DescribedDataField}
|
|
1275
|
-
* @protected
|
|
1276
|
-
* @memberof module:datarestructor.Transform
|
|
1277
|
-
*/
|
|
1278
|
-
function toDescribedField(entry, recursionContext) {
|
|
1279
|
-
var field = new described_field.DescribedDataFieldBuilder().category(entry.category).type(entry.type).abbreviation(entry.abbreviation).image(entry.image).index(entry.index).displayName(entry.displayName).fieldName(entry.fieldName).value(entry.value).build();
|
|
1280
|
-
if (recursionContext.recursionDepth > recursionContext.config.maxRecursionDepth) {
|
|
1281
|
-
return field;
|
|
1182
|
+
function describedFieldEqual(a, b) {
|
|
1183
|
+
return defaultEmpty(a.category) === defaultEmpty(b.category) && defaultEmpty(a.type) === defaultEmpty(b.type) && a.fieldName === b.fieldName && a.value === b.value;
|
|
1282
1184
|
}
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
var fieldGroups = new described_field.DescribedDataFieldGroup(field);
|
|
1286
|
-
forEachGroupEntry(entry, function (groupName, groupEntry, allGroupEntries) {
|
|
1287
|
-
if (recursionContext.groupToSkip === groupName) {
|
|
1288
|
-
if (recursionContext.config.debugMode) {
|
|
1289
|
-
console.log("Removed duplicate group " + groupName + " at recursion depth " + recursionContext.recursionDepth);
|
|
1290
|
-
}
|
|
1291
|
-
return;
|
|
1292
|
-
}
|
|
1293
|
-
duplicateGroupNameToSkip = "";
|
|
1294
|
-
if (recursionContext.recursionDepth >= recursionContext.config.removeDuplicationAboveRecursionDepth) {
|
|
1295
|
-
duplicateGroupNameToSkip = arraysEqual(groupEntry[groupName], allGroupEntries, describedFieldEqual) ? groupName : "";
|
|
1296
|
-
}
|
|
1297
|
-
nextRecursionContext = {
|
|
1298
|
-
recursionDepth: recursionContext.recursionDepth + 1,
|
|
1299
|
-
config: recursionContext.config,
|
|
1300
|
-
groupToSkip: duplicateGroupNameToSkip
|
|
1301
|
-
};
|
|
1302
|
-
fieldGroups.addGroupEntry(groupName, toDescribedField(groupEntry, nextRecursionContext));
|
|
1303
|
-
});
|
|
1304
|
-
return field;
|
|
1305
|
-
}
|
|
1306
|
-
function describedFieldEqual(a, b) {
|
|
1307
|
-
return defaultEmpty(a.category) === defaultEmpty(b.category) && defaultEmpty(a.type) === defaultEmpty(b.type) && a.fieldName === b.fieldName && a.value === b.value;
|
|
1308
|
-
}
|
|
1309
|
-
function defaultEmpty(value) {
|
|
1310
|
-
return defaultValue(value, "");
|
|
1311
|
-
}
|
|
1312
|
-
function defaultValue(value, valueAsDefault) {
|
|
1313
|
-
if (typeof value === "undefined" || !value) {
|
|
1314
|
-
return valueAsDefault;
|
|
1185
|
+
function defaultEmpty(value) {
|
|
1186
|
+
return defaultValue(value, "");
|
|
1315
1187
|
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
// Added "elementEqualFunction" to implement equal object detection.
|
|
1320
|
-
// Arrays are assumed to be sorted. Differently ordered entries are treated as not equal.
|
|
1321
|
-
function arraysEqual(a, b, elementEqualFunction) {
|
|
1322
|
-
if (a === b) return true;
|
|
1323
|
-
if (a == null || b == null) return false;
|
|
1324
|
-
if (a.length !== b.length) return false;
|
|
1325
|
-
for (var i = 0; i < a.length; ++i) {
|
|
1326
|
-
if (!elementEqualFunction(a[i], b[i])) return false;
|
|
1188
|
+
function defaultValue(value, valueAsDefault) {
|
|
1189
|
+
if (typeof value === "undefined" || !value) return valueAsDefault;
|
|
1190
|
+
return value;
|
|
1327
1191
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
* Traverses through all groups and their entries and calls the given function on every found entry
|
|
1340
|
-
* with the group name and the entry itself as parameters.
|
|
1341
|
-
* @param {module:datarestructor.DescribedEntry} rootEntry
|
|
1342
|
-
* @param {module:datarestructor.onEntryFoundFunction} onFoundEntry
|
|
1343
|
-
* @protected
|
|
1344
|
-
* @memberof module:datarestructor.Transform
|
|
1345
|
-
*/
|
|
1346
|
-
function forEachGroupEntry(rootEntry, onFoundEntry) {
|
|
1347
|
-
var groupIndex, entryIndex;
|
|
1348
|
-
var groupName, entry;
|
|
1349
|
-
for (groupIndex = 0; groupIndex < rootEntry.groupNames.length; groupIndex += 1) {
|
|
1350
|
-
groupName = rootEntry.groupNames[groupIndex];
|
|
1351
|
-
for (entryIndex = 0; entryIndex < rootEntry[groupName].length; entryIndex += 1) {
|
|
1352
|
-
entry = rootEntry[groupName][entryIndex];
|
|
1353
|
-
onFoundEntry(groupName, entry, rootEntry[groupName]);
|
|
1354
|
-
}
|
|
1192
|
+
// Reference: https://stackoverflow.com/questions/3115982/how-to-check-if-two-arrays-are-equal-with-javascript/16430730
|
|
1193
|
+
// Added "elementEqualFunction" to implement equal object detection.
|
|
1194
|
+
// Arrays are assumed to be sorted. Differently ordered entries are treated as not equal.
|
|
1195
|
+
function arraysEqual(a, b, elementEqualFunction) {
|
|
1196
|
+
if (a === b) return true;
|
|
1197
|
+
if (a == null || b == null) return false;
|
|
1198
|
+
if (a.length !== b.length) return false;
|
|
1199
|
+
for(var i = 0; i < a.length; ++i){
|
|
1200
|
+
if (!elementEqualFunction(a[i], b[i])) return false;
|
|
1201
|
+
}
|
|
1202
|
+
return true;
|
|
1355
1203
|
}
|
|
1356
|
-
|
|
1357
|
-
|
|
1204
|
+
/**
|
|
1205
|
+
* Takes the full qualified original property name and extracts a simple name out of it.
|
|
1206
|
+
*
|
|
1207
|
+
* @callback module:datarestructor.onEntryFoundFunction
|
|
1208
|
+
* @param {string} groupName name of the group where the entry had been found.
|
|
1209
|
+
* @param {module:datarestructor.DescribedEntry} foundEntry the found entry itself.
|
|
1210
|
+
* @param {module:datarestructor.DescribedEntry[]} allEntries the array of all entries where the found entry is an element of.
|
|
1211
|
+
*/ /**
|
|
1212
|
+
* Traverses through all groups and their entries and calls the given function on every found entry
|
|
1213
|
+
* with the group name and the entry itself as parameters.
|
|
1214
|
+
* @param {module:datarestructor.DescribedEntry} rootEntry
|
|
1215
|
+
* @param {module:datarestructor.onEntryFoundFunction} onFoundEntry
|
|
1216
|
+
* @protected
|
|
1217
|
+
* @memberof module:datarestructor.Transform
|
|
1218
|
+
*/ function forEachGroupEntry(rootEntry, onFoundEntry) {
|
|
1219
|
+
var groupIndex, entryIndex;
|
|
1220
|
+
var groupName, entry;
|
|
1221
|
+
for(groupIndex = 0; groupIndex < rootEntry.groupNames.length; groupIndex += 1){
|
|
1222
|
+
groupName = rootEntry.groupNames[groupIndex];
|
|
1223
|
+
for(entryIndex = 0; entryIndex < rootEntry[groupName].length; entryIndex += 1){
|
|
1224
|
+
entry = rootEntry[groupName][entryIndex];
|
|
1225
|
+
onFoundEntry(groupName, entry, rootEntry[groupName]);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
return Transform;
|
|
1358
1230
|
})();
|
|
1359
1231
|
/**
|
|
1360
|
-
* Main fassade for the data restructor as static function(s).
|
|
1361
|
-
*
|
|
1362
|
-
* @example
|
|
1363
|
-
* var allDescriptions = [];
|
|
1364
|
-
* allDescriptions.push(summariesDescription());
|
|
1365
|
-
* allDescriptions.push(detailsDescription());
|
|
1366
|
-
* var result = datarestructor.Restructor.processJsonUsingDescriptions(jsonData, allDescriptions);
|
|
1367
|
-
* @namespace module:datarestructor.Restructor
|
|
1368
|
-
*/
|
|
1369
|
-
|
|
1232
|
+
* Main fassade for the data restructor as static function(s).
|
|
1233
|
+
*
|
|
1234
|
+
* @example
|
|
1235
|
+
* var allDescriptions = [];
|
|
1236
|
+
* allDescriptions.push(summariesDescription());
|
|
1237
|
+
* allDescriptions.push(detailsDescription());
|
|
1238
|
+
* var result = datarestructor.Restructor.processJsonUsingDescriptions(jsonData, allDescriptions);
|
|
1239
|
+
* @namespace module:datarestructor.Restructor
|
|
1240
|
+
*/ datarestructor.Restructor = {
|
|
1241
|
+
};
|
|
1370
1242
|
/**
|
|
1371
|
-
* Static fassade function for the "Assembly line", that takes the jsonData and processes it using all given descriptions in their given order.
|
|
1372
|
-
* @param {object} jsonData - parsed JSON data or any other data object
|
|
1373
|
-
* @param {module:datarestructor.PropertyStructureDescription[]} descriptions - already grouped entries
|
|
1374
|
-
* @param {boolean} debugMode - false=default=off, true=write additional logs for detailed debugging
|
|
1375
|
-
* @returns {module:datarestructor.DescribedEntry[]}
|
|
1376
|
-
* @memberof module:datarestructor.Restructor
|
|
1377
|
-
* @deprecated since v3.1.0, please use "new datarestructor.Transform(descriptions).processJson(jsonData)".
|
|
1378
|
-
*/
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
restructor.enableDebugMode();
|
|
1383
|
-
}
|
|
1384
|
-
return restructor.processJson(jsonData);
|
|
1243
|
+
* Static fassade function for the "Assembly line", that takes the jsonData and processes it using all given descriptions in their given order.
|
|
1244
|
+
* @param {object} jsonData - parsed JSON data or any other data object
|
|
1245
|
+
* @param {module:datarestructor.PropertyStructureDescription[]} descriptions - already grouped entries
|
|
1246
|
+
* @param {boolean} debugMode - false=default=off, true=write additional logs for detailed debugging
|
|
1247
|
+
* @returns {module:datarestructor.DescribedEntry[]}
|
|
1248
|
+
* @memberof module:datarestructor.Restructor
|
|
1249
|
+
* @deprecated since v3.1.0, please use "new datarestructor.Transform(descriptions).processJson(jsonData)".
|
|
1250
|
+
*/ datarestructor.Restructor.processJsonUsingDescriptions = function(jsonData, descriptions, debugMode) {
|
|
1251
|
+
var restructor = new datarestructor.Transform(descriptions);
|
|
1252
|
+
if (debugMode) restructor.enableDebugMode();
|
|
1253
|
+
return restructor.processJson(jsonData);
|
|
1385
1254
|
};
|
|
1386
1255
|
|
|
1387
|
-
},{"../../lib/js/flattenToArray":"
|
|
1256
|
+
},{"../../lib/js/flattenToArray":"ipjOk","../../src/js/templateResolver":"41qn9","../../src/js/describedfield":"cleYG"}],"ipjOk":[function(require,module,exports) {
|
|
1388
1257
|
"use strict";
|
|
1389
1258
|
/**
|
|
1390
|
-
* @fileOverview Modded (compatibility, recursion depth) version of: https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objectss
|
|
1391
|
-
* @version ${project.version}
|
|
1392
|
-
* @see {@link https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objectss|stackoverflow flatten nested json objects}
|
|
1393
|
-
*/
|
|
1394
|
-
|
|
1395
|
-
// Fallback for vanilla js without modules
|
|
1259
|
+
* @fileOverview Modded (compatibility, recursion depth) version of: https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objectss
|
|
1260
|
+
* @version ${project.version}
|
|
1261
|
+
* @see {@link https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objectss|stackoverflow flatten nested json objects}
|
|
1262
|
+
*/ var module = module || {
|
|
1263
|
+
}; // Fallback for vanilla js without modules
|
|
1396
1264
|
/**
|
|
1397
|
-
* internal_object_tools. Not meant to be used outside this repository.
|
|
1398
|
-
* @default {}
|
|
1399
|
-
*/
|
|
1400
|
-
|
|
1401
|
-
// Export module for npm...
|
|
1265
|
+
* internal_object_tools. Not meant to be used outside this repository.
|
|
1266
|
+
* @default {}
|
|
1267
|
+
*/ var internal_object_tools = module.exports = {
|
|
1268
|
+
}; // Export module for npm...
|
|
1402
1269
|
/**
|
|
1403
|
-
* @typedef {Object} NameValuePair
|
|
1404
|
-
* @property {string} name - point separated names of the flattened main and sub properties, e.g. "responses[2].hits.hits[4]._source.name".
|
|
1405
|
-
* @property {string} value - value of the property
|
|
1406
|
-
*/
|
|
1407
|
-
|
|
1408
|
-
* @param {
|
|
1409
|
-
* @
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
if (depth > maxRecursionDepth || typeof cur === "function") {
|
|
1419
|
-
return;
|
|
1420
|
-
}
|
|
1421
|
-
if (Object(cur) !== cur) {
|
|
1422
|
-
result.push({
|
|
1423
|
-
name: prop,
|
|
1424
|
-
value: cur
|
|
1425
|
-
});
|
|
1426
|
-
} else if (Array.isArray(cur)) {
|
|
1427
|
-
var i;
|
|
1428
|
-
var l = cur.length;
|
|
1429
|
-
for (i = 0; i < l; i += 1) {
|
|
1430
|
-
recurse(cur[i], prop + "[" + i + "]", depth + 1);
|
|
1431
|
-
}
|
|
1432
|
-
if (l === 0) {
|
|
1433
|
-
result[prop] = [];
|
|
1434
|
-
result.push({
|
|
1435
|
-
name: prop,
|
|
1436
|
-
value: ""
|
|
1437
|
-
});
|
|
1438
|
-
}
|
|
1439
|
-
} else {
|
|
1440
|
-
var isEmpty = true;
|
|
1441
|
-
var p;
|
|
1442
|
-
for (p in cur) {
|
|
1443
|
-
isEmpty = false;
|
|
1444
|
-
recurse(cur[p], prop ? prop + "." + p : p, depth + 1);
|
|
1445
|
-
}
|
|
1446
|
-
if (isEmpty && prop) {
|
|
1447
|
-
result.push({
|
|
1448
|
-
name: prop,
|
|
1449
|
-
value: ""
|
|
1270
|
+
* @typedef {Object} NameValuePair
|
|
1271
|
+
* @property {string} name - point separated names of the flattened main and sub properties, e.g. "responses[2].hits.hits[4]._source.name".
|
|
1272
|
+
* @property {string} value - value of the property
|
|
1273
|
+
*/ /**
|
|
1274
|
+
* @param {object} data hierarchical object that may consist fo fields, subfields and arrays.
|
|
1275
|
+
* @param {number} maxRecursionDepth
|
|
1276
|
+
* @returns {NameValuePair[]} array of property name and value pairs
|
|
1277
|
+
*/ internal_object_tools.flattenToArray = function(data, maxRecursionDepth) {
|
|
1278
|
+
var result = [];
|
|
1279
|
+
if (typeof maxRecursionDepth !== "number" || maxRecursionDepth < 1) maxRecursionDepth = 20;
|
|
1280
|
+
function recurse(cur, prop, depth) {
|
|
1281
|
+
if (depth > maxRecursionDepth || typeof cur === "function") return;
|
|
1282
|
+
if (Object(cur) !== cur) result.push({
|
|
1283
|
+
name: prop,
|
|
1284
|
+
value: cur
|
|
1450
1285
|
});
|
|
1451
|
-
|
|
1286
|
+
else if (Array.isArray(cur)) {
|
|
1287
|
+
var i;
|
|
1288
|
+
var l = cur.length;
|
|
1289
|
+
for(i = 0; i < l; i += 1)recurse(cur[i], prop + "[" + i + "]", depth + 1);
|
|
1290
|
+
if (l === 0) {
|
|
1291
|
+
result[prop] = [];
|
|
1292
|
+
result.push({
|
|
1293
|
+
name: prop,
|
|
1294
|
+
value: ""
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
} else {
|
|
1298
|
+
var isEmpty = true;
|
|
1299
|
+
var p;
|
|
1300
|
+
for(p in cur){
|
|
1301
|
+
isEmpty = false;
|
|
1302
|
+
recurse(cur[p], prop ? prop + "." + p : p, depth + 1);
|
|
1303
|
+
}
|
|
1304
|
+
if (isEmpty && prop) result.push({
|
|
1305
|
+
name: prop,
|
|
1306
|
+
value: ""
|
|
1307
|
+
});
|
|
1308
|
+
}
|
|
1452
1309
|
}
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
return result;
|
|
1310
|
+
recurse(data, "", 0);
|
|
1311
|
+
return result;
|
|
1456
1312
|
};
|
|
1457
1313
|
|
|
1458
|
-
},{}],"
|
|
1314
|
+
},{}],"41qn9":[function(require,module,exports) {
|
|
1459
1315
|
/**
|
|
1460
|
-
* @file Provides a simple template resolver, that replaces variables in double curly brackets with the values of a given object.
|
|
1461
|
-
* @version {@link https://github.com/JohT/data-restructor-js/releases/latest latest version}
|
|
1462
|
-
* @author JohT
|
|
1463
|
-
* @version ${project.version}
|
|
1464
|
-
*/
|
|
1465
|
-
|
|
1466
|
-
var module = templateResolverInternalCreateIfNotExists(module);
|
|
1467
|
-
// Fallback for vanilla js without modules
|
|
1316
|
+
* @file Provides a simple template resolver, that replaces variables in double curly brackets with the values of a given object.
|
|
1317
|
+
* @version {@link https://github.com/JohT/data-restructor-js/releases/latest latest version}
|
|
1318
|
+
* @author JohT
|
|
1319
|
+
* @version ${project.version}
|
|
1320
|
+
*/ "use strict";
|
|
1321
|
+
var module = templateResolverInternalCreateIfNotExists(module); // Fallback for vanilla js without modules
|
|
1468
1322
|
function templateResolverInternalCreateIfNotExists(objectToCheck) {
|
|
1469
|
-
|
|
1323
|
+
return objectToCheck || {
|
|
1324
|
+
};
|
|
1470
1325
|
}
|
|
1471
1326
|
/**
|
|
1472
|
-
* Provides a simple template resolver, that replaces variables in double curly brackets with the values of a given object.
|
|
1473
|
-
* @module template_resolver
|
|
1474
|
-
*/
|
|
1475
|
-
|
|
1476
|
-
// Export module for npm...
|
|
1327
|
+
* Provides a simple template resolver, that replaces variables in double curly brackets with the values of a given object.
|
|
1328
|
+
* @module template_resolver
|
|
1329
|
+
*/ var template_resolver = module.exports = {
|
|
1330
|
+
}; // Export module for npm...
|
|
1477
1331
|
template_resolver.internalCreateIfNotExists = templateResolverInternalCreateIfNotExists;
|
|
1478
|
-
var internal_object_tools = internal_object_tools || require("../../lib/js/flattenToArray");
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
var removeArrayBracketsRegEx = new RegExp("\\[\\d+\\]", "gi");
|
|
1482
|
-
/**
|
|
1483
|
-
* Resolver. Is used inside this repository. It could also be used outside.
|
|
1484
|
-
* @param {*} sourceDataObject The properties of this object will be used to replace the placeholders in the template.
|
|
1485
|
-
* @constructs Resolver
|
|
1486
|
-
* @alias module:template_resolver.Resolver
|
|
1487
|
-
*/
|
|
1488
|
-
function Resolver(sourceDataObject) {
|
|
1489
|
-
/**
|
|
1490
|
-
* The properties of this source data object will be used to replace the placeholders in the template.
|
|
1491
|
-
*/
|
|
1492
|
-
this.sourceDataObject = sourceDataObject;
|
|
1493
|
-
/**
|
|
1494
|
-
* Resolves the given template.
|
|
1495
|
-
*
|
|
1496
|
-
* The template may contain variables in double curly brackets.
|
|
1497
|
-
* Supported variables are all properties of this object, e.g. "{{fieldName}}", "{{displayName}}", "{{value}}".
|
|
1498
|
-
* Since this object may also contains (described) groups of sub objects, they can also be used, e.g. "{{summaries[0].value}}"
|
|
1499
|
-
* Parts of the index can be inserted by using e.g. "{{index[1]}}".
|
|
1500
|
-
*
|
|
1501
|
-
* @param {string} template
|
|
1502
|
-
* @returns {string} resolved template
|
|
1503
|
-
*/
|
|
1504
|
-
this.resolveTemplate = function (template) {
|
|
1505
|
-
return this.replaceResolvableFields(template, addFieldsPerGroup(this.resolvableFieldsOfAll(this.sourceDataObject)));
|
|
1506
|
-
};
|
|
1507
|
-
/**
|
|
1508
|
-
* Returns a map like object, that contains all resolvable fields and their values as properties.
|
|
1509
|
-
* This function takes a variable count of input parameters,
|
|
1510
|
-
* each containing an object that contains resolvable fields to extract from.
|
|
1511
|
-
*
|
|
1512
|
-
* The recursion depth is limited to 3, so that an object,
|
|
1513
|
-
* that contains an object can contain another object (but not further).
|
|
1514
|
-
*
|
|
1515
|
-
* Properties beginning with an underscore in their name will be filtered out, since they are considered as internal fields.
|
|
1516
|
-
*
|
|
1517
|
-
* @param {...object} varArgs variable count of parameters. Each parameter contains an object that fields should be resolvable for variables.
|
|
1518
|
-
* @returns {object} object with resolvable field names and their values.
|
|
1519
|
-
* @public
|
|
1520
|
-
*/
|
|
1521
|
-
this.resolvableFieldsOfAll = function () {
|
|
1522
|
-
var map = {};
|
|
1523
|
-
var ignoreInternalFields = function (propertyName) {
|
|
1524
|
-
return propertyName.indexOf("_") !== 0 && propertyName.indexOf("._") < 0;
|
|
1525
|
-
};
|
|
1526
|
-
var index;
|
|
1527
|
-
for (index = 0; index < arguments.length; index += 1) {
|
|
1528
|
-
addToFilteredMapObject(internal_object_tools.flattenToArray(arguments[index], 3), map, ignoreInternalFields);
|
|
1529
|
-
}
|
|
1530
|
-
return map;
|
|
1531
|
-
};
|
|
1332
|
+
var internal_object_tools = internal_object_tools || require("../../lib/js/flattenToArray"); // supports vanilla js & npm
|
|
1333
|
+
template_resolver.Resolver = (function() {
|
|
1334
|
+
var removeArrayBracketsRegEx = new RegExp("\\[\\d+\\]", "gi");
|
|
1532
1335
|
/**
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1336
|
+
* Resolver. Is used inside this repository. It could also be used outside.
|
|
1337
|
+
* @param {*} sourceDataObject The properties of this object will be used to replace the placeholders in the template.
|
|
1338
|
+
* @constructs Resolver
|
|
1339
|
+
* @alias module:template_resolver.Resolver
|
|
1340
|
+
*/ function Resolver(sourceDataObject) {
|
|
1341
|
+
/**
|
|
1342
|
+
* The properties of this source data object will be used to replace the placeholders in the template.
|
|
1343
|
+
*/ this.sourceDataObject = sourceDataObject;
|
|
1344
|
+
/**
|
|
1345
|
+
* Resolves the given template.
|
|
1346
|
+
*
|
|
1347
|
+
* The template may contain variables in double curly brackets.
|
|
1348
|
+
* Supported variables are all properties of this object, e.g. "{{fieldName}}", "{{displayName}}", "{{value}}".
|
|
1349
|
+
* Since this object may also contains (described) groups of sub objects, they can also be used, e.g. "{{summaries[0].value}}"
|
|
1350
|
+
* Parts of the index can be inserted by using e.g. "{{index[1]}}".
|
|
1351
|
+
*
|
|
1352
|
+
* @param {string} template
|
|
1353
|
+
* @returns {string} resolved template
|
|
1354
|
+
*/ this.resolveTemplate = function(template) {
|
|
1355
|
+
return this.replaceResolvableFields(template, addFieldsPerGroup(this.resolvableFieldsOfAll(this.sourceDataObject)));
|
|
1356
|
+
};
|
|
1357
|
+
/**
|
|
1358
|
+
* Returns a map like object, that contains all resolvable fields and their values as properties.
|
|
1359
|
+
* This function takes a variable count of input parameters,
|
|
1360
|
+
* each containing an object that contains resolvable fields to extract from.
|
|
1361
|
+
*
|
|
1362
|
+
* The recursion depth is limited to 3, so that an object,
|
|
1363
|
+
* that contains an object can contain another object (but not further).
|
|
1364
|
+
*
|
|
1365
|
+
* Properties beginning with an underscore in their name will be filtered out, since they are considered as internal fields.
|
|
1366
|
+
*
|
|
1367
|
+
* @param {...object} varArgs variable count of parameters. Each parameter contains an object that fields should be resolvable for variables.
|
|
1368
|
+
* @returns {object} object with resolvable field names and their values.
|
|
1369
|
+
* @public
|
|
1370
|
+
*/ this.resolvableFieldsOfAll = function() {
|
|
1371
|
+
var map = {
|
|
1372
|
+
};
|
|
1373
|
+
var ignoreInternalFields = function(propertyName) {
|
|
1374
|
+
return propertyName.indexOf("_") !== 0 && propertyName.indexOf("._") < 0;
|
|
1375
|
+
};
|
|
1376
|
+
var index;
|
|
1377
|
+
for(index = 0; index < arguments.length; index += 1)addToFilteredMapObject(internal_object_tools.flattenToArray(arguments[index], 3), map, ignoreInternalFields);
|
|
1378
|
+
return map;
|
|
1379
|
+
};
|
|
1380
|
+
/**
|
|
1381
|
+
* Replaces all variables in double curly brackets, e.g. {{property}},
|
|
1382
|
+
* with the value of that property from the resolvableProperties.
|
|
1383
|
+
*
|
|
1384
|
+
* Supported property types: string, number, boolean
|
|
1385
|
+
* @param {string} stringContainingVariables
|
|
1386
|
+
* @param {object[]} resolvableFields (name=value)
|
|
1387
|
+
*/ this.replaceResolvableFields = function(stringContainingVariables, resolvableFields) {
|
|
1388
|
+
var replaced = stringContainingVariables;
|
|
1389
|
+
var propertyNames = Object.keys(resolvableFields);
|
|
1390
|
+
var propertyIndex = 0;
|
|
1391
|
+
var propertyName = "";
|
|
1392
|
+
var propertyValue = "";
|
|
1393
|
+
for(propertyIndex = 0; propertyIndex < propertyNames.length; propertyIndex += 1){
|
|
1394
|
+
propertyName = propertyNames[propertyIndex];
|
|
1395
|
+
propertyValue = resolvableFields[propertyName];
|
|
1396
|
+
replaced = replaced.replace("{{" + propertyName + "}}", propertyValue);
|
|
1397
|
+
}
|
|
1398
|
+
return replaced;
|
|
1399
|
+
};
|
|
1576
1400
|
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1401
|
+
/**
|
|
1402
|
+
* Adds the value of the "fieldName" property (including its group prefix) and its associated "value" property content.
|
|
1403
|
+
* For example: detail[2].fieldName="name", detail[2].value="Smith" lead to the additional property detail.name="Smith".
|
|
1404
|
+
* @param {object} object with resolvable field names and their values.
|
|
1405
|
+
* @returns {object} object with resolvable field names and their values.
|
|
1406
|
+
* @protected
|
|
1407
|
+
* @memberof module:template_resolver.Resolver
|
|
1408
|
+
*/ function addFieldsPerGroup(map) {
|
|
1409
|
+
var propertyNames = Object.keys(map);
|
|
1410
|
+
var i, fullPropertyName, propertyInfo, propertyValue;
|
|
1411
|
+
for(i = 0; i < propertyNames.length; i += 1){
|
|
1412
|
+
fullPropertyName = propertyNames[i];
|
|
1413
|
+
propertyValue = map[fullPropertyName];
|
|
1414
|
+
propertyInfo = getPropertyNameInfos(fullPropertyName);
|
|
1415
|
+
// Supports fields that are defined by a property named "fieldName" (containing the name)
|
|
1416
|
+
// and a property named "value" inside the same sub object (containing its value).
|
|
1417
|
+
// Ignore custom fields that are named "fieldName"(propertyValue), since this would lead to an unpredictable behavior.
|
|
1418
|
+
// TODO could make "fieldName" and "value" configurable
|
|
1419
|
+
if (propertyInfo.name === "fieldName" && propertyValue !== "fieldName") map[propertyInfo.groupWithoutArrayIndices + propertyValue] = map[propertyInfo.group + "value"];
|
|
1420
|
+
}
|
|
1421
|
+
return map;
|
|
1591
1422
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1423
|
+
/**
|
|
1424
|
+
* Infos about the full property name including the name of the group (followed by the separator) and the name of the property itself.
|
|
1425
|
+
* @param {String} fullPropertyName
|
|
1426
|
+
* @returns {Object} Contains "group" (empty or group name including trailing separator "."), "groupWithoutArrayIndices" and "name" (property name).
|
|
1427
|
+
* @protected
|
|
1428
|
+
* @memberof module:template_resolver.Resolver
|
|
1429
|
+
*/ function getPropertyNameInfos(fullPropertyName) {
|
|
1430
|
+
var positionOfRightMostSeparator = fullPropertyName.lastIndexOf(".");
|
|
1431
|
+
var propertyName = fullPropertyName;
|
|
1432
|
+
if (positionOfRightMostSeparator > 0) propertyName = fullPropertyName.substr(positionOfRightMostSeparator + 1);
|
|
1433
|
+
var propertyGroup = "";
|
|
1434
|
+
if (positionOfRightMostSeparator > 0) propertyGroup = fullPropertyName.substr(0, positionOfRightMostSeparator + 1); //includes the trailing ".".
|
|
1435
|
+
var propertyGroupWithoutArrayIndices = propertyGroup.replace(removeArrayBracketsRegEx, "");
|
|
1436
|
+
return {
|
|
1437
|
+
group: propertyGroup,
|
|
1438
|
+
groupWithoutArrayIndices: propertyGroupWithoutArrayIndices,
|
|
1439
|
+
name: propertyName
|
|
1440
|
+
};
|
|
1595
1441
|
}
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
*/
|
|
1613
|
-
function addToFilteredMapObject(elements, mapObject, filterMatchesFunction) {
|
|
1614
|
-
var index, element;
|
|
1615
|
-
for (index = 0; index < elements.length; index += 1) {
|
|
1616
|
-
element = elements[index];
|
|
1617
|
-
if (typeof filterMatchesFunction === "function" && filterMatchesFunction(element.name)) {
|
|
1618
|
-
mapObject[element.name] = element.value;
|
|
1619
|
-
}
|
|
1442
|
+
/**
|
|
1443
|
+
* Collects all flattened name-value-pairs into one object using the property names as keys and their values as values (map-like).
|
|
1444
|
+
* Example: `{name: "accountNumber", value: "12345"}` becomes `mapObject["accountNumber"]="12345"`.
|
|
1445
|
+
*
|
|
1446
|
+
* @param {NameValuePair[]} elements flattened array of name-value-pairs
|
|
1447
|
+
* @param {object} mapObject container to collect the results. Needs to be created before e.g. using `{}`.
|
|
1448
|
+
* @param {function} filterMatchesFunction takes the property name as string argument and returns true (include) or false (exclude).
|
|
1449
|
+
* @protected
|
|
1450
|
+
* @memberof module:template_resolver.Resolver
|
|
1451
|
+
*/ function addToFilteredMapObject(elements, mapObject, filterMatchesFunction) {
|
|
1452
|
+
var index, element;
|
|
1453
|
+
for(index = 0; index < elements.length; index += 1){
|
|
1454
|
+
element = elements[index];
|
|
1455
|
+
if (typeof filterMatchesFunction === "function" && filterMatchesFunction(element.name)) mapObject[element.name] = element.value;
|
|
1456
|
+
}
|
|
1457
|
+
return mapObject;
|
|
1620
1458
|
}
|
|
1621
|
-
return
|
|
1622
|
-
}
|
|
1623
|
-
return Resolver;
|
|
1459
|
+
return Resolver;
|
|
1624
1460
|
})();
|
|
1625
1461
|
|
|
1626
|
-
},{"../../lib/js/flattenToArray":"
|
|
1462
|
+
},{"../../lib/js/flattenToArray":"ipjOk"}],"cleYG":[function(require,module,exports) {
|
|
1627
1463
|
/**
|
|
1628
|
-
* @file Describes a data field of the restructured data.
|
|
1629
|
-
* @version {@link https://github.com/JohT/data-restructor-js/releases/latest latest version}
|
|
1630
|
-
* @author JohT
|
|
1631
|
-
* @version ${project.version}
|
|
1632
|
-
*/
|
|
1633
|
-
|
|
1634
|
-
var module = describedFieldInternalCreateIfNotExists(module);
|
|
1635
|
-
// Fallback for vanilla js without modules
|
|
1464
|
+
* @file Describes a data field of the restructured data.
|
|
1465
|
+
* @version {@link https://github.com/JohT/data-restructor-js/releases/latest latest version}
|
|
1466
|
+
* @author JohT
|
|
1467
|
+
* @version ${project.version}
|
|
1468
|
+
*/ "use strict";
|
|
1469
|
+
var module = describedFieldInternalCreateIfNotExists(module); // Fallback for vanilla js without modules
|
|
1636
1470
|
function describedFieldInternalCreateIfNotExists(objectToCheck) {
|
|
1637
|
-
|
|
1471
|
+
return objectToCheck || {
|
|
1472
|
+
};
|
|
1638
1473
|
}
|
|
1639
1474
|
/**
|
|
1640
|
-
* Describes a data field of the restructured data.
|
|
1641
|
-
* @module described_field
|
|
1642
|
-
*/
|
|
1643
|
-
|
|
1644
|
-
// Export module for npm...
|
|
1475
|
+
* Describes a data field of the restructured data.
|
|
1476
|
+
* @module described_field
|
|
1477
|
+
*/ var described_field = module.exports = {
|
|
1478
|
+
}; // Export module for npm...
|
|
1645
1479
|
described_field.internalCreateIfNotExists = describedFieldInternalCreateIfNotExists;
|
|
1646
1480
|
/**
|
|
1647
|
-
* Describes a field of the restructured data.
|
|
1648
|
-
* Dynamically added properties represent custom named groups containing DescribedDataField-Arrays.
|
|
1649
|
-
*
|
|
1650
|
-
* @typedef {Object} module:described_field.DescribedDataField
|
|
1651
|
-
* @property {string} [category=""] - name of the category. Could contain a short domain name like "product" or "vendor".
|
|
1652
|
-
* @property {string} [type=""] - type of the data element. Examples: "summary" for e.g. a list overview. "detail" e.g. when a summary is selected. "filter" e.g. for field/value pair results that can be selected as data filters.
|
|
1653
|
-
* @property {string} [abbreviation=""] - one optional character, a symbol character or a short abbreviation of the category
|
|
1654
|
-
* @property {string} [image=""] - one optional path to an image resource
|
|
1655
|
-
* @property {string} index - array of numbers containing the splitted index. Example: "responses[2].hits.hits[4]._source.name" will have an index of [2,4]
|
|
1656
|
-
* @property {string[]} groupNames - array of names of all dynamically added properties representing groups
|
|
1657
|
-
* @property {string} displayName - display name of the field
|
|
1658
|
-
* @property {string} fieldName - field name
|
|
1659
|
-
* @property {{*}} value - content of the field
|
|
1660
|
-
* @property {module:described_field.DescribedDataField[]} [couldBeAnyCustomGroupName] any number of groups attached to the field each containing multiple fields
|
|
1661
|
-
*/
|
|
1662
|
-
described_field.DescribedDataFieldBuilder = (function () {
|
|
1663
|
-
/**
|
|
1664
|
-
* Builds a {@link module:described_field.DescribedDataField}.
|
|
1665
|
-
* DescribedDataField is the main element of the restructured data and therefore considered "public".
|
|
1666
|
-
* @constructs DescribedDataFieldBuilder
|
|
1667
|
-
* @alias module:described_field.DescribedDataFieldBuilder
|
|
1668
|
-
*/
|
|
1669
|
-
function DescribedDataFieldBuilder() {
|
|
1670
|
-
/**
|
|
1671
|
-
* @type {module:described_field.DescribedDataField}
|
|
1672
|
-
*/
|
|
1673
|
-
this.describedField = {
|
|
1674
|
-
category: "",
|
|
1675
|
-
type: "",
|
|
1676
|
-
abbreviation: "",
|
|
1677
|
-
image: "",
|
|
1678
|
-
index: [],
|
|
1679
|
-
groupNames: [],
|
|
1680
|
-
displayName: "",
|
|
1681
|
-
fieldName: "",
|
|
1682
|
-
value: ""
|
|
1683
|
-
};
|
|
1684
|
-
/**
|
|
1685
|
-
* Takes over all values of the template {@link module:described_field.DescribedDataField}.
|
|
1686
|
-
* @function
|
|
1687
|
-
* @param {module:described_field.DescribedDataField} template
|
|
1688
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1689
|
-
* @example fromDescribedDataField(sourceField)
|
|
1690
|
-
*/
|
|
1691
|
-
this.fromDescribedDataField = function (template) {
|
|
1692
|
-
this.category(template.category);
|
|
1693
|
-
this.type(template.type);
|
|
1694
|
-
this.abbreviation(template.abbreviation);
|
|
1695
|
-
this.image(template.image);
|
|
1696
|
-
this.index(template.index);
|
|
1697
|
-
this.groupNames(template.groupNames);
|
|
1698
|
-
this.displayName(template.displayName);
|
|
1699
|
-
this.fieldName(template.fieldName);
|
|
1700
|
-
this.value(template.value);
|
|
1701
|
-
return this;
|
|
1702
|
-
};
|
|
1703
|
-
/**
|
|
1704
|
-
* Sets the category.
|
|
1705
|
-
*
|
|
1706
|
-
* Contains a short domain nam, for example:
|
|
1707
|
-
* - "product" for products
|
|
1708
|
-
* - "vendor" for vendors
|
|
1709
|
-
*
|
|
1710
|
-
* @function
|
|
1711
|
-
* @param {String} [value=""]
|
|
1712
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1713
|
-
* @example category("Product")
|
|
1714
|
-
*/
|
|
1715
|
-
this.category = function (value) {
|
|
1716
|
-
this.describedField.category = withDefaultString(value, "");
|
|
1717
|
-
return this;
|
|
1718
|
-
};
|
|
1719
|
-
/**
|
|
1720
|
-
* Sets the type.
|
|
1721
|
-
*
|
|
1722
|
-
* Contains the type of the entry, for example:
|
|
1723
|
-
* - "summary" for e.g. a list overview.
|
|
1724
|
-
* - "detail" e.g. when a summary is selected.
|
|
1725
|
-
* - "filter" e.g. for field/value pair results that can be selected as search parameters.
|
|
1726
|
-
*
|
|
1727
|
-
* @function
|
|
1728
|
-
* @param {String} [value=""]
|
|
1729
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1730
|
-
* @example type("summary")
|
|
1731
|
-
*/
|
|
1732
|
-
this.type = function (value) {
|
|
1733
|
-
this.describedField.type = withDefaultString(value, "");
|
|
1734
|
-
return this;
|
|
1735
|
-
};
|
|
1481
|
+
* Describes a field of the restructured data.
|
|
1482
|
+
* Dynamically added properties represent custom named groups containing DescribedDataField-Arrays.
|
|
1483
|
+
*
|
|
1484
|
+
* @typedef {Object} module:described_field.DescribedDataField
|
|
1485
|
+
* @property {string} [category=""] - name of the category. Could contain a short domain name like "product" or "vendor".
|
|
1486
|
+
* @property {string} [type=""] - type of the data element. Examples: "summary" for e.g. a list overview. "detail" e.g. when a summary is selected. "filter" e.g. for field/value pair results that can be selected as data filters.
|
|
1487
|
+
* @property {string} [abbreviation=""] - one optional character, a symbol character or a short abbreviation of the category
|
|
1488
|
+
* @property {string} [image=""] - one optional path to an image resource
|
|
1489
|
+
* @property {string} index - array of numbers containing the splitted index. Example: "responses[2].hits.hits[4]._source.name" will have an index of [2,4]
|
|
1490
|
+
* @property {string[]} groupNames - array of names of all dynamically added properties representing groups
|
|
1491
|
+
* @property {string} displayName - display name of the field
|
|
1492
|
+
* @property {string} fieldName - field name
|
|
1493
|
+
* @property {{*}} value - content of the field
|
|
1494
|
+
* @property {module:described_field.DescribedDataField[]} [couldBeAnyCustomGroupName] any number of groups attached to the field each containing multiple fields
|
|
1495
|
+
*/ described_field.DescribedDataFieldBuilder = (function() {
|
|
1736
1496
|
/**
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1497
|
+
* Builds a {@link module:described_field.DescribedDataField}.
|
|
1498
|
+
* DescribedDataField is the main element of the restructured data and therefore considered "public".
|
|
1499
|
+
* @constructs DescribedDataFieldBuilder
|
|
1500
|
+
* @alias module:described_field.DescribedDataFieldBuilder
|
|
1501
|
+
*/ function DescribedDataFieldBuilder() {
|
|
1502
|
+
/**
|
|
1503
|
+
* @type {module:described_field.DescribedDataField}
|
|
1504
|
+
*/ this.describedField = {
|
|
1505
|
+
category: "",
|
|
1506
|
+
type: "",
|
|
1507
|
+
abbreviation: "",
|
|
1508
|
+
image: "",
|
|
1509
|
+
index: [],
|
|
1510
|
+
groupNames: [],
|
|
1511
|
+
displayName: "",
|
|
1512
|
+
fieldName: "",
|
|
1513
|
+
value: ""
|
|
1514
|
+
};
|
|
1515
|
+
/**
|
|
1516
|
+
* Takes over all values of the template {@link module:described_field.DescribedDataField}.
|
|
1517
|
+
* @function
|
|
1518
|
+
* @param {module:described_field.DescribedDataField} template
|
|
1519
|
+
* @returns {DescribedDataFieldBuilder}
|
|
1520
|
+
* @example fromDescribedDataField(sourceField)
|
|
1521
|
+
*/ this.fromDescribedDataField = function(template) {
|
|
1522
|
+
this.category(template.category);
|
|
1523
|
+
this.type(template.type);
|
|
1524
|
+
this.abbreviation(template.abbreviation);
|
|
1525
|
+
this.image(template.image);
|
|
1526
|
+
this.index(template.index);
|
|
1527
|
+
this.groupNames(template.groupNames);
|
|
1528
|
+
this.displayName(template.displayName);
|
|
1529
|
+
this.fieldName(template.fieldName);
|
|
1530
|
+
this.value(template.value);
|
|
1531
|
+
return this;
|
|
1532
|
+
};
|
|
1533
|
+
/**
|
|
1534
|
+
* Sets the category.
|
|
1535
|
+
*
|
|
1536
|
+
* Contains a short domain nam, for example:
|
|
1537
|
+
* - "product" for products
|
|
1538
|
+
* - "vendor" for vendors
|
|
1539
|
+
*
|
|
1540
|
+
* @function
|
|
1541
|
+
* @param {String} [value=""]
|
|
1542
|
+
* @returns {DescribedDataFieldBuilder}
|
|
1543
|
+
* @example category("Product")
|
|
1544
|
+
*/ this.category = function(value) {
|
|
1545
|
+
this.describedField.category = withDefaultString(value, "");
|
|
1546
|
+
return this;
|
|
1547
|
+
};
|
|
1548
|
+
/**
|
|
1549
|
+
* Sets the type.
|
|
1550
|
+
*
|
|
1551
|
+
* Contains the type of the entry, for example:
|
|
1552
|
+
* - "summary" for e.g. a list overview.
|
|
1553
|
+
* - "detail" e.g. when a summary is selected.
|
|
1554
|
+
* - "filter" e.g. for field/value pair results that can be selected as search parameters.
|
|
1555
|
+
*
|
|
1556
|
+
* @function
|
|
1557
|
+
* @param {String} [value=""]
|
|
1558
|
+
* @returns {DescribedDataFieldBuilder}
|
|
1559
|
+
* @example type("summary")
|
|
1560
|
+
*/ this.type = function(value) {
|
|
1561
|
+
this.describedField.type = withDefaultString(value, "");
|
|
1562
|
+
return this;
|
|
1563
|
+
};
|
|
1564
|
+
/**
|
|
1565
|
+
* Sets the optional abbreviation.
|
|
1566
|
+
*
|
|
1567
|
+
* Contains a symbol character or a very short abbreviation of the category.
|
|
1568
|
+
* - "P" for products
|
|
1569
|
+
* - "V" for vendors
|
|
1570
|
+
*
|
|
1571
|
+
* @function
|
|
1572
|
+
* @param {String} [value=""]
|
|
1573
|
+
* @returns {DescribedDataFieldBuilder}
|
|
1574
|
+
* @example abbreviation("P")
|
|
1575
|
+
*/ this.abbreviation = function(value) {
|
|
1576
|
+
this.describedField.abbreviation = withDefaultString(value, "");
|
|
1577
|
+
return this;
|
|
1578
|
+
};
|
|
1579
|
+
/**
|
|
1580
|
+
* Sets the optional path to an image resource.
|
|
1581
|
+
*
|
|
1582
|
+
* @function
|
|
1583
|
+
* @param {String} [value=""]
|
|
1584
|
+
* @returns {DescribedDataFieldBuilder}
|
|
1585
|
+
* @example image("img/product.png")
|
|
1586
|
+
*/ this.image = function(value) {
|
|
1587
|
+
this.describedField.image = withDefaultString(value, "");
|
|
1588
|
+
return this;
|
|
1589
|
+
};
|
|
1590
|
+
/**
|
|
1591
|
+
* Sets the index as an array of numbers containing the splitted array indexes of the source field.
|
|
1592
|
+
* Example: "responses[2].hits.hits[4]._source.name" will have an index of [2,4].
|
|
1593
|
+
*
|
|
1594
|
+
* @function
|
|
1595
|
+
* @param {number[]} [value=[]]
|
|
1596
|
+
* @returns {DescribedDataFieldBuilder}
|
|
1597
|
+
* @example index([2,4])
|
|
1598
|
+
*/ this.index = function(value) {
|
|
1599
|
+
this.describedField.index = withDefaultArray(value, []);
|
|
1600
|
+
return this;
|
|
1601
|
+
};
|
|
1602
|
+
/**
|
|
1603
|
+
* Sets the group names as an array of strings containing the names of the dynamically added properties,
|
|
1604
|
+
* that contain an array of {@link module:described_field.DescribedDataField}-Objects.
|
|
1605
|
+
*
|
|
1606
|
+
* @function
|
|
1607
|
+
* @param {string[]} [value=[]]
|
|
1608
|
+
* @returns {DescribedDataFieldBuilder}
|
|
1609
|
+
* @example groupNames(["summaries","details","options"])
|
|
1610
|
+
*/ this.groupNames = function(value) {
|
|
1611
|
+
this.describedField.groupNames = withDefaultArray(value, []);
|
|
1612
|
+
return this;
|
|
1613
|
+
};
|
|
1614
|
+
/**
|
|
1615
|
+
* Sets the display name.
|
|
1616
|
+
*
|
|
1617
|
+
* @function
|
|
1618
|
+
* @param {String} [value=""]
|
|
1619
|
+
* @returns {DescribedDataFieldBuilder}
|
|
1620
|
+
* @example displayName("Color")
|
|
1621
|
+
*/ this.displayName = function(value) {
|
|
1622
|
+
this.describedField.displayName = withDefaultString(value, "");
|
|
1623
|
+
return this;
|
|
1624
|
+
};
|
|
1625
|
+
/**
|
|
1626
|
+
* Sets the (technical) field name.
|
|
1627
|
+
*
|
|
1628
|
+
* @function
|
|
1629
|
+
* @param {String} [value=""]
|
|
1630
|
+
* @returns {DescribedDataFieldBuilder}
|
|
1631
|
+
* @example fieldName("color")
|
|
1632
|
+
*/ this.fieldName = function(value) {
|
|
1633
|
+
this.describedField.fieldName = withDefaultString(value, "");
|
|
1634
|
+
return this;
|
|
1635
|
+
};
|
|
1636
|
+
/**
|
|
1637
|
+
* Sets the value/content of the field.
|
|
1638
|
+
*
|
|
1639
|
+
* @function
|
|
1640
|
+
* @param {*} value
|
|
1641
|
+
* @returns {DescribedDataFieldBuilder}
|
|
1642
|
+
* @example value("darkblue")
|
|
1643
|
+
*/ this.value = function(value) {
|
|
1644
|
+
this.describedField.value = value;
|
|
1645
|
+
return this;
|
|
1646
|
+
};
|
|
1647
|
+
/**
|
|
1648
|
+
* Finalizes the settings and builds the {@link module:described_field.DescribedDataField}.
|
|
1649
|
+
* @function
|
|
1650
|
+
* @returns {module:described_field.DescribedDataField}
|
|
1651
|
+
*/ this.build = function() {
|
|
1652
|
+
return this.describedField;
|
|
1653
|
+
};
|
|
1654
|
+
}
|
|
1655
|
+
function isSpecifiedString(value) {
|
|
1656
|
+
return typeof value === "string" && value !== null && value !== "";
|
|
1657
|
+
}
|
|
1658
|
+
function withDefaultString(value, defaultValue) {
|
|
1659
|
+
return isSpecifiedString(value) ? value : defaultValue;
|
|
1660
|
+
}
|
|
1661
|
+
function withDefaultArray(value, defaultValue) {
|
|
1662
|
+
return value === undefined || value === null ? defaultValue : value;
|
|
1663
|
+
}
|
|
1664
|
+
return DescribedDataFieldBuilder;
|
|
1845
1665
|
})();
|
|
1846
1666
|
/**
|
|
1847
|
-
* Creates a new described data field with all properties of the original one except for dynamically added groups.
|
|
1848
|
-
* @param {module:described_field.DescribedDataField} describedDataField
|
|
1849
|
-
* @returns {module:described_field.DescribedDataField}
|
|
1850
|
-
* @memberof module:described_field
|
|
1851
|
-
*/
|
|
1852
|
-
described_field.
|
|
1853
|
-
return new described_field.DescribedDataFieldBuilder().fromDescribedDataField(describedDataField).groupNames([]).build();
|
|
1667
|
+
* Creates a new described data field with all properties of the original one except for dynamically added groups.
|
|
1668
|
+
* @param {module:described_field.DescribedDataField} describedDataField
|
|
1669
|
+
* @returns {module:described_field.DescribedDataField}
|
|
1670
|
+
* @memberof module:described_field
|
|
1671
|
+
*/ described_field.copyWithoutGroups = function(describedDataField) {
|
|
1672
|
+
return new described_field.DescribedDataFieldBuilder().fromDescribedDataField(describedDataField).groupNames([]).build();
|
|
1854
1673
|
};
|
|
1855
|
-
described_field.DescribedDataFieldGroup = (function
|
|
1856
|
-
/**
|
|
1857
|
-
* Adds groups to {@link module:described_field.DescribedDataField}s. These groups are dynamically added properties
|
|
1858
|
-
* that contain an array of sub fields of the same type {@link module:described_field.DescribedDataField}s.
|
|
1859
|
-
*
|
|
1860
|
-
* @param {module:described_field.DescribedDataField} dataField
|
|
1861
|
-
* @constructs DescribedDataFieldGroup
|
|
1862
|
-
* @alias module:described_field.DescribedDataFieldGroup
|
|
1863
|
-
* @example new described_field.DescribedDataFieldGroup(field).addGroupEntry("details", detailField);
|
|
1864
|
-
*/
|
|
1865
|
-
function DescribedDataFieldGroup(dataField) {
|
|
1866
|
-
this.dataField = dataField;
|
|
1867
|
-
/**
|
|
1868
|
-
* Adds an entry to the given group. If the group does not exist, it will be created.
|
|
1869
|
-
* @function
|
|
1870
|
-
* @param {String} groupName name of the group to which the entry will be added
|
|
1871
|
-
* @param {module:described_field.DescribedDataField} describedField sub field that is added to the group
|
|
1872
|
-
* @returns {DescribedDataFieldGroup}
|
|
1873
|
-
*/
|
|
1874
|
-
this.addGroupEntry = function (groupName, describedField) {
|
|
1875
|
-
this.addGroupEntries(groupName, [describedField]);
|
|
1876
|
-
return this;
|
|
1877
|
-
};
|
|
1674
|
+
described_field.DescribedDataFieldGroup = (function() {
|
|
1878
1675
|
/**
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1676
|
+
* Adds groups to {@link module:described_field.DescribedDataField}s. These groups are dynamically added properties
|
|
1677
|
+
* that contain an array of sub fields of the same type {@link module:described_field.DescribedDataField}s.
|
|
1678
|
+
*
|
|
1679
|
+
* @param {module:described_field.DescribedDataField} dataField
|
|
1680
|
+
* @constructs DescribedDataFieldGroup
|
|
1681
|
+
* @alias module:described_field.DescribedDataFieldGroup
|
|
1682
|
+
* @example new described_field.DescribedDataFieldGroup(field).addGroupEntry("details", detailField);
|
|
1683
|
+
*/ function DescribedDataFieldGroup(dataField) {
|
|
1684
|
+
this.dataField = dataField;
|
|
1685
|
+
/**
|
|
1686
|
+
* Adds an entry to the given group. If the group does not exist, it will be created.
|
|
1687
|
+
* @function
|
|
1688
|
+
* @param {String} groupName name of the group to which the entry will be added
|
|
1689
|
+
* @param {module:described_field.DescribedDataField} describedField sub field that is added to the group
|
|
1690
|
+
* @returns {DescribedDataFieldGroup}
|
|
1691
|
+
*/ this.addGroupEntry = function(groupName, describedField) {
|
|
1692
|
+
this.addGroupEntries(groupName, [
|
|
1693
|
+
describedField
|
|
1694
|
+
]);
|
|
1695
|
+
return this;
|
|
1696
|
+
};
|
|
1697
|
+
/**
|
|
1698
|
+
* Adds entries to the given group. If the group does not exist, it will be created.
|
|
1699
|
+
* @function
|
|
1700
|
+
* @param {String} groupName name of the group to which the entries will be added
|
|
1701
|
+
* @param {module:described_field.DescribedDataField[]} describedFields sub fields that are added to the group
|
|
1702
|
+
* @returns {DescribedDataFieldGroup}
|
|
1703
|
+
*/ this.addGroupEntries = function(groupName, describedFields) {
|
|
1704
|
+
if (!groupName || groupName.length === 0) return this;
|
|
1705
|
+
if (!describedFields || describedFields.length === 0) return this;
|
|
1706
|
+
if (this.dataField[groupName] === undefined) {
|
|
1707
|
+
this.dataField.groupNames.push(groupName);
|
|
1708
|
+
this.dataField[groupName] = [];
|
|
1709
|
+
}
|
|
1710
|
+
var index;
|
|
1711
|
+
var describedField;
|
|
1712
|
+
for(index = 0; index < describedFields.length; index += 1){
|
|
1713
|
+
describedField = describedFields[index];
|
|
1714
|
+
this.dataField[groupName].push(describedField);
|
|
1715
|
+
}
|
|
1716
|
+
return this;
|
|
1717
|
+
};
|
|
1718
|
+
}
|
|
1719
|
+
return DescribedDataFieldGroup;
|
|
1906
1720
|
})();
|
|
1907
1721
|
|
|
1908
|
-
},{}]},["
|
|
1722
|
+
},{}]},["2gjIT"], "2gjIT", "parcelRequirec1f2")
|
|
1909
1723
|
|