@ui5/task-adaptation 1.1.0 → 1.1.2

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 (80) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/README.md +1 -1
  3. package/dist/annotationManager.d.ts +0 -3
  4. package/dist/annotationManager.js +8 -43
  5. package/dist/annotations/comparator/comparator.d.ts +47 -0
  6. package/dist/annotations/comparator/comparator.js +276 -0
  7. package/dist/annotations/comparator/diffCase.d.ts +4 -0
  8. package/dist/annotations/comparator/diffCase.js +3 -0
  9. package/dist/annotations/comparator/interchangableCase.d.ts +25 -0
  10. package/dist/annotations/comparator/interchangableCase.js +65 -0
  11. package/dist/annotations/converter/metadataJsonReferenceUtil.d.ts +12 -0
  12. package/dist/annotations/converter/metadataJsonReferenceUtil.js +50 -0
  13. package/dist/annotations/converter/metadataJsonUtil.d.ts +30 -0
  14. package/dist/annotations/converter/metadataJsonUtil.js +73 -0
  15. package/dist/annotations/converter/ui5JsonConverter.d.ts +21 -0
  16. package/dist/annotations/converter/ui5JsonConverter.js +253 -0
  17. package/dist/annotations/converter/ui5MetadataJsonUtil.d.ts +3 -0
  18. package/dist/annotations/converter/ui5MetadataJsonUtil.js +13 -0
  19. package/dist/annotations/converter/ui5XmlConverter.d.ts +5 -0
  20. package/dist/annotations/converter/ui5XmlConverter.js +17 -0
  21. package/dist/annotations/dataSource/dataSource.d.ts +34 -0
  22. package/dist/annotations/dataSource/dataSource.js +62 -0
  23. package/dist/annotations/dataSource/dataSourceManager.d.ts +13 -0
  24. package/dist/annotations/dataSource/dataSourceManager.js +58 -0
  25. package/dist/annotations/dataSource/dataSourceOData.d.ts +17 -0
  26. package/dist/annotations/dataSource/dataSourceOData.js +47 -0
  27. package/dist/annotations/dataSource/dataSourceODataAnnotation.d.ts +6 -0
  28. package/dist/annotations/dataSource/dataSourceODataAnnotation.js +14 -0
  29. package/dist/annotations/dataSource/dataSourceODataAnnotationBeta.d.ts +6 -0
  30. package/dist/annotations/dataSource/dataSourceODataAnnotationBeta.js +18 -0
  31. package/dist/annotations/serviceRequestor.d.ts +1 -9
  32. package/dist/annotations/serviceRequestor.js +52 -17
  33. package/dist/annotations/transformers/convertV2ToV4.d.ts +4 -0
  34. package/dist/annotations/transformers/convertV2ToV4.js +16 -0
  35. package/dist/annotations/transformers/makeAnnotationNamespaceUnique.d.ts +6 -0
  36. package/dist/annotations/transformers/makeAnnotationNamespaceUnique.js +44 -0
  37. package/dist/annotations/transformers/removeAllSchemaNodesExceptAnnotations.d.ts +4 -0
  38. package/dist/annotations/transformers/removeAllSchemaNodesExceptAnnotations.js +17 -0
  39. package/dist/annotations/transformers/transformer.d.ts +12 -0
  40. package/dist/annotations/transformers/transformer.js +3 -0
  41. package/dist/annotations/transformers/traverseReferences.d.ts +9 -0
  42. package/dist/annotations/transformers/traverseReferences.js +67 -0
  43. package/dist/appVariantManager.d.ts +4 -2
  44. package/dist/appVariantManager.js +44 -18
  45. package/dist/baseAppManager.d.ts +2 -1
  46. package/dist/baseAppManager.js +26 -31
  47. package/dist/bundle-odata.js +5498 -0
  48. package/dist/bundle.js +1786 -13
  49. package/dist/i18nManager.d.ts +5 -7
  50. package/dist/i18nManager.js +29 -32
  51. package/dist/index.js +4 -3
  52. package/dist/model/annotationDiffStructureError.js +2 -0
  53. package/dist/model/language.js +1 -1
  54. package/dist/model/serverError.d.ts +3 -0
  55. package/dist/model/serverError.js +9 -0
  56. package/dist/model/types.d.ts +13 -2
  57. package/dist/repositories/abapRepoManager.js +2 -2
  58. package/dist/util/commonUtil.d.ts +7 -0
  59. package/dist/util/commonUtil.js +72 -18
  60. package/dist/util/i18nMerger.d.ts +1 -1
  61. package/dist/util/i18nMerger.js +3 -4
  62. package/dist/util/requestUtil.js +4 -0
  63. package/dist/util/resourceUtil.d.ts +3 -0
  64. package/dist/util/resourceUtil.js +14 -1
  65. package/dist/util/urlUtil.d.ts +4 -0
  66. package/dist/util/urlUtil.js +21 -0
  67. package/package.json +9 -6
  68. package/scripts/bundler.ts +4 -33
  69. package/scripts/metadataDownloadHelper.ts +7 -5
  70. package/scripts/rollup/bundleDefinition-odata.js +9 -0
  71. package/scripts/rollup/overrides/sap/ui/performance/Measurement.js +4 -0
  72. package/scripts/rollup/ui5Resolve.ts +34 -5
  73. package/scripts/rollup.ts +12 -3
  74. package/dist/annotations/oDataModel.d.ts +0 -20
  75. package/dist/annotations/oDataModel.js +0 -46
  76. package/dist/annotations/oDataV2Model.d.ts +0 -4
  77. package/dist/annotations/oDataV2Model.js +0 -13
  78. package/dist/util/jsonDiffUtil.d.ts +0 -28
  79. package/dist/util/jsonDiffUtil.js +0 -74
  80. package/scripts/rollup/overrides/sap/ui/thirdparty/URI.js +0 -16
package/CHANGELOG.md CHANGED
@@ -2,7 +2,13 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
4
4
 
5
- A list of unreleased changes can be found [here](https://github.com/SAP/ui5-task-adaptation/compare/v1.1.0...HEAD).
5
+ A list of unreleased changes can be found [here](https://github.com/SAP/ui5-task-adaptation/compare/v1.1.2...HEAD).
6
+
7
+ <a name="v1.1.2"></a>
8
+ ## [v1.1.2] - 2024-02-23
9
+
10
+ <a name="v1.1.1"></a>
11
+ ## [v1.1.1] - 2024-02-16
6
12
 
7
13
  <a name="v1.1.0"></a>
8
14
  ## [v1.1.0] - 2024-01-30
@@ -73,6 +79,8 @@ A list of unreleased changes can be found [here](https://github.com/SAP/ui5-task
73
79
  <a name="v1.0.0"></a>
74
80
  ## v1.0.0 - 2020-12-09
75
81
 
82
+ [v1.1.2]: https://github.com/SAP/ui5-task-adaptation/compare/v1.1.1...v1.1.2
83
+ [v1.1.1]: https://github.com/SAP/ui5-task-adaptation/compare/v1.1.0...v1.1.1
76
84
  [v1.1.0]: https://github.com/SAP/ui5-task-adaptation/compare/v1.0.23...v1.1.0
77
85
  [v1.0.23]: https://github.com/SAP/ui5-task-adaptation/compare/v1.0.21...v1.0.23
78
86
  [v1.0.21]: https://github.com/SAP/ui5-task-adaptation/compare/v1.0.20...v1.0.21
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![npm version](https://badge.fury.io/js/@ui5%2Ftask-adaptation.svg)](https://badge.fury.io/js/@ui5%2Ftask-adaptation)
5
5
 
6
6
  ## Description
7
- A custom task for [ui5-builder](https://github.com/SAP/ui5-builder) that allows building [UI5 Flexibility adaptation projects](https://help.sap.com/viewer/584e0bcbfd4a4aff91c815cefa0bce2d/Cloud/en-US/019b0c38a6b043d1a66b11d992eed290.html) for SAP BTP, Cloud Foundry environment.
7
+ A custom task for [ui5-builder](https://github.com/SAP/ui5-builder) that allows building SAPUI5 adaptation projects for [SAP S/4HANA Cloud](https://help.sap.com/docs/bas/584e0bcbfd4a4aff91c815cefa0bce2d/6fc4e11a4b1941efa8e37a428d046f8f.html?locale=en-US&state=PRODUCTION&version=Cloud) and [SAP BTP, Cloud Foundry environment](https://help.sap.com/viewer/584e0bcbfd4a4aff91c815cefa0bce2d/Cloud/en-US/019b0c38a6b043d1a66b11d992eed290.html).
8
8
 
9
9
  ## How to obtain support
10
10
  In case you need any support, please create a [GitHub issue](https://github.com/SAP/ui5-task-adaptation/issues).
@@ -12,10 +12,7 @@ export default class AnnotationManager {
12
12
  ANNOTATIONS_FOLDER: string;
13
13
  process(renamedBaseAppManifest: any, languages: Language[]): Promise<Map<string, string>>;
14
14
  private normalizeAppVariantId;
15
- private createAnnotationFile;
16
15
  private updateManifestModel;
17
- private updateManifestDataSources;
18
16
  private createManifestModel;
19
17
  private enhanceManifestModel;
20
- private createODataModels;
21
18
  }
@@ -1,15 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const baseAppManager_1 = require("./baseAppManager");
4
+ const dataSourceManager_1 = require("./annotations/dataSource/dataSourceManager");
4
5
  const i18nManager_1 = require("./i18nManager");
5
- const oDataV2Model_1 = require("./annotations/oDataV2Model");
6
6
  const serviceRequestor_1 = require("./annotations/serviceRequestor");
7
- const xmlUtil_1 = require("./util/xmlUtil");
8
7
  const path_1 = require("path");
9
8
  const I18N_DEFAULT_PATH = "i18n/annotations";
10
9
  const I18N_DEFAULT_MODEL_NAME = "@i18n";
11
10
  const SAPUI5 = "sap.ui5";
12
- const SAPAPP = "sap.app";
13
11
  class AnnotationManager {
14
12
  constructor(configuration, abapRepoManager) {
15
13
  this.ANNOTATIONS_FOLDER = "annotations";
@@ -23,46 +21,26 @@ class AnnotationManager {
23
21
  //TODO: switch to this after resolving @i18n custom model
24
22
  const modelName = I18N_DEFAULT_MODEL_NAME; //`i18n_a9n_${normalisedId}`;
25
23
  const i18nPathName = path_1.posix.join(I18N_DEFAULT_PATH, normalisedId);
26
- const annotationFiles = new Map();
27
- const metaInfo = new Array();
28
24
  const i18nManager = new i18nManager_1.default(modelName, id, languages);
29
- const oDataModels = this.createODataModels(renamedBaseAppManifest);
30
- for (const oDataModel of oDataModels) {
31
- for (const { annotationJsons, annotationName } of oDataModel.getAnnotationJsons(languages)) {
32
- const annotationXml = await this.createAnnotationFile(await annotationJsons, i18nManager);
33
- const annotationFileName = `annotations/annotation_${annotationName}.xml`;
34
- annotationFiles.set(annotationFileName, annotationXml);
35
- metaInfo.push({ annotationFileName, annotationName });
36
- }
37
- }
38
- if (metaInfo.length > 0) {
39
- this.updateManifestDataSources(renamedBaseAppManifest, metaInfo);
40
- if (i18nManager.hasTranslations()) {
41
- this.updateManifestModel(renamedBaseAppManifest, modelName, i18nPathName);
42
- }
43
- }
25
+ const serviceRequestor = new serviceRequestor_1.default(this.configuration, this.abapRepoManager);
26
+ const dataSourceManager = new dataSourceManager_1.default();
27
+ dataSourceManager.addDataSources(renamedBaseAppManifest["sap.app"]?.dataSources, this.configuration);
28
+ const annotationFiles = await dataSourceManager.createAnnotationFiles(languages, i18nManager, serviceRequestor);
44
29
  const i18nFiles = i18nManager.createFiles(i18nPathName);
30
+ if (i18nManager.hasTranslations()) {
31
+ this.updateManifestModel(renamedBaseAppManifest, modelName, i18nPathName);
32
+ }
45
33
  return new Map([...annotationFiles, ...i18nFiles]);
46
34
  }
47
35
  normalizeAppVariantId(id, replaceWith = "") {
48
36
  return id.replace(/[.\W]+/gi, replaceWith);
49
37
  }
50
- async createAnnotationFile(annotationJsons, i18nManager) {
51
- const annotationJson = i18nManager.populateTranslations(annotationJsons);
52
- return xmlUtil_1.default.jsonToXml(annotationJson.json);
53
- }
54
38
  updateManifestModel(renamedBaseAppManifest, modelName, i18nPathName) {
55
39
  const uri = `${i18nPathName}/i18n.properties`;
56
40
  this.enhanceManifestModel(renamedBaseAppManifest, modelName, uri);
57
41
  //TODO: switch to this after resolving @i18n custom model
58
42
  //this.createManifestModel(renamedBaseAppManifest, modelName, uri);
59
43
  }
60
- updateManifestDataSources(renamedBaseAppManifest, metaInfo) {
61
- const dataSources = renamedBaseAppManifest[SAPAPP]?.dataSources;
62
- for (const { annotationName, annotationFileName } of metaInfo) {
63
- dataSources[annotationName].uri = annotationFileName;
64
- }
65
- }
66
44
  createManifestModel(manifest, modelName, uri) {
67
45
  let sapui5 = manifest[SAPUI5] == null ? manifest[SAPUI5] = {} : manifest[SAPUI5];
68
46
  if (sapui5.models == null) {
@@ -97,19 +75,6 @@ class AnnotationManager {
97
75
  this.createManifestModel(manifest, modelToEnhance, bundleUrl);
98
76
  }
99
77
  }
100
- createODataModels(renamedBaseAppManifest) {
101
- const serviceRequestor = new serviceRequestor_1.default(this.configuration, this.abapRepoManager);
102
- const oDataModels = [
103
- new oDataV2Model_1.default(serviceRequestor)
104
- ];
105
- const dataSources = renamedBaseAppManifest["sap.app"]?.dataSources;
106
- if (dataSources) {
107
- for (const name of Object.keys(dataSources)) {
108
- oDataModels.forEach(model => model.addDataSource(dataSources[name], name));
109
- }
110
- }
111
- return oDataModels;
112
- }
113
78
  }
114
79
  exports.default = AnnotationManager;
115
80
  //# sourceMappingURL=annotationManager.js.map
@@ -0,0 +1,47 @@
1
+ export interface IDiffProperty {
2
+ object: any;
3
+ property: string | number;
4
+ }
5
+ export declare class Diff {
6
+ __old: string;
7
+ __new: string;
8
+ constructor(__old: string, __new: string);
9
+ toString(): string;
10
+ }
11
+ export interface DiffJson {
12
+ json: any;
13
+ properties: Set<IDiffProperty>;
14
+ }
15
+ export default class Comparator {
16
+ private diffs;
17
+ private xml_a;
18
+ private xml_b;
19
+ constructor(xml_a: string, xml_b: string);
20
+ compare(): DiffJson;
21
+ private traverseCompare;
22
+ /**
23
+ * If one language annotation has one property it is an object, if other
24
+ * language same annotation consists of multiple properties, we need to
25
+ * equal them, so they are both arrays (see test 01-04).
26
+ */
27
+ private arrayIfNeeded;
28
+ /**
29
+ * If some node (Annotations, Annotation, PropertyValue, LabeledElement) has
30
+ * an id, we can compare by id, so the items order doesn't matter anymore.
31
+ * @param a array of nodes with id of one language
32
+ * @param b array of nodes with id of the other language
33
+ * @param idProperty property which value is an id (e.g. Target="<unique-id>")
34
+ * @param property node name (Annotations, Annotation, PropertyValue, ...)
35
+ */
36
+ private traverseById;
37
+ /**
38
+ * Some nodes, like Annotations, Annotation, PropertyValue have unique id
39
+ * among other same nodes. We can use it to know what to compare with what
40
+ * even if the order is different. IdProperty is a property name of that id,
41
+ * e.g. for Annotations it will be Target (like in
42
+ * Target="<some-unique-id>").
43
+ * @param property node which might have an id: Annotations, PropertyValue
44
+ * @return the property name which represents id: Target, Property
45
+ */
46
+ private getIdProperty;
47
+ }
@@ -0,0 +1,276 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Diff = void 0;
4
+ const commonUtil_1 = require("../../util/commonUtil");
5
+ const annotationDiffStructureError_1 = require("../../model/annotationDiffStructureError");
6
+ const interchangableCase_1 = require("./interchangableCase");
7
+ const metadataJsonUtil_1 = require("../converter/metadataJsonUtil");
8
+ const xmlUtil_1 = require("../../util/xmlUtil");
9
+ class Diff {
10
+ constructor(__old, __new) {
11
+ this.__old = __old;
12
+ this.__new = __new;
13
+ }
14
+ toString() {
15
+ return `{ __old: ${this.__old}, __new: ${this.__new} }`;
16
+ }
17
+ }
18
+ exports.Diff = Diff;
19
+ class Comparator {
20
+ constructor(xml_a, xml_b) {
21
+ this.diffs = new Set();
22
+ this.xml_a = xml_a;
23
+ this.xml_b = xml_b;
24
+ }
25
+ compare() {
26
+ const json_a = typeof this.xml_a === "string" ? xmlUtil_1.default.xmlToJson(this.xml_a) : this.xml_a;
27
+ const json_b = typeof this.xml_b === "string" ? xmlUtil_1.default.xmlToJson(this.xml_b) : this.xml_b;
28
+ const scheme_a = metadataJsonUtil_1.default.getSchemaNode(json_a);
29
+ const scheme_b = metadataJsonUtil_1.default.getSchemaNode(json_b);
30
+ if (scheme_a && scheme_b) {
31
+ // we compare only Annotations, other types are left as it is
32
+ this.traverseCompare(scheme_a, scheme_b, "Annotations");
33
+ }
34
+ return {
35
+ json: json_a,
36
+ properties: this.diffs
37
+ };
38
+ }
39
+ traverseCompare(obj_a, obj_b, property) {
40
+ let a = obj_a[property];
41
+ let b = obj_b[property];
42
+ if (typeof a === "object" && !(a instanceof Diff) && typeof b !== "object" ||
43
+ typeof b === "object" && !(b instanceof Diff) && typeof a !== "object" ||
44
+ a == null || b == null) {
45
+ // When during traversing we end up in primitives like string, we
46
+ // compare the values. If one of them is not primitive or oone of
47
+ // them is undefined, we throw exception (see test 06, 07).
48
+ throw new annotationDiffStructureError_1.default({ a, b });
49
+ }
50
+ else if (typeof a !== "object" && typeof b !== "object") {
51
+ // If primitive values are not same - we assume they are
52
+ // translations, so we save them.
53
+ if (a !== b) {
54
+ obj_a[property] = new Diff(a, b);
55
+ this.diffs.add({ object: obj_a, property });
56
+ }
57
+ }
58
+ else {
59
+ a = this.arrayIfNeeded(obj_a, obj_b, property);
60
+ b = this.arrayIfNeeded(obj_b, obj_a, property);
61
+ if (Array.isArray(a)) {
62
+ let idProperty = this.getIdProperty(property);
63
+ if (idProperty) {
64
+ this.traverseById(a, b, idProperty, property);
65
+ }
66
+ else {
67
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
68
+ if (a[i] && b[i]) {
69
+ this.traverseCompare(a, b, i);
70
+ }
71
+ else {
72
+ // If the number of items of nodes without id are
73
+ // different, we throw error (see test 08).
74
+ throw new annotationDiffStructureError_1.default({ a, b });
75
+ }
76
+ }
77
+ }
78
+ }
79
+ else {
80
+ for (const key of Object.keys(a)) {
81
+ this.traverseCompare(a, b, key);
82
+ }
83
+ }
84
+ }
85
+ }
86
+ /**
87
+ * If one language annotation has one property it is an object, if other
88
+ * language same annotation consists of multiple properties, we need to
89
+ * equal them, so they are both arrays (see test 01-04).
90
+ */
91
+ arrayIfNeeded(obj_a, obj_b, property) {
92
+ if (!Array.isArray(obj_a[property])) {
93
+ // If node with id - make array anyway, so it's easier to compare (see test 04).
94
+ if (simpleIdentifiers.has(property) || Array.isArray(obj_b[property])) {
95
+ obj_a[property] = [obj_a[property]];
96
+ }
97
+ }
98
+ return obj_a[property];
99
+ }
100
+ /**
101
+ * If some node (Annotations, Annotation, PropertyValue, LabeledElement) has
102
+ * an id, we can compare by id, so the items order doesn't matter anymore.
103
+ * @param a array of nodes with id of one language
104
+ * @param b array of nodes with id of the other language
105
+ * @param idProperty property which value is an id (e.g. Target="<unique-id>")
106
+ * @param property node name (Annotations, Annotation, PropertyValue, ...)
107
+ */
108
+ traverseById(a, b, idProperty, property) {
109
+ if (typeof property !== "string") {
110
+ return;
111
+ }
112
+ let items_a = new Items(a, idProperty);
113
+ let items_b = new Items(b, idProperty);
114
+ const includer_a = new Includer(a, property);
115
+ const includer_b = new Includer(b, property);
116
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
117
+ const id_a = a[i]?._attributes[idProperty];
118
+ const id_b = b[i]?._attributes[idProperty];
119
+ if (id_a !== id_b) {
120
+ // We go down the array and if suddenly the ids for comparing
121
+ // items are not the same, we need to find the item with the
122
+ // same id if it exists.
123
+ if (items_b.has(id_a) && items_a.has(id_b)) {
124
+ // If we found the item with the same id, we swap places
125
+ // with current item (see test 05).
126
+ items_b.swap(id_a, i);
127
+ }
128
+ else if (!items_a.has(id_b) && id_b) {
129
+ // If 1st language missing the item, include it from 2nd (see test 02).
130
+ includer_a.include(b, i);
131
+ }
132
+ else if (!items_b.has(id_a) && id_a) {
133
+ // If 2nd language missing the item, include it from 1st (see test 03).
134
+ includer_b.include(a, i);
135
+ }
136
+ }
137
+ this.traverseCompare(a, b, i);
138
+ }
139
+ }
140
+ /**
141
+ * Some nodes, like Annotations, Annotation, PropertyValue have unique id
142
+ * among other same nodes. We can use it to know what to compare with what
143
+ * even if the order is different. IdProperty is a property name of that id,
144
+ * e.g. for Annotations it will be Target (like in
145
+ * Target="<some-unique-id>").
146
+ * @param property node which might have an id: Annotations, PropertyValue
147
+ * @return the property name which represents id: Target, Property
148
+ */
149
+ getIdProperty(property) {
150
+ return simpleIdentifiers.get(property);
151
+ }
152
+ }
153
+ exports.default = Comparator;
154
+ class Includer {
155
+ /**
156
+ * It will decide what to do with the item missing in one language.
157
+ * @param target an array which might miss the item
158
+ * @param property the node name needed to decide how to include the missing
159
+ * item in array
160
+ * @param shouldClear if the item is missing and it's not Label or QuickInfo
161
+ * or Heading, we clear all the properties except Ids, so in i18n.properties
162
+ * they will have empty values. Because we don't know what should be there.
163
+ */
164
+ constructor(target, property, shouldClear = true) {
165
+ this.ALL_DIFF_CASES = [
166
+ new interchangableCase_1.default()
167
+ ];
168
+ this.diffCases = new Array();
169
+ this.shouldClear = shouldClear;
170
+ this.target = target;
171
+ this.property = property;
172
+ for (const diffCase of this.ALL_DIFF_CASES) {
173
+ if (diffCase.canAccept(target, property)) {
174
+ this.diffCases.push(diffCase);
175
+ }
176
+ }
177
+ }
178
+ /**
179
+ * If in some language some array missing the item, we include the missing
180
+ * item from other language array with the same id.
181
+ * @param source the item from other language array that is missed in target
182
+ * @param index here to put it in the array
183
+ */
184
+ include(source, index) {
185
+ // Insert node with empty value (see test 02) if missing in default
186
+ // language or default language value if missing in other language
187
+ // (see test 03).
188
+ const clone = Includer.cloneAndClear(source[index], this.shouldClear);
189
+ (0, commonUtil_1.insertInArray)(this.target, index, clone);
190
+ // Some annotations like Label, QuickInfo or Heading are
191
+ // interchangable so if QuickInfo is missing we can copy the value
192
+ // from Label or Heading (see test 01).
193
+ for (const diffCase of this.diffCases) {
194
+ diffCase.accept(this.target, index, this.property);
195
+ }
196
+ }
197
+ /**
198
+ * if the item is missing in default language, and it's not Label or
199
+ * QuickInfo or Heading, we clear all the properties except Ids, so in
200
+ * i18n.properties they will have empty values. Because we don't know what
201
+ * should be there. But if the item is missing in language other than
202
+ * default, we include the copy of item from default language and not
203
+ * clearing them (see test 02, 04).
204
+ */
205
+ static cloneAndClear(obj, shouldClear = true) {
206
+ const clone = structuredClone(obj);
207
+ if (shouldClear) {
208
+ (0, commonUtil_1.traverse)(clone, [], (json, key) => {
209
+ if (typeof key !== "string" || !simpleIdentifiersReversed.has(key)) {
210
+ json[key] = "";
211
+ }
212
+ });
213
+ }
214
+ return clone;
215
+ }
216
+ }
217
+ class Items {
218
+ /**
219
+ * Map of id per item which is lazy initialized if needed
220
+ * @param array
221
+ * @param idProperty
222
+ */
223
+ constructor(array, idProperty) {
224
+ this.objectMap = null;
225
+ this.array = array;
226
+ this.idProperty = idProperty;
227
+ }
228
+ /**
229
+ * Find the item with by id and swap their places.
230
+ * @param id of the item which seems like not in the place it should be
231
+ * @param newIndex new place where the item should actually be
232
+ */
233
+ swap(id, newIndex) {
234
+ const oldIndex = this.initMap().get(id);
235
+ const temp = this.array[newIndex];
236
+ this.array[newIndex] = this.array[oldIndex];
237
+ this.array[oldIndex] = temp;
238
+ this.initMap(true);
239
+ }
240
+ has(idProperty) {
241
+ return this.initMap().has(idProperty);
242
+ }
243
+ get(idProperty) {
244
+ return this.array[this.initMap().get(idProperty)];
245
+ }
246
+ /**
247
+ * Lazy init the map only if the order of items are messed up, which
248
+ * actually an eexception, so will make it lazy way.
249
+ * @param force force to update.
250
+ * @returns the map id per item index.
251
+ */
252
+ initMap(force = false) {
253
+ if (this.objectMap == null || force) {
254
+ this.objectMap = new Map(this.array.map((item, index) => [item._attributes[this.idProperty], index]));
255
+ }
256
+ return this.objectMap;
257
+ }
258
+ }
259
+ class Identifiers extends Map {
260
+ has(property) {
261
+ return typeof property === "string" && super.has(property);
262
+ }
263
+ get(property) {
264
+ return typeof property === "string" ? super.get(property) : undefined;
265
+ }
266
+ }
267
+ // According to OData schema some nodes MUST have the ids, by these nodes the
268
+ // property which contains the id is named differently as you can see.
269
+ const simpleIdentifiers = new Identifiers([
270
+ ["Annotations", "Target"],
271
+ ["Annotation", "Term"],
272
+ ["LabeledElement", "Name"],
273
+ ["PropertyValue", "Property"]
274
+ ]);
275
+ const simpleIdentifiersReversed = new Identifiers([...simpleIdentifiers].map(([name, idProperty]) => [idProperty, name]));
276
+ //# sourceMappingURL=comparator.js.map
@@ -0,0 +1,4 @@
1
+ export default interface DiffCase {
2
+ accept(target: any[], i: number, name?: string): void;
3
+ canAccept(target: any[], name?: string): boolean;
4
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=diffCase.js.map
@@ -0,0 +1,25 @@
1
+ import DiffCase from "./diffCase";
2
+ export default class InterchangableCase implements DiffCase {
3
+ accept(target: any[], i: number, name: string): void;
4
+ /**
5
+ * When default language source is already compared, it contains diff, e.g.
6
+ * { __old: value, __new: wert 1 }, if target annotation in other language
7
+ * has other value, it should also reflect the value, be { __old: value,
8
+ * __new: wert 2 }, not { __old: value, __new: wert 1 }. So we remove the
9
+ * diff completely from value and let it be compared again. Other language
10
+ * source will be empty anyway.
11
+ */
12
+ private getSourceValue;
13
+ /**
14
+ * If the array doesn't have any other annotations to take the values from,
15
+ * we just don't do it and include the annotations from other language as it
16
+ * is. E.g. we include Label but there are no Heading or QuickInfo to take
17
+ * values from. So we just don't do it.
18
+ * @param target where to put the missing item
19
+ * @param property node name
20
+ * @returns true if there are some annotations to take the values from.
21
+ */
22
+ canAccept(target: any[], property: string): boolean;
23
+ private interchangableTerms;
24
+ private findByPriority;
25
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const comparator_1 = require("./comparator");
4
+ class InterchangableCase {
5
+ constructor() {
6
+ // If one of the terms is missing, its values can be filled by others.
7
+ // Usually Heading or QuickInfo is missing. So we order terms by source
8
+ // priority (take from label first).
9
+ this.interchangableTerms = ["SAP__common.Label", "SAP__common.Heading", "SAP__common.QuickInfo"];
10
+ }
11
+ accept(target, i, name) {
12
+ if (name === "Annotation" && this.interchangableTerms.includes(target[i]?._attributes?.Term)) {
13
+ const source = this.findByPriority(target, i);
14
+ if (source) {
15
+ for (const attribute of Object.keys(source._attributes)) {
16
+ if (attribute !== "Term") {
17
+ const sourceValue = this.getSourceValue(source, attribute);
18
+ target[i]._attributes[attribute] = sourceValue;
19
+ }
20
+ }
21
+ }
22
+ }
23
+ }
24
+ /**
25
+ * When default language source is already compared, it contains diff, e.g.
26
+ * { __old: value, __new: wert 1 }, if target annotation in other language
27
+ * has other value, it should also reflect the value, be { __old: value,
28
+ * __new: wert 2 }, not { __old: value, __new: wert 1 }. So we remove the
29
+ * diff completely from value and let it be compared again. Other language
30
+ * source will be empty anyway.
31
+ */
32
+ getSourceValue(source, attribute) {
33
+ let value = source._attributes[attribute];
34
+ if (value instanceof comparator_1.Diff) {
35
+ value = value.__old;
36
+ }
37
+ return value;
38
+ }
39
+ /**
40
+ * If the array doesn't have any other annotations to take the values from,
41
+ * we just don't do it and include the annotations from other language as it
42
+ * is. E.g. we include Label but there are no Heading or QuickInfo to take
43
+ * values from. So we just don't do it.
44
+ * @param target where to put the missing item
45
+ * @param property node name
46
+ * @returns true if there are some annotations to take the values from.
47
+ */
48
+ canAccept(target, property) {
49
+ return property === "Annotation" && target
50
+ .map(item => item._attributes?.Term)
51
+ .some(term => this.interchangableTerms.includes(term));
52
+ }
53
+ findByPriority(annotations, index) {
54
+ for (const interchangableTerm of this.interchangableTerms) {
55
+ for (const annotation of annotations) {
56
+ if (annotation._attributes?.Term === interchangableTerm &&
57
+ annotation !== annotations[index]) {
58
+ return annotation;
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
64
+ exports.default = InterchangableCase;
65
+ //# sourceMappingURL=interchangableCase.js.map
@@ -0,0 +1,12 @@
1
+ export default class MetadataJsonReferenceUtil {
2
+ private json;
3
+ private aliases;
4
+ private namespaces;
5
+ constructor(json: any);
6
+ aliasToNamespace(target: string): string;
7
+ namespaceToAlias(target: string): string;
8
+ private convertReference;
9
+ private getAliases;
10
+ private getNamespaces;
11
+ private initReferences;
12
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const metadataJsonUtil_1 = require("./metadataJsonUtil");
4
+ class MetadataJsonReferenceUtil {
5
+ constructor(json) {
6
+ this.aliases = null;
7
+ this.namespaces = null;
8
+ this.json = json;
9
+ }
10
+ aliasToNamespace(target) {
11
+ return this.convertReference(this.getAliases(), target);
12
+ }
13
+ namespaceToAlias(target) {
14
+ return this.convertReference(this.getNamespaces(), target);
15
+ }
16
+ convertReference(references, target) {
17
+ for (const alias of references.keys()) {
18
+ target = target.replaceAll(alias + ".", references.get(alias) + ".");
19
+ }
20
+ return target;
21
+ }
22
+ getAliases() {
23
+ this.initReferences();
24
+ return this.aliases;
25
+ }
26
+ getNamespaces() {
27
+ this.initReferences();
28
+ return this.namespaces;
29
+ }
30
+ initReferences() {
31
+ if (!this.aliases || !this.namespaces) {
32
+ const references = new Array();
33
+ for (const ref of metadataJsonUtil_1.default.getReferences(this.json)) {
34
+ references.push(...ref.includes);
35
+ }
36
+ references.push(metadataJsonUtil_1.default.getSchemaReference(this.json));
37
+ this.aliases = new Map();
38
+ this.namespaces = new Map();
39
+ for (const mapping of references) {
40
+ if (mapping.alias && mapping.namespace) {
41
+ const { alias, namespace } = mapping;
42
+ this.aliases.set(alias, namespace);
43
+ this.namespaces.set(namespace, alias);
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ exports.default = MetadataJsonReferenceUtil;
50
+ //# sourceMappingURL=metadataJsonReferenceUtil.js.map
@@ -0,0 +1,30 @@
1
+ export default class MetadataJsonUtil {
2
+ static mapAnnotationsPerTarget(json: any): Map<string, IJsonIndex>;
3
+ static getVersion(json: any): any;
4
+ static getAnnotations(json: any): any[];
5
+ static setAnnotations(json: any, annotations: any[]): void;
6
+ static getSchemaNode(json: any): any;
7
+ static getSchemaReference(json: any): MetadataInclude;
8
+ static getEdmx(json: any): any;
9
+ static getDataServices(json: any): any;
10
+ static getReferences(json: any): MetadataReference[];
11
+ static toArrayReadOnly(json: any): any[];
12
+ static toArrayTransform(json: any, property: string): void;
13
+ }
14
+ export declare class MetadataReference {
15
+ uri: string;
16
+ includes: MetadataInclude[];
17
+ constructor(referenceJson: any);
18
+ getAlias(namespace: string): string | undefined;
19
+ }
20
+ export declare class MetadataInclude {
21
+ namespace: string;
22
+ alias: string;
23
+ constructor(alias: string, namespace: string);
24
+ equals(other: MetadataInclude): boolean;
25
+ static fromJson(json: any): MetadataInclude;
26
+ }
27
+ export interface IJsonIndex {
28
+ json: any;
29
+ index: number;
30
+ }