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