data-restructor 3.3.4 → 3.4.1

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