data-restructor 3.3.4 → 3.4.0

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