data-restructor 3.3.3 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +2 -2
- package/.github/workflows/codeql-analysis.yml +4 -4
- package/.github/workflows/continuous-integration.yaml +84 -0
- package/CHANGELOG.md +103 -75
- package/CONTRIBUTING.md +51 -43
- package/Commands.md +15 -15
- package/README.md +188 -137
- package/SECURITY.md +15 -0
- package/coverage/coverage-summary.json +4 -4
- package/coverage/datarestructor.js.html +446 -320
- package/coverage/describedfield.js.html +47 -47
- package/coverage/index.html +19 -19
- package/coverage/templateResolver.js.html +26 -26
- package/devdist/datarestructor-global-all.js +65 -23
- package/devdist/datarestructor-ie-global-all.js +65 -23
- package/devdist/datarestructor-ie.js +1479 -1616
- package/devdist/datarestructor.js +1439 -1559
- package/devdist/describedfield-ie.js +259 -279
- package/devdist/describedfield.js +257 -277
- package/devdist/templateResolver-ie.js +220 -252
- package/devdist/templateResolver.js +196 -227
- package/dist/datarestructor-global-all-min.js +1 -1
- package/dist/datarestructor-ie-global-all-min.js +1 -1
- package/dist/datarestructor-ie.js +1 -1
- package/dist/datarestructor-ie.js.map +1 -1
- package/dist/datarestructor.js +1 -1
- package/dist/datarestructor.js.map +1 -1
- package/dist/describedfield-ie.js +1 -1
- package/dist/describedfield-ie.js.map +1 -1
- package/dist/describedfield.js +1 -1
- package/dist/describedfield.js.map +1 -1
- package/dist/templateResolver-ie.js +1 -1
- package/dist/templateResolver-ie.js.map +1 -1
- package/dist/templateResolver.js +1 -1
- package/dist/templateResolver.js.map +1 -1
- package/docs/datarestructor.js.html +66 -24
- package/docs/describedfield.js.html +1 -1
- package/docs/index.html +49 -44
- package/docs/module-datarestructor.DescribedEntryCreator.html +1 -1
- package/docs/module-datarestructor.PropertyStructureDescriptionBuilder.html +1 -1
- package/docs/module-datarestructor.Restructor.html +3 -3
- package/docs/module-datarestructor.Transform.html +7 -30
- package/docs/module-datarestructor.html +100 -3
- package/docs/module-described_field.DescribedDataFieldBuilder.html +1 -1
- package/docs/module-described_field.DescribedDataFieldGroup.html +1 -1
- package/docs/module-described_field.html +1 -1
- package/docs/module-template_resolver.Resolver.html +1 -1
- package/docs/module-template_resolver.html +1 -1
- package/docs/templateResolver.js.html +1 -1
- package/package.json +16 -14
- package/renovate.json +20 -0
- package/src/js/datarestructor.js +65 -23
- package/test/js/DataRestructorUseCaseTest.js +36 -0
- package/.github/workflows/action.yaml +0 -44
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// anything defined in a previous bundle is accessed via the
|
|
7
7
|
// orig method which is the require for previous bundles
|
|
8
8
|
|
|
9
|
-
(function(modules, entry, mainEntry, parcelRequireName, globalName) {
|
|
9
|
+
(function (modules, entry, mainEntry, parcelRequireName, globalName) {
|
|
10
10
|
/* eslint-disable no-undef */
|
|
11
11
|
var globalObject =
|
|
12
12
|
typeof globalThis !== 'undefined'
|
|
@@ -80,11 +80,13 @@
|
|
|
80
80
|
return cache[name].exports;
|
|
81
81
|
|
|
82
82
|
function localRequire(x) {
|
|
83
|
-
|
|
83
|
+
var res = localRequire.resolve(x);
|
|
84
|
+
return res === false ? {} : newRequire(res);
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
function resolve(x) {
|
|
87
|
-
|
|
88
|
+
var id = modules[name][1][x];
|
|
89
|
+
return id != null ? id : x;
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
92
|
|
|
@@ -99,9 +101,9 @@
|
|
|
99
101
|
newRequire.modules = modules;
|
|
100
102
|
newRequire.cache = cache;
|
|
101
103
|
newRequire.parent = previousRequire;
|
|
102
|
-
newRequire.register = function(id, exports) {
|
|
104
|
+
newRequire.register = function (id, exports) {
|
|
103
105
|
modules[id] = [
|
|
104
|
-
function(require, module) {
|
|
106
|
+
function (require, module) {
|
|
105
107
|
module.exports = exports;
|
|
106
108
|
},
|
|
107
109
|
{},
|
|
@@ -109,7 +111,7 @@
|
|
|
109
111
|
};
|
|
110
112
|
|
|
111
113
|
Object.defineProperty(newRequire, 'root', {
|
|
112
|
-
get: function() {
|
|
114
|
+
get: function () {
|
|
113
115
|
return globalObject[parcelRequireName];
|
|
114
116
|
},
|
|
115
117
|
});
|
|
@@ -131,7 +133,7 @@
|
|
|
131
133
|
|
|
132
134
|
// RequireJS
|
|
133
135
|
} else if (typeof define === 'function' && define.amd) {
|
|
134
|
-
define(function() {
|
|
136
|
+
define(function () {
|
|
135
137
|
return mainExports;
|
|
136
138
|
});
|
|
137
139
|
|
|
@@ -140,1637 +142,1515 @@
|
|
|
140
142
|
this[globalName] = mainExports;
|
|
141
143
|
}
|
|
142
144
|
}
|
|
143
|
-
})({"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* @
|
|
190
|
-
* @property {string}
|
|
191
|
-
* @property {string}
|
|
192
|
-
* @property {string} [
|
|
193
|
-
* @property {
|
|
194
|
-
* @property {
|
|
195
|
-
* @property {string}
|
|
196
|
-
* @property {
|
|
197
|
-
* @property {module:datarestructor.propertyNameFunction}
|
|
198
|
-
* @property {
|
|
199
|
-
* @property {string}
|
|
200
|
-
* @property {string}
|
|
201
|
-
* @property {string}
|
|
202
|
-
* @property {string}
|
|
203
|
-
|
|
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
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
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
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
478
|
+
function upperCaseFirstLetterForFunction(nameExtractFunction) {
|
|
479
|
+
return function(propertyName) {
|
|
480
|
+
return upperCaseFirstLetter(nameExtractFunction(propertyName));
|
|
481
|
+
};
|
|
488
482
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
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
|
-
|
|
500
|
-
|
|
501
|
-
|
|
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
|
-
|
|
505
|
-
|
|
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
|
-
|
|
515
|
-
|
|
516
|
-
|
|
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
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
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
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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
|
-
*
|
|
583
|
-
*
|
|
584
|
-
* @
|
|
585
|
-
* @param {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
* @
|
|
590
|
-
* @property {string}
|
|
591
|
-
* @property {string}
|
|
592
|
-
* @property {string}
|
|
593
|
-
* @property {string}
|
|
594
|
-
* @property {string}
|
|
595
|
-
* @property {string}
|
|
596
|
-
* @property {string}
|
|
597
|
-
* @property {
|
|
598
|
-
* @property {
|
|
599
|
-
* @property {
|
|
600
|
-
* @property {
|
|
601
|
-
* @property {
|
|
602
|
-
* @property {
|
|
603
|
-
* @property {string} _identifier.
|
|
604
|
-
* @property {string} _identifier.
|
|
605
|
-
* @property {string} _identifier.
|
|
606
|
-
* @property {string} _identifier.
|
|
607
|
-
* @property {string} _identifier.
|
|
608
|
-
* @property {
|
|
609
|
-
|
|
610
|
-
*
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
*
|
|
614
|
-
*
|
|
615
|
-
|
|
616
|
-
|
|
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
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
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
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
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
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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;
|
|
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() {
|
|
752
678
|
/**
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
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
|
+
};
|
|
762
|
+
}
|
|
793
763
|
/**
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
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;
|
|
816
|
+
}
|
|
805
817
|
/**
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
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;
|
|
851
|
+
}
|
|
825
852
|
/**
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
console.log("flattened data with array values:");
|
|
855
|
-
console.log(processedData);
|
|
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);
|
|
856
881
|
}
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
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;
|
|
866
898
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
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
|
+
});
|
|
871
917
|
}
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
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;
|
|
877
942
|
}
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
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;
|
|
883
963
|
}
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
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
|
+
}
|
|
990
|
+
}
|
|
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];
|
|
995
|
+
}
|
|
996
|
+
return groupedObject;
|
|
891
997
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
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;
|
|
925
1039
|
}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
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);
|
|
1047
|
+
}
|
|
1048
|
+
return result;
|
|
929
1049
|
}
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
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;
|
|
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
|
+
}));
|
|
1070
|
+
}
|
|
1071
|
+
return result;
|
|
959
1072
|
}
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
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;
|
|
980
1114
|
}
|
|
981
|
-
|
|
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);
|
|
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;
|
|
1032
1117
|
}
|
|
1033
|
-
|
|
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);
|
|
1054
|
-
}
|
|
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);
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1118
|
+
function defaultEmpty(value) {
|
|
1119
|
+
return defaultValue(value, "");
|
|
1086
1120
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
delete groupedObject[keyToDelete];
|
|
1121
|
+
function defaultValue(value, valueAsDefault) {
|
|
1122
|
+
if (typeof value === "undefined" || !value) return valueAsDefault;
|
|
1123
|
+
return value;
|
|
1091
1124
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
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 = "";
|
|
1116
|
-
}
|
|
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 = "";
|
|
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;
|
|
1130
1134
|
}
|
|
1131
|
-
|
|
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);
|
|
1135
|
+
return true;
|
|
1145
1136
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
* Converts a internal described entry to a newly created public described field.
|
|
1170
|
-
* Since the structure of a described field is hierarchical, this function is called recursively.
|
|
1171
|
-
* Because the internal described entries may very likely contain cyclic references, the depth of recursion
|
|
1172
|
-
* needs to be limited. Therefore, the current recursion depth is taken as second parameter
|
|
1173
|
-
* and the maximum recursion depth is taken as third parameter.
|
|
1174
|
-
* @param {module:datarestructor.DescribedEntry} entry the internal entry that will be converted
|
|
1175
|
-
* @param {number} recursionDepth current hierarchy recursion depth
|
|
1176
|
-
* @param {module:datarestructor.TransformConfig} config configuration for the data transformation
|
|
1177
|
-
* @returns {module:described_field.DescribedDataField}
|
|
1178
|
-
* @protected
|
|
1179
|
-
* @memberof module:datarestructor.Transform
|
|
1180
|
-
*/
|
|
1181
|
-
function toDescribedField(entry, recursionDepth, config) {
|
|
1182
|
-
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();
|
|
1183
|
-
if (recursionDepth > config.maxRecursionDepth) {
|
|
1184
|
-
return field;
|
|
1185
|
-
}
|
|
1186
|
-
var fieldGroups = new described_field.DescribedDataFieldGroup(field);
|
|
1187
|
-
forEachGroupEntry(entry, function (groupName, groupEntry) {
|
|
1188
|
-
if (groupEntry != entry || recursionDepth <= config.removeDuplicationAboveRecursionDepth) {
|
|
1189
|
-
fieldGroups.addGroupEntry(groupName, toDescribedField(groupEntry, recursionDepth + 1, config));
|
|
1190
|
-
} else {
|
|
1191
|
-
if (config.debugMode) {
|
|
1192
|
-
console.log("Removed duplicate field " + groupEntry.fieldName + " with value " + groupEntry.value + " of group " + groupName + " at recursion depth " + recursionDepth);
|
|
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
|
+
}
|
|
1193
1160
|
}
|
|
1194
|
-
}
|
|
1195
|
-
});
|
|
1196
|
-
return field;
|
|
1197
|
-
}
|
|
1198
|
-
/**
|
|
1199
|
-
* Takes the full qualified original property name and extracts a simple name out of it.
|
|
1200
|
-
*
|
|
1201
|
-
* @callback module:datarestructor.onEntryFoundFunction
|
|
1202
|
-
* @param {string} groupName name of the group where the entry had been found.
|
|
1203
|
-
* @param {module:datarestructor.DescribedEntry} foundEntry the found entry itself.
|
|
1204
|
-
*/
|
|
1205
|
-
/**
|
|
1206
|
-
* Traverses through all groups and their entries and calls the given function on every found entry
|
|
1207
|
-
* with the group name and the entry itself as parameters.
|
|
1208
|
-
* @param {module:datarestructor.DescribedEntry} rootEntry
|
|
1209
|
-
* @param {module:datarestructor.onEntryFoundFunction} onFoundEntry
|
|
1210
|
-
* @protected
|
|
1211
|
-
* @memberof module:datarestructor.Transform
|
|
1212
|
-
*/
|
|
1213
|
-
function forEachGroupEntry(rootEntry, onFoundEntry) {
|
|
1214
|
-
var groupIndex, entryIndex;
|
|
1215
|
-
var groupName, entry;
|
|
1216
|
-
for (groupIndex = 0; groupIndex < rootEntry.groupNames.length; groupIndex += 1) {
|
|
1217
|
-
groupName = rootEntry.groupNames[groupIndex];
|
|
1218
|
-
for (entryIndex = 0; entryIndex < rootEntry[groupName].length; entryIndex += 1) {
|
|
1219
|
-
entry = rootEntry[groupName][entryIndex];
|
|
1220
|
-
onFoundEntry(groupName, entry);
|
|
1221
|
-
}
|
|
1222
1161
|
}
|
|
1223
|
-
|
|
1224
|
-
return Transform;
|
|
1162
|
+
return Transform;
|
|
1225
1163
|
})();
|
|
1226
1164
|
/**
|
|
1227
|
-
* Main fassade for the data restructor as static function(s).
|
|
1228
|
-
*
|
|
1229
|
-
* @example
|
|
1230
|
-
* var allDescriptions = [];
|
|
1231
|
-
* allDescriptions.push(summariesDescription());
|
|
1232
|
-
* allDescriptions.push(detailsDescription());
|
|
1233
|
-
* var result = datarestructor.Restructor.processJsonUsingDescriptions(jsonData, allDescriptions);
|
|
1234
|
-
* @namespace module:datarestructor.Restructor
|
|
1235
|
-
*/
|
|
1236
|
-
|
|
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
|
+
};
|
|
1237
1175
|
/**
|
|
1238
|
-
* Static fassade function for the "Assembly line", that takes the jsonData and processes it using all given descriptions in their given order.
|
|
1239
|
-
* @param {object} jsonData - parsed JSON data or any other data object
|
|
1240
|
-
* @param {module:datarestructor.PropertyStructureDescription[]} descriptions - already grouped entries
|
|
1241
|
-
* @param {boolean} debugMode - false=default=off, true=write additional logs for detailed debugging
|
|
1242
|
-
* @returns {module:datarestructor.DescribedEntry[]}
|
|
1243
|
-
* @memberof module:datarestructor.Restructor
|
|
1244
|
-
* @deprecated since v3.1.0, please use "new datarestructor.Transform(descriptions).processJson(jsonData)".
|
|
1245
|
-
*/
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
restructor.enableDebugMode();
|
|
1250
|
-
}
|
|
1251
|
-
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);
|
|
1252
1187
|
};
|
|
1253
1188
|
|
|
1254
|
-
},{"../../lib/js/flattenToArray":"
|
|
1189
|
+
},{"../../lib/js/flattenToArray":"ipjOk","../../src/js/templateResolver":"41qn9","../../src/js/describedfield":"cleYG"}],"ipjOk":[function(require,module,exports) {
|
|
1255
1190
|
"use strict";
|
|
1256
1191
|
/**
|
|
1257
|
-
* @fileOverview Modded (compatibility, recursion depth) version of: https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objectss
|
|
1258
|
-
* @version ${project.version}
|
|
1259
|
-
* @see {@link https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objectss|stackoverflow flatten nested json objects}
|
|
1260
|
-
*/
|
|
1261
|
-
|
|
1262
|
-
// Fallback for vanilla js without modules
|
|
1263
|
-
/**
|
|
1264
|
-
* internal_object_tools. Not meant to be used outside this repository.
|
|
1265
|
-
* @default {}
|
|
1266
|
-
*/
|
|
1267
|
-
var internal_object_tools = module.exports = {};
|
|
1268
|
-
// 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
|
|
1269
1197
|
/**
|
|
1270
|
-
*
|
|
1271
|
-
* @
|
|
1272
|
-
|
|
1273
|
-
|
|
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...
|
|
1274
1202
|
/**
|
|
1275
|
-
* @
|
|
1276
|
-
* @
|
|
1277
|
-
* @
|
|
1278
|
-
*/
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
name: prop,
|
|
1291
|
-
value: cur
|
|
1292
|
-
});
|
|
1293
|
-
} else if (Array.isArray(cur)) {
|
|
1294
|
-
var i;
|
|
1295
|
-
var l = cur.length;
|
|
1296
|
-
for (i = 0; i < l; i += 1) {
|
|
1297
|
-
recurse(cur[i], prop + "[" + i + "]", depth + 1);
|
|
1298
|
-
}
|
|
1299
|
-
if (l === 0) {
|
|
1300
|
-
result[prop] = [];
|
|
1301
|
-
result.push({
|
|
1302
|
-
name: prop,
|
|
1303
|
-
value: ""
|
|
1304
|
-
});
|
|
1305
|
-
}
|
|
1306
|
-
} else {
|
|
1307
|
-
var isEmpty = true;
|
|
1308
|
-
var p;
|
|
1309
|
-
for (p in cur) {
|
|
1310
|
-
isEmpty = false;
|
|
1311
|
-
recurse(cur[p], prop ? prop + "." + p : p, depth + 1);
|
|
1312
|
-
}
|
|
1313
|
-
if (isEmpty && prop) {
|
|
1314
|
-
result.push({
|
|
1315
|
-
name: prop,
|
|
1316
|
-
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
|
|
1317
1218
|
});
|
|
1318
|
-
|
|
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
|
+
}
|
|
1319
1242
|
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
return result;
|
|
1243
|
+
recurse(data, "", 0);
|
|
1244
|
+
return result;
|
|
1323
1245
|
};
|
|
1324
1246
|
|
|
1325
|
-
},{}],"
|
|
1247
|
+
},{}],"41qn9":[function(require,module,exports) {
|
|
1326
1248
|
/**
|
|
1327
|
-
* @file Provides a simple template resolver, that replaces variables in double curly brackets with the values of a given object.
|
|
1328
|
-
* @version {@link https://github.com/JohT/data-restructor-js/releases/latest latest version}
|
|
1329
|
-
* @author JohT
|
|
1330
|
-
* @version ${project.version}
|
|
1331
|
-
*/
|
|
1332
|
-
|
|
1333
|
-
var module = templateResolverInternalCreateIfNotExists(module);
|
|
1334
|
-
// 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
|
|
1335
1255
|
function templateResolverInternalCreateIfNotExists(objectToCheck) {
|
|
1336
|
-
|
|
1256
|
+
return objectToCheck || {
|
|
1257
|
+
};
|
|
1337
1258
|
}
|
|
1338
1259
|
/**
|
|
1339
|
-
* Provides a simple template resolver, that replaces variables in double curly brackets with the values of a given object.
|
|
1340
|
-
* @module template_resolver
|
|
1341
|
-
*/
|
|
1342
|
-
|
|
1343
|
-
// 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...
|
|
1344
1264
|
template_resolver.internalCreateIfNotExists = templateResolverInternalCreateIfNotExists;
|
|
1345
|
-
var internal_object_tools = internal_object_tools || require("../../lib/js/flattenToArray");
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
var removeArrayBracketsRegEx = new RegExp("\\[\\d+\\]", "gi");
|
|
1349
|
-
/**
|
|
1350
|
-
* Resolver. Is used inside this repository. It could also be used outside.
|
|
1351
|
-
* @param {*} sourceDataObject The properties of this object will be used to replace the placeholders in the template.
|
|
1352
|
-
* @constructs Resolver
|
|
1353
|
-
* @alias module:template_resolver.Resolver
|
|
1354
|
-
*/
|
|
1355
|
-
function Resolver(sourceDataObject) {
|
|
1356
|
-
/**
|
|
1357
|
-
* The properties of this source data object will be used to replace the placeholders in the template.
|
|
1358
|
-
*/
|
|
1359
|
-
this.sourceDataObject = sourceDataObject;
|
|
1360
|
-
/**
|
|
1361
|
-
* Resolves the given template.
|
|
1362
|
-
*
|
|
1363
|
-
* The template may contain variables in double curly brackets.
|
|
1364
|
-
* Supported variables are all properties of this object, e.g. "{{fieldName}}", "{{displayName}}", "{{value}}".
|
|
1365
|
-
* Since this object may also contains (described) groups of sub objects, they can also be used, e.g. "{{summaries[0].value}}"
|
|
1366
|
-
* Parts of the index can be inserted by using e.g. "{{index[1]}}".
|
|
1367
|
-
*
|
|
1368
|
-
* @param {string} template
|
|
1369
|
-
* @returns {string} resolved template
|
|
1370
|
-
*/
|
|
1371
|
-
this.resolveTemplate = function (template) {
|
|
1372
|
-
return this.replaceResolvableFields(template, addFieldsPerGroup(this.resolvableFieldsOfAll(this.sourceDataObject)));
|
|
1373
|
-
};
|
|
1374
|
-
/**
|
|
1375
|
-
* Returns a map like object, that contains all resolvable fields and their values as properties.
|
|
1376
|
-
* This function takes a variable count of input parameters,
|
|
1377
|
-
* each containing an object that contains resolvable fields to extract from.
|
|
1378
|
-
*
|
|
1379
|
-
* The recursion depth is limited to 3, so that an object,
|
|
1380
|
-
* that contains an object can contain another object (but not further).
|
|
1381
|
-
*
|
|
1382
|
-
* Properties beginning with an underscore in their name will be filtered out, since they are considered as internal fields.
|
|
1383
|
-
*
|
|
1384
|
-
* @param {...object} varArgs variable count of parameters. Each parameter contains an object that fields should be resolvable for variables.
|
|
1385
|
-
* @returns {object} object with resolvable field names and their values.
|
|
1386
|
-
* @public
|
|
1387
|
-
*/
|
|
1388
|
-
this.resolvableFieldsOfAll = function () {
|
|
1389
|
-
var map = {};
|
|
1390
|
-
var ignoreInternalFields = function (propertyName) {
|
|
1391
|
-
return propertyName.indexOf("_") !== 0 && propertyName.indexOf("._") < 0;
|
|
1392
|
-
};
|
|
1393
|
-
var index;
|
|
1394
|
-
for (index = 0; index < arguments.length; index += 1) {
|
|
1395
|
-
addToFilteredMapObject(internal_object_tools.flattenToArray(arguments[index], 3), map, ignoreInternalFields);
|
|
1396
|
-
}
|
|
1397
|
-
return map;
|
|
1398
|
-
};
|
|
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");
|
|
1399
1268
|
/**
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
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
|
+
};
|
|
1443
1333
|
}
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
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;
|
|
1458
1355
|
}
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
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
|
+
};
|
|
1462
1374
|
}
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
*/
|
|
1480
|
-
function addToFilteredMapObject(elements, mapObject, filterMatchesFunction) {
|
|
1481
|
-
var index, element;
|
|
1482
|
-
for (index = 0; index < elements.length; index += 1) {
|
|
1483
|
-
element = elements[index];
|
|
1484
|
-
if (typeof filterMatchesFunction === "function" && filterMatchesFunction(element.name)) {
|
|
1485
|
-
mapObject[element.name] = element.value;
|
|
1486
|
-
}
|
|
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;
|
|
1487
1391
|
}
|
|
1488
|
-
return
|
|
1489
|
-
}
|
|
1490
|
-
return Resolver;
|
|
1392
|
+
return Resolver;
|
|
1491
1393
|
})();
|
|
1492
1394
|
|
|
1493
|
-
},{"../../lib/js/flattenToArray":"
|
|
1395
|
+
},{"../../lib/js/flattenToArray":"ipjOk"}],"cleYG":[function(require,module,exports) {
|
|
1494
1396
|
/**
|
|
1495
|
-
* @file Describes a data field of the restructured data.
|
|
1496
|
-
* @version {@link https://github.com/JohT/data-restructor-js/releases/latest latest version}
|
|
1497
|
-
* @author JohT
|
|
1498
|
-
* @version ${project.version}
|
|
1499
|
-
*/
|
|
1500
|
-
|
|
1501
|
-
var module = describedFieldInternalCreateIfNotExists(module);
|
|
1502
|
-
// 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
|
|
1503
1403
|
function describedFieldInternalCreateIfNotExists(objectToCheck) {
|
|
1504
|
-
|
|
1404
|
+
return objectToCheck || {
|
|
1405
|
+
};
|
|
1505
1406
|
}
|
|
1506
1407
|
/**
|
|
1507
|
-
* Describes a data field of the restructured data.
|
|
1508
|
-
* @module described_field
|
|
1509
|
-
*/
|
|
1510
|
-
|
|
1511
|
-
// 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...
|
|
1512
1412
|
described_field.internalCreateIfNotExists = describedFieldInternalCreateIfNotExists;
|
|
1513
1413
|
/**
|
|
1514
|
-
* Describes a field of the restructured data.
|
|
1515
|
-
* Dynamically added properties represent custom named groups containing DescribedDataField-Arrays.
|
|
1516
|
-
*
|
|
1517
|
-
* @typedef {Object} module:described_field.DescribedDataField
|
|
1518
|
-
* @property {string} [category=""] - name of the category. Could contain a short domain name like "product" or "vendor".
|
|
1519
|
-
* @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.
|
|
1520
|
-
* @property {string} [abbreviation=""] - one optional character, a symbol character or a short abbreviation of the category
|
|
1521
|
-
* @property {string} [image=""] - one optional path to an image resource
|
|
1522
|
-
* @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]
|
|
1523
|
-
* @property {string[]} groupNames - array of names of all dynamically added properties representing groups
|
|
1524
|
-
* @property {string} displayName - display name of the field
|
|
1525
|
-
* @property {string} fieldName - field name
|
|
1526
|
-
* @property {{*}} value - content of the field
|
|
1527
|
-
* @property {module:described_field.DescribedDataField[]} [couldBeAnyCustomGroupName] any number of groups attached to the field each containing multiple fields
|
|
1528
|
-
*/
|
|
1529
|
-
described_field.DescribedDataFieldBuilder = (function () {
|
|
1530
|
-
/**
|
|
1531
|
-
* Builds a {@link module:described_field.DescribedDataField}.
|
|
1532
|
-
* DescribedDataField is the main element of the restructured data and therefore considered "public".
|
|
1533
|
-
* @constructs DescribedDataFieldBuilder
|
|
1534
|
-
* @alias module:described_field.DescribedDataFieldBuilder
|
|
1535
|
-
*/
|
|
1536
|
-
function DescribedDataFieldBuilder() {
|
|
1537
|
-
/**
|
|
1538
|
-
* @type {module:described_field.DescribedDataField}
|
|
1539
|
-
*/
|
|
1540
|
-
this.describedField = {
|
|
1541
|
-
category: "",
|
|
1542
|
-
type: "",
|
|
1543
|
-
abbreviation: "",
|
|
1544
|
-
image: "",
|
|
1545
|
-
index: [],
|
|
1546
|
-
groupNames: [],
|
|
1547
|
-
displayName: "",
|
|
1548
|
-
fieldName: "",
|
|
1549
|
-
value: ""
|
|
1550
|
-
};
|
|
1551
|
-
/**
|
|
1552
|
-
* Takes over all values of the template {@link module:described_field.DescribedDataField}.
|
|
1553
|
-
* @function
|
|
1554
|
-
* @param {module:described_field.DescribedDataField} template
|
|
1555
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1556
|
-
* @example fromDescribedDataField(sourceField)
|
|
1557
|
-
*/
|
|
1558
|
-
this.fromDescribedDataField = function (template) {
|
|
1559
|
-
this.category(template.category);
|
|
1560
|
-
this.type(template.type);
|
|
1561
|
-
this.abbreviation(template.abbreviation);
|
|
1562
|
-
this.image(template.image);
|
|
1563
|
-
this.index(template.index);
|
|
1564
|
-
this.groupNames(template.groupNames);
|
|
1565
|
-
this.displayName(template.displayName);
|
|
1566
|
-
this.fieldName(template.fieldName);
|
|
1567
|
-
this.value(template.value);
|
|
1568
|
-
return this;
|
|
1569
|
-
};
|
|
1570
|
-
/**
|
|
1571
|
-
* Sets the category.
|
|
1572
|
-
*
|
|
1573
|
-
* Contains a short domain nam, for example:
|
|
1574
|
-
* - "product" for products
|
|
1575
|
-
* - "vendor" for vendors
|
|
1576
|
-
*
|
|
1577
|
-
* @function
|
|
1578
|
-
* @param {String} [value=""]
|
|
1579
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1580
|
-
* @example category("Product")
|
|
1581
|
-
*/
|
|
1582
|
-
this.category = function (value) {
|
|
1583
|
-
this.describedField.category = withDefaultString(value, "");
|
|
1584
|
-
return this;
|
|
1585
|
-
};
|
|
1586
|
-
/**
|
|
1587
|
-
* Sets the type.
|
|
1588
|
-
*
|
|
1589
|
-
* Contains the type of the entry, for example:
|
|
1590
|
-
* - "summary" for e.g. a list overview.
|
|
1591
|
-
* - "detail" e.g. when a summary is selected.
|
|
1592
|
-
* - "filter" e.g. for field/value pair results that can be selected as search parameters.
|
|
1593
|
-
*
|
|
1594
|
-
* @function
|
|
1595
|
-
* @param {String} [value=""]
|
|
1596
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1597
|
-
* @example type("summary")
|
|
1598
|
-
*/
|
|
1599
|
-
this.type = function (value) {
|
|
1600
|
-
this.describedField.type = withDefaultString(value, "");
|
|
1601
|
-
return this;
|
|
1602
|
-
};
|
|
1603
|
-
/**
|
|
1604
|
-
* Sets the optional abbreviation.
|
|
1605
|
-
*
|
|
1606
|
-
* Contains a symbol character or a very short abbreviation of the category.
|
|
1607
|
-
* - "P" for products
|
|
1608
|
-
* - "V" for vendors
|
|
1609
|
-
*
|
|
1610
|
-
* @function
|
|
1611
|
-
* @param {String} [value=""]
|
|
1612
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1613
|
-
* @example abbreviation("P")
|
|
1614
|
-
*/
|
|
1615
|
-
this.abbreviation = function (value) {
|
|
1616
|
-
this.describedField.abbreviation = withDefaultString(value, "");
|
|
1617
|
-
return this;
|
|
1618
|
-
};
|
|
1619
|
-
/**
|
|
1620
|
-
* Sets the optional path to an image resource.
|
|
1621
|
-
*
|
|
1622
|
-
* @function
|
|
1623
|
-
* @param {String} [value=""]
|
|
1624
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1625
|
-
* @example image("img/product.png")
|
|
1626
|
-
*/
|
|
1627
|
-
this.image = function (value) {
|
|
1628
|
-
this.describedField.image = withDefaultString(value, "");
|
|
1629
|
-
return this;
|
|
1630
|
-
};
|
|
1631
|
-
/**
|
|
1632
|
-
* Sets the index as an array of numbers containing the splitted array indexes of the source field.
|
|
1633
|
-
* Example: "responses[2].hits.hits[4]._source.name" will have an index of [2,4].
|
|
1634
|
-
*
|
|
1635
|
-
* @function
|
|
1636
|
-
* @param {number[]} [value=[]]
|
|
1637
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1638
|
-
* @example index([2,4])
|
|
1639
|
-
*/
|
|
1640
|
-
this.index = function (value) {
|
|
1641
|
-
this.describedField.index = withDefaultArray(value, []);
|
|
1642
|
-
return this;
|
|
1643
|
-
};
|
|
1644
|
-
/**
|
|
1645
|
-
* Sets the group names as an array of strings containing the names of the dynamically added properties,
|
|
1646
|
-
* that contain an array of {@link module:described_field.DescribedDataField}-Objects.
|
|
1647
|
-
*
|
|
1648
|
-
* @function
|
|
1649
|
-
* @param {string[]} [value=[]]
|
|
1650
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1651
|
-
* @example groupNames(["summaries","details","options"])
|
|
1652
|
-
*/
|
|
1653
|
-
this.groupNames = function (value) {
|
|
1654
|
-
this.describedField.groupNames = withDefaultArray(value, []);
|
|
1655
|
-
return this;
|
|
1656
|
-
};
|
|
1657
|
-
/**
|
|
1658
|
-
* Sets the display name.
|
|
1659
|
-
*
|
|
1660
|
-
* @function
|
|
1661
|
-
* @param {String} [value=""]
|
|
1662
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1663
|
-
* @example displayName("Color")
|
|
1664
|
-
*/
|
|
1665
|
-
this.displayName = function (value) {
|
|
1666
|
-
this.describedField.displayName = withDefaultString(value, "");
|
|
1667
|
-
return this;
|
|
1668
|
-
};
|
|
1669
|
-
/**
|
|
1670
|
-
* Sets the (technical) field name.
|
|
1671
|
-
*
|
|
1672
|
-
* @function
|
|
1673
|
-
* @param {String} [value=""]
|
|
1674
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1675
|
-
* @example fieldName("color")
|
|
1676
|
-
*/
|
|
1677
|
-
this.fieldName = function (value) {
|
|
1678
|
-
this.describedField.fieldName = withDefaultString(value, "");
|
|
1679
|
-
return this;
|
|
1680
|
-
};
|
|
1681
|
-
/**
|
|
1682
|
-
* Sets the value/content of the field.
|
|
1683
|
-
*
|
|
1684
|
-
* @function
|
|
1685
|
-
* @param {*} value
|
|
1686
|
-
* @returns {DescribedDataFieldBuilder}
|
|
1687
|
-
* @example value("darkblue")
|
|
1688
|
-
*/
|
|
1689
|
-
this.value = function (value) {
|
|
1690
|
-
this.describedField.value = value;
|
|
1691
|
-
return this;
|
|
1692
|
-
};
|
|
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() {
|
|
1693
1429
|
/**
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
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;
|
|
1712
1598
|
})();
|
|
1713
1599
|
/**
|
|
1714
|
-
* Creates a new described data field with all properties of the original one except for dynamically added groups.
|
|
1715
|
-
* @param {module:described_field.DescribedDataField} describedDataField
|
|
1716
|
-
* @returns {module:described_field.DescribedDataField}
|
|
1717
|
-
* @memberof module:described_field
|
|
1718
|
-
*/
|
|
1719
|
-
described_field.
|
|
1720
|
-
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();
|
|
1721
1606
|
};
|
|
1722
|
-
described_field.DescribedDataFieldGroup = (function
|
|
1723
|
-
/**
|
|
1724
|
-
* Adds groups to {@link module:described_field.DescribedDataField}s. These groups are dynamically added properties
|
|
1725
|
-
* that contain an array of sub fields of the same type {@link module:described_field.DescribedDataField}s.
|
|
1726
|
-
*
|
|
1727
|
-
* @param {module:described_field.DescribedDataField} dataField
|
|
1728
|
-
* @constructs DescribedDataFieldGroup
|
|
1729
|
-
* @alias module:described_field.DescribedDataFieldGroup
|
|
1730
|
-
* @example new described_field.DescribedDataFieldGroup(field).addGroupEntry("details", detailField);
|
|
1731
|
-
*/
|
|
1732
|
-
function DescribedDataFieldGroup(dataField) {
|
|
1733
|
-
this.dataField = dataField;
|
|
1734
|
-
/**
|
|
1735
|
-
* Adds an entry to the given group. If the group does not exist, it will be created.
|
|
1736
|
-
* @function
|
|
1737
|
-
* @param {String} groupName name of the group to which the entry will be added
|
|
1738
|
-
* @param {module:described_field.DescribedDataField} describedField sub field that is added to the group
|
|
1739
|
-
* @returns {DescribedDataFieldGroup}
|
|
1740
|
-
*/
|
|
1741
|
-
this.addGroupEntry = function (groupName, describedField) {
|
|
1742
|
-
this.addGroupEntries(groupName, [describedField]);
|
|
1743
|
-
return this;
|
|
1744
|
-
};
|
|
1607
|
+
described_field.DescribedDataFieldGroup = (function() {
|
|
1745
1608
|
/**
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
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;
|
|
1773
1653
|
})();
|
|
1774
1654
|
|
|
1775
|
-
},{}]},["
|
|
1655
|
+
},{}]},["7hzxy"], "7hzxy", "parcelRequirec1f2")
|
|
1776
1656
|
|