@sapui5/sap.fe.core 1.95.0 → 1.98.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 (207) hide show
  1. package/package.json +5 -5
  2. package/src/sap/fe/core/.library +1 -1
  3. package/src/sap/fe/core/AnnotationHelper.js +3 -3
  4. package/src/sap/fe/core/AppComponent.js +9 -44
  5. package/src/sap/fe/core/AppStateHandler.js +2 -2
  6. package/src/sap/fe/core/BaseController.js +1 -1
  7. package/src/sap/fe/core/BusyLocker.js +13 -1
  8. package/src/sap/fe/core/CommonUtils.js +129 -219
  9. package/src/sap/fe/core/ExtensionAPI.js +14 -6
  10. package/src/sap/fe/core/PageController.js +9 -35
  11. package/src/sap/fe/core/RouterProxy.js +79 -75
  12. package/src/sap/fe/core/Synchronization.js +1 -1
  13. package/src/sap/fe/core/TemplateComponent.js +16 -7
  14. package/src/sap/fe/core/TemplateModel.js +1 -1
  15. package/src/sap/fe/core/TransactionHelper.js +183 -65
  16. package/src/sap/fe/core/actions/draft.js +50 -23
  17. package/src/sap/fe/core/actions/messageHandling.js +86 -7
  18. package/src/sap/fe/core/actions/nonDraft.js +1 -1
  19. package/src/sap/fe/core/actions/operations.js +75 -33
  20. package/src/sap/fe/core/actions/sticky.js +1 -1
  21. package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +1 -1
  22. package/src/sap/fe/core/controllerextensions/EditFlow.js +276 -122
  23. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +1 -1
  24. package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +14 -6
  25. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +90 -46
  26. package/src/sap/fe/core/controllerextensions/InternalRouting.js +234 -232
  27. package/src/sap/fe/core/controllerextensions/KPIManagement.js +539 -209
  28. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +550 -213
  29. package/src/sap/fe/core/controllerextensions/MassEdit.js +79 -0
  30. package/src/sap/fe/core/controllerextensions/MessageHandler.js +227 -103
  31. package/src/sap/fe/core/controllerextensions/PageReady.js +2 -2
  32. package/src/sap/fe/core/controllerextensions/PageReady.ts +3 -7
  33. package/src/sap/fe/core/controllerextensions/Paginator.js +38 -12
  34. package/src/sap/fe/core/controllerextensions/Placeholder.js +16 -19
  35. package/src/sap/fe/core/controllerextensions/Routing.js +17 -2
  36. package/src/sap/fe/core/controllerextensions/RoutingListener.js +1 -1
  37. package/src/sap/fe/core/controllerextensions/Share.js +20 -7
  38. package/src/sap/fe/core/controllerextensions/SideEffects.js +8 -9
  39. package/src/sap/fe/core/controllerextensions/SideEffects.ts +19 -17
  40. package/src/sap/fe/core/controllerextensions/ViewState.js +54 -9
  41. package/src/sap/fe/core/controls/ActionParameterDialog.fragment.xml +40 -34
  42. package/src/sap/fe/core/controls/ActionParameterDialogValueHelp.fragment.xml +35 -0
  43. package/src/sap/fe/core/controls/CommandExecution.js +1 -1
  44. package/src/sap/fe/core/controls/ConditionalWrapper.js +1 -1
  45. package/src/sap/fe/core/controls/CustomQuickViewPage.js +110 -109
  46. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +7 -4
  47. package/src/sap/fe/core/controls/FieldWrapper.js +10 -4
  48. package/src/sap/fe/core/controls/FilterBar.js +1 -1
  49. package/src/sap/fe/core/controls/FormElementWrapper.js +1 -6
  50. package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +45 -0
  51. package/src/sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog.fragment.xml +1 -1
  52. package/src/sap/fe/core/controls/filterbar/FilterContainer.js +1 -1
  53. package/src/sap/fe/core/controls/filterbar/VisualFilter.js +1 -1
  54. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +1 -1
  55. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +1 -1
  56. package/src/sap/fe/core/controls/massEdit/MassEditDialog.fragment.xml +106 -0
  57. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +78 -0
  58. package/src/sap/fe/core/converters/ConverterContext.js +13 -1
  59. package/src/sap/fe/core/converters/ConverterContext.ts +10 -0
  60. package/src/sap/fe/core/converters/ManifestSettings.js +2 -1
  61. package/src/sap/fe/core/converters/ManifestSettings.ts +7 -1
  62. package/src/sap/fe/core/converters/ManifestWrapper.js +18 -7
  63. package/src/sap/fe/core/converters/ManifestWrapper.ts +15 -6
  64. package/src/sap/fe/core/converters/MetaModelConverter.js +920 -882
  65. package/src/sap/fe/core/converters/MetaModelConverter.ts +829 -853
  66. package/src/sap/fe/core/converters/annotations/DataField.js +54 -4
  67. package/src/sap/fe/core/converters/annotations/DataField.ts +53 -3
  68. package/src/sap/fe/core/converters/common/AnnotationConverter.js +83 -48
  69. package/src/sap/fe/core/converters/controls/Common/Action.js +15 -3
  70. package/src/sap/fe/core/converters/controls/Common/Action.ts +12 -3
  71. package/src/sap/fe/core/converters/controls/Common/Chart.js +1 -3
  72. package/src/sap/fe/core/converters/controls/Common/Chart.ts +0 -2
  73. package/src/sap/fe/core/converters/controls/Common/Form.js +68 -21
  74. package/src/sap/fe/core/converters/controls/Common/Form.ts +60 -16
  75. package/src/sap/fe/core/converters/controls/Common/KPI.js +331 -248
  76. package/src/sap/fe/core/converters/controls/Common/KPI.ts +355 -287
  77. package/src/sap/fe/core/converters/controls/Common/Table.js +426 -332
  78. package/src/sap/fe/core/converters/controls/Common/Table.ts +516 -383
  79. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +468 -0
  80. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +609 -0
  81. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +30 -13
  82. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +31 -12
  83. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.js +2 -2
  84. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.ts +1 -1
  85. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +15 -7
  86. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +27 -6
  87. package/src/sap/fe/core/converters/helpers/Aggregation.js +8 -1
  88. package/src/sap/fe/core/converters/helpers/Aggregation.ts +9 -1
  89. package/src/sap/fe/core/converters/helpers/BindingHelper.js +3 -2
  90. package/src/sap/fe/core/converters/helpers/BindingHelper.ts +2 -2
  91. package/src/sap/fe/core/converters/helpers/ID.js +9 -1
  92. package/src/sap/fe/core/converters/helpers/ID.ts +6 -2
  93. package/src/sap/fe/core/converters/helpers/IssueManager.js +7 -5
  94. package/src/sap/fe/core/converters/helpers/IssueManager.ts +6 -4
  95. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +2 -2
  96. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +1 -1
  97. package/src/sap/fe/core/converters/templates/ListReportConverter.js +34 -4
  98. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +36 -7
  99. package/src/sap/fe/core/converters/templates/ObjectPageConverter.js +2 -5
  100. package/src/sap/fe/core/converters/templates/ObjectPageConverter.ts +1 -2
  101. package/src/sap/fe/core/designtime/AppComponent.designtime.js +11 -2
  102. package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
  103. package/src/sap/fe/core/formatters/FPMFormatter.ts +8 -3
  104. package/src/sap/fe/core/formatters/TableFormatter.js +27 -4
  105. package/src/sap/fe/core/formatters/TableFormatter.ts +20 -3
  106. package/src/sap/fe/core/formatters/ValueFormatter.js +30 -5
  107. package/src/sap/fe/core/formatters/ValueFormatter.ts +25 -3
  108. package/src/sap/fe/core/fpm/Component.js +2 -2
  109. package/src/sap/fe/core/helpers/AppStartupHelper.js +359 -0
  110. package/src/sap/fe/core/helpers/AppStartupHelper.ts +388 -0
  111. package/src/sap/fe/core/helpers/BindingExpression.js +199 -111
  112. package/src/sap/fe/core/helpers/BindingExpression.ts +193 -102
  113. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +1 -1
  114. package/src/sap/fe/core/helpers/EditState.js +1 -1
  115. package/src/sap/fe/core/helpers/ExcelFormatHelper.js +1 -3
  116. package/src/sap/fe/core/helpers/FPMHelper.js +1 -1
  117. package/src/sap/fe/core/helpers/KeepAliveHelper.js +211 -0
  118. package/src/sap/fe/core/helpers/KeepAliveHelper.ts +202 -0
  119. package/src/sap/fe/core/helpers/KeepAliveRefreshTypes.js +32 -0
  120. package/src/sap/fe/core/helpers/KeepAliveRefreshTypes.ts +36 -0
  121. package/src/sap/fe/core/helpers/MassEditHelper.js +678 -0
  122. package/src/sap/fe/core/helpers/ModelHelper.js +64 -1
  123. package/src/sap/fe/core/helpers/PasteHelper.js +7 -1
  124. package/src/sap/fe/core/helpers/SemanticDateOperators.js +1 -1
  125. package/src/sap/fe/core/helpers/SemanticKeyHelper.js +1 -1
  126. package/src/sap/fe/core/helpers/StableIdHelper.js +2 -2
  127. package/src/sap/fe/core/helpers/StableIdHelper.ts +1 -1
  128. package/src/sap/fe/core/library.js +28 -2
  129. package/src/sap/fe/core/library.support.js +10 -4
  130. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +62 -0
  131. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +66 -0
  132. package/src/sap/fe/core/messagebundle.properties +67 -3
  133. package/src/sap/fe/core/messagebundle_ar.properties +40 -3
  134. package/src/sap/fe/core/messagebundle_bg.properties +40 -3
  135. package/src/sap/fe/core/messagebundle_ca.properties +41 -4
  136. package/src/sap/fe/core/messagebundle_cs.properties +41 -4
  137. package/src/sap/fe/core/messagebundle_cy.properties +40 -3
  138. package/src/sap/fe/core/messagebundle_da.properties +40 -3
  139. package/src/sap/fe/core/messagebundle_de.properties +40 -3
  140. package/src/sap/fe/core/messagebundle_el.properties +40 -3
  141. package/src/sap/fe/core/messagebundle_en.properties +37 -0
  142. package/src/sap/fe/core/messagebundle_en_GB.properties +37 -0
  143. package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +37 -0
  144. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +46 -2
  145. package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +44 -0
  146. package/src/sap/fe/core/messagebundle_es.properties +40 -3
  147. package/src/sap/fe/core/messagebundle_es_MX.properties +41 -4
  148. package/src/sap/fe/core/messagebundle_et.properties +40 -3
  149. package/src/sap/fe/core/messagebundle_fi.properties +40 -3
  150. package/src/sap/fe/core/messagebundle_fr.properties +41 -4
  151. package/src/sap/fe/core/messagebundle_fr_CA.properties +40 -3
  152. package/src/sap/fe/core/messagebundle_hi.properties +40 -3
  153. package/src/sap/fe/core/messagebundle_hr.properties +40 -3
  154. package/src/sap/fe/core/messagebundle_hu.properties +41 -4
  155. package/src/sap/fe/core/messagebundle_id.properties +42 -5
  156. package/src/sap/fe/core/messagebundle_it.properties +40 -3
  157. package/src/sap/fe/core/messagebundle_iw.properties +40 -3
  158. package/src/sap/fe/core/messagebundle_ja.properties +49 -12
  159. package/src/sap/fe/core/messagebundle_kk.properties +40 -3
  160. package/src/sap/fe/core/messagebundle_ko.properties +40 -3
  161. package/src/sap/fe/core/messagebundle_lt.properties +40 -3
  162. package/src/sap/fe/core/messagebundle_lv.properties +40 -3
  163. package/src/sap/fe/core/messagebundle_ms.properties +40 -3
  164. package/src/sap/fe/core/messagebundle_nl.properties +40 -3
  165. package/src/sap/fe/core/messagebundle_no.properties +40 -3
  166. package/src/sap/fe/core/messagebundle_pl.properties +40 -3
  167. package/src/sap/fe/core/messagebundle_pt.properties +42 -5
  168. package/src/sap/fe/core/messagebundle_pt_PT.properties +40 -3
  169. package/src/sap/fe/core/messagebundle_ro.properties +40 -3
  170. package/src/sap/fe/core/messagebundle_ru.properties +40 -3
  171. package/src/sap/fe/core/messagebundle_sh.properties +40 -3
  172. package/src/sap/fe/core/messagebundle_sk.properties +40 -3
  173. package/src/sap/fe/core/messagebundle_sl.properties +40 -3
  174. package/src/sap/fe/core/messagebundle_sv.properties +41 -4
  175. package/src/sap/fe/core/messagebundle_th.properties +40 -3
  176. package/src/sap/fe/core/messagebundle_tr.properties +40 -3
  177. package/src/sap/fe/core/messagebundle_uk.properties +40 -3
  178. package/src/sap/fe/core/messagebundle_vi.properties +40 -3
  179. package/src/sap/fe/core/messagebundle_zh_CN.properties +40 -3
  180. package/src/sap/fe/core/messagebundle_zh_TW.properties +40 -3
  181. package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +1 -1
  182. package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +1 -1
  183. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +4 -3
  184. package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +3 -0
  185. package/src/sap/fe/core/services/NavigationServiceFactory.js +1 -1
  186. package/src/sap/fe/core/services/ResourceModelServiceFactory.js +1 -1
  187. package/src/sap/fe/core/services/RoutingServiceFactory.js +98 -328
  188. package/src/sap/fe/core/services/ShellServicesFactory.js +31 -2
  189. package/src/sap/fe/core/services/ShellServicesFactory.ts +30 -1
  190. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +8 -5
  191. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +11 -6
  192. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +14 -5
  193. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +1 -1
  194. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.js +38 -0
  195. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.ts +18 -0
  196. package/src/sap/fe/core/templating/DataModelPathHelper.js +8 -37
  197. package/src/sap/fe/core/templating/DataModelPathHelper.ts +13 -33
  198. package/src/sap/fe/core/templating/DisplayModeFormatter.js +114 -0
  199. package/src/sap/fe/core/templating/DisplayModeFormatter.ts +86 -0
  200. package/src/sap/fe/core/templating/EntitySetHelper.js +86 -3
  201. package/src/sap/fe/core/templating/EntitySetHelper.ts +44 -0
  202. package/src/sap/fe/core/templating/FilterHelper.js +10 -7
  203. package/src/sap/fe/core/templating/FilterHelper.ts +8 -6
  204. package/src/sap/fe/core/templating/PropertyHelper.js +2 -2
  205. package/src/sap/fe/core/templating/PropertyHelper.ts +1 -1
  206. package/src/sap/fe/core/templating/UIFormatters.js +47 -107
  207. package/src/sap/fe/core/templating/UIFormatters.ts +76 -72
@@ -6,6 +6,7 @@ import {
6
6
  ConverterOutput,
7
7
  EntitySet as _EntitySet,
8
8
  EntityType as _EntityType,
9
+ Singleton as _Singleton,
9
10
  NavigationProperty as _NavigationProperty
10
11
  } from "@sap-ux/annotation-converter";
11
12
  import {
@@ -18,7 +19,8 @@ import {
18
19
  Action,
19
20
  Reference,
20
21
  EntityContainer,
21
- Singleton
22
+ Singleton,
23
+ TypeDefinition
22
24
  } from "@sap-ux/vocabularies-types/dist/Parser";
23
25
  import { Context } from "sap/ui/model";
24
26
  import { DataModelObjectPath } from "sap/fe/core/templating/DataModelPathHelper";
@@ -41,13 +43,15 @@ export type EnvironmentCapabilities = {
41
43
  MicroChart: boolean;
42
44
  UShell: boolean;
43
45
  IntentBasedNavigation: boolean;
46
+ Situations: boolean;
44
47
  };
45
48
 
46
49
  export const DefaultEnvironmentCapabilities = {
47
50
  Chart: true,
48
51
  MicroChart: true,
49
52
  UShell: true,
50
- IntentBasedNavigation: true
53
+ IntentBasedNavigation: true,
54
+ Situations: false
51
55
  };
52
56
 
53
57
  type MetaModelAction = {
@@ -68,944 +72,871 @@ type MetaModelAction = {
68
72
  };
69
73
  };
70
74
 
71
- const MetaModelConverter = {
72
- parsePropertyValue(
73
- annotationObject: any,
74
- propertyKey: string,
75
- currentTarget: string,
76
- annotationsLists: any[],
77
- oCapabilities: EnvironmentCapabilities
78
- ): any {
79
- let value;
80
- const currentPropertyTarget: string = currentTarget + "/" + propertyKey;
81
- if (annotationObject === null) {
82
- value = { type: "Null", Null: null };
83
- } else if (typeof annotationObject === "string") {
84
- value = { type: "String", String: annotationObject };
85
- } else if (typeof annotationObject === "boolean") {
86
- value = { type: "Bool", Bool: annotationObject };
87
- } else if (typeof annotationObject === "number") {
88
- value = { type: "Int", Int: annotationObject };
89
- } else if (Array.isArray(annotationObject)) {
90
- value = {
91
- type: "Collection",
92
- Collection: annotationObject.map((subAnnotationObject, subAnnotationObjectIndex) =>
93
- this.parseAnnotationObject(
94
- subAnnotationObject,
95
- currentPropertyTarget + "/" + subAnnotationObjectIndex,
96
- annotationsLists,
97
- oCapabilities
98
- )
75
+ function parsePropertyValue(
76
+ annotationObject: any,
77
+ propertyKey: string,
78
+ currentTarget: string,
79
+ annotationsLists: Record<string, AnnotationList>,
80
+ oCapabilities: EnvironmentCapabilities
81
+ ): any {
82
+ let value;
83
+ const currentPropertyTarget: string = currentTarget + "/" + propertyKey;
84
+ const typeOfAnnotation = typeof annotationObject;
85
+ if (annotationObject === null) {
86
+ value = { type: "Null", Null: null };
87
+ } else if (typeOfAnnotation === "string") {
88
+ value = { type: "String", String: annotationObject };
89
+ } else if (typeOfAnnotation === "boolean") {
90
+ value = { type: "Bool", Bool: annotationObject };
91
+ } else if (typeOfAnnotation === "number") {
92
+ value = { type: "Int", Int: annotationObject };
93
+ } else if (Array.isArray(annotationObject)) {
94
+ value = {
95
+ type: "Collection",
96
+ Collection: annotationObject.map((subAnnotationObject, subAnnotationObjectIndex) =>
97
+ parseAnnotationObject(
98
+ subAnnotationObject,
99
+ currentPropertyTarget + "/" + subAnnotationObjectIndex,
100
+ annotationsLists,
101
+ oCapabilities
99
102
  )
100
- };
101
- if (annotationObject.length > 0) {
102
- if (annotationObject[0].hasOwnProperty("$PropertyPath")) {
103
- (value.Collection as any).type = "PropertyPath";
104
- } else if (annotationObject[0].hasOwnProperty("$Path")) {
105
- (value.Collection as any).type = "Path";
106
- } else if (annotationObject[0].hasOwnProperty("$NavigationPropertyPath")) {
107
- (value.Collection as any).type = "NavigationPropertyPath";
108
- } else if (annotationObject[0].hasOwnProperty("$AnnotationPath")) {
109
- (value.Collection as any).type = "AnnotationPath";
110
- } else if (annotationObject[0].hasOwnProperty("$Type")) {
111
- (value.Collection as any).type = "Record";
112
- } else if (annotationObject[0].hasOwnProperty("$If")) {
113
- (value.Collection as any).type = "If";
114
- } else if (annotationObject[0].hasOwnProperty("$Or")) {
115
- (value.Collection as any).type = "Or";
116
- } else if (annotationObject[0].hasOwnProperty("$And")) {
117
- (value.Collection as any).type = "And";
118
- } else if (annotationObject[0].hasOwnProperty("$Eq")) {
119
- (value.Collection as any).type = "Eq";
120
- } else if (annotationObject[0].hasOwnProperty("$Ne")) {
121
- (value.Collection as any).type = "Ne";
122
- } else if (annotationObject[0].hasOwnProperty("$Not")) {
123
- (value.Collection as any).type = "Not";
124
- } else if (annotationObject[0].hasOwnProperty("$Gt")) {
125
- (value.Collection as any).type = "Gt";
126
- } else if (annotationObject[0].hasOwnProperty("$Ge")) {
127
- (value.Collection as any).type = "Ge";
128
- } else if (annotationObject[0].hasOwnProperty("$Lt")) {
129
- (value.Collection as any).type = "Lt";
130
- } else if (annotationObject[0].hasOwnProperty("$Le")) {
131
- (value.Collection as any).type = "Le";
132
- } else if (annotationObject[0].hasOwnProperty("$Apply")) {
133
- (value.Collection as any).type = "Apply";
134
- } else if (typeof annotationObject[0] === "object") {
135
- // $Type is optional...
136
- (value.Collection as any).type = "Record";
137
- } else {
138
- (value.Collection as any).type = "String";
139
- }
103
+ )
104
+ };
105
+ if (annotationObject.length > 0) {
106
+ if (annotationObject[0].hasOwnProperty("$PropertyPath")) {
107
+ (value.Collection as any).type = "PropertyPath";
108
+ } else if (annotationObject[0].hasOwnProperty("$Path")) {
109
+ (value.Collection as any).type = "Path";
110
+ } else if (annotationObject[0].hasOwnProperty("$NavigationPropertyPath")) {
111
+ (value.Collection as any).type = "NavigationPropertyPath";
112
+ } else if (annotationObject[0].hasOwnProperty("$AnnotationPath")) {
113
+ (value.Collection as any).type = "AnnotationPath";
114
+ } else if (annotationObject[0].hasOwnProperty("$Type")) {
115
+ (value.Collection as any).type = "Record";
116
+ } else if (annotationObject[0].hasOwnProperty("$If")) {
117
+ (value.Collection as any).type = "If";
118
+ } else if (annotationObject[0].hasOwnProperty("$Or")) {
119
+ (value.Collection as any).type = "Or";
120
+ } else if (annotationObject[0].hasOwnProperty("$And")) {
121
+ (value.Collection as any).type = "And";
122
+ } else if (annotationObject[0].hasOwnProperty("$Eq")) {
123
+ (value.Collection as any).type = "Eq";
124
+ } else if (annotationObject[0].hasOwnProperty("$Ne")) {
125
+ (value.Collection as any).type = "Ne";
126
+ } else if (annotationObject[0].hasOwnProperty("$Not")) {
127
+ (value.Collection as any).type = "Not";
128
+ } else if (annotationObject[0].hasOwnProperty("$Gt")) {
129
+ (value.Collection as any).type = "Gt";
130
+ } else if (annotationObject[0].hasOwnProperty("$Ge")) {
131
+ (value.Collection as any).type = "Ge";
132
+ } else if (annotationObject[0].hasOwnProperty("$Lt")) {
133
+ (value.Collection as any).type = "Lt";
134
+ } else if (annotationObject[0].hasOwnProperty("$Le")) {
135
+ (value.Collection as any).type = "Le";
136
+ } else if (annotationObject[0].hasOwnProperty("$Apply")) {
137
+ (value.Collection as any).type = "Apply";
138
+ } else if (typeof annotationObject[0] === "object") {
139
+ // $Type is optional...
140
+ (value.Collection as any).type = "Record";
141
+ } else {
142
+ (value.Collection as any).type = "String";
140
143
  }
141
- } else if (annotationObject.$Path !== undefined) {
142
- value = { type: "Path", Path: annotationObject.$Path };
143
- } else if (annotationObject.$Decimal !== undefined) {
144
- value = { type: "Decimal", Decimal: parseFloat(annotationObject.$Decimal) };
145
- } else if (annotationObject.$PropertyPath !== undefined) {
146
- value = { type: "PropertyPath", PropertyPath: annotationObject.$PropertyPath };
147
- } else if (annotationObject.$NavigationPropertyPath !== undefined) {
148
- value = {
149
- type: "NavigationPropertyPath",
150
- NavigationPropertyPath: annotationObject.$NavigationPropertyPath
151
- };
152
- } else if (annotationObject.$If !== undefined) {
153
- value = { type: "If", If: annotationObject.$If };
154
- } else if (annotationObject.$And !== undefined) {
155
- value = { type: "And", And: annotationObject.$And };
156
- } else if (annotationObject.$Or !== undefined) {
157
- value = { type: "Or", Or: annotationObject.$Or };
158
- } else if (annotationObject.$Not !== undefined) {
159
- value = { type: "Not", Not: annotationObject.$Not };
160
- } else if (annotationObject.$Eq !== undefined) {
161
- value = { type: "Eq", Eq: annotationObject.$Eq };
162
- } else if (annotationObject.$Ne !== undefined) {
163
- value = { type: "Ne", Ne: annotationObject.$Ne };
164
- } else if (annotationObject.$Gt !== undefined) {
165
- value = { type: "Gt", Gt: annotationObject.$Gt };
166
- } else if (annotationObject.$Ge !== undefined) {
167
- value = { type: "Ge", Ge: annotationObject.$Ge };
168
- } else if (annotationObject.$Lt !== undefined) {
169
- value = { type: "Lt", Lt: annotationObject.$Lt };
170
- } else if (annotationObject.$Le !== undefined) {
171
- value = { type: "Le", Le: annotationObject.$Le };
172
- } else if (annotationObject.$Apply !== undefined) {
173
- value = { type: "Apply", Apply: annotationObject.$Apply, Function: annotationObject.$Function };
174
- } else if (annotationObject.$AnnotationPath !== undefined) {
175
- value = { type: "AnnotationPath", AnnotationPath: annotationObject.$AnnotationPath };
176
- } else if (annotationObject.$EnumMember !== undefined) {
177
- value = {
178
- type: "EnumMember",
179
- EnumMember:
180
- this.mapNameToAlias(annotationObject.$EnumMember.split("/")[0]) + "/" + annotationObject.$EnumMember.split("/")[1]
181
- };
182
- } else if (annotationObject.$Type) {
183
- value = {
184
- type: "Record",
185
- Record: this.parseAnnotationObject(annotationObject, currentTarget, annotationsLists, oCapabilities)
186
- };
187
- } else {
188
- value = {
189
- type: "Record",
190
- Record: this.parseAnnotationObject(annotationObject, currentTarget, annotationsLists, oCapabilities)
191
- };
192
144
  }
145
+ } else if (annotationObject.$Path !== undefined) {
146
+ value = { type: "Path", Path: annotationObject.$Path };
147
+ } else if (annotationObject.$Decimal !== undefined) {
148
+ value = { type: "Decimal", Decimal: parseFloat(annotationObject.$Decimal) };
149
+ } else if (annotationObject.$PropertyPath !== undefined) {
150
+ value = { type: "PropertyPath", PropertyPath: annotationObject.$PropertyPath };
151
+ } else if (annotationObject.$NavigationPropertyPath !== undefined) {
152
+ value = {
153
+ type: "NavigationPropertyPath",
154
+ NavigationPropertyPath: annotationObject.$NavigationPropertyPath
155
+ };
156
+ } else if (annotationObject.$If !== undefined) {
157
+ value = { type: "If", If: annotationObject.$If };
158
+ } else if (annotationObject.$And !== undefined) {
159
+ value = { type: "And", And: annotationObject.$And };
160
+ } else if (annotationObject.$Or !== undefined) {
161
+ value = { type: "Or", Or: annotationObject.$Or };
162
+ } else if (annotationObject.$Not !== undefined) {
163
+ value = { type: "Not", Not: annotationObject.$Not };
164
+ } else if (annotationObject.$Eq !== undefined) {
165
+ value = { type: "Eq", Eq: annotationObject.$Eq };
166
+ } else if (annotationObject.$Ne !== undefined) {
167
+ value = { type: "Ne", Ne: annotationObject.$Ne };
168
+ } else if (annotationObject.$Gt !== undefined) {
169
+ value = { type: "Gt", Gt: annotationObject.$Gt };
170
+ } else if (annotationObject.$Ge !== undefined) {
171
+ value = { type: "Ge", Ge: annotationObject.$Ge };
172
+ } else if (annotationObject.$Lt !== undefined) {
173
+ value = { type: "Lt", Lt: annotationObject.$Lt };
174
+ } else if (annotationObject.$Le !== undefined) {
175
+ value = { type: "Le", Le: annotationObject.$Le };
176
+ } else if (annotationObject.$Apply !== undefined) {
177
+ value = { type: "Apply", Apply: annotationObject.$Apply, Function: annotationObject.$Function };
178
+ } else if (annotationObject.$AnnotationPath !== undefined) {
179
+ value = { type: "AnnotationPath", AnnotationPath: annotationObject.$AnnotationPath };
180
+ } else if (annotationObject.$EnumMember !== undefined) {
181
+ value = {
182
+ type: "EnumMember",
183
+ EnumMember: mapNameToAlias(annotationObject.$EnumMember.split("/")[0]) + "/" + annotationObject.$EnumMember.split("/")[1]
184
+ };
185
+ } else if (annotationObject.$Type) {
186
+ value = {
187
+ type: "Record",
188
+ Record: parseAnnotationObject(annotationObject, currentTarget, annotationsLists, oCapabilities)
189
+ };
190
+ } else {
191
+ value = {
192
+ type: "Record",
193
+ Record: parseAnnotationObject(annotationObject, currentTarget, annotationsLists, oCapabilities)
194
+ };
195
+ }
193
196
 
194
- return {
195
- name: propertyKey,
196
- value
197
+ return {
198
+ name: propertyKey,
199
+ value
200
+ };
201
+ }
202
+ function mapNameToAlias(annotationName: string): string {
203
+ let [pathPart, annoPart] = annotationName.split("@");
204
+ if (!annoPart) {
205
+ annoPart = pathPart;
206
+ pathPart = "";
207
+ } else {
208
+ pathPart += "@";
209
+ }
210
+ const lastDot = annoPart.lastIndexOf(".");
211
+ return pathPart + VOCABULARY_ALIAS[annoPart.substr(0, lastDot)] + "." + annoPart.substr(lastDot + 1);
212
+ }
213
+ function parseAnnotationObject(
214
+ annotationObject: any,
215
+ currentObjectTarget: string,
216
+ annotationsLists: Record<string, AnnotationList>,
217
+ oCapabilities: EnvironmentCapabilities
218
+ ): Expression | AnnotationRecord | Annotation {
219
+ let parsedAnnotationObject: any = {};
220
+ const typeOfObject = typeof annotationObject;
221
+ if (annotationObject === null) {
222
+ parsedAnnotationObject = { type: "Null", Null: null };
223
+ } else if (typeOfObject === "string") {
224
+ parsedAnnotationObject = { type: "String", String: annotationObject };
225
+ } else if (typeOfObject === "boolean") {
226
+ parsedAnnotationObject = { type: "Bool", Bool: annotationObject };
227
+ } else if (typeOfObject === "number") {
228
+ parsedAnnotationObject = { type: "Int", Int: annotationObject };
229
+ } else if (annotationObject.$AnnotationPath !== undefined) {
230
+ parsedAnnotationObject = { type: "AnnotationPath", AnnotationPath: annotationObject.$AnnotationPath };
231
+ } else if (annotationObject.$Path !== undefined) {
232
+ parsedAnnotationObject = { type: "Path", Path: annotationObject.$Path };
233
+ } else if (annotationObject.$Decimal !== undefined) {
234
+ parsedAnnotationObject = { type: "Decimal", Decimal: parseFloat(annotationObject.$Decimal) };
235
+ } else if (annotationObject.$PropertyPath !== undefined) {
236
+ parsedAnnotationObject = { type: "PropertyPath", PropertyPath: annotationObject.$PropertyPath };
237
+ } else if (annotationObject.$If !== undefined) {
238
+ parsedAnnotationObject = { type: "If", If: annotationObject.$If };
239
+ } else if (annotationObject.$And !== undefined) {
240
+ parsedAnnotationObject = { type: "And", And: annotationObject.$And };
241
+ } else if (annotationObject.$Or !== undefined) {
242
+ parsedAnnotationObject = { type: "Or", Or: annotationObject.$Or };
243
+ } else if (annotationObject.$Not !== undefined) {
244
+ parsedAnnotationObject = { type: "Not", Not: annotationObject.$Not };
245
+ } else if (annotationObject.$Eq !== undefined) {
246
+ parsedAnnotationObject = { type: "Eq", Eq: annotationObject.$Eq };
247
+ } else if (annotationObject.$Ne !== undefined) {
248
+ parsedAnnotationObject = { type: "Ne", Ne: annotationObject.$Ne };
249
+ } else if (annotationObject.$Gt !== undefined) {
250
+ parsedAnnotationObject = { type: "Gt", Gt: annotationObject.$Gt };
251
+ } else if (annotationObject.$Ge !== undefined) {
252
+ parsedAnnotationObject = { type: "Ge", Ge: annotationObject.$Ge };
253
+ } else if (annotationObject.$Lt !== undefined) {
254
+ parsedAnnotationObject = { type: "Lt", Lt: annotationObject.$Lt };
255
+ } else if (annotationObject.$Le !== undefined) {
256
+ parsedAnnotationObject = { type: "Le", Le: annotationObject.$Le };
257
+ } else if (annotationObject.$Apply !== undefined) {
258
+ parsedAnnotationObject = { type: "Apply", Apply: annotationObject.$Apply, Function: annotationObject.$Function };
259
+ } else if (annotationObject.$NavigationPropertyPath !== undefined) {
260
+ parsedAnnotationObject = {
261
+ type: "NavigationPropertyPath",
262
+ NavigationPropertyPath: annotationObject.$NavigationPropertyPath
263
+ };
264
+ } else if (annotationObject.$EnumMember !== undefined) {
265
+ parsedAnnotationObject = {
266
+ type: "EnumMember",
267
+ EnumMember: mapNameToAlias(annotationObject.$EnumMember.split("/")[0]) + "/" + annotationObject.$EnumMember.split("/")[1]
268
+ };
269
+ } else if (Array.isArray(annotationObject)) {
270
+ const parsedAnnotationCollection = parsedAnnotationObject as any;
271
+ parsedAnnotationCollection.collection = annotationObject.map((subAnnotationObject, subAnnotationIndex) =>
272
+ parseAnnotationObject(subAnnotationObject, currentObjectTarget + "/" + subAnnotationIndex, annotationsLists, oCapabilities)
273
+ );
274
+ if (annotationObject.length > 0) {
275
+ if (annotationObject[0].hasOwnProperty("$PropertyPath")) {
276
+ (parsedAnnotationCollection.collection as any).type = "PropertyPath";
277
+ } else if (annotationObject[0].hasOwnProperty("$Path")) {
278
+ (parsedAnnotationCollection.collection as any).type = "Path";
279
+ } else if (annotationObject[0].hasOwnProperty("$NavigationPropertyPath")) {
280
+ (parsedAnnotationCollection.collection as any).type = "NavigationPropertyPath";
281
+ } else if (annotationObject[0].hasOwnProperty("$AnnotationPath")) {
282
+ (parsedAnnotationCollection.collection as any).type = "AnnotationPath";
283
+ } else if (annotationObject[0].hasOwnProperty("$Type")) {
284
+ (parsedAnnotationCollection.collection as any).type = "Record";
285
+ } else if (annotationObject[0].hasOwnProperty("$If")) {
286
+ (parsedAnnotationCollection.collection as any).type = "If";
287
+ } else if (annotationObject[0].hasOwnProperty("$And")) {
288
+ (parsedAnnotationCollection.collection as any).type = "And";
289
+ } else if (annotationObject[0].hasOwnProperty("$Or")) {
290
+ (parsedAnnotationCollection.collection as any).type = "Or";
291
+ } else if (annotationObject[0].hasOwnProperty("$Eq")) {
292
+ (parsedAnnotationCollection.collection as any).type = "Eq";
293
+ } else if (annotationObject[0].hasOwnProperty("$Ne")) {
294
+ (parsedAnnotationCollection.collection as any).type = "Ne";
295
+ } else if (annotationObject[0].hasOwnProperty("$Not")) {
296
+ (parsedAnnotationCollection.collection as any).type = "Not";
297
+ } else if (annotationObject[0].hasOwnProperty("$Gt")) {
298
+ (parsedAnnotationCollection.collection as any).type = "Gt";
299
+ } else if (annotationObject[0].hasOwnProperty("$Ge")) {
300
+ (parsedAnnotationCollection.collection as any).type = "Ge";
301
+ } else if (annotationObject[0].hasOwnProperty("$Lt")) {
302
+ (parsedAnnotationCollection.collection as any).type = "Lt";
303
+ } else if (annotationObject[0].hasOwnProperty("$Le")) {
304
+ (parsedAnnotationCollection.collection as any).type = "Le";
305
+ } else if (annotationObject[0].hasOwnProperty("$Apply")) {
306
+ (parsedAnnotationCollection.collection as any).type = "Apply";
307
+ } else if (typeof annotationObject[0] === "object") {
308
+ (parsedAnnotationCollection.collection as any).type = "Record";
309
+ } else {
310
+ (parsedAnnotationCollection.collection as any).type = "String";
311
+ }
312
+ }
313
+ } else {
314
+ if (annotationObject.$Type) {
315
+ const typeValue = annotationObject.$Type;
316
+ parsedAnnotationObject.type = typeValue; //`${typeAlias}.${typeTerm}`;
317
+ }
318
+ const propertyValues: any = [];
319
+ Object.keys(annotationObject).forEach(propertyKey => {
320
+ if (
321
+ propertyKey !== "$Type" &&
322
+ propertyKey !== "$If" &&
323
+ propertyKey !== "$Apply" &&
324
+ propertyKey !== "$And" &&
325
+ propertyKey !== "$Or" &&
326
+ propertyKey !== "$Ne" &&
327
+ propertyKey !== "$Gt" &&
328
+ propertyKey !== "$Ge" &&
329
+ propertyKey !== "$Lt" &&
330
+ propertyKey !== "$Le" &&
331
+ propertyKey !== "$Not" &&
332
+ propertyKey !== "$Eq" &&
333
+ !propertyKey.startsWith("@")
334
+ ) {
335
+ propertyValues.push(
336
+ parsePropertyValue(annotationObject[propertyKey], propertyKey, currentObjectTarget, annotationsLists, oCapabilities)
337
+ );
338
+ } else if (propertyKey.startsWith("@")) {
339
+ // Annotation of annotation
340
+ createAnnotationLists(
341
+ { [propertyKey]: annotationObject[propertyKey] },
342
+ currentObjectTarget,
343
+ annotationsLists,
344
+ oCapabilities
345
+ );
346
+ }
347
+ });
348
+ parsedAnnotationObject.propertyValues = propertyValues;
349
+ }
350
+ return parsedAnnotationObject;
351
+ }
352
+ function getOrCreateAnnotationList(target: string, annotationsLists: Record<string, AnnotationList>): AnnotationList {
353
+ if (!annotationsLists.hasOwnProperty(target)) {
354
+ annotationsLists[target] = {
355
+ target: target,
356
+ annotations: []
197
357
  };
198
- },
199
- mapNameToAlias(annotationName: string): string {
200
- let [pathPart, annoPart] = annotationName.split("@");
201
- if (!annoPart) {
202
- annoPart = pathPart;
203
- pathPart = "";
358
+ }
359
+ return annotationsLists[target];
360
+ }
361
+
362
+ function removeChartAnnotations(annotationObject: any) {
363
+ return annotationObject.filter((oRecord: any) => {
364
+ if (oRecord.Target && oRecord.Target.$AnnotationPath) {
365
+ return oRecord.Target.$AnnotationPath.indexOf("@com.sap.vocabularies.UI.v1.Chart") === -1;
366
+ } else {
367
+ return true;
368
+ }
369
+ });
370
+ }
371
+
372
+ function removeIBNAnnotations(annotationObject: any) {
373
+ return annotationObject.filter((oRecord: any) => {
374
+ return oRecord.$Type !== "com.sap.vocabularies.UI.v1.DataFieldForIntentBasedNavigation";
375
+ });
376
+ }
377
+
378
+ function handlePresentationVariant(annotationObject: any) {
379
+ return annotationObject.filter((oRecord: any) => {
380
+ return oRecord.$AnnotationPath !== "@com.sap.vocabularies.UI.v1.Chart";
381
+ });
382
+ }
383
+
384
+ function createAnnotationLists(
385
+ annotationObjects: any,
386
+ annotationTarget: string,
387
+ annotationLists: Record<string, AnnotationList>,
388
+ oCapabilities: EnvironmentCapabilities
389
+ ) {
390
+ if (Object.keys(annotationObjects).length === 0) {
391
+ return;
392
+ }
393
+ const outAnnotationObject = getOrCreateAnnotationList(annotationTarget, annotationLists);
394
+ if (!oCapabilities.MicroChart) {
395
+ delete annotationObjects["@com.sap.vocabularies.UI.v1.Chart"];
396
+ }
397
+
398
+ for (let annotationKey in annotationObjects) {
399
+ let annotationObject = annotationObjects[annotationKey];
400
+ switch (annotationKey) {
401
+ case "@com.sap.vocabularies.UI.v1.HeaderFacets":
402
+ if (!oCapabilities.MicroChart) {
403
+ annotationObject = removeChartAnnotations(annotationObject);
404
+ annotationObjects[annotationKey] = annotationObject;
405
+ }
406
+ break;
407
+ case "@com.sap.vocabularies.UI.v1.Identification":
408
+ if (!oCapabilities.IntentBasedNavigation) {
409
+ annotationObject = removeIBNAnnotations(annotationObject);
410
+ annotationObjects[annotationKey] = annotationObject;
411
+ }
412
+ break;
413
+ case "@com.sap.vocabularies.UI.v1.LineItem":
414
+ if (!oCapabilities.IntentBasedNavigation) {
415
+ annotationObject = removeIBNAnnotations(annotationObject);
416
+ annotationObjects[annotationKey] = annotationObject;
417
+ }
418
+ if (!oCapabilities.MicroChart) {
419
+ annotationObject = removeChartAnnotations(annotationObject);
420
+ annotationObjects[annotationKey] = annotationObject;
421
+ }
422
+ break;
423
+ case "@com.sap.vocabularies.UI.v1.FieldGroup":
424
+ if (!oCapabilities.IntentBasedNavigation) {
425
+ annotationObject.Data = removeIBNAnnotations(annotationObject.Data);
426
+ annotationObjects[annotationKey] = annotationObject;
427
+ }
428
+ if (!oCapabilities.MicroChart) {
429
+ annotationObject.Data = removeChartAnnotations(annotationObject.Data);
430
+ annotationObjects[annotationKey] = annotationObject;
431
+ }
432
+ break;
433
+ case "@com.sap.vocabularies.UI.v1.PresentationVariant":
434
+ if (!oCapabilities.Chart && annotationObject.Visualizations) {
435
+ annotationObject.Visualizations = handlePresentationVariant(annotationObject.Visualizations);
436
+ annotationObjects[annotationKey] = annotationObject;
437
+ }
438
+ break;
439
+ default:
440
+ break;
441
+ }
442
+
443
+ let currentOutAnnotationObject = outAnnotationObject;
444
+
445
+ // Check for annotation of annotation
446
+ const annotationOfAnnotationSplit = annotationKey.split("@");
447
+ if (annotationOfAnnotationSplit.length > 2) {
448
+ currentOutAnnotationObject = getOrCreateAnnotationList(
449
+ annotationTarget + "@" + annotationOfAnnotationSplit[1],
450
+ annotationLists
451
+ );
452
+ annotationKey = annotationOfAnnotationSplit[2];
204
453
  } else {
205
- pathPart += "@";
454
+ annotationKey = annotationOfAnnotationSplit[1];
206
455
  }
207
- const lastDot = annoPart.lastIndexOf(".");
208
- return pathPart + VOCABULARY_ALIAS[annoPart.substr(0, lastDot)] + "." + annoPart.substr(lastDot + 1);
209
- },
210
- parseAnnotationObject(
211
- annotationObject: any,
212
- currentObjectTarget: string,
213
- annotationsLists: any[],
214
- oCapabilities: EnvironmentCapabilities
215
- ): Expression | AnnotationRecord | Annotation {
216
- let parsedAnnotationObject: any = {};
456
+
457
+ const annotationQualifierSplit = annotationKey.split("#");
458
+ const qualifier = annotationQualifierSplit[1];
459
+ annotationKey = annotationQualifierSplit[0];
460
+
461
+ const parsedAnnotationObject: any = {
462
+ term: `${annotationKey}`,
463
+ qualifier: qualifier
464
+ };
465
+ let currentAnnotationTarget = annotationTarget + "@" + parsedAnnotationObject.term;
466
+ if (qualifier) {
467
+ currentAnnotationTarget += "#" + qualifier;
468
+ }
469
+ let isCollection = false;
470
+ const typeofAnnotation = typeof annotationObject;
217
471
  if (annotationObject === null) {
218
- parsedAnnotationObject = { type: "Null", Null: null };
219
- } else if (typeof annotationObject === "string") {
220
- parsedAnnotationObject = { type: "String", String: annotationObject };
221
- } else if (typeof annotationObject === "boolean") {
222
- parsedAnnotationObject = { type: "Bool", Bool: annotationObject };
223
- } else if (typeof annotationObject === "number") {
224
- parsedAnnotationObject = { type: "Int", Int: annotationObject };
225
- } else if (annotationObject.$AnnotationPath !== undefined) {
226
- parsedAnnotationObject = { type: "AnnotationPath", AnnotationPath: annotationObject.$AnnotationPath };
227
- } else if (annotationObject.$Path !== undefined) {
228
- parsedAnnotationObject = { type: "Path", Path: annotationObject.$Path };
229
- } else if (annotationObject.$Decimal !== undefined) {
230
- parsedAnnotationObject = { type: "Decimal", Decimal: parseFloat(annotationObject.$Decimal) };
231
- } else if (annotationObject.$PropertyPath !== undefined) {
232
- parsedAnnotationObject = { type: "PropertyPath", PropertyPath: annotationObject.$PropertyPath };
472
+ parsedAnnotationObject.value = { type: "Bool", Bool: annotationObject };
473
+ } else if (typeofAnnotation === "string") {
474
+ parsedAnnotationObject.value = { type: "String", String: annotationObject };
475
+ } else if (typeofAnnotation === "boolean") {
476
+ parsedAnnotationObject.value = { type: "Bool", Bool: annotationObject };
477
+ } else if (typeofAnnotation === "number") {
478
+ parsedAnnotationObject.value = { type: "Int", Int: annotationObject };
233
479
  } else if (annotationObject.$If !== undefined) {
234
- parsedAnnotationObject = { type: "If", If: annotationObject.$If };
480
+ parsedAnnotationObject.value = { type: "If", If: annotationObject.$If };
235
481
  } else if (annotationObject.$And !== undefined) {
236
- parsedAnnotationObject = { type: "And", And: annotationObject.$And };
482
+ parsedAnnotationObject.value = { type: "And", And: annotationObject.$And };
237
483
  } else if (annotationObject.$Or !== undefined) {
238
- parsedAnnotationObject = { type: "Or", Or: annotationObject.$Or };
484
+ parsedAnnotationObject.value = { type: "Or", Or: annotationObject.$Or };
239
485
  } else if (annotationObject.$Not !== undefined) {
240
- parsedAnnotationObject = { type: "Not", Not: annotationObject.$Not };
486
+ parsedAnnotationObject.value = { type: "Not", Not: annotationObject.$Not };
241
487
  } else if (annotationObject.$Eq !== undefined) {
242
- parsedAnnotationObject = { type: "Eq", Eq: annotationObject.$Eq };
488
+ parsedAnnotationObject.value = { type: "Eq", Eq: annotationObject.$Eq };
243
489
  } else if (annotationObject.$Ne !== undefined) {
244
- parsedAnnotationObject = { type: "Ne", Ne: annotationObject.$Ne };
490
+ parsedAnnotationObject.value = { type: "Ne", Ne: annotationObject.$Ne };
245
491
  } else if (annotationObject.$Gt !== undefined) {
246
- parsedAnnotationObject = { type: "Gt", Gt: annotationObject.$Gt };
492
+ parsedAnnotationObject.value = { type: "Gt", Gt: annotationObject.$Gt };
247
493
  } else if (annotationObject.$Ge !== undefined) {
248
- parsedAnnotationObject = { type: "Ge", Ge: annotationObject.$Ge };
494
+ parsedAnnotationObject.value = { type: "Ge", Ge: annotationObject.$Ge };
249
495
  } else if (annotationObject.$Lt !== undefined) {
250
- parsedAnnotationObject = { type: "Lt", Lt: annotationObject.$Lt };
496
+ parsedAnnotationObject.value = { type: "Lt", Lt: annotationObject.$Lt };
251
497
  } else if (annotationObject.$Le !== undefined) {
252
- parsedAnnotationObject = { type: "Le", Le: annotationObject.$Le };
498
+ parsedAnnotationObject.value = { type: "Le", Le: annotationObject.$Le };
253
499
  } else if (annotationObject.$Apply !== undefined) {
254
- parsedAnnotationObject = { type: "Apply", Apply: annotationObject.$Apply, Function: annotationObject.$Function };
255
- } else if (annotationObject.$NavigationPropertyPath !== undefined) {
256
- parsedAnnotationObject = {
257
- type: "NavigationPropertyPath",
258
- NavigationPropertyPath: annotationObject.$NavigationPropertyPath
500
+ parsedAnnotationObject.value = { type: "Apply", Apply: annotationObject.$Apply, Function: annotationObject.$Function };
501
+ } else if (annotationObject.$Path !== undefined) {
502
+ parsedAnnotationObject.value = { type: "Path", Path: annotationObject.$Path };
503
+ } else if (annotationObject.$AnnotationPath !== undefined) {
504
+ parsedAnnotationObject.value = {
505
+ type: "AnnotationPath",
506
+ AnnotationPath: annotationObject.$AnnotationPath
259
507
  };
508
+ } else if (annotationObject.$Decimal !== undefined) {
509
+ parsedAnnotationObject.value = { type: "Decimal", Decimal: parseFloat(annotationObject.$Decimal) };
260
510
  } else if (annotationObject.$EnumMember !== undefined) {
261
- parsedAnnotationObject = {
511
+ parsedAnnotationObject.value = {
262
512
  type: "EnumMember",
263
- EnumMember:
264
- this.mapNameToAlias(annotationObject.$EnumMember.split("/")[0]) + "/" + annotationObject.$EnumMember.split("/")[1]
513
+ EnumMember: mapNameToAlias(annotationObject.$EnumMember.split("/")[0]) + "/" + annotationObject.$EnumMember.split("/")[1]
265
514
  };
266
515
  } else if (Array.isArray(annotationObject)) {
267
- const parsedAnnotationCollection = parsedAnnotationObject as any;
268
- parsedAnnotationCollection.collection = annotationObject.map((subAnnotationObject, subAnnotationIndex) =>
269
- this.parseAnnotationObject(
516
+ isCollection = true;
517
+ parsedAnnotationObject.collection = annotationObject.map((subAnnotationObject, subAnnotationIndex) =>
518
+ parseAnnotationObject(
270
519
  subAnnotationObject,
271
- currentObjectTarget + "/" + subAnnotationIndex,
272
- annotationsLists,
520
+ currentAnnotationTarget + "/" + subAnnotationIndex,
521
+ annotationLists,
273
522
  oCapabilities
274
523
  )
275
524
  );
276
525
  if (annotationObject.length > 0) {
277
526
  if (annotationObject[0].hasOwnProperty("$PropertyPath")) {
278
- (parsedAnnotationCollection.collection as any).type = "PropertyPath";
527
+ (parsedAnnotationObject.collection as any).type = "PropertyPath";
279
528
  } else if (annotationObject[0].hasOwnProperty("$Path")) {
280
- (parsedAnnotationCollection.collection as any).type = "Path";
529
+ (parsedAnnotationObject.collection as any).type = "Path";
281
530
  } else if (annotationObject[0].hasOwnProperty("$NavigationPropertyPath")) {
282
- (parsedAnnotationCollection.collection as any).type = "NavigationPropertyPath";
531
+ (parsedAnnotationObject.collection as any).type = "NavigationPropertyPath";
283
532
  } else if (annotationObject[0].hasOwnProperty("$AnnotationPath")) {
284
- (parsedAnnotationCollection.collection as any).type = "AnnotationPath";
533
+ (parsedAnnotationObject.collection as any).type = "AnnotationPath";
285
534
  } else if (annotationObject[0].hasOwnProperty("$Type")) {
286
- (parsedAnnotationCollection.collection as any).type = "Record";
535
+ (parsedAnnotationObject.collection as any).type = "Record";
287
536
  } else if (annotationObject[0].hasOwnProperty("$If")) {
288
- (parsedAnnotationCollection.collection as any).type = "If";
289
- } else if (annotationObject[0].hasOwnProperty("$And")) {
290
- (parsedAnnotationCollection.collection as any).type = "And";
537
+ (parsedAnnotationObject.collection as any).type = "If";
291
538
  } else if (annotationObject[0].hasOwnProperty("$Or")) {
292
- (parsedAnnotationCollection.collection as any).type = "Or";
539
+ (parsedAnnotationObject.collection as any).type = "Or";
293
540
  } else if (annotationObject[0].hasOwnProperty("$Eq")) {
294
- (parsedAnnotationCollection.collection as any).type = "Eq";
541
+ (parsedAnnotationObject.collection as any).type = "Eq";
295
542
  } else if (annotationObject[0].hasOwnProperty("$Ne")) {
296
- (parsedAnnotationCollection.collection as any).type = "Ne";
543
+ (parsedAnnotationObject.collection as any).type = "Ne";
297
544
  } else if (annotationObject[0].hasOwnProperty("$Not")) {
298
- (parsedAnnotationCollection.collection as any).type = "Not";
545
+ (parsedAnnotationObject.collection as any).type = "Not";
299
546
  } else if (annotationObject[0].hasOwnProperty("$Gt")) {
300
- (parsedAnnotationCollection.collection as any).type = "Gt";
547
+ (parsedAnnotationObject.collection as any).type = "Gt";
301
548
  } else if (annotationObject[0].hasOwnProperty("$Ge")) {
302
- (parsedAnnotationCollection.collection as any).type = "Ge";
549
+ (parsedAnnotationObject.collection as any).type = "Ge";
303
550
  } else if (annotationObject[0].hasOwnProperty("$Lt")) {
304
- (parsedAnnotationCollection.collection as any).type = "Lt";
551
+ (parsedAnnotationObject.collection as any).type = "Lt";
305
552
  } else if (annotationObject[0].hasOwnProperty("$Le")) {
306
- (parsedAnnotationCollection.collection as any).type = "Le";
553
+ (parsedAnnotationObject.collection as any).type = "Le";
554
+ } else if (annotationObject[0].hasOwnProperty("$And")) {
555
+ (parsedAnnotationObject.collection as any).type = "And";
307
556
  } else if (annotationObject[0].hasOwnProperty("$Apply")) {
308
- (parsedAnnotationCollection.collection as any).type = "Apply";
557
+ (parsedAnnotationObject.collection as any).type = "Apply";
309
558
  } else if (typeof annotationObject[0] === "object") {
310
- (parsedAnnotationCollection.collection as any).type = "Record";
559
+ (parsedAnnotationObject.collection as any).type = "Record";
311
560
  } else {
312
- (parsedAnnotationCollection.collection as any).type = "String";
561
+ (parsedAnnotationObject.collection as any).type = "String";
313
562
  }
314
563
  }
315
564
  } else {
565
+ const record: AnnotationRecord = {
566
+ propertyValues: []
567
+ };
316
568
  if (annotationObject.$Type) {
317
569
  const typeValue = annotationObject.$Type;
318
- parsedAnnotationObject.type = typeValue; //`${typeAlias}.${typeTerm}`;
570
+ record.type = `${typeValue}`;
319
571
  }
320
- const propertyValues: any = [];
321
- Object.keys(annotationObject).forEach(propertyKey => {
322
- if (
323
- propertyKey !== "$Type" &&
324
- propertyKey !== "$If" &&
325
- propertyKey !== "$Apply" &&
326
- propertyKey !== "$And" &&
327
- propertyKey !== "$Or" &&
328
- propertyKey !== "$Ne" &&
329
- propertyKey !== "$Gt" &&
330
- propertyKey !== "$Ge" &&
331
- propertyKey !== "$Lt" &&
332
- propertyKey !== "$Le" &&
333
- propertyKey !== "$Not" &&
334
- propertyKey !== "$Eq" &&
335
- !propertyKey.startsWith("@")
336
- ) {
572
+ const propertyValues: any[] = [];
573
+ for (const propertyKey in annotationObject) {
574
+ if (propertyKey !== "$Type" && !propertyKey.startsWith("@")) {
337
575
  propertyValues.push(
338
- this.parsePropertyValue(
576
+ parsePropertyValue(
339
577
  annotationObject[propertyKey],
340
578
  propertyKey,
341
- currentObjectTarget,
342
- annotationsLists,
579
+ currentAnnotationTarget,
580
+ annotationLists,
343
581
  oCapabilities
344
582
  )
345
583
  );
346
584
  } else if (propertyKey.startsWith("@")) {
347
- // Annotation of annotation
348
- this.createAnnotationLists(
585
+ // Annotation of record
586
+ createAnnotationLists(
349
587
  { [propertyKey]: annotationObject[propertyKey] },
350
- currentObjectTarget,
351
- annotationsLists,
588
+ currentAnnotationTarget,
589
+ annotationLists,
352
590
  oCapabilities
353
591
  );
354
592
  }
355
- });
356
- parsedAnnotationObject.propertyValues = propertyValues;
357
- }
358
- return parsedAnnotationObject;
359
- },
360
- getOrCreateAnnotationList(target: string, annotationsLists: AnnotationList[]): AnnotationList {
361
- let potentialTarget = annotationsLists.find(annotationList => annotationList.target === target);
362
- if (!potentialTarget) {
363
- potentialTarget = {
364
- target: target,
365
- annotations: []
366
- };
367
- annotationsLists.push(potentialTarget);
593
+ }
594
+ record.propertyValues = propertyValues;
595
+ parsedAnnotationObject.record = record;
368
596
  }
369
- return potentialTarget;
370
- },
597
+ parsedAnnotationObject.isCollection = isCollection;
598
+ currentOutAnnotationObject.annotations.push(parsedAnnotationObject);
599
+ }
600
+ }
371
601
 
372
- createAnnotationLists(
373
- annotationObjects: any,
374
- annotationTarget: string,
375
- annotationLists: any[],
376
- oCapabilities: EnvironmentCapabilities
377
- ) {
378
- const outAnnotationObject = this.getOrCreateAnnotationList(annotationTarget, annotationLists);
379
- if (!oCapabilities.MicroChart) {
380
- delete annotationObjects["@com.sap.vocabularies.UI.v1.Chart"];
381
- }
602
+ function prepareProperty(propertyDefinition: any, entityTypeObject: EntityType | ComplexType, propertyName: string): Property {
603
+ const propertyObject: Property = {
604
+ _type: "Property",
605
+ name: propertyName,
606
+ fullyQualifiedName: `${entityTypeObject.fullyQualifiedName}/${propertyName}`,
607
+ type: propertyDefinition.$Type,
608
+ maxLength: propertyDefinition.$MaxLength,
609
+ precision: propertyDefinition.$Precision,
610
+ scale: propertyDefinition.$Scale,
611
+ nullable: propertyDefinition.$Nullable
612
+ };
613
+ return propertyObject;
614
+ }
382
615
 
383
- function removeChartAnnotations(annotationObject: any) {
384
- return annotationObject.filter((oRecord: any) => {
385
- if (oRecord.Target && oRecord.Target.$AnnotationPath) {
386
- return oRecord.Target.$AnnotationPath.indexOf("@com.sap.vocabularies.UI.v1.Chart") === -1;
387
- } else {
388
- return true;
389
- }
390
- });
391
- }
616
+ function prepareNavigationProperty(
617
+ navPropertyDefinition: any,
618
+ entityTypeObject: EntityType | ComplexType,
619
+ navPropertyName: string
620
+ ): V4NavigationProperty {
621
+ let referentialConstraint: ReferentialConstraint[] = [];
622
+ if (navPropertyDefinition.$ReferentialConstraint) {
623
+ referentialConstraint = Object.keys(navPropertyDefinition.$ReferentialConstraint).map(sourcePropertyName => {
624
+ return {
625
+ sourceTypeName: entityTypeObject.name,
626
+ sourceProperty: sourcePropertyName,
627
+ targetTypeName: navPropertyDefinition.$Type,
628
+ targetProperty: navPropertyDefinition.$ReferentialConstraint[sourcePropertyName]
629
+ };
630
+ });
631
+ }
632
+ const navigationProperty: V4NavigationProperty = {
633
+ _type: "NavigationProperty",
634
+ name: navPropertyName,
635
+ fullyQualifiedName: `${entityTypeObject.fullyQualifiedName}/${navPropertyName}`,
636
+ partner: navPropertyDefinition.$Partner,
637
+ isCollection: navPropertyDefinition.$isCollection ? navPropertyDefinition.$isCollection : false,
638
+ containsTarget: navPropertyDefinition.$ContainsTarget,
639
+ targetTypeName: navPropertyDefinition.$Type,
640
+ referentialConstraint
641
+ };
392
642
 
393
- function removeIBNAnnotations(annotationObject: any) {
394
- return annotationObject.filter((oRecord: any) => {
395
- return oRecord.$Type !== "com.sap.vocabularies.UI.v1.DataFieldForIntentBasedNavigation";
396
- });
397
- }
643
+ return navigationProperty;
644
+ }
398
645
 
399
- function handlePresentationVariant(annotationObject: any) {
400
- return annotationObject.filter((oRecord: any) => {
401
- return oRecord.$AnnotationPath !== "@com.sap.vocabularies.UI.v1.Chart";
402
- });
403
- }
646
+ function prepareEntitySet(entitySetDefinition: any, entitySetName: string, entityContainerName: string): EntitySet {
647
+ const entitySetObject: EntitySet = {
648
+ _type: "EntitySet",
649
+ name: entitySetName,
650
+ navigationPropertyBinding: {},
651
+ entityTypeName: entitySetDefinition.$Type,
652
+ fullyQualifiedName: `${entityContainerName}/${entitySetName}`
653
+ };
654
+ return entitySetObject;
655
+ }
404
656
 
405
- Object.keys(annotationObjects).forEach(annotationKey => {
406
- let annotationObject = annotationObjects[annotationKey];
407
- switch (annotationKey) {
408
- case "@com.sap.vocabularies.UI.v1.HeaderFacets":
409
- if (!oCapabilities.MicroChart) {
410
- annotationObject = removeChartAnnotations(annotationObject);
411
- }
412
- break;
413
- case "@com.sap.vocabularies.UI.v1.Identification":
414
- if (!oCapabilities.IntentBasedNavigation) {
415
- annotationObject = removeIBNAnnotations(annotationObject);
416
- }
417
- break;
418
- case "@com.sap.vocabularies.UI.v1.LineItem":
419
- if (!oCapabilities.IntentBasedNavigation) {
420
- annotationObject = removeIBNAnnotations(annotationObject);
421
- }
422
- if (!oCapabilities.MicroChart) {
423
- annotationObject = removeChartAnnotations(annotationObject);
424
- }
425
- break;
426
- case "@com.sap.vocabularies.UI.v1.FieldGroup":
427
- if (!oCapabilities.IntentBasedNavigation) {
428
- annotationObject.Data = removeIBNAnnotations(annotationObject.Data);
429
- }
430
- if (!oCapabilities.MicroChart) {
431
- annotationObject.Data = removeChartAnnotations(annotationObject.Data);
432
- }
433
- break;
434
- case "@com.sap.vocabularies.UI.v1.PresentationVariant":
435
- if (!oCapabilities.Chart && annotationObject.Visualizations) {
436
- annotationObject.Visualizations = handlePresentationVariant(annotationObject.Visualizations);
437
- }
438
- break;
439
- default:
440
- break;
441
- }
442
- annotationObjects[annotationKey] = annotationObject;
443
- let currentOutAnnotationObject = outAnnotationObject;
657
+ function prepareSingleton(singletonDefinition: any, singletonName: string, entityContainerName: string): Singleton {
658
+ const singletonObject: Singleton = {
659
+ _type: "Singleton",
660
+ name: singletonName,
661
+ navigationPropertyBinding: {},
662
+ typeName: singletonDefinition.$Type,
663
+ fullyQualifiedName: `${entityContainerName}/${singletonName}`,
664
+ nullable: true
665
+ };
666
+ return singletonObject;
667
+ }
444
668
 
445
- // Check for annotation of annotation
446
- const annotationOfAnnotationSplit = annotationKey.split("@");
447
- if (annotationOfAnnotationSplit.length > 2) {
448
- currentOutAnnotationObject = this.getOrCreateAnnotationList(
449
- annotationTarget + "@" + annotationOfAnnotationSplit[1],
450
- annotationLists
451
- );
452
- annotationKey = annotationOfAnnotationSplit[2];
453
- } else {
454
- annotationKey = annotationOfAnnotationSplit[1];
455
- }
669
+ function prepareTypeDefinition(typeDefinition: any, typeName: string, namespace: string): TypeDefinition {
670
+ const typeObject: TypeDefinition = {
671
+ _type: "TypeDefinition",
672
+ name: typeName.replace(namespace + ".", ""),
673
+ fullyQualifiedName: typeName,
674
+ underlyingType: typeDefinition.$UnderlyingType
675
+ };
676
+ return typeObject;
677
+ }
456
678
 
457
- const annotationQualifierSplit = annotationKey.split("#");
458
- const qualifier = annotationQualifierSplit[1];
459
- annotationKey = annotationQualifierSplit[0];
679
+ function prepareComplexType(complexTypeDefinition: any, complexTypeName: string, namespace: string): ComplexType {
680
+ const complexTypeObject: ComplexType = {
681
+ _type: "ComplexType",
682
+ name: complexTypeName.replace(namespace + ".", ""),
683
+ fullyQualifiedName: complexTypeName,
684
+ properties: [],
685
+ navigationProperties: []
686
+ };
460
687
 
461
- const parsedAnnotationObject: any = {
462
- term: `${annotationKey}`,
463
- qualifier: qualifier
464
- };
465
- let currentAnnotationTarget = annotationTarget + "@" + parsedAnnotationObject.term;
466
- if (qualifier) {
467
- currentAnnotationTarget += "#" + qualifier;
688
+ const complexTypeProperties = Object.keys(complexTypeDefinition)
689
+ .filter(propertyNameOrNot => {
690
+ if (propertyNameOrNot != "$Key" && propertyNameOrNot != "$kind") {
691
+ return complexTypeDefinition[propertyNameOrNot].$kind === "Property";
468
692
  }
469
- let isCollection = false;
470
- if (annotationObject === null) {
471
- parsedAnnotationObject.value = { type: "Bool", Bool: annotationObject };
472
- } else if (typeof annotationObject === "string") {
473
- parsedAnnotationObject.value = { type: "String", String: annotationObject };
474
- } else if (typeof annotationObject === "boolean") {
475
- parsedAnnotationObject.value = { type: "Bool", Bool: annotationObject };
476
- } else if (typeof annotationObject === "number") {
477
- parsedAnnotationObject.value = { type: "Int", Int: annotationObject };
478
- } else if (annotationObject.$If !== undefined) {
479
- parsedAnnotationObject.value = { type: "If", If: annotationObject.$If };
480
- } else if (annotationObject.$And !== undefined) {
481
- parsedAnnotationObject.value = { type: "And", And: annotationObject.$And };
482
- } else if (annotationObject.$Or !== undefined) {
483
- parsedAnnotationObject.value = { type: "Or", Or: annotationObject.$Or };
484
- } else if (annotationObject.$Not !== undefined) {
485
- parsedAnnotationObject.value = { type: "Not", Not: annotationObject.$Not };
486
- } else if (annotationObject.$Eq !== undefined) {
487
- parsedAnnotationObject.value = { type: "Eq", Eq: annotationObject.$Eq };
488
- } else if (annotationObject.$Ne !== undefined) {
489
- parsedAnnotationObject.value = { type: "Ne", Ne: annotationObject.$Ne };
490
- } else if (annotationObject.$Gt !== undefined) {
491
- parsedAnnotationObject.value = { type: "Gt", Gt: annotationObject.$Gt };
492
- } else if (annotationObject.$Ge !== undefined) {
493
- parsedAnnotationObject.value = { type: "Ge", Ge: annotationObject.$Ge };
494
- } else if (annotationObject.$Lt !== undefined) {
495
- parsedAnnotationObject.value = { type: "Lt", Lt: annotationObject.$Lt };
496
- } else if (annotationObject.$Le !== undefined) {
497
- parsedAnnotationObject.value = { type: "Le", Le: annotationObject.$Le };
498
- } else if (annotationObject.$Apply !== undefined) {
499
- parsedAnnotationObject.value = { type: "Apply", Apply: annotationObject.$Apply, Function: annotationObject.$Function };
500
- } else if (annotationObject.$Path !== undefined) {
501
- parsedAnnotationObject.value = { type: "Path", Path: annotationObject.$Path };
502
- } else if (annotationObject.$AnnotationPath !== undefined) {
503
- parsedAnnotationObject.value = {
504
- type: "AnnotationPath",
505
- AnnotationPath: annotationObject.$AnnotationPath
506
- };
507
- } else if (annotationObject.$Decimal !== undefined) {
508
- parsedAnnotationObject.value = { type: "Decimal", Decimal: parseFloat(annotationObject.$Decimal) };
509
- } else if (annotationObject.$EnumMember !== undefined) {
510
- parsedAnnotationObject.value = {
511
- type: "EnumMember",
512
- EnumMember:
513
- this.mapNameToAlias(annotationObject.$EnumMember.split("/")[0]) + "/" + annotationObject.$EnumMember.split("/")[1]
514
- };
515
- } else if (Array.isArray(annotationObject)) {
516
- isCollection = true;
517
- parsedAnnotationObject.collection = annotationObject.map((subAnnotationObject, subAnnotationIndex) =>
518
- this.parseAnnotationObject(
519
- subAnnotationObject,
520
- currentAnnotationTarget + "/" + subAnnotationIndex,
521
- annotationLists,
522
- oCapabilities
523
- )
524
- );
525
- if (annotationObject.length > 0) {
526
- if (annotationObject[0].hasOwnProperty("$PropertyPath")) {
527
- (parsedAnnotationObject.collection as any).type = "PropertyPath";
528
- } else if (annotationObject[0].hasOwnProperty("$Path")) {
529
- (parsedAnnotationObject.collection as any).type = "Path";
530
- } else if (annotationObject[0].hasOwnProperty("$NavigationPropertyPath")) {
531
- (parsedAnnotationObject.collection as any).type = "NavigationPropertyPath";
532
- } else if (annotationObject[0].hasOwnProperty("$AnnotationPath")) {
533
- (parsedAnnotationObject.collection as any).type = "AnnotationPath";
534
- } else if (annotationObject[0].hasOwnProperty("$Type")) {
535
- (parsedAnnotationObject.collection as any).type = "Record";
536
- } else if (annotationObject[0].hasOwnProperty("$If")) {
537
- (parsedAnnotationObject.collection as any).type = "If";
538
- } else if (annotationObject[0].hasOwnProperty("$Or")) {
539
- (parsedAnnotationObject.collection as any).type = "Or";
540
- } else if (annotationObject[0].hasOwnProperty("$Eq")) {
541
- (parsedAnnotationObject.collection as any).type = "Eq";
542
- } else if (annotationObject[0].hasOwnProperty("$Ne")) {
543
- (parsedAnnotationObject.collection as any).type = "Ne";
544
- } else if (annotationObject[0].hasOwnProperty("$Not")) {
545
- (parsedAnnotationObject.collection as any).type = "Not";
546
- } else if (annotationObject[0].hasOwnProperty("$Gt")) {
547
- (parsedAnnotationObject.collection as any).type = "Gt";
548
- } else if (annotationObject[0].hasOwnProperty("$Ge")) {
549
- (parsedAnnotationObject.collection as any).type = "Ge";
550
- } else if (annotationObject[0].hasOwnProperty("$Lt")) {
551
- (parsedAnnotationObject.collection as any).type = "Lt";
552
- } else if (annotationObject[0].hasOwnProperty("$Le")) {
553
- (parsedAnnotationObject.collection as any).type = "Le";
554
- } else if (annotationObject[0].hasOwnProperty("$And")) {
555
- (parsedAnnotationObject.collection as any).type = "And";
556
- } else if (annotationObject[0].hasOwnProperty("$Apply")) {
557
- (parsedAnnotationObject.collection as any).type = "Apply";
558
- } else if (typeof annotationObject[0] === "object") {
559
- (parsedAnnotationObject.collection as any).type = "Record";
560
- } else {
561
- (parsedAnnotationObject.collection as any).type = "String";
562
- }
563
- }
564
- } else {
565
- const record: AnnotationRecord = {
566
- propertyValues: []
567
- };
568
- if (annotationObject.$Type) {
569
- const typeValue = annotationObject.$Type;
570
- record.type = `${typeValue}`;
571
- }
572
- const propertyValues: any[] = [];
573
- Object.keys(annotationObject).forEach(propertyKey => {
574
- if (propertyKey !== "$Type" && !propertyKey.startsWith("@")) {
575
- propertyValues.push(
576
- this.parsePropertyValue(
577
- annotationObject[propertyKey],
578
- propertyKey,
579
- currentAnnotationTarget,
580
- annotationLists,
581
- oCapabilities
582
- )
583
- );
584
- } else if (propertyKey.startsWith("@")) {
585
- // Annotation of record
586
- this.createAnnotationLists(
587
- { [propertyKey]: annotationObject[propertyKey] },
588
- currentAnnotationTarget,
589
- annotationLists,
590
- oCapabilities
591
- );
592
- }
593
- });
594
- record.propertyValues = propertyValues;
595
- parsedAnnotationObject.record = record;
596
- }
597
- parsedAnnotationObject.isCollection = isCollection;
598
- currentOutAnnotationObject.annotations.push(parsedAnnotationObject);
693
+ })
694
+ .sort((a, b) => (a > b ? 1 : -1))
695
+ .map(propertyName => {
696
+ return prepareProperty(complexTypeDefinition[propertyName], complexTypeObject, propertyName);
599
697
  });
600
- },
601
- parseProperty(
602
- oMetaModel: any,
603
- entityTypeObject: EntityType | ComplexType,
604
- propertyName: string,
605
- annotationLists: AnnotationList[],
606
- oCapabilities: EnvironmentCapabilities
607
- ): Property {
608
- const propertyAnnotation = oMetaModel.getObject(`/${entityTypeObject.fullyQualifiedName}/${propertyName}@`);
609
- const propertyDefinition = oMetaModel.getObject(`/${entityTypeObject.fullyQualifiedName}/${propertyName}`);
610
-
611
- const propertyObject: Property = {
612
- _type: "Property",
613
- name: propertyName,
614
- fullyQualifiedName: `${entityTypeObject.fullyQualifiedName}/${propertyName}`,
615
- type: propertyDefinition.$Type,
616
- maxLength: propertyDefinition.$MaxLength,
617
- precision: propertyDefinition.$Precision,
618
- scale: propertyDefinition.$Scale,
619
- nullable: propertyDefinition.$Nullable
620
- };
621
-
622
- this.createAnnotationLists(propertyAnnotation, propertyObject.fullyQualifiedName, annotationLists, oCapabilities);
623
698
 
624
- return propertyObject;
625
- },
626
- parseNavigationProperty(
627
- oMetaModel: any,
628
- entityTypeObject: EntityType | ComplexType,
629
- navPropertyName: string,
630
- annotationLists: AnnotationList[],
631
- oCapabilities: EnvironmentCapabilities
632
- ): V4NavigationProperty {
633
- const navPropertyAnnotation = oMetaModel.getObject(`/${entityTypeObject.fullyQualifiedName}/${navPropertyName}@`);
634
- const navPropertyDefinition = oMetaModel.getObject(`/${entityTypeObject.fullyQualifiedName}/${navPropertyName}`);
699
+ complexTypeObject.properties = complexTypeProperties;
700
+ const complexTypeNavigationProperties = Object.keys(complexTypeDefinition)
701
+ .filter(propertyNameOrNot => {
702
+ if (propertyNameOrNot != "$Key" && propertyNameOrNot != "$kind") {
703
+ return complexTypeDefinition[propertyNameOrNot].$kind === "NavigationProperty";
704
+ }
705
+ })
706
+ .sort((a, b) => (a > b ? 1 : -1))
707
+ .map(navPropertyName => {
708
+ return prepareNavigationProperty(complexTypeDefinition[navPropertyName], complexTypeObject, navPropertyName);
709
+ });
710
+ complexTypeObject.navigationProperties = complexTypeNavigationProperties;
711
+ return complexTypeObject;
712
+ }
635
713
 
636
- let referentialConstraint: ReferentialConstraint[] = [];
637
- if (navPropertyDefinition.$ReferentialConstraint) {
638
- referentialConstraint = Object.keys(navPropertyDefinition.$ReferentialConstraint).map(sourcePropertyName => {
639
- return {
640
- sourceTypeName: entityTypeObject.name,
641
- sourceProperty: sourcePropertyName,
642
- targetTypeName: navPropertyDefinition.$Type,
643
- targetProperty: navPropertyDefinition.$ReferentialConstraint[sourcePropertyName]
644
- };
645
- });
646
- }
647
- const navigationProperty: V4NavigationProperty = {
648
- _type: "NavigationProperty",
649
- name: navPropertyName,
650
- fullyQualifiedName: `${entityTypeObject.fullyQualifiedName}/${navPropertyName}`,
651
- partner: navPropertyDefinition.$Partner,
652
- isCollection: navPropertyDefinition.$isCollection ? navPropertyDefinition.$isCollection : false,
653
- containsTarget: navPropertyDefinition.$ContainsTarget,
654
- targetTypeName: navPropertyDefinition.$Type,
655
- referentialConstraint
656
- };
714
+ function prepareEntityKeys(entityTypeDefinition: any, oMetaModelData: any): any {
715
+ if (!entityTypeDefinition.$Key && entityTypeDefinition.$BaseType) {
716
+ return prepareEntityKeys(oMetaModelData[`${entityTypeDefinition.$BaseType}`], oMetaModelData);
717
+ }
718
+ return entityTypeDefinition.$Key || []; //handling of entity types without key as well as basetype
719
+ }
657
720
 
658
- this.createAnnotationLists(navPropertyAnnotation, navigationProperty.fullyQualifiedName, annotationLists, oCapabilities);
721
+ function prepareEntityType(entityTypeDefinition: any, entityTypeName: string, namespace: string, metaModelData: any): EntityType {
722
+ const entityKeys: any = prepareEntityKeys(entityTypeDefinition, metaModelData);
659
723
 
660
- return navigationProperty;
661
- },
662
- parseEntitySet(
663
- oMetaModel: any,
664
- entitySetName: string,
665
- annotationLists: AnnotationList[],
666
- entityContainerName: string,
667
- oCapabilities: EnvironmentCapabilities
668
- ): EntitySet {
669
- const entitySetDefinition = oMetaModel.getObject(`/${entitySetName}`);
670
- const entitySetAnnotation = oMetaModel.getObject(`/${entitySetName}@`);
671
- const entitySetObject: EntitySet = {
672
- _type: "EntitySet",
673
- name: entitySetName,
674
- navigationPropertyBinding: {},
675
- entityTypeName: entitySetDefinition.$Type,
676
- fullyQualifiedName: `${entityContainerName}/${entitySetName}`
677
- };
678
- this.createAnnotationLists(entitySetAnnotation, entitySetObject.fullyQualifiedName, annotationLists, oCapabilities);
679
- return entitySetObject;
680
- },
724
+ const entityTypeObject: EntityType = {
725
+ _type: "EntityType",
726
+ name: entityTypeName.replace(namespace + ".", ""),
727
+ fullyQualifiedName: entityTypeName,
728
+ keys: [],
729
+ entityProperties: [],
730
+ navigationProperties: []
731
+ };
681
732
 
682
- parseSingleton(
683
- oMetaModel: any,
684
- singletonName: string,
685
- annotationLists: AnnotationList[],
686
- entityContainerName: string,
687
- oCapabilities: EnvironmentCapabilities
688
- ): Singleton {
689
- const singletonDefinition = oMetaModel.getObject(`/${singletonName}`);
690
- const singletonAnnotation = oMetaModel.getObject(`/${singletonName}@`);
691
- const singletonObject: Singleton = {
692
- _type: "Singleton",
693
- name: singletonName,
694
- navigationPropertyBinding: {},
695
- typeName: singletonDefinition.$Type,
696
- fullyQualifiedName: `${entityContainerName}/${singletonName}`,
697
- nullable: true
698
- };
699
- this.createAnnotationLists(singletonAnnotation, singletonObject.fullyQualifiedName, annotationLists, oCapabilities);
700
- return singletonObject;
701
- },
733
+ const entityProperties = Object.keys(entityTypeDefinition)
734
+ .filter(propertyNameOrNot => {
735
+ if (propertyNameOrNot != "$Key" && propertyNameOrNot != "$kind") {
736
+ return entityTypeDefinition[propertyNameOrNot].$kind === "Property";
737
+ }
738
+ })
739
+ .map(propertyName => {
740
+ return prepareProperty(entityTypeDefinition[propertyName], entityTypeObject, propertyName);
741
+ });
702
742
 
703
- parseEntityType(
704
- oMetaModel: any,
705
- entityTypeName: string,
706
- annotationLists: AnnotationList[],
707
- namespace: string,
708
- oCapabilities: EnvironmentCapabilities
709
- ): EntityType {
710
- const entityTypeAnnotation = oMetaModel.getObject(`/${entityTypeName}@`);
711
- const entityTypeDefinition = oMetaModel.getObject(`/${entityTypeName}`);
743
+ const navigationProperties = Object.keys(entityTypeDefinition)
744
+ .filter(propertyNameOrNot => {
745
+ if (propertyNameOrNot != "$Key" && propertyNameOrNot != "$kind") {
746
+ return entityTypeDefinition[propertyNameOrNot].$kind === "NavigationProperty";
747
+ }
748
+ })
749
+ .map(navPropertyName => {
750
+ return prepareNavigationProperty(entityTypeDefinition[navPropertyName], entityTypeObject, navPropertyName);
751
+ });
712
752
 
713
- const entityKeys: any = getEntityKeys(entityTypeDefinition);
753
+ entityTypeObject.keys = entityKeys
754
+ .map((entityKey: string) => entityProperties.find((property: Property) => property.name === entityKey))
755
+ .filter((property: Property) => property !== undefined);
756
+ entityTypeObject.entityProperties = entityProperties;
757
+ entityTypeObject.navigationProperties = navigationProperties;
714
758
 
715
- function getEntityKeys(entityTypeDefinition: any): any {
716
- if (!entityTypeDefinition.$Key && entityTypeDefinition.$BaseType) {
717
- return getEntityKeys(oMetaModel.getObject(`/${entityTypeDefinition.$BaseType}`));
759
+ return entityTypeObject;
760
+ }
761
+ function prepareAction(actionName: string, actionRawData: MetaModelAction, namespace: string, entityContainerName: string): Action {
762
+ let actionEntityType: string = "";
763
+ let actionFQN = `${actionName}`;
764
+ const actionShortName = actionName.substr(namespace.length + 1);
765
+ if (actionRawData.$IsBound) {
766
+ const bindingParameter = actionRawData.$Parameter[0];
767
+ actionEntityType = bindingParameter.$Type;
768
+ if (bindingParameter.$isCollection === true) {
769
+ actionFQN = `${actionName}(Collection(${actionEntityType}))`;
770
+ } else {
771
+ actionFQN = `${actionName}(${actionEntityType})`;
772
+ }
773
+ } else {
774
+ actionFQN = `${entityContainerName}/${actionShortName}`;
775
+ }
776
+ const parameters = actionRawData.$Parameter || [];
777
+ return {
778
+ _type: "Action",
779
+ name: actionShortName,
780
+ fullyQualifiedName: actionFQN,
781
+ isBound: actionRawData.$IsBound,
782
+ isFunction: false,
783
+ sourceType: actionEntityType,
784
+ returnType: actionRawData.$ReturnType ? actionRawData.$ReturnType.$Type : "",
785
+ parameters: parameters.map(param => {
786
+ return {
787
+ _type: "ActionParameter",
788
+ isEntitySet: param.$Type === actionRawData.$EntitySetPath,
789
+ fullyQualifiedName: `${actionFQN}/${param.$Name}`,
790
+ type: param.$Type
791
+ // TODO missing properties ?
792
+ };
793
+ })
794
+ };
795
+ }
796
+ export function prepareEntityTypes(
797
+ oMetaModel: ODataMetaModel,
798
+ oCapabilities: EnvironmentCapabilities = DefaultEnvironmentCapabilities
799
+ ): ParserOutput {
800
+ const oMetaModelData = oMetaModel.getObject("/$");
801
+ const annotationLists: Record<string, AnnotationList> = {};
802
+ const entityTypes: EntityType[] = [];
803
+ const entitySets: EntitySet[] = [];
804
+ const singletons: Singleton[] = [];
805
+ const complexTypes: ComplexType[] = [];
806
+ const typeDefinitions: TypeDefinition[] = [];
807
+ const entityContainerName = oMetaModelData.$EntityContainer;
808
+ let namespace = "";
809
+ const schemaKeys = Object.keys(oMetaModelData).filter(metamodelKey => oMetaModelData[metamodelKey].$kind === "Schema");
810
+ if (schemaKeys && schemaKeys.length > 0) {
811
+ namespace = schemaKeys[0].substr(0, schemaKeys[0].length - 1);
812
+ } else if (entityTypes && entityTypes.length) {
813
+ namespace = entityTypes[0].fullyQualifiedName.replace(entityTypes[0].name, "");
814
+ namespace = namespace.substr(0, namespace.length - 1);
815
+ }
816
+ Object.keys(oMetaModelData).forEach(sObjectName => {
817
+ if (sObjectName !== "$kind") {
818
+ switch (oMetaModelData[sObjectName].$kind) {
819
+ case "EntityType":
820
+ const entityType = prepareEntityType(oMetaModelData[sObjectName], sObjectName, namespace, oMetaModelData);
821
+ // Check if there are filter facets defined for the entityType and if yes, check if all of them have an ID
822
+ // The ID is optional, but it is internally taken for grouping filter fields and if it's not present
823
+ // a fallback ID needs to be generated here.
824
+ if (
825
+ oMetaModelData.$Annotations[entityType.fullyQualifiedName] &&
826
+ oMetaModelData.$Annotations[entityType.fullyQualifiedName]["@com.sap.vocabularies.UI.v1.FilterFacets"]
827
+ ) {
828
+ oMetaModelData.$Annotations[entityType.fullyQualifiedName]["@com.sap.vocabularies.UI.v1.FilterFacets"].forEach(
829
+ (filterFacetAnnotation: any) => {
830
+ filterFacetAnnotation.ID = filterFacetAnnotation.ID || generate([{ Facet: filterFacetAnnotation }]);
831
+ }
832
+ );
833
+ }
834
+ entityType.entityProperties.forEach(entityProperty => {
835
+ if (!oMetaModelData.$Annotations[entityProperty.fullyQualifiedName]) {
836
+ oMetaModelData.$Annotations[entityProperty.fullyQualifiedName] = {};
837
+ }
838
+ if (
839
+ !oMetaModelData.$Annotations[entityProperty.fullyQualifiedName]["@com.sap.vocabularies.UI.v1.DataFieldDefault"]
840
+ ) {
841
+ oMetaModelData.$Annotations[entityProperty.fullyQualifiedName][
842
+ "@com.sap.vocabularies.UI.v1.DataFieldDefault"
843
+ ] = {
844
+ $Type: "com.sap.vocabularies.UI.v1.DataField",
845
+ Value: { $Path: entityProperty.name }
846
+ };
847
+ }
848
+ });
849
+ entityTypes.push(entityType);
850
+ break;
851
+ case "ComplexType":
852
+ const complexType = prepareComplexType(oMetaModelData[sObjectName], sObjectName, namespace);
853
+ complexTypes.push(complexType);
854
+ break;
855
+ case "TypeDefinition":
856
+ const typeDefinition = prepareTypeDefinition(oMetaModelData[sObjectName], sObjectName, namespace);
857
+ typeDefinitions.push(typeDefinition);
858
+ break;
718
859
  }
719
- return entityTypeDefinition.$Key || []; //handling of entity types without key as well as basetype
720
860
  }
721
- const entityTypeObject: EntityType = {
722
- _type: "EntityType",
723
- name: entityTypeName.replace(namespace + ".", ""),
724
- fullyQualifiedName: entityTypeName,
725
- keys: [],
726
- entityProperties: [],
727
- navigationProperties: []
728
- };
729
-
730
- this.createAnnotationLists(entityTypeAnnotation, entityTypeObject.fullyQualifiedName, annotationLists, oCapabilities);
731
- const entityProperties = Object.keys(entityTypeDefinition)
732
- .filter(propertyNameOrNot => {
733
- if (propertyNameOrNot != "$Key" && propertyNameOrNot != "$kind") {
734
- return entityTypeDefinition[propertyNameOrNot].$kind === "Property";
735
- }
736
- })
737
- .map(propertyName => {
738
- return this.parseProperty(oMetaModel, entityTypeObject, propertyName, annotationLists, oCapabilities);
739
- });
740
-
741
- const navigationProperties = Object.keys(entityTypeDefinition)
742
- .filter(propertyNameOrNot => {
743
- if (propertyNameOrNot != "$Key" && propertyNameOrNot != "$kind") {
744
- return entityTypeDefinition[propertyNameOrNot].$kind === "NavigationProperty";
745
- }
746
- })
747
- .map(navPropertyName => {
748
- return this.parseNavigationProperty(oMetaModel, entityTypeObject, navPropertyName, annotationLists, oCapabilities);
749
- });
750
-
751
- entityTypeObject.keys = entityKeys
752
- .map((entityKey: string) => entityProperties.find((property: Property) => property.name === entityKey))
753
- .filter((property: Property) => property !== undefined);
754
- entityTypeObject.entityProperties = entityProperties;
755
- entityTypeObject.navigationProperties = navigationProperties;
756
-
757
- return entityTypeObject;
758
- },
759
- parseComplexType(
760
- oMetaModel: any,
761
- complexTypeName: string,
762
- annotationLists: AnnotationList[],
763
- namespace: string,
764
- oCapabilities: EnvironmentCapabilities
765
- ): ComplexType {
766
- const complexTypeAnnotation = oMetaModel.getObject(`/${complexTypeName}@`);
767
- const complexTypeDefinition = oMetaModel.getObject(`/${complexTypeName}`);
768
- const complexTypeObject: ComplexType = {
769
- _type: "ComplexType",
770
- name: complexTypeName.replace(namespace + ".", ""),
771
- fullyQualifiedName: complexTypeName,
772
- properties: [],
773
- navigationProperties: []
774
- };
861
+ });
775
862
 
776
- this.createAnnotationLists(complexTypeAnnotation, complexTypeObject.fullyQualifiedName, annotationLists, oCapabilities);
777
- const complexTypeProperties = Object.keys(complexTypeDefinition)
778
- .filter(propertyNameOrNot => {
779
- if (propertyNameOrNot != "$Key" && propertyNameOrNot != "$kind") {
780
- return complexTypeDefinition[propertyNameOrNot].$kind === "Property";
781
- }
782
- })
783
- .map(propertyName => {
784
- return this.parseProperty(oMetaModel, complexTypeObject, propertyName, annotationLists, oCapabilities);
785
- });
786
-
787
- complexTypeObject.properties = complexTypeProperties;
788
- const complexTypeNavigationProperties = Object.keys(complexTypeDefinition)
789
- .filter(propertyNameOrNot => {
790
- if (propertyNameOrNot != "$Key" && propertyNameOrNot != "$kind") {
791
- return complexTypeDefinition[propertyNameOrNot].$kind === "NavigationProperty";
792
- }
793
- })
794
- .map(navPropertyName => {
795
- return this.parseNavigationProperty(oMetaModel, complexTypeObject, navPropertyName, annotationLists, oCapabilities);
796
- });
797
- complexTypeObject.navigationProperties = complexTypeNavigationProperties;
798
- return complexTypeObject;
799
- },
800
- parseAction(actionName: string, actionRawData: MetaModelAction, namespace: string, entityContainerName: string): Action {
801
- let actionEntityType: string = "";
802
- let actionFQN = `${actionName}`;
803
- const actionShortName = actionName.substr(namespace.length + 1);
804
- if (actionRawData.$IsBound) {
805
- const bindingParameter = actionRawData.$Parameter[0];
806
- actionEntityType = bindingParameter.$Type;
807
- if (bindingParameter.$isCollection === true) {
808
- actionFQN = `${actionName}(Collection(${actionEntityType}))`;
809
- } else {
810
- actionFQN = `${actionName}(${actionEntityType})`;
863
+ const oEntityContainer = oMetaModelData[entityContainerName];
864
+ Object.keys(oEntityContainer).forEach(sObjectName => {
865
+ if (sObjectName !== "$kind") {
866
+ switch (oEntityContainer[sObjectName].$kind) {
867
+ case "EntitySet":
868
+ const entitySet = prepareEntitySet(oEntityContainer[sObjectName], sObjectName, entityContainerName);
869
+ entitySets.push(entitySet);
870
+ break;
871
+ case "Singleton":
872
+ const singleton = prepareSingleton(oEntityContainer[sObjectName], sObjectName, entityContainerName);
873
+ singletons.push(singleton);
874
+ break;
811
875
  }
812
- } else {
813
- actionFQN = `${entityContainerName}/${actionShortName}`;
814
876
  }
815
- const parameters = actionRawData.$Parameter || [];
816
- return {
817
- _type: "Action",
818
- name: actionShortName,
819
- fullyQualifiedName: actionFQN,
820
- isBound: actionRawData.$IsBound,
821
- sourceType: actionEntityType,
822
- returnType: actionRawData.$ReturnType ? actionRawData.$ReturnType.$Type : "",
823
- parameters: parameters.map(param => {
824
- return {
825
- _type: "ActionParameter",
826
- isEntitySet: param.$Type === actionRawData.$EntitySetPath,
827
- fullyQualifiedName: `${actionFQN}/${param.$Name}`,
828
- type: param.$Type
829
- // TODO missing properties ?
830
- };
831
- })
877
+ });
878
+
879
+ let entityContainer: EntityContainer = {};
880
+ if (entityContainerName) {
881
+ entityContainer = {
882
+ name: entityContainerName.replace(namespace + ".", ""),
883
+ fullyQualifiedName: entityContainerName
832
884
  };
833
- },
834
- parseEntityTypes(oMetaModel: any, oInCapabilities?: EnvironmentCapabilities): ParserOutput {
835
- let oCapabilities: EnvironmentCapabilities;
836
- if (!oInCapabilities) {
837
- oCapabilities = DefaultEnvironmentCapabilities;
838
- } else {
839
- oCapabilities = oInCapabilities;
840
- }
841
- const oMetaModelData = oMetaModel.getObject("/$");
842
- const oEntitySets = oMetaModel.getObject("/");
843
- let annotationLists: AnnotationList[] = [];
844
- const entityTypes: EntityType[] = [];
845
- const entitySets: EntitySet[] = [];
846
- const singletons: Singleton[] = [];
847
- const complexTypes: ComplexType[] = [];
848
- const entityContainerName = oMetaModelData.$EntityContainer;
849
- let namespace = "";
850
- const schemaKeys = Object.keys(oMetaModelData).filter(metamodelKey => oMetaModelData[metamodelKey].$kind === "Schema");
851
- if (schemaKeys && schemaKeys.length > 0) {
852
- namespace = schemaKeys[0].substr(0, schemaKeys[0].length - 1);
853
- } else if (entityTypes && entityTypes.length) {
854
- namespace = entityTypes[0].fullyQualifiedName.replace(entityTypes[0].name, "");
855
- namespace = namespace.substr(0, namespace.length - 1);
856
- }
857
- Object.keys(oMetaModelData)
858
- .filter(entityTypeName => {
859
- return entityTypeName !== "$kind" && oMetaModelData[entityTypeName].$kind === "EntityType";
860
- })
861
- .forEach(entityTypeName => {
862
- const entityType = this.parseEntityType(oMetaModel, entityTypeName, annotationLists, namespace, oCapabilities);
863
- // Check if there are filter facets defined for the entityType and if yes, check if all of them have an ID
864
- // The ID is optional, but it is internally taken for grouping filter fields and if it's not present
865
- // a fallback ID needs to be generated here.
866
- if (
867
- oMetaModelData.$Annotations[entityType.fullyQualifiedName] &&
868
- oMetaModelData.$Annotations[entityType.fullyQualifiedName]["@com.sap.vocabularies.UI.v1.FilterFacets"]
869
- ) {
870
- oMetaModelData.$Annotations[entityType.fullyQualifiedName]["@com.sap.vocabularies.UI.v1.FilterFacets"].forEach(
871
- (filterFacetAnnotation: any) => {
872
- filterFacetAnnotation.ID = filterFacetAnnotation.ID || generate([{ Facet: filterFacetAnnotation }]);
873
- this.createAnnotationLists(
874
- {
875
- "@com.sap.vocabularies.UI.v1.FilterFacets":
876
- oMetaModelData.$Annotations[entityType.fullyQualifiedName][
877
- "@com.sap.vocabularies.UI.v1.FilterFacets"
878
- ]
879
- },
880
- entityType.fullyQualifiedName,
881
- annotationLists,
882
- oCapabilities
883
- );
884
- }
885
- );
885
+ }
886
+ entitySets.forEach(entitySet => {
887
+ const navPropertyBindings = oEntityContainer[entitySet.name].$NavigationPropertyBinding;
888
+ if (navPropertyBindings) {
889
+ Object.keys(navPropertyBindings).forEach(navPropName => {
890
+ const targetEntitySet = entitySets.find(entitySetName => entitySetName.name === navPropertyBindings[navPropName]);
891
+ if (targetEntitySet) {
892
+ entitySet.navigationPropertyBinding[navPropName] = targetEntitySet;
886
893
  }
887
- entityType.entityProperties.forEach(entityProperty => {
888
- if (!oMetaModelData.$Annotations[entityProperty.fullyQualifiedName]) {
889
- oMetaModelData.$Annotations[entityProperty.fullyQualifiedName] = {};
890
- }
891
- if (!oMetaModelData.$Annotations[entityProperty.fullyQualifiedName]["@com.sap.vocabularies.UI.v1.DataFieldDefault"]) {
892
- oMetaModelData.$Annotations[entityProperty.fullyQualifiedName]["@com.sap.vocabularies.UI.v1.DataFieldDefault"] = {
893
- $Type: "com.sap.vocabularies.UI.v1.DataField",
894
- Value: { $Path: entityProperty.name }
895
- };
896
- this.createAnnotationLists(
897
- {
898
- "@com.sap.vocabularies.UI.v1.DataFieldDefault":
899
- oMetaModelData.$Annotations[entityProperty.fullyQualifiedName][
900
- "@com.sap.vocabularies.UI.v1.DataFieldDefault"
901
- ]
902
- },
903
- entityProperty.fullyQualifiedName,
904
- annotationLists,
905
- oCapabilities
906
- );
907
- }
908
- });
909
- entityTypes.push(entityType);
910
- });
911
- Object.keys(oEntitySets)
912
- .filter(entitySetName => {
913
- return entitySetName !== "$kind" && oEntitySets[entitySetName].$kind === "EntitySet";
914
- })
915
- .forEach(entitySetName => {
916
- const entitySet = this.parseEntitySet(oMetaModel, entitySetName, annotationLists, entityContainerName, oCapabilities);
917
- entitySets.push(entitySet);
918
894
  });
919
- Object.keys(oEntitySets)
920
- .filter(singletonName => {
921
- return singletonName !== "$kind" && oEntitySets[singletonName].$kind === "Singleton";
922
- })
923
- .forEach(singletonName => {
924
- const singleton = this.parseSingleton(oMetaModel, singletonName, annotationLists, entityContainerName, oCapabilities);
925
- singletons.push(singleton);
926
- });
927
- Object.keys(oMetaModelData)
928
- .filter(complexTypeName => {
929
- return complexTypeName !== "$kind" && oMetaModelData[complexTypeName].$kind === "ComplexType";
930
- })
931
- .forEach(complexTypeName => {
932
- const complexType = this.parseComplexType(oMetaModel, complexTypeName, annotationLists, namespace, oCapabilities);
933
- complexTypes.push(complexType);
934
- });
935
- const oEntityContainerName = Object.keys(oMetaModelData).find(entityContainerName => {
936
- return entityContainerName !== "$kind" && oMetaModelData[entityContainerName].$kind === "EntityContainer";
937
- });
938
- let entityContainer: EntityContainer = {};
939
- if (oEntityContainerName) {
940
- entityContainer = {
941
- name: oEntityContainerName.replace(namespace + ".", ""),
942
- fullyQualifiedName: oEntityContainerName
943
- };
944
895
  }
945
- entitySets.forEach(entitySet => {
946
- const navPropertyBindings = oMetaModelData[entityContainerName][entitySet.name].$NavigationPropertyBinding;
947
- if (navPropertyBindings) {
948
- Object.keys(navPropertyBindings).forEach(navPropName => {
949
- const targetEntitySet = entitySets.find(entitySetName => entitySetName.name === navPropertyBindings[navPropName]);
950
- if (targetEntitySet) {
951
- entitySet.navigationPropertyBinding[navPropName] = targetEntitySet;
952
- }
953
- });
954
- }
955
- });
896
+ });
956
897
 
957
- const actions: Action[] = Object.keys(oMetaModelData)
958
- .filter(key => {
959
- return Array.isArray(oMetaModelData[key]) && oMetaModelData[key].length > 0 && oMetaModelData[key][0].$kind === "Action";
960
- })
961
- .reduce((outActions: Action[], actionName) => {
962
- const actions = oMetaModelData[actionName];
963
- actions.forEach((action: MetaModelAction) => {
964
- outActions.push(this.parseAction(actionName, action, namespace, entityContainerName));
965
- });
966
- return outActions;
967
- }, []);
968
- // FIXME Crappy code to deal with annotations for functions
969
- const annotations = oMetaModelData.$Annotations;
970
- const actionAnnotations = Object.keys(annotations).filter(target => target.indexOf("(") !== -1);
971
- actionAnnotations.forEach(target => {
972
- this.createAnnotationLists(oMetaModelData.$Annotations[target], target, annotationLists, oCapabilities);
973
- });
974
- const actionsNameWithoutOverload = actions.map(action => action.fullyQualifiedName.split("(")[0]);
975
- actionsNameWithoutOverload.forEach(actionName => {
976
- if (annotations.hasOwnProperty(actionName)) {
977
- this.createAnnotationLists(oMetaModelData.$Annotations[actionName], actionName, annotationLists, oCapabilities);
978
- }
979
- });
980
- const entityContainerAnnotations = annotations[entityContainerName];
898
+ const actions: Action[] = Object.keys(oMetaModelData)
899
+ .filter(key => {
900
+ return Array.isArray(oMetaModelData[key]) && oMetaModelData[key].length > 0 && oMetaModelData[key][0].$kind === "Action";
901
+ })
902
+ .reduce((outActions: Action[], actionName) => {
903
+ const actions = oMetaModelData[actionName];
904
+ actions.forEach((action: MetaModelAction) => {
905
+ outActions.push(prepareAction(actionName, action, namespace, entityContainerName));
906
+ });
907
+ return outActions;
908
+ }, []);
981
909
 
982
- // Retrieve Entity Container annotations
983
- if (entityContainerAnnotations) {
984
- this.createAnnotationLists(entityContainerAnnotations, entityContainerName, annotationLists, oCapabilities);
985
- }
986
- // Sort by target length
987
- annotationLists = annotationLists.sort((a, b) => (a.target.length >= b.target.length ? 1 : -1));
988
- const references: Reference[] = [];
989
- return {
990
- identification: "metamodelResult",
991
- version: "4.0",
992
- schema: {
993
- entityContainer,
994
- entitySets,
995
- entityTypes,
996
- complexTypes,
997
- singletons,
998
- associations: [],
999
- actions,
1000
- namespace,
1001
- annotations: {
1002
- "metamodelResult": annotationLists
1003
- }
1004
- },
1005
- references: references
1006
- };
910
+ for (const target in oMetaModelData.$Annotations) {
911
+ createAnnotationLists(oMetaModelData.$Annotations[target], target, annotationLists, oCapabilities);
1007
912
  }
1008
- };
913
+
914
+ // Sort by target length
915
+ const outAnnotationLists = Object.keys(annotationLists)
916
+ .sort((a, b) => (a.length >= b.length ? 1 : -1))
917
+ .map(sAnnotationName => annotationLists[sAnnotationName]);
918
+ const references: Reference[] = [];
919
+ return {
920
+ identification: "metamodelResult",
921
+ version: "4.0",
922
+ schema: {
923
+ entityContainer,
924
+ entitySets,
925
+ entityTypes,
926
+ complexTypes,
927
+ typeDefinitions,
928
+ singletons,
929
+ associations: [],
930
+ associationSets: [],
931
+ actions,
932
+ namespace,
933
+ annotations: {
934
+ "metamodelResult": outAnnotationLists
935
+ }
936
+ },
937
+ references: references
938
+ };
939
+ }
1009
940
 
1010
941
  const mMetaModelMap: Record<string, ParserOutput> = {};
1011
942
 
@@ -1019,22 +950,58 @@ const mMetaModelMap: Record<string, ParserOutput> = {};
1019
950
  export function convertTypes(oMetaModel: ODataMetaModel, oCapabilities?: EnvironmentCapabilities): ConverterOutput {
1020
951
  const sMetaModelId = (oMetaModel as any).id;
1021
952
  if (!mMetaModelMap.hasOwnProperty(sMetaModelId)) {
1022
- const parsedOutput = MetaModelConverter.parseEntityTypes(oMetaModel, oCapabilities);
1023
- mMetaModelMap[sMetaModelId] = AnnotationConverter.convertTypes(parsedOutput);
953
+ const parsedOutput = prepareEntityTypes(oMetaModel, oCapabilities);
954
+ if (oCapabilities && oCapabilities.Situations) {
955
+ // Only Experimental Feature!
956
+ mMetaModelMap[sMetaModelId] = addSyntheticAnnotations(AnnotationConverter.convertTypes(parsedOutput));
957
+ } else {
958
+ mMetaModelMap[sMetaModelId] = AnnotationConverter.convertTypes(parsedOutput);
959
+ }
1024
960
  }
1025
961
  return (mMetaModelMap[sMetaModelId] as any) as ConverterOutput;
1026
962
  }
1027
963
 
964
+ function addSyntheticAnnotations(metaModel: ParserOutput) {
965
+ // [Situations POC] Determine mixed-in situations navigation property.
966
+ // This will probably happen either
967
+ // - by a fixed navigation property name ("SAP__Situation"), or
968
+ // - by an entity type annotation that declares the navigation property to use (similar to com.sap.vocabularies.Common.v1.Messages)
969
+ //
970
+ // For now, we add an 'invented' annotation "com.sap.vocabularies.FioriElements.v1.Situations" consisting of a path to the situations navigation property
971
+ ((metaModel as any) as ConverterOutput).entityTypes.forEach(entityType => {
972
+ const situationsNavProp = entityType.navigationProperties.find(
973
+ navProp => navProp.name === "SAP__Situation" || navProp.name === "_SAP__Situation"
974
+ );
975
+
976
+ if (situationsNavProp) {
977
+ (entityType.annotations as any).FE = {
978
+ Situations: {
979
+ term: "com.sap.vocabularies.FioriElements.v1.Situations",
980
+ type: "Path",
981
+ path: situationsNavProp.name,
982
+ $target: situationsNavProp
983
+ }
984
+ };
985
+ }
986
+ });
987
+ return metaModel;
988
+ }
989
+
1028
990
  export function deleteModelCacheData(oMetaModel: ODataMetaModel) {
1029
991
  delete mMetaModelMap[(oMetaModel as any).id];
1030
992
  }
1031
993
 
1032
- export function convertMetaModelContext(oMetaModelContext: Context, bIncludeVisitedObjects: boolean = false): any {
1033
- const oConverterOutput = convertTypes((oMetaModelContext.getModel() as unknown) as ODataMetaModel);
994
+ export function convertMetaModelContext(oMetaModelContext: Context<ODataMetaModel>, bIncludeVisitedObjects: boolean = false): any {
995
+ const oConverterOutput = convertTypes(oMetaModelContext.getModel());
1034
996
  const sPath = oMetaModelContext.getPath();
1035
997
 
1036
998
  const aPathSplit = sPath.split("/");
1037
- let targetEntitySet: _EntitySet = oConverterOutput.entitySets.find(entitySet => entitySet.name === aPathSplit[1]) as _EntitySet;
999
+ let targetEntitySet: _EntitySet | _Singleton = oConverterOutput.entitySets.find(
1000
+ entitySet => entitySet.name === aPathSplit[1]
1001
+ ) as _EntitySet;
1002
+ if (!targetEntitySet) {
1003
+ targetEntitySet = oConverterOutput.singletons.find(singleton => singleton.name === aPathSplit[1]) as _Singleton;
1004
+ }
1038
1005
  let relativePath = aPathSplit.slice(2).join("/");
1039
1006
 
1040
1007
  const localObjects: any[] = [targetEntitySet];
@@ -1073,7 +1040,13 @@ export function convertMetaModelContext(oMetaModelContext: Context, bIncludeVisi
1073
1040
  localObjects.push(targetEntitySet);
1074
1041
  }
1075
1042
  // Re-calculating the relative path
1076
- relativePath = relativeSplit.slice(aNavProps.length || 1).join("/");
1043
+ // As each navigation name is enclosed between '$NavigationPropertyBinding' and '$' (to be able to access the entityset easily in the metamodel)
1044
+ // we need to remove the closing '$' to be able to switch to the next navigation
1045
+ relativeSplit = relativeSplit.slice(aNavProps.length || 1);
1046
+ if (relativeSplit.length && relativeSplit[0] === "$") {
1047
+ relativeSplit.shift();
1048
+ }
1049
+ relativePath = relativeSplit.join("/");
1077
1050
  }
1078
1051
  if (relativePath.startsWith("$Type")) {
1079
1052
  // We're anyway going to look on the entityType...
@@ -1123,7 +1096,10 @@ export type ResolvedTarget = {
1123
1096
  visitedObjects: ConverterObject[];
1124
1097
  };
1125
1098
 
1126
- export function getInvolvedDataModelObjects(oMetaModelContext: Context, oEntitySetMetaModelContext?: Context): DataModelObjectPath {
1099
+ export function getInvolvedDataModelObjects(
1100
+ oMetaModelContext: Context<ODataMetaModel>,
1101
+ oEntitySetMetaModelContext?: Context<ODataMetaModel>
1102
+ ): DataModelObjectPath {
1127
1103
  const metaModelContext = convertMetaModelContext(oMetaModelContext, true);
1128
1104
  let targetEntitySetLocation;
1129
1105
  if (oEntitySetMetaModelContext && oEntitySetMetaModelContext.getPath() !== "/") {