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.
Files changed (54) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +2 -2
  2. package/.github/workflows/codeql-analysis.yml +4 -4
  3. package/.github/workflows/continuous-integration.yaml +84 -0
  4. package/CHANGELOG.md +103 -75
  5. package/CONTRIBUTING.md +51 -43
  6. package/Commands.md +15 -15
  7. package/README.md +188 -137
  8. package/SECURITY.md +15 -0
  9. package/coverage/coverage-summary.json +4 -4
  10. package/coverage/datarestructor.js.html +446 -320
  11. package/coverage/describedfield.js.html +47 -47
  12. package/coverage/index.html +19 -19
  13. package/coverage/templateResolver.js.html +26 -26
  14. package/devdist/datarestructor-global-all.js +65 -23
  15. package/devdist/datarestructor-ie-global-all.js +65 -23
  16. package/devdist/datarestructor-ie.js +1479 -1616
  17. package/devdist/datarestructor.js +1439 -1559
  18. package/devdist/describedfield-ie.js +259 -279
  19. package/devdist/describedfield.js +257 -277
  20. package/devdist/templateResolver-ie.js +220 -252
  21. package/devdist/templateResolver.js +196 -227
  22. package/dist/datarestructor-global-all-min.js +1 -1
  23. package/dist/datarestructor-ie-global-all-min.js +1 -1
  24. package/dist/datarestructor-ie.js +1 -1
  25. package/dist/datarestructor-ie.js.map +1 -1
  26. package/dist/datarestructor.js +1 -1
  27. package/dist/datarestructor.js.map +1 -1
  28. package/dist/describedfield-ie.js +1 -1
  29. package/dist/describedfield-ie.js.map +1 -1
  30. package/dist/describedfield.js +1 -1
  31. package/dist/describedfield.js.map +1 -1
  32. package/dist/templateResolver-ie.js +1 -1
  33. package/dist/templateResolver-ie.js.map +1 -1
  34. package/dist/templateResolver.js +1 -1
  35. package/dist/templateResolver.js.map +1 -1
  36. package/docs/datarestructor.js.html +66 -24
  37. package/docs/describedfield.js.html +1 -1
  38. package/docs/index.html +49 -44
  39. package/docs/module-datarestructor.DescribedEntryCreator.html +1 -1
  40. package/docs/module-datarestructor.PropertyStructureDescriptionBuilder.html +1 -1
  41. package/docs/module-datarestructor.Restructor.html +3 -3
  42. package/docs/module-datarestructor.Transform.html +7 -30
  43. package/docs/module-datarestructor.html +100 -3
  44. package/docs/module-described_field.DescribedDataFieldBuilder.html +1 -1
  45. package/docs/module-described_field.DescribedDataFieldGroup.html +1 -1
  46. package/docs/module-described_field.html +1 -1
  47. package/docs/module-template_resolver.Resolver.html +1 -1
  48. package/docs/module-template_resolver.html +1 -1
  49. package/docs/templateResolver.js.html +1 -1
  50. package/package.json +16 -14
  51. package/renovate.json +20 -0
  52. package/src/js/datarestructor.js +65 -23
  53. package/test/js/DataRestructorUseCaseTest.js +36 -0
  54. package/.github/workflows/action.yaml +0 -44
@@ -1689,11 +1689,22 @@ datarestructor.Transform = (function () {
1689
1689
  var describedEntity;
1690
1690
  for (index = 0; index < describedEntries.length; index += 1) {
1691
1691
  describedEntity = describedEntries[index];
1692
- result.push(toDescribedField(describedEntity, 0, config));
1692
+ result.push(toDescribedField(describedEntity, {recursionDepth:0, config: config, groupToSkip:""}));
1693
1693
  }
1694
1694
  return result;
1695
1695
  }
1696
1696
 
1697
+ /**
1698
+ * Describes the context type for the recursive DescribedDataField conversion,
1699
+ * that contains everything that needs to be accessible throughout recursion regardless of the
1700
+ * recursion depth.
1701
+ *
1702
+ * @typedef {Object} module:datarestructor.DescribedFieldRecursionContext
1703
+ * @param {number} recursionDepth current recursion depth
1704
+ * @param {String} groupToSkip name of a group to skip or "" when no group should be skipped.
1705
+ * @param {module:datarestructor.TransformConfig} config configuration for the data transformation
1706
+ */
1707
+
1697
1708
  /**
1698
1709
  * Converts a internal described entry to a newly created public described field.
1699
1710
  * Since the structure of a described field is hierarchical, this function is called recursively.
@@ -1701,13 +1712,12 @@ datarestructor.Transform = (function () {
1701
1712
  * needs to be limited. Therefore, the current recursion depth is taken as second parameter
1702
1713
  * and the maximum recursion depth is taken as third parameter.
1703
1714
  * @param {module:datarestructor.DescribedEntry} entry the internal entry that will be converted
1704
- * @param {number} recursionDepth current hierarchy recursion depth
1705
- * @param {module:datarestructor.TransformConfig} config configuration for the data transformation
1715
+ * @param {module:datarestructor.DescribedFieldRecursionContext} recursionContext context contains everything that needs to be accessible throughout the recursion.
1706
1716
  * @returns {module:described_field.DescribedDataField}
1707
1717
  * @protected
1708
1718
  * @memberof module:datarestructor.Transform
1709
1719
  */
1710
- function toDescribedField(entry, recursionDepth, config) {
1720
+ function toDescribedField(entry, recursionContext) {
1711
1721
  var field = new described_field.DescribedDataFieldBuilder()
1712
1722
  .category(entry.category)
1713
1723
  .type(entry.type)
@@ -1718,37 +1728,70 @@ datarestructor.Transform = (function () {
1718
1728
  .fieldName(entry.fieldName)
1719
1729
  .value(entry.value)
1720
1730
  .build();
1721
- if (recursionDepth > config.maxRecursionDepth) {
1731
+ if (recursionContext.recursionDepth > recursionContext.config.maxRecursionDepth) {
1722
1732
  return field;
1723
1733
  }
1734
+ var nextRecursionContext = null;
1735
+ var duplicateGroupNameToSkip = "";
1724
1736
  var fieldGroups = new described_field.DescribedDataFieldGroup(field);
1725
- forEachGroupEntry(entry, function (groupName, groupEntry) {
1726
- if (groupEntry != entry || recursionDepth <= config.removeDuplicationAboveRecursionDepth) {
1727
- fieldGroups.addGroupEntry(groupName, toDescribedField(groupEntry, recursionDepth + 1, config));
1728
- } else {
1729
- if (config.debugMode) {
1730
- console.log(
1731
- "Removed duplicate field " +
1732
- groupEntry.fieldName +
1733
- " with value " +
1734
- groupEntry.value +
1735
- " of group " +
1736
- groupName +
1737
- " at recursion depth " +
1738
- recursionDepth
1739
- );
1737
+ forEachGroupEntry(entry, function (groupName, groupEntry, allGroupEntries) {
1738
+ if (recursionContext.groupToSkip === groupName) {
1739
+ if (recursionContext.config.debugMode) {
1740
+ console.log("Removed duplicate group " + groupName + " at recursion depth " + recursionContext.recursionDepth);
1740
1741
  }
1742
+ return;
1743
+ }
1744
+ duplicateGroupNameToSkip = "";
1745
+ if (recursionContext.recursionDepth >= recursionContext.config.removeDuplicationAboveRecursionDepth) {
1746
+ duplicateGroupNameToSkip = arraysEqual(groupEntry[groupName], allGroupEntries, describedFieldEqual)? groupName : "";
1741
1747
  }
1748
+ nextRecursionContext = {recursionDepth: recursionContext.recursionDepth + 1, config: recursionContext.config, groupToSkip: duplicateGroupNameToSkip};
1749
+ fieldGroups.addGroupEntry(groupName, toDescribedField(groupEntry, nextRecursionContext));
1742
1750
  });
1743
1751
  return field;
1744
1752
  }
1745
1753
 
1754
+ function describedFieldEqual(a, b) {
1755
+ return (
1756
+ defaultEmpty(a.category) === defaultEmpty(b.category) &&
1757
+ defaultEmpty(a.type) === defaultEmpty(b.type) &&
1758
+ a.fieldName === b.fieldName &&
1759
+ a.value === b.value
1760
+ );
1761
+ }
1762
+
1763
+ function defaultEmpty(value) {
1764
+ return defaultValue(value, "");
1765
+ }
1766
+
1767
+ function defaultValue(value, valueAsDefault) {
1768
+ if (typeof value === "undefined" || !value) {
1769
+ return valueAsDefault;
1770
+ }
1771
+ return value;
1772
+ }
1773
+
1774
+ // Reference: https://stackoverflow.com/questions/3115982/how-to-check-if-two-arrays-are-equal-with-javascript/16430730
1775
+ // Added "elementEqualFunction" to implement equal object detection.
1776
+ // Arrays are assumed to be sorted. Differently ordered entries are treated as not equal.
1777
+ function arraysEqual(a, b, elementEqualFunction) {
1778
+ if (a === b) return true;
1779
+ if (a == null || b == null) return false;
1780
+ if (a.length !== b.length) return false;
1781
+
1782
+ for (var i = 0; i < a.length; ++i) {
1783
+ if (!elementEqualFunction(a[i], b[i])) return false;
1784
+ }
1785
+ return true;
1786
+ }
1787
+
1746
1788
  /**
1747
1789
  * Takes the full qualified original property name and extracts a simple name out of it.
1748
1790
  *
1749
1791
  * @callback module:datarestructor.onEntryFoundFunction
1750
1792
  * @param {string} groupName name of the group where the entry had been found.
1751
1793
  * @param {module:datarestructor.DescribedEntry} foundEntry the found entry itself.
1794
+ * @param {module:datarestructor.DescribedEntry[]} allEntries the array of all entries where the found entry is an element of.
1752
1795
  */
1753
1796
 
1754
1797
  /**
@@ -1766,13 +1809,12 @@ datarestructor.Transform = (function () {
1766
1809
  groupName = rootEntry.groupNames[groupIndex];
1767
1810
  for (entryIndex = 0; entryIndex < rootEntry[groupName].length; entryIndex += 1) {
1768
1811
  entry = rootEntry[groupName][entryIndex];
1769
- onFoundEntry(groupName, entry);
1812
+ onFoundEntry(groupName, entry, rootEntry[groupName]);
1770
1813
  }
1771
1814
  }
1772
1815
  }
1773
-
1774
1816
  return Transform;
1775
- })();
1817
+ }());
1776
1818
 
1777
1819
  /**
1778
1820
  * Main fassade for the data restructor as static function(s).